2020-10-25 06:12 PM
I can see an output in my serial monitor if i am using CubeMX and CubeIDE but with baremetal in Keil, I dont understand why i am not seeing any . I have a B-l475E-IOT01a board with me, and from the schematic I can see both UART1_TX and UART1_RX connected to ST-Link via PB6 and PB7.
//
//Objective: Use USART1 to transmit data to serial monitor software (Putty).
//
//
//USART1 uses APB2 bus
//USART1 is an alternate function of PA9 & PB6
//USART1_TX is alternate function AF7 of PA9 & PB6
//USART1_RX is an alternate function of PA10 & PB7.
//
//PA2, PA3, PD5, PD6, PA9, PB6, PA10 & PB7 all use the AHB2 bus.
//ST-Link UART1_TX & UART1_RX connected to PB6 and PB7
#include "stm32l4xx.h"
#include "stm32l475xx.h" // Device header
void usart1_init(void);
void usart1_write(int ch);
void delayMS(int delay);
int main(void){
usart1_init();
while(1){
usart1_write('S');
usart1_write('T');
usart1_write('M');
usart1_write('3');
usart1_write('2');
delayMS(100);
}
}
void usart1_init(void){
RCC->APB2ENR |= (1<<14); //Bit 14 in RCC_APB2ENR is used to enable USART1 clock
//RCC->AHB2ENR |= (1<<0); //Bit 0 in RCC_AHB2ENR is used to enable GPIOA clock
RCC->AHB2ENR |= (1<<1); //Bit 1 in RCC_AHB2ENR is used to enable GPIOB clock
//GPIOA->MODER &=~ (0xC0000); //PA9: Set Port A Pin 9 to "Analog Mode(Reset State)"
//GPIOB->MODER &=~ (0x3000); //PB6: Set Port B Pin 6 to "Analog Mode(Reset State)"
//GPIOA->MODER |= (1<<19); //Set PA9 to alternate Function mode
GPIOB->MODER |= (1<<13); //Set PB6 to alternate Function mode
GPIOA->AFR[1] = (0x70); /Set PA9 alternate function to USART1_TX
GPIOB->AFR[0] = (0x7000000); //Set PB6 alternate function to USART1_TX
GPIOA->AFR[1] = (0x70); //Set PA10 alternate function to USART1_RX
GPIOB->AFR[0] = (0x70000000); //Set PB7 alternate function to USART1_RX
//USART1->BRR = (0x0045); //15 bits | 0000 0000 0100 0101 ~ 0x0045 |SysClk/
//Baudrate = 8MHz/115200
//USART1->BRR = (0x0683);
USART1->BRR = 0x8b;
USART1->CR1 |= (1<<3); // Enable TE (Transmitter)
USART1->CR1 |= (1<<2); //Enable RE (Receiver)
USART1->CR1 |= (1<<0); // Enable USART
}
void usart1_write(int ch){
//wait while TX buffer is empty
while(!(USART1->ISR & 0x80)){}
USART1->TDR = (ch & 0xFF);
}
void delayMS(int delay){
int i;
for(;delay>0;delay--){
for(i=0;i<3195;i++);
}
}
2020-10-25 07:40 PM
This statement:
> GPIOB->AFR[0] = (0x7000000);
gets overwritten by:
> GPIOB->AFR[0] = (0x70000000);
Your delayMS function may or may not do anything, depending on compiler settings.
Could be other issues.
Also no way these comments are both correct, since the statement is identical. The first one won't even compile since it's missing a slash.
> GPIOA->AFR[1] = (0x70); /Set PA9 alternate function to USART1_TX
> GPIOA->AFR[1] = (0x70); //Set PA10 alternate function to USART1_RX
Edit: changed my response which was initially incorrect.
2020-10-26 04:38 AM
For a bare metal delay function look at:
https://community.st.com/s/question/0D53W00000BJ7KdSAL/is-haldelay1-quaranteed-to-be-close-to-1ms
Need to enable the DWT counter:
void bspTsInit_ (void)
{
/* DWT cycle counter enable. The M7 requires DWT unlocking.*/
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk ;
#if defined __CM7_REV
DWT->LAR = 0xC5ACCE55U ;
#endif
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk ;
// DWT->CYCNT frequency is SystemCoreClock Hz
// Compute divider to convert delta values to microseconds
bspTsMhzDiv = SystemCoreClock / 1000000u ;
}
2020-10-26 07:35 PM - edited 2023-11-20 09:17 AM
Thanks TDK. Yes, my values at GPIO-> AFR gets over written and so I have deleted the part related to RX as I dont need it yet at this point. I am just trying to output a character to serial monitor. Now I have cleaned up the code and I am able to see some characters displayed but it is no where near the expected characters. For BRR calculation I have used the formula usartdiv = ***/(16*baudrate) where *** is 8MHz (XTAL freq). I have read read somewhere that I should use the APB2 bus clock instead which in my case is 80MHz. I have tried using this but I dont see any output at the serial monitor. I am using the BL475E-IOT01a board.
The delayMS function was copied from the tutorial I was using so it should somehow work. I just use his code as reference as he was using a different stm32 chip. Another thing, in keil target options, what shoudl i use as value of core clock? is it 80MHz?
//
//Objective: Use USART1 to transmit data to serial monitor software (Putty).
//
//USART1 uses APB2 bus
//USART1 is an alternate function of PA9 & PB6
//USART1_TX is alternate function AF7 of PA9 & PB6
//USART1_RX is an alternate function of PA10 & PB7.
//
//PA2, PA3, PD5, PD6, PA9, PB6, PA10 & PB7 all use the AHB2 bus.
//ST-Link UART1_TX & UART1_RX connected to PB6 and PB7
#include "stm32l4xx.h"
#include "stm32l475xx.h" // Device header
void usart1_init(void);
void usart1_write(int ch);
void delayMS(int delay);
int main(void){
usart1_init();
while(1){
usart1_write('S');
usart1_write('T');
delayMS(100);
}
}
void usart1_init(void){
RCC->APB2ENR |= (1AHB2ENR |= (1MODER &=~ (0x3000); //PB6: Set Port B Pin 6 to "Analog Mode(Reset State)"
GPIOB->MODER |= (1AFR[0] = (0x7000000); //Set PB6 alternate function to USART1_TX
USART1->BRR = (0x683); //(2x 8Mhz) div 9600 = 1667 = 0x683 **
USART1->CR1 |= (1CR1 |= (1CR1 |= (1ISR & 0x80)){}
USART1->TDR = (ch & 0xFF);
}
void delayMS(int delay){
int i;
for(;delay>0;delay--){
for(i=0;i
2020-10-26 07:37 PM
Thanks @Nikita91 . I will take a look into it.
2020-10-26 07:42 PM
> RCC->APB2ENR |= (1AHB2ENR |= (1MODER &=~ (0x3000); //PB6: Set Port B Pin 6 to "Analog Mode(Reset State)"
> GPIOB->MODER |= (1AFR[0] = (0x7000000); //Set PB6 alternate function to USART1_TX
> ...
> USART1->CR1 |= (1CR1 |= (1CR1 |= (1ISR & 0x80)){}
Something is wrong with your formatting. None of these statements will compile. Hard to see the issue when you're showing code that doesn't compile.
2020-10-26 07:57 PM
//
//Objective: Use USART1 to transmit data to serial monitor software (Putty).
//
//USART1 uses APB2 bus
//USART1 is an alternate function of PA9 & PB6
//USART1_TX is alternate function AF7 of PA9 & PB6
//USART1_RX is an alternate function of PA10 & PB7.
//
//PA2, PA3, PD5, PD6, PA9, PB6, PA10 & PB7 all use the AHB2 bus.
//ST-Link UART1_TX & UART1_RX connected to PB6 and PB7
#include "stm32l4xx.h"
#include "stm32l475xx.h" // Device header
void usart1_init(void);
void usart1_write(int ch);
void delayMS(int delay);
int main(void){
usart1_init();
while(1){
usart1_write('S');
usart1_write('T');
delayMS(100);
}
}
void usart1_init(void){
RCC->APB2ENR |= (1<<14); //Bit 14 in RCC_APB2ENR is used to enable USART1 clock
RCC->AHB2ENR |= (1<<1); //Bit 1 in RCC_AHB2ENR is used to enable GPIOB clock
GPIOB->MODER &=~ (0x3000); //PB6: Set Port B Pin 6 to "Analog Mode(Reset State)"
GPIOB->MODER |= (1<<13); //Set PB6 to alternate Function mode
GPIOB->AFR[0] = (0x7000000); //Set PB6 alternate function to USART1_TX
USART1->BRR = (0x683); //(2x 8Mhz) div 9600 = 1667 = 0x683 **
USART1->CR1 |= (1<<3); //Enable TE (Transmitter)
USART1->CR1 |= (1<<2); //Enable RE (Receiver)
USART1->CR1 |= (1<<0); //Enable USART
}
void usart1_write(int ch){
//wait while TX buffer is empty
while(!(USART1->ISR & 0x80)){}
USART1->TDR = (ch & 0xFF);
}
void delayMS(int delay){
int i;
for(;delay>0;delay--){
for(i=0;i<3195;i++);
}
}
Tried copying it again as the code snippet messed everything up
2020-10-26 08:00 PM
I have used the formula usartdiv = FClock/(16*Baudrate) for a value of 0x341 at 80MHz, 9600 baud for BRR. Serial monitor output will then just be a bunch of ff ff ffs ....
2020-10-26 10:30 PM
I finally got to make it work. In L475 chip, default core clock is 4Mz. usartdiv = Fclock/9600 for a value of 0x1A0.
USART1->BRR = (0x1A0);