stm32/common: Implement handling for setting the baud rate correctly when in 8x oversampling mode
This commit is contained in:
committed by
Piotr Esden-Tempski
parent
9480f493b9
commit
2d15b12ff2
@@ -94,10 +94,11 @@ specific memorymap.h header before including this header file.*/
|
|||||||
/* ONEBIT: One sample bit method enable */
|
/* ONEBIT: One sample bit method enable */
|
||||||
#define USART_CR3_ONEBIT (1 << 11)
|
#define USART_CR3_ONEBIT (1 << 11)
|
||||||
|
|
||||||
|
#define USART_BRR_UPPER_MASK (0x0000fff0U)
|
||||||
|
#define USART_BRR_LOWER_MASK (0x0000000fU)
|
||||||
#endif
|
#endif
|
||||||
/** @cond */
|
/** @cond */
|
||||||
#else
|
#else
|
||||||
#warning "usart_common_f24.h should not be included directly, only via usart.h"
|
#warning "usart_common_f24.h should not be included directly, only via usart.h"
|
||||||
#endif
|
#endif
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
|
|||||||
@@ -440,6 +440,9 @@
|
|||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
#define USART_BRR_UPPER_MASK (0x0000fff0U)
|
||||||
|
#define USART_BRR_LOWER_MASK (0x0000000fU)
|
||||||
|
|
||||||
/** @defgroup usart_gtpr_values USART_GTPR Values
|
/** @defgroup usart_gtpr_values USART_GTPR Values
|
||||||
* @ingroup usart_defines
|
* @ingroup usart_defines
|
||||||
* @{
|
* @{
|
||||||
|
|||||||
@@ -71,7 +71,27 @@ void usart_set_baudrate(uint32_t usart, uint32_t baud)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USART_CR1_OVER8
|
||||||
|
if (USART_CR1(usart) & USART_CR1_OVER8) {
|
||||||
|
/*
|
||||||
|
* When using 8x oversampling instead of 16x, the calculation works slightly differently.
|
||||||
|
* We do the same main calculation as for 16x, but with the clock rate effectively doubled.
|
||||||
|
* This keeps accuracy up and gives us the best possible divider. However, to set BRR,
|
||||||
|
* we have to do some shenanigans - specifically, USARTDIV[15:4] = BRR[15:4], but
|
||||||
|
* UARTDIV[3:0] = BRR[2:0] << 1 and we are required to keep BRR[3] as 0.
|
||||||
|
*/
|
||||||
|
const uint32_t divider = ((2 * clock) + (baud / 2)) / baud;
|
||||||
|
USART_BRR(usart) = (divider & USART_BRR_UPPER_MASK) | ((divider & USART_BRR_LOWER_MASK) >> 1U);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Modified version of the formula from the datasheets that tries to improve
|
||||||
|
* the accuracy of the calculated dividers by introducing a rounding factor
|
||||||
|
*/
|
||||||
|
USART_BRR(usart) = (clock + baud / 2) / baud;
|
||||||
|
}
|
||||||
|
#else
|
||||||
USART_BRR(usart) = (clock + baud / 2) / baud;
|
USART_BRR(usart) = (clock + baud / 2) / baud;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user