timerembeddedstm32pwmstm32f1

I can't program STM32F100RBTx to send pwm signals


I am trying to send PWM signals using STM32F100RBTx but it is not working. I double checked all the addresses but it is still the same. I wasn't sure if I was flashing at the beginning but I configured the PB7 pin to be GPIO output and connected to a LED and the LED is working so I can flash it and my GPIO conifgurations must be working. Here is the code, I don't know what to try:

TUFAN_VLDCMS_Global.h:

#include <stdint.h>

#define RCC         0x40021000
#define RCC_AHBENR  0x40021014
#define RCC_APB2ENR 0x40021018
#define RCC_APB1ENR 0x4002101C


#define AFIO        0x40010000
#define AFIO_MAPR   0x40010004


#define GPIOB       0x40010C00
#define GPIOB_ODR   0x40010C0C 


#define TIM4        0x40000800  
#define TIM4_CR1    0x40000800 
#define TIM4_CR2    0x40000804
#define TIM4_SMCR   0x40000808
#define TIM4_DIER   0x4000080C
#define TIM4_SR     0x40000810
#define TIM4_EGR    0x40000814
#define TIM4_CCMR1  0x40000818
#define TIM4_CCMR2  0x4000081C
#define TIM4_CCER   0x40000820
#define TIM4_CNT    0x40000824
#define TIM4_PSC    0x40000828
#define TIM4_ARR    0x4000082C
#define TIM4_CCR1   0x40000834
#define TIM4_CCR2   0x40000838
#define TIM4_CCR3   0x4000083C
#define TIM4_CCR4   0x40000840
#define TIM4_DCR    0x40000848
#define TIM4_DMAR   0x4000084C

main.c:

#include <stdio.h>
#include <stdint.h>
#include "TUFAN_VLDCMS_Global.h"



int main(){
    

     volatile uint32_t * tim4Cr1     =  (volatile uint32_t *) TIM4_CR1;
     volatile uint32_t * tim4Psc     =  (volatile uint32_t *) TIM4_PSC;
     volatile uint32_t * tim4Arr     =  (volatile uint32_t *) TIM4_ARR;
     volatile uint32_t * tim4Ccr1    =  (volatile uint32_t *) TIM4_CCR1;
     volatile uint32_t * tim4Ccmr1   =  (volatile uint32_t *) TIM4_CCMR1;
     volatile uint32_t * tim4Ccer    =  (volatile uint32_t *) TIM4_CCER;
     volatile uint32_t * tim4Egr     =  (volatile uint32_t *) TIM4_EGR;


     volatile uint32_t * rccApb1enr  =  (volatile uint32_t *) RCC_APB1ENR;
     volatile uint32_t * rccApb2enr  =  (volatile uint32_t *) RCC_APB2ENR;

     
     
     volatile uint32_t * gpiobCrL    =  (volatile uint32_t *) GPIOB;
     volatile uint32_t * gpiobOdr    =  (volatile uint32_t *) GPIOB_ODR;

     volatile uint32_t * afioMapr    =  (volatile uint32_t *) AFIO_MAPR;

     *rccApb1enr    |= (1<<2);     //enable TIM4 from APB1
     *rccApb2enr    |= (1<<0);     //enable AFIO from APB2
     *rccApb2enr    |= (1<<3);     //enable IOPB from APB2

     *afioMapr      &= ~(1<<12);   //set alternate function remap to 0

     *gpiobCrL      |= (3<<24);    //PB6 Output Mode 50Mhz
     *gpiobCrL      |= (2<<26);    //PB6 Alternate function Push-Pull
     
     *gpiobCrL      |= (3<<28);    //Configuring PB7 to for test to see if i can flash it
     *gpiobCrL      &= ~(3<<30);   

     *tim4Cr1       |= 0x0000;     //reseting it just in case 
     *tim4Psc       =  7;          //calculated it thinking default clock speed is 8MHz
     *tim4Arr       =  62;         //I want to have PWM signal around 16kHz
     *tim4Ccr1      =  31;         //and %50 duty cycle

     *tim4Ccmr1     |= 0x68;       //configuring channel 1
     *tim4Ccer      |= (1<<0);     //enabling channel 1

     *tim4Cr1       |= (1<<0);     //enable the timer
     *tim4Egr       |= (1<<0);

     while (1){
       
          *tim4Ccr1      =  31;
          *gpiobOdr      |= (1<<7);
     }
     
}

Solution

  • The problem with:

    *gpiobCrL      |= (3<<24);   //PB6 Output Mode 50Mhz
    *gpiobCrL      |= (2<<26);   //PB6 Alternate function Push-Pull
         
    *gpiobCrL      |= (3<<28);   
    *gpiobCrL      &= ~(3<<30);
    

    is that the reset state of GPIOx_CRL is 0x44444444 and not zero:

    (0x44444444 | (3<<24) | (2<<26) | (3<<28)) & ~(3<<30) == 0x3F444444
    

    The part (2<<26) does not clear bit 26 which is 1 in the reset state, so you end up with CNF6 == 3. To set CNF6 == 2 you need:

    *gpiobCrL      &= ~(3<<26);  // Clear CNF6 bits
    *gpiobCrL      |= (2<<26);   // PB6 Alternate function Push-Pull
    
    ((0x44444444 & ~(3<<26)) | (3<<24) | (2<<26) | (3<<28)) & ~(3<<30) == 0x3B444444
                 ^^^^^^^^^^