问题描述
华大低功耗MCU HC32L13x在设置串口波特率为115200时,串口打印乱码,而设置9600串口打印ok。官方例程也是9600bps,然而平常串口打印习惯性还是配置为115200-8-N-1(8bit数据位,无校验位,1停止位)
标准的115200bps的最小脉宽应该为8.68us,标准的9600bps的最小脉宽应该为104.17us
现象分析
配置115200打印乱码而不是没有打印说明有数据出来,但是不满足要求,软件在串口输出字符“123”,用逻辑分析仪抓取的乱码波形,关键,可以看到最小脉宽是7.99us,远小于8.68us,误差率7.95%
对比9600抓取的可以正常打印的波形,最小脉宽103.83us,误差率不到0.33%
如此对比,发现实测的115200bps和实际配置的差别太远
在HC32L13x用户手册上看到了相关说明,在PCLK=4MHz的条件下说明了各波特率的误差情况(注:PCLK字面意思也就是外设时钟)
另外PCLK=24MHz条件下对各波特率误差就相对友好,居然还有0误差的。
那么问题来了,当前工程配置的PCLK为多少呢,虽然根据表格明显应该是4MHz,查看时钟结构图如下
关注SYSCTRL0寄存器即可,BIT7:5是选择SystemCLK哪个时钟源,BIT10:8选择SystemCLK到HCLK的分频值,BIT12:11选择HCLK到PCLK的分频值
进入Keil仿真,查看SYSCTRL寄存器组,其中SYSCTRL0为0x0000 0001 ,解释为选择内部高速时钟,SystemCLK到HCLK不分频,HCLK到PCLK也不分频,也就是PCLK = RCH。
问题是RCH标称为4M-24M,RCH具体为多少呢,事实上RCH最多为24M也就决定了PCLK最多为24M,(也可选择PLL,可以把RCH倍频上去到48MHz,这样PCLK也可以得到48MHz)
调试-改SystemCLK为RCH 24M
查看main入口前的SystemInit函数
void SystemInit(void)
{
M0P_SYSCTRL->RCL_CR_f.TRIM = (*((volatile uint16_t*) (0x00100C22ul)));
M0P_SYSCTRL->RCH_CR_f.TRIM = (*((volatile uint16_t*) (0x00100C08ul)));
SystemCoreClockUpdate();
_HidePinInit();
}
uint32_t SystemCoreClock = 4000000;
//add clock source.
void SystemCoreClockUpdate (void) // Update SystemCoreClock variable
{
SystemCoreClock = Sysctrl_GetHClkFreq();
}
结合下图解释选择的正是4M,要改为24M,直接替换地址
改后,跟踪SystemCoreClock的值由4M变为了24M,该值也就是HCLK,也就是PCLK(没有分频)
M0P_SYSCTRL->RCH_CR_f.TRIM = (*((volatile uint16_t*) (0x00100C00ul)));
验证
串口部分确认配置为115200-8-N-1
//串口模块配置
void App_UartCfg(void)
{
stc_uart_cfg_t stcCfg;
stc_uart_baud_t stcBaud;
DDL_ZERO_STRUCT(stcCfg);
DDL_ZERO_STRUCT(stcBaud);
Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE); ///<使能UART0外设时钟门控开关
///<UART Init
stcCfg.enRunMode = UartMskMode1; ///<模式1
stcCfg.enStopBit = UartMsk1bit; ///<1bit停止位
stcCfg.enMmdorCk = UartMskDataOrAddr; //无校验
stcCfg.stcBaud.u32Baud = 115200; ///<波特率115200
stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div; ///<通道采样分频配置
stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq(); ///</<获得外设时钟(PCLK)频率值
Uart_Init(M0P_UART0, &stcCfg); ///<串口初始化
///<UART中断使能
Uart_ClrStatus(M0P_UART0,UartRC); //清接收请求
Uart_ClrStatus(M0P_UART0,UartTC); //清发送请求
Uart_EnableIrq(M0P_UART0,UartRxIrq); //使能串口接收中断
//Uart_EnableIrq(M0P_UART0,UartTxIrq); //使能串口发送中断
//EnableNvic(UART0_IRQn, IrqLevel3, TRUE); ///<系统中断使能
}
再次抓取波形,123轻松识别,脉宽8.65us,误差不到0.35%,验证ok
总结
HC32L13x 串口例程PCLK给的是4MHz,默认串口波特率也是9600,要正常使用115200bps通信,需调高PCLK的值。
也许这就是低功耗MCU吧,时钟跑这么低,PLL也不用。