[技术问答]

38.4K低速工作,lpuart用2400收发正常,uart1或uart0的2400收发不正常,这有什么坑吗?hc32l110

[复制链接]
1690|16
手机看帖
扫描二维码
随时随地手机跟帖
huangwentao|  楼主 | 2025-5-21 17:45 | 显示全部楼层 |阅读模式
38.4K低速工作,lpuart用2400收发正常,uart1或uart0的2400收发不正常,这有什么坑吗?hc32l110的,,,,

情况描述:lpuart能正常收发,uart1或uart0的2400收发不正常,完整的数据包是10个字节,最终只接收了5个字节或者6个字节,
分析:1、电压不一致,pass掉,我切换为4M时钟uart0就能正常收发
2、硬件问题,pass,同1一样操作正常
3、波特率误差问题,计算过了,波特率误差在38.4k用2400可以说是0误差。
4、中断优先级冲突,pass,提为最高优先级了
5、使能双倍波特率才能接收到5个字节,不使能都是乱码。


配置代码如下


nt32_t main(void)
{   
    uint8_t falg=0;
                uint8_t i = 0;
                uint8_t txLen = 0;
          volatile uint8_t u8TestFlag = 0;

    uint8_t arr[5]={1,2,3,4,5};
       
    stc_lpuart_config_t  stcConfig;
    stc_lpuart_irq_cb_t stcLPUartIrqCb;
    stc_lpuart_multimode_t stcMulti;
    stc_lpuart_sclk_sel_t  stcLpuart_clk;
    stc_lpuart_mode_t       stcRunMode;

    stc_bt_config_t stcBtConfig;
    stc_lpm_config_t stcLpmCfg;
          stc_wdt_config_t  stcWdt_Config;

    DDL_ZERO_STRUCT(stcConfig);
    DDL_ZERO_STRUCT(stcLPUartIrqCb);
    DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBtConfig);
    DDL_ZERO_STRUCT(stcLpmCfg);


    Clk_Enable(ClkRCL, TRUE);

    Clk_SetRCLFreq(ClkFreq38_4K);//内部38.4K   ClkFreq32768  ClkFreq38_4K
    Clk_SwitchTo(ClkRCL);//使用rcl做主时钟,串口9600唤醒有问题,300波特率可以接收完整数据唤醒



//看门狗配置
    stcWdt_Config.u8LoadValue = 0x0b;//3.2s
    stcWdt_Config.enResetEnable = WINT_EN;//WRESET_EN;////
    stcWdt_Config.pfnWdtIrqCb = WdtCallback;//
               
    Clk_SetPeripheralGate(ClkPeripheralWdt,TRUE);//
    Wdt_Init(&stcWdt_Config);
    Wdt_Start();
               
//LpTimer配置

    LptTimerTest();


    Flash_Init(FlashInt, 0);//0.8ma
    Read_BaseData();

//LpUart配置
    Clk_SetPeripheralGate(ClkPeripheralLpUart,TRUE);//使能LPUART时钟
    Clk_SetPeripheralGate(ClkPeripheralBt,TRUE);

    //通道端口配置
    Gpio_InitIOExt(2,5,GpioDirIn,TRUE,FALSE,FALSE,FALSE);
    Gpio_InitIOExt(2,6,GpioDirOut,TRUE,FALSE,FALSE,FALSE);

    Gpio_SetFunc_UART2RX_P25();
    Gpio_SetFunc_UART2TX_P26();



    stcLpuart_clk.enSclk_sel = LPUart_Rcl;//LPUart_Pclk   LPUart_Rcl


    stcLpuart_clk.enSclk_Prs = LPUartDiv32;//Div:1-9600,32-300bps,4-2400bps
    stcConfig.pstcLpuart_clk = &stcLpuart_clk;

    stcRunMode.enLpMode = LPUartLPMode;//正常工作模式或低功耗工作模式配置,Baud = fclk/(prescale*4)
    stcRunMode.enMode   = LPUartMode1;//LPUartMode3
    stcConfig.pstcRunMode = &stcRunMode;

    stcLPUartIrqCb.pfnRxIrqCb = bspLPUuart_RxIntCallback;//RxIntCallback  bspLPUuart_RxIntCallback
    stcLPUartIrqCb.pfnTxIrqCb = NULL;
    stcLPUartIrqCb.pfnRxErrIrqCb = NULL;
    stcConfig.pstcIrqCb = &stcLPUartIrqCb;
    stcConfig.bTouchNvic = TRUE;

    stcMulti.enMulti_mode = LPUartNormal;//只有模式2/3才有多主机模式

    stcConfig.pstcMultiMode = &stcMulti;
    LPUart_EnableIrq(LPUartRxIrq);
    LPUart_Init(&stcConfig);

                for(txLen=0;txLen<sizeof(u8TxData);txLen++)
                {
                        LPUart_SendData(u8TxData[txLen]);
                }

