1.问题描述:
使用GD32单片机替代一个老项目的产品,串口波特率设置为1200bps,项目写好后,发现数据输出不对。
2.问题分析:
怀疑单片机不支持1200bps的低速传输,但手册中并未找到相关说明。
打开库函数源码查看,void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)。
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
{
uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U;
switch(usart_periph){
/* get clock frequency */
case USART0:
/* get USART0 clock */
uclk=rcu_clock_freq_get(CK_APB2);
break;
case USART1:
/* get USART1 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case USART2:
/* get USART2 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case UART3:
/* get UART3 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case UART4:
/* get UART4 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
default:
break;
}
/* oversampling by 16, configure the value of USART_BAUD */
udiv = (uclk+baudval/2U)/baudval;
intdiv = udiv & (0x0000fff0U);
fradiv = udiv & (0x0000000fU);
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
}
本项目选择的系统时钟为,__SYSTEM_CLOCK_96M_PLL_HXTAL,串口使用的是USART0
根据后面库函数的计算公式:
uclk = rcu_clock_freq_get(CK_APB2) = 96000 000;
udiv = (96000 000 + 1200/2)/1200 = 80000.5;
∵ udiv > 65535; intdiv = udiv & (0x0000fff0U);
∴ 波特率计算的整数部分数值intdiv,就获取不完全了。
所以,要想获取正确的波特率数据值,就必须保持udiv < 65535;
3.解决方案:
通过上面分析,可以通过降低系统时钟的办法解决,设置系统时钟为,__SYSTEM_CLOCK_48M_PLL_HXTAL,计算的 udiv = 40000.5 < 65535,降频后重新测试,波特率正常,数据也正常,但是也牺牲了单片机的性能。
个人理解,欢迎补充纠正。