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
1 ACCEPTED SOLUTION

Accepted Solutions
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

View solution in original post

13 REPLIES 13
Posted on July 02, 2018 at 22:54

You can init USART beforehand. All you need to do is then is to change the Tx pin from AF to Out in GPIOx_MODER for the wakeup pulse, and then change it back from Out to AF. Nothing else.

Look up the GPIOx_MODER register in the GPIO chapter of Reference Manual.

JW

Posted on July 03, 2018 at 12:41

Check that TXE is high before sending data

Check that TC goes high, and make sure you clear it, to determine when the last bit hits the wire.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 03, 2018 at 11:42

Waclawek.Jan

? - 

I tried the following piece of code:

timer16_config()

usart1_init(10400)

GPIOA-&gtMODER &= ~(GPIO_MODER_MODER0 << (0x0A * 2))          //Clear previous config of MODER

GPIOA-&gtMODER |= (((uint32_t)0x01) << (0x0A * 2))          //Set MODER register to OUT mode

//Wakeup Pattern

GPIO_ResetBits(GPIOA, GPIO_Pin_10)

delay_nMSEC(25)

GPIO_SetBits(GPIOA, GPIO_Pin_10)

delay_nMSEC(25)

GPIOA-&gtMODER &= ~(GPIO_MODER_MODER0 << (0x0A * 2))       //Clear previous config of MODER

GPIOA-&gtMODER |= (((uint32_t)0x02) << (0x0A * 2))          //Set MODER register to AF mode

USART1-&gtCR1 |= USART_CR1_UE //Enable USART1

USART_SendData(USART1, 0xC1)

while(((USART1-&gtISR & USART_ISR_TXE) && (USART1-&gtISR & USART_ISR_TC)) == 0){}0690X00000602X6QAI.bmp

The above is the response I got on DSO. 

If say, I repeat the SendData command to the code, 

USART_SendData(USART1, 0xC1)

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

USART_SendData(USART1, 0xC1)

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

I end up with this:

 0690X00000602UoQAI.bmp

If I add the USART_SendData command to a while(1) loop, I eventually get my sequence, but that is after at least 100msecs

0690X00000602XGQAY.bmp         0690X00000602TjQAI.bmp

Eventually, after some time has passed: 

0690X00000602XBQAY.bmp

Instead of the custom Hardware I have been using, I also tried a translated version of the code on my STM32F3 Discovery. I get the same response.

0690X00000602XLQAY.bmp

Posted on July 03, 2018 at 13:25

0690X00000602XQQAY.bmp and 0690X00000602XVQAY.bmp are clearly taken at different IO setting (or very different scope setting/external circuitry), given the edges/slope.

It's hard to discuss a moving target.

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

OD and internal pullup alone is a suspicious combination.

JW

Posted on July 03, 2018 at 13:56

Hi

Waclawek.Jan

?,

The only difference between the two images is that this 0690X00000602XaQAI.bmp is for 

USART_SendData(USART1, 0xC1)

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

USART_SendData(USART1, 0xC1)

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

while(1)

{

//   USART_SendData(USART1, 0xC1)

//   while(((USART1-&gtISR & USART_ISR_TXE) && (USART1-&gtISR & USART_ISR_TC)) == 0){}

}

while the following image: 0690X00000602XfQAI.bmp is for 

// USART_SendData(USART1, 0xC1)

// while(((USART1-&gtISR & USART_ISR_TXE) && (USART1-&gtISR & USART_ISR_TC)) == 0){}

// USART_SendData(USART1, 0xC1)

// while(((USART1-&gtISR & USART_ISR_TXE) && (USART1-&gtISR & USART_ISR_TC)) == 0){}

while(1)

{

      USART_SendData(USART1, 0xC1)

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

}

My GPIO config for USART1 remains the same as my original question. The MODER command works well when I converted from AF to OUT. However, OUT to AF is having the same effect as before. 

The OD and PP configuration, while suspicious, is the only set which works for my external circuitry which converts the RX and TX into a single wire protocol. I needed the external circuitry because in another part of my code, I am also using the CAN functionality offered on the same pins. 

Posted on July 03, 2018 at 19:01

The OD and PP configuration, while suspicious, is the only set which works for my external circuitry which converts the RX and TX into a single wire protocol. I needed the external circuitry because in another part of my code, I am also using the CAN functionality offered on the same pins. 

Maybe it's time to show us this circuitry.

JW

Posted on July 04, 2018 at 11:02

Waclawek.Jan

- Let me get back to you regarding the circuitry. It is proprietary and not mine to give out. I hope you will bear with me for a couple of days. Till then, I will keep working on the code and see if something else strikes me. 

Posted on July 04, 2018 at 12:55

I understand.

I am honestly not interested in the circuitry/schematics; I just wanted to point out that that's something you maybe should be concentrating at, rather than software.

JW

Posted on July 04, 2018 at 13:04

Waclawek.Jan

? - I am looking for issues at both ends (Hardware and Firmware). However, I am also simulating the same code on a F3 discovery board. I am getting the same response. On the F3 discovery, I am using the following: 

timer16_config()

timer17_config()

usart1_init(10400)

GPIOA-&gtMODER &= ~(GPIO_MODER_MODER0 << (0x0A * 2)) //Clear previous config of MODER

GPIOA-&gtMODER |= (((uint32_t)0x01) << (0x0A * 2)) //Set MODER register to OUT mode

 //This is just so that I get a high Line similar to my hardware. Otherwise it is of no use. 

GPIO_SetBits(GPIOA, GPIO_Pin_10)              

delay_nSEC(2)

//Wakeup Pattern

GPIO_ResetBits(GPIOA, GPIO_Pin_10)

delay_nMSEC(25)

GPIO_SetBits(GPIOA, GPIO_Pin_10)

delay_nMSEC(25)

GPIOA-&gtMODER &= ~(GPIO_MODER_MODER0 << (0x0A * 2)) //Clear previous config of MODER

GPIOA-&gtMODER |= (((uint32_t)0x02) << (0x0A * 2)) //Set MODER register to AF mode

USART1-&gtCR1 |= USART_CR1_UE //Enable USART1

USART_SendData(USART1, 0xC1)

while((USART1-&gtISR & USART_ISR_TXE) == 0){}

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_Pin_10

   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF 

   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz

   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP 

   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL 

   GPIO_Init(GPIOA, &ampGPIO_InitStruct) 

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7)

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7)

   USART_Cmd(USART1, DISABLE) //Disable and previous USART1 configuration

   USART_InitTypeDef USART_InitStruct // this is for the USART1 initialization

   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, &ampUSART_InitStruct)

   NVIC_InitTypeDef NVIC_InitStructure 

   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE

   NVIC_Init(&ampNVIC_InitStructure)

   /*Swap Rx and Tx Pins*/

   USART_SWAPPinCmd(USART1, ENABLE)

   USART_ITConfig(USART1, USART_IT_RXNE, DISABLE) // enable the USART1 receive interrupt

   

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

   USART_Cmd(USART1, DISABLE)

}

Apart from that, I made the usual adjustments to the timer variables to account for changes in clock frequency. The output I received was this:

0690X00000602XkQAI.bmp