Changing USART baudrate on the fly

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I've been trying to change the USART baudrate on the fly.

 

The datasheet states that the peripheral needs to be turned off 

The following registers are enable-protected, meaning they can only be written when the USART is disabled (CTRL.ENABLE=0):

• Control A register (CTRLA), except the Enable (ENABLE) and Software Reset (SWRST) bits. SAM D21/DA1 Family SERCOM USART 

• Control B register (CTRLB), except the Receiver Enable (RXEN) and Transmitter Enable (TXEN) bits.

• Baud register (BAUD)

When the USART is enabled or is being enabled (CTRLA.ENABLE=1), any writing attempt to these registers will be discarded. If the peripheral is being disabled, writing to these registers will be executed after disabling is completed. Enable-protection is denoted by the "Enable-Protection" property in the register description.

 So testing the USART at normal speed 115200 seems to work fine but then when turning off the periheral and changing the baudrate with usart_async_set_baud_rate(&USART_0, 9600); it ends up showing garbage on the terminal for both the new and old baudrate.

 

int main(void)
{
	static uint8_t testbuffer[100]={"hello world"};

	/* Initializes MCU, drivers and middleware */
	atmel_start_init();
// 	ClocksInit();
	UART0_init();
	UARTS_init();
	setup_leds();
	//USART_write(&USART_0, 100, testbuffer);
	usart_async_disable(&USART_0);
	usart_async_set_baud_rate(&USART_0, 9600);
	delay_ms(10);
	usart_async_enable(&USART_0);

 //   gpio_set_pin_level(LED1_RED, true);
	while (1) {
		USART_write(&USART_0, 12, testbuffer);
		delay_ms(1);
	}
}

What am i missing?

EDIT: Device used is the samd21 xplained board

Last Edited: Wed. Jul 15, 2020 - 12:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Even if TXEN is turned off, the port pin needs to remain high.
Do you configure IO to do that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure what you mean.

The only thing im doing is disabling the usart peripheral

	usart_async_disable(&USART_0);

 

 

The port pins are initialized by atmel in driver_init.c and i don't touch those in my main.

So i assume that those remain initialized in a high state since the disable function only changes this bit  CTRL.ENABLE=0.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So i've done some more testing.

 

Apparently i need to calculate the baudrate myself and not just pass a baudrate value like the API says.

 

int main() {

    uint32_t baudrate = 9600;
    double freq = 47972352; // remember possible SERCOM frequency
    uint32_t min = freq/16. *  (1. - 65535. / 65536.); // calculate the minimum baud rate for this frequency
    uint32_t max = freq/16. *  (1. - 1. / 65536.); // calculate the maximum baud rate for this frequency
    uint16_t baud = round(65536. * (1. - 16. * (baudrate/freq)));

    printf("min %d\n", min );
    printf("max %d\n", max );
    printf("baud %d\n", baud );


}

Passing the baud value to the set baudrate function seems to make my uart run at the desired 9600 frequency.

The API from asf4 could've been a bit more clear in this i feel like.

 

Either way my problem seems to be solved.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It would be nice if your assumptions were true.
I can't judge because the code of usart_async_disable is not posted.
For example, is it possible to stop at a breakpoint after disable and check the TX pin level with a multimeter?

I think that dust is generated because the start bit is triggered by the low level of the TX pin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The usart async function is a standard function from the ASF4 API which can be found here  link

 

But for now the problem seems to be solved so thanks for the help either way.

Last Edited: Tue. Jul 14, 2020 - 10:27 PM