//    Flash_Init(FlashInt, 0);//0.8ma
//    Read_BaseData();
//   

    LPUart_EnableFunc(LPUartRx);               
  bspUsart1_Init();
   bspUsart0_Init();

  Usart1Tx(arr,5);
  Usart0Tx(arr,5);

    for (i = 0; i < ARRAY_SZ(gGpiolist); i++)
    {
        Gpio_InitIOExt(gGpiolist[i].u8Port,
        gGpiolist[i].u8Pin,
        GpioDirIn, TRUE, FALSE, FALSE, FALSE);
    }
               

导致SWD连接不上

                delay1ms(2500);


    stcLpmCfg.enSLEEPDEEP = SlpDpEnable;//SlpDpDisable;//
    stcLpmCfg.enSLEEPONEXIT = SlpExtDisable;//唤醒后不自动进入睡眠

    Lpm_Config(&stcLpmCfg);


//    change_clock();
//    Gpio_InitIO(0,3,GpioDirOut);
//                SCB->SCR |= 0x4;       //sleepdeep
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();


//    Lpm_GotoLpmMode();
#endif   
    while (1)
    {

      Wdt_Feed();
      delay1ms(2000);
     Usart1Tx(arr,5);
     Usart0Tx(arr,5);



//       if (0x01 == u32LptTestFlag)
//        {
//            u32LptTestFlag = 0;

//                                        Lpm_GotoLpmMode();
//                                }

    }
}


void bspUsart0_Init(void)
{

     uint32_t timer=0;
    uint32_t pclk=0;
       
    stc_uart_config_t  stcConfig;
    stc_uart_irq_cb_t stcUartIrqCb;
    stc_uart_multimode_t stcMulti;
    stc_uart_baud_config_t stcBaud;
    stc_bt_config_t stcBtConfig;


    DDL_ZERO_STRUCT(stcUartIrqCb);
    DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBaud);
    DDL_ZERO_STRUCT(stcBtConfig);


  Gpio_InitIOExt(1,5,GpioDirOut,TRUE,FALSE,FALSE,FALSE);
    //Gpio_InitIOExt(1,5,GpioDirIn,FALSE,TRUE,FALSE,FALSE);   
    Gpio_InitIOExt(1,4,GpioDirOut,TRUE,FALSE,FALSE,FALSE);

    //通道端口配置
    Gpio_SetFunc_UART0TX_P14();
    Gpio_SetFunc_UART0RX_P15();

    //外设时钟使能
    Clk_SetPeripheralGate(ClkPeripheralBt,TRUE);//模式0/2可以不使能
    Clk_SetPeripheralGate(ClkPeripheralUart0,TRUE);

    stcUartIrqCb.pfnRxIrqCb = USART0_IRQHandler;
    stcUartIrqCb.pfnTxIrqCb = NULL;
    stcUartIrqCb.pfnRxErrIrqCb = NULL;//ErrIntCallback;
    stcConfig.pstcIrqCb = &stcUartIrqCb;
    stcConfig.bTouchNvic = TRUE;


    stcConfig.enRunMode = UartMode1;//UartMode3;//测试项,更改此处来转换4种模式测试


    stcMulti.enMulti_mode = UartNormal;//测试项,更改此处来转换多主机模式,mode2/3才有多主机模式

    stcConfig.pstcMultiMode = &stcMulti;

    stcBaud.bDbaud = 1u;//双倍波特率功能
    stcBaud.u32Baud = 2400;//9600u;//更新波特率位置2400         300
    stcBaud.u8Mode = UartMode1;//UartMode3; //计算波特率需要模式参数
    pclk = Clk_GetPClkFreq();//获得PCLK
    timer=Uart_SetBaudRate(UARTCH0,pclk,&stcBaud);//计算波特率所需TIMER值

    aaaaaabbbb=pclk;
    aaaaaa=timer;

    stcBtConfig.enMD = BtMode2;//自动重装载16位计数器/定时器
    stcBtConfig.enCT = BtTimer;//定时模式
    Bt_Init(TIM0, &stcBtConfig);//调用basetimer1设置函数产生波特率
    Bt_ARRSet(TIM0,timer);//配置重载值
    Bt_Cnt16Set(TIM0,timer);//配置计数值
    Bt_Run(TIM0); //启动定时

    EnableNvic(UART0_IRQn, 0, TRUE);


    Uart_Init(UARTCH0, &stcConfig);//串口1初始化
    Uart_EnableIrq(UARTCH0,UartRxIrq);//允许串口1接收中断
    Uart_ClrStatus(UARTCH0,UartRxFull);//清串口1接收中断标志
    Uart_EnableFunc(UARTCH0,UartRx); //串口1接收中断使能
       
}


