串口接收中断事件:HAL_UART_RX_FULL

PC机每隔100ms给协调器发送28字节的数据,协调器接收后,回显。

过一段时间后,会提示:HAL_UART_RX_FULL,而且发送的数据也不是完整的28个字节。

18 个回复

  • 当缓冲区数据长度大于等于HAL_UART_DMA_FULL 时, 触发HAL_UART_RX_FULL事件
    你的数据是否及时读出以及及时释放。
    你把你uart 贴下

    Best Regards

    Alvin Chen

  • 回复 Alvin Chen:

    我用的是中断方式:
    /********************************************
    * @brief 自定义的串口初始化函数
    * @para
    ********************************************/
    void MyApp_UartInit(void)
    {
    halUARTCfg_t uartConfig;
    uartConfig.configured = TRUE; // 2x30 don't care - see uart driver.
    uartConfig.baudRate = MY_APP_BAUD;
    uartConfig.flowControl = FALSE;
    uartConfig.flowControlThreshold = MY_APP_THRESH; // 2x30 don't care - see uart driver.
    uartConfig.rx.maxBufSize = MY_APP_RX_SZ; // 2x30 don't care - see uart driver.
    uartConfig.tx.maxBufSize = MY_APP_TX_SZ; // 2x30 don't care - see uart driver.
    uartConfig.idleTimeout = MY_APP_IDLE; // 2x30 don't care - see uart driver.
    uartConfig.intEnable = TRUE; // 2x30 don't care - see uart driver.
    uartConfig.callBackFunc = rxCB; //串口接收到数据时的处理
    HalUARTOpen (0, &uartConfig);
    }
    /********************************************************************
    * @brief 串口处理函数,将接收到的数据发送出去
    * @para uint8 port :串口号 0 、1
    * @para uint8 event:事件
    *********************************************************************/
    #define UART_DATA_MAX 28 //最大32个字节的数据
    static uint8 MyApp_AFTxBuf[UART_DATA_MAX+5]={0}; //缓存从串口中接收到的数据,+5:帧头4个字节,帧尾1个字节
    void rxCB( uint8 port, uint8 event )
    {
    static uint8 temp = 0;
    if((event & (HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT))&&(!MyApp_Tx_Len))
    {
    //打印事件
    temp = (event&0x0F)+'B';
    HalUARTWrite(0,&temp,1);
    //清空MyApp_AFTxBuf数组。
    osal_memset(MyApp_AFTxBuf,0,UART_DATA_MAX+5);
    MyApp_AFSendUartData(); //将数据读取并将标志位置位
    }
    }
    /*************************************************
    *
    *************************************************/
    void MyApp_AFSendUartData(void)
    {
    #ifdef MYAPP_LOOPBACK_TEST //还回测试,测试串口功能

    #else
    if(!MyApp_Tx_Len)
    {

    MyApp_Tx_Len=HalUARTRead(HAL_UART_PORT_0,MyApp_AFTxBuf+5,UART_DATA_MAX);

    MyApp_Tx_Len_Buf = MyApp_Tx_Len; //缓存
    osal_memcpy(Myapp_Uart_RBuf,MyApp_AFTxBuf,MyApp_Tx_Len_Buf+5);
    }
    #endif
    }

    //在事件处理函数中,每隔99ms,轮询MyApp_Tx_Len_Buf 是否非零,如果是,则AF发送
    uint16 MyApp_ProcessEvent( uint8 task_id, uint16 events )
    {
    ……
    if(events & MYAPP_UART_DTU_EVT)
    {
    MyApp_UartDtu_Pro();
    osal_start_timerEx(MyApp_TaskID,MYAPP_UART_DTU_EVT,99); //每隔90ms,检测一次是否有数据需要透传。
    return (events ^ MYAPP_UART_DTU_EVT);
    }
    ……
    }
    MyApp_UartDtu_Pro() //这个函数有点乱,没贴代码
    {
    判断MyApp_Tx_Len_Buf 是否非零,如果是,则进行处理;
    处理完成后,MyApp_Tx_Len_Buf = 0;MyApp_Tx_Len= 0;
    }
  • 回复 user4711142:

    数据怎么及时读出,及时释放?是要在底层更改还是应用层更改?
  • 回复 user4711142:

    给你个建议应该是个原因:
    你把你RXcall的处理修正一下:
    不要在callback去处理数据,仅去HalUARTRead,数据在其他地方处理,这样应该会有所改善。

    Best Regards

    Alvin Chen

  • 回复 Alvin Chen:

    1、我只在callback中读取数据;
    2、定义用户事件处理函数,每隔100ms检测是否有数据,如果有在进行处理
    这样可以么?
  • 回复 user4711142:

    建议你直接在你的callback 里面read 到然后启动一个events去处理。
    你现在只在你的callback ,然后做一个events去 回write试试。

    Best Regards

    Alvin Chen

  • 回复 Alvin Chen:

    void rxCB( uint8 port, uint8 event )
    {
    uint8 *MyApp_AFTxBuf;

    if((event & (HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT))&&(!MyApp_Tx_Len))
    {
    if(!(MyApp_AFTxBuf=osal_mem_alloc(UART_DATA_MAX))) //申请一段内存,如果申请不成功,则直接返回。
    {
    HalUARTWrite(0,"Return\r\n",8);
    return ;
    }
    MyApp_Tx_Len=HalUARTRead(HAL_UART_PORT_0,MyApp_AFTxBuf,UART_DATA_MAX); //读取数据

    osal_memcpy(&Myapp_Uart_RBuf[5],MyApp_AFTxBuf,MyApp_Tx_Len_Buf); //数据缓冲

    osal_mem_free(MyApp_AFTxBuf); //释放申请的内存

    //数据处理事件
    osal_set_event(MyApp_TaskID,MYAPP_UART_DTU_EVT);
    }
    }

    请问这样可以么?是否还需要继续精简??
  • 回复 user4711142:

    测试了一下,还是不行,还是有产生rxbuf满事件HAL_UART_DMA_FULL
  • 回复 Alvin Chen:

    void rxCB( uint8 port, uint8 event )
    {
    static uint8 len = 0;
    if((event & (HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT))&&(!MyApp_Tx_Len))
    {

    Evt_temp = event; //保存事件
    MyApp_Tx_Len=HalUARTRead(HAL_UART_PORT_0,MyApp_AFTxBuf,UART_DATA_MAX); //读取数据
    MyApp_Tx_Len_Buf = MyApp_Tx_Len; //数据缓冲
    osal_set_event(MyApp_TaskID,MYAPP_UART_DTU_EVT); //数据处理事件
    }
    }

    这样还是会有接收缓冲区满的事件HAL_UART_DMA_FULL ,该怎么办呀
  • 回复 user4711142:

    你好,我自己写了一个测试正常如下:

    void AF_Uart_config(void)
    {
      halUARTCfg_t uartConfig;
      uartConfig.configured = TRUE;
      uartConfig.baudRate = HAL_UART_BR_9600;
      uartConfig.flowControl = FALSE;
      uartConfig.flowControlThreshold = 32; 
      uartConfig.rx.maxBufSize = 64; 
      uartConfig.tx.maxBufSize = 64; 
      uartConfig.idleTimeout = 6; 
      uartConfig.intEnable = TRUE; 
      uartConfig.callBackFunc = AF_Uart_Callback; 
      HalUARTOpen (HAL_UART_PORT_0, &uartConfig); 
    
    }
    void AF_Uart_Callback( uint8 port, uint8 event )
    {
      uint16 data_len;
      uint8 *uart_data;
      if(event & (HAL_UART_RX_FULL|HAL_UART_RX_ABOUT_FULL|HAL_UART_RX_TIMEOUT))
      { 
        data_len=Hal_UART_RxBufLen(HAL_UART_PORT_0);
       
    
            uart_data=osal_mem_alloc(data_len);
            if ( uart_data != NULL )
            {     
                  HalUARTRead(HAL_UART_PORT_0,uart_data,data_len);
                  HalUARTWrite(HAL_UART_PORT_0,uart_data,data_len);
                  data_len=0;
            }
            osal_mem_free( uart_data );
      } 
    
    }

    Best Regards

    Alvin Chen