cancel
Showing results for 
Search instead for 
Did you mean: 

Issues in changing baudrate of USART1 on the fly

Abhishek Deouskar
Associate III
Posted on July 02, 2018 at 11:00

Hello,

I am using an STM32F042 controller. I have to send a wake-up pattern followed immediately by 5 bytes (@10400 baud) from my device. 

Wakeup pattern: 25msec LOW followed by 25msec HIGH

5 byte sequence: 0xC1, 0x11, 0xF1, 0x81, 0x44

I tried the following: 

1) I configured the GPIOA, Pin 10, created a delay function and sent the Wakeup pattern. However, I am facing difficulties reconfiguring the GPIO into the USART Mode on the fly and then transmitting the 5-byte sequence.

GPIO_ResetBits(GPIOA, GPIO_Pin_10);

delay_nMSEC(25);

GPIO_SetBits(GPIOA, GPIO_Pin_10);

delay_nMSEC(25);

usart1_init(10400);

USART_SendData(USART1, 0xC1);

while(((USART1->ISR & USART_ISR_TXE) && (USART1->ISR & USART_ISR_TC)) == 0){}

The above code does not work. I get the wakeup pattern correctly and then a single pulse of roughly 5msec after that. But no 0xC1. However, if I put the

USART_SendData(USART1, 0xC1);

in a while(1) loop, I get data transmission correctly. However, I need to transmit it only once. 

2) I sent the wake-up pattern in USART mode at 200 baud (SysClock is 8Mhz) and then tried to reconfigure the frequency to 10400 baud, but no data is transmitted after reconfiguration as well. 

usart1_init(200);   //FOr 8Mhz, 0xF0 at 200 baud is 25msec LOW and 25msec HIGH

USART_SendData(USART1, 0xF0);

while(((USART1->ISR & USART_ISR_TXE) && (USART1->ISR & USART_ISR_TC)) == 0){}

usart1_init(10400);

USART_SendData(USART1, 0xC1);

while(((USART1->ISR & USART_ISR_TXE) && (USART1->ISR & USART_ISR_TC)) == 0){}

Here too, the wake-up sequence is correctly transmitted, but not the following transmission. 

PS: The USART1 configuration below is correct as it has been independently tested. Also the delay_mSec function works correctly. I have verified the same on a DSO.

Here are some of the functions I have used:

void usart1_init(int baudrate)

{

   GPIO_DeInit(GPIOA);

   GPIO_InitTypeDef GPIO_InitStruct;

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;

   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

   GPIO_Init(GPIOA, &GPIO_InitStruct);

   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;

   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;

   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

   GPIO_Init(GPIOA, &GPIO_InitStruct);

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);

   

   USART_Cmd(USART1, DISABLE);

   USART_InitTypeDef USART_InitStruct;

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

   

   USART_InitStruct.USART_BaudRate = baudrate;

   USART_InitStruct.USART_WordLength = USART_WordLength_8b;

   USART_InitStruct.USART_StopBits = USART_StopBits_1;

   USART_InitStruct.USART_Parity = USART_Parity_No;

   USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

   USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

   USART_Init(USART1, &USART_InitStruct);

   NVIC_InitTypeDef NVIC_InitStructure;

   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

   /*Swap Rx and Tx Pins*/   

   USART_SWAPPinCmd(USART1, ENABLE);

   USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

   USART_Cmd(USART1, ENABLE);

}

void TIM16_IRQHandler(void)

{

   if(TIM_GetITStatus(TIM16,TIM_IT_Update))

   {

      TIM_ClearITPendingBit (TIM16, TIM_IT_Update);

      TIM_Cmd(TIM16, DISABLE);

      overflow_delaynMSEC = 1;

   }

}

void delay_nMSEC(int miliseconds)

{

   overflow_delaynMSEC = 0;

   TIM_Cmd(TIM16, DISABLE);

   TIM_SetAutoreload(TIM16, miliseconds*79);

   TIM_SetCounter (TIM16, 0);

   TIM_Cmd(TIM16, ENABLE);

   

   while(overflow_delaynMSEC == 0){}

   overflow_delaynMSEC = 0;

}

#usart1 #gpio-remap #baudrate-change #reconfigure #usart-speed #on-the-fly #gpio #stm32f042
13 REPLIES 13
Posted on July 06, 2018 at 13:30

Turvey.Clive.002

- I tried this. I set the TCCF to clear the TC flag, but it did not work. I also checked for TXE before sending data. 

I am pondering over a different approach:

PA10 pin has TIM1_CH3 also as an AF. Could I use this to create PWM output with a variable duty cycle? I was thinking of using a baud rate of 10400*9 = 93600 because at the max I can have 9 ones or 9 zeros in a sequence (including start and stop bits). My question to you is this, Will it work?

Abhishek Deouskar
Associate III
Posted on July 09, 2018 at 14:48

Waclawek.Jan

? and

Turvey.Clive.002

? -  Thank You for your responses. My issue was that my DSO was not capturing the bytes when it was the 250ms or higher scale. When I enabled edge-triggering on my DSO at 1ms scale, the data was captured perfectly. So the original code I gave out worked. 

 0690X00000602UNQAY.bmp

Posted on July 09, 2018 at 17:38

Ah, that explains it.

Thanks for coming back with the result.

Can you please tag your last post as 'Correct' so that that it can be seen that issue was resolved.

JW

AL.8
Associate

To change the baud rate on the fly, you need to wait for the completion of the transmission and reception of UART.

To do this, in the functions HAL_UART_RxCpltCallback and HAL_UART_TxCpltCallback set your completion flags.

Next, wait for the completion of reception / transmission. then switch the baud rate.

void setBaudRate (uint32_t br)

{

uint32_t pclk = HAL_RCC_GetPCLK1Freq ();

huart4.Instance-> BRR = UART_BRR_SAMPLING16 (pclk, huart4.Init.BaudRate = br);

}

Do not prohibit or allow UART in the body of this function! Tested on STM32F103VE.