uint8_t aaadrr[10];
uint8_t aalen=0;

void USART0_IRQHandler(void)
{
    Uart_ClrStatus(UARTCH0,UartRxFull);
        /* Read one byte from the receive data register */
                               
  aaadrr[aalen++]=Uart_ReceiveData(UARTCH0);

  if(aalen>9)
  {
    aalen=0;  
  }


}

使用特权

评论回复
probedog| | 2025-5-27 11:52 | 显示全部楼层
LPUART支持双时钟,在深度休眠模式下可使用内部低速时钟,而UART1或UART0的时钟源配置可能不同,导致波特率计算不准确。

使用特权

评论回复
flycamelaaa| | 2025-5-27 13:00 | 显示全部楼层
UART1或UART0的波特率误差可能较大,尤其是在使用内部高速时钟时,计算出的波特率与实际值存在偏差。

使用特权

评论回复
powerantone| | 2025-5-27 14:00 | 显示全部楼层
UART1或UART0在无校验模式下可能接收不稳定,而LPUART在特定工作模式下接收正常。

使用特权

评论回复
stormwind123| | 2025-5-27 15:00 | 显示全部楼层
UART1或UART0的中断使能及优先级配置可能不正确,或者中断服务程序存在阻塞逻辑,导致数据接收异常。

使用特权

评论回复
probedog| | 2025-5-27 17:36 | 显示全部楼层
统一时钟源.

使用特权

评论回复
ex7s4| | 2025-6-11 18:13 | 显示全部楼层
波特率误差可能是导致问题的原因之一。即使计算出的波特率误差理论上为0,实际硬件中仍可能存在微小差异。

使用特权

评论回复
b5z1giu| | 2025-6-11 19:22 | 显示全部楼层
尝试使能双倍波特率功能。在某些情况下,使能双倍波特率可以改善接收效果,而不使能时可能出现乱码或接收不完整的情况。

使用特权

评论回复
suw12q| | 2025-6-11 20:27 | 显示全部楼层
确认UART1或UART0的时钟源配置是否正确。不同的时钟源可能会影响波特率的准确性

使用特权

评论回复
w2nme1ai7| | 2025-6-11 21:29 | 显示全部楼层
检查是否选择了合适的时钟分频系数,以确保UART模块能够获得稳定的时钟信号。

使用特权

评论回复
liu96jp| | 2025-6-11 22:41 | 显示全部楼层
引脚复用与硬件连接

使用特权

评论回复
q1d0mnx| | 2025-6-12 06:28 | 显示全部楼层
确保UART1或UART0的引脚已正确配置为UART功能,并且没有与其他外设发生冲突。

使用特权

评论回复
lamanius| | 2025-6-12 09:02 | 显示全部楼层
检查硬件连接,确保RX和TX引脚与通信对端的连接正确无误,且没有外部干扰信号

使用特权

评论回复
zhizia4f| | 2025-6-12 10:07 | 显示全部楼层
如果使用中断接收模式,确保UART1或UART0的中断已正确使能,并且中断服务程序没有阻塞逻辑。

使用特权

评论回复
t1ngus4| | 2025-6-12 11:25 | 显示全部楼层
检查中断优先级配置,确保UART中断不会被其他高优先级中断阻塞。

使用特权

评论回复
d1ng2x| | 2025-6-12 13:29 | 显示全部楼层
确认UART1或UART0的工作模式(如模式1、模式3等)和数据格式(如数据位、停止位、校验位等)与通信对端一致。

使用特权

评论回复
wubangmi| | 2025-6-12 16:03 | 显示全部楼层
我给楼主算一下,L110的波特率是有定时器产生的,现在楼主的主频是38400,根据楼主的配置以及手册上的波特率计算公式来算:
2400=2*38400/32/(0x10000-TM);算出此时的TM=0xFFFF;也就是BT0的自动重载值是0xFFFF,所以我认为BT0定时器不能给UART0产生一个波特率时钟。我觉得本身用38400跑主频有待商榷

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

14

帖子

0

粉丝