Rynxie
Rynxie

Reputation: 69

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);
     }
     
}

Upvotes: 0

Views: 71

Answers (2)

Clifford
Clifford

Reputation: 93556

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
             ^^^^^^^^^^

Upvotes: 0

Rynxie
Rynxie

Reputation: 69

After @AndreyTurkin's answer, I learned how to look at memory addresses with OpenOCD and realized the GPIOB_CRL register has a different value than what I wrote into it. I solved the problem by writing *gpiobCrL = 0x3B444444;, but I still have no clue why the previous method didn't work.

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

When I write it like this at the top, it irrelevantly opens the PB4 pin. If anyone knows why this happens and let me know, it would be highly appreciated.

After all my TUFAN_VLDCMS_Global.h file was not have any incorrect registers. so I don't share it here I didn't change anything in the file. But Here is the main.c file;

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;

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

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

     *gpiobCrL    = 0x3B444444;

     //this doesn't work I dont know why yet
     /* *gpiobCrL      |= (3<<24);   //PB6 Output Mode 50Mhz
     *gpiobCrL      |= (2<<26);   //PB6 Alternate function Push-Pull

     *gpiobCrL      |= (3<<28);   
     *gpiobCrL      &= ~(3<<30);  */  

     
     *tim4Psc       =  7;
     *tim4Arr       =  62;
     *tim4Ccr1      =  0;

     *tim4Ccmr1    =  0x0000;
     *tim4Ccmr1    |= (3<<5);
     *tim4Ccmr1    |= (1<<3);

     *tim4Ccer     |= (1<<0);

     
    

     while (1){
          *tim4Cr1       |= (1<<0);
          *tim4Ccr1      =  30;
          *gpiobOdr      |= (1<<7);
     }
     
}

Upvotes: 0

Related Questions