[libopenstm32-devel] usart_set_baudrate(...)
Status: Inactive
Brought to you by:
uh1763
From: Nico v. G. <Nic...@FU...> - 2011-03-09 13:34:20
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hey, I had some problems with the usart_set_baudrate() function and so I took a deeper look how it works. The baud rade generation for stm32 is described in the section "Fractional baud rate generation" in RM0008 Reference manual, Page 747. To set the baud rate for the stm32 boards, you have to set the correct unsigned fixed point number (fraction and mantissa) USARTDIV in USART_BRR. USART_BRR is a 32 Bit Register and divided into the following regions: Bit 3:0 DIV_FRACTION of USARTDIV Bit 15:4 DIV_MANTISSA of USARTDIV BIT 16:31 reserverd formula for baud rate Baud = f_ck / (16 * USARTDIV) , f_ck = PCLK1 (for USART 2,3,4,5, max 36MHz) or PCLK2 (for USART 1, max 72Mhz) => USARTDIV = f_ck / (16 * BAUD) We have to set the mantissa and fraction of USARTDIV in USART_BRR DIV_Mantissa = (u16) f_ck / (16* BAUD) -- USART_DIV value before the comma DIV_Fraction = f_ck / (16* BAUD) - DIV_Mantissa -- USART_DIV value after the comma To set the baud rate we have to form the correct unsigned fixed point number. For that we have to combine DIV_Mantissa and DIV_Fraction. The first four bits are for the fraction value and the next 11 bits are for the mantissa (for that shift DIV_Mantissa 4 times). USART_BRR = (DIV_MANTISSA << 4) | DIV_FRACTION the current implementation in lib/stm32/lib/usart.c: void usart_set_baudrate(u32 usart, u32 baud) { u32 clock = 72000000; /* FIXME: Don't hardcode this clock! */ /* TODO: Document and explain calculation. */ USART_BRR(usart) = (u16)((clock << 4) / (baud * 16)); } The assignment in the function does the calculation and the shift in one step but ignores the fraction value. With that I think you can not set all possible baud rate values... USART_BRR(usart) = (clock << 4) / (baud * 16) For the stm-h107 development the current implementation works fine for usart 2,3 but not for usart1. Usart1 has a different clock source (PCLK2, 72Mhz) and so you have to divide the baud parameter (for usart_set_baudrate(...)) by two to get the correct values. As it is hard to get the current pclk1 or pclk2 values, wouldn't it be better if there is a function like the following: void usart_set_baudrate(u32 clock, u32 usart, u32 baud); //set the clock manually or void rcc_get_pclkX(); //to get the clock for the calculation Then you don't have to hardcode the clock. Greetings Nico -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNd4HUAAoJEBnE9vofeFrkc2kH+QHE8x+u7pCcvCrsysU64b9v 2Bf923Bjuzfjs6uNN2vw2RUuYl+7wXhNdgYhcGvKcyIDvlCT3oYLsPSmt6DCo0Gb o/W/isET4bd9dthu0lvAGmiBAOHsgTfv8IaiqvhrlDLTQdCp/QiJqLNPHrkczKBb IJ9HFFSMkTu+vK8l4KH+UcMpcw0ZVH7V3pS40illHLQmqiae5X7N1LyjutDI9H9d Ikzf9wE4zPXBNWCZ1kUB7qLAWpjUcgm2qCXnnwQed7vy/g7VUg13eV2eQQUdnTbz 5uvEgecyvJ2vrlAeFCxGXdUDOVke8xyw/IPOc1qFF/CsdTEB1LWVvWmBnL2Raik= =0oHY -----END PGP SIGNATURE----- |