Reputation: 69
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
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
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