打印

裸机下获取USART串口数据容易卡死 ??

[复制链接]
357|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
王将|  楼主 | 2018-8-8 11:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
裸机下获取USART串口数据容易卡死 ??

具体如下:

裸机情况下,貌似使用 UART1_GetCharEx 这个函数获取数据时,每次最大不能够超过 20 byte,如果超过 程序卡死,另外 获取的数据后,貌似需要等一会后 才可以继续获取数据,这是怎么回事啊 ???

typedef struct
{
        uint8_t *pRxBuf;                        /* 接收缓冲区 */
        uint16_t usRxBufSize;                /* 接收缓冲区大小 */

        uint16_t usRxWrite;                        /* 接收缓冲区写指针 */
        uint16_t usRxRead;                        /* 接收缓冲区读指针 */
        uint16_t usRxCount;                        /* 还未读取的新数据个数 */
} _UART1_T;


_UART1_T  g_tUART1;


/*
*********************************************************************************************************
*        函 数 名: UART1_UartVarInit
*        功能说明: 初始化串口相关的变量
*        形    参: 无
*        返 回 值: 无
*********************************************************************************************************
*/
static void UART1_UartVarInit(void)
{
        g_tUART1.pRxBuf = g_Uart1RxBuf;                                        /* 接收缓冲区指针 */
        g_tUART1.usRxBufSize = UART1_RX_BUF_SIZE;        /* 接收缓冲区大小 */
        g_tUART1.usRxWrite = 0;                                                /* 接收FIFO写索引 */
        g_tUART1.usRxRead = 0;                                                /* 接收FIFO读索引 */
        g_tUART1.usRxCount = 0;                                                /* 接收到的新数据个数 */
}


#define UART1_RX_BUF_SIZE          1*1024
  __attribute__((section (".RAM_D4"))) uint8_t g_Uart1RxBuf[UART1_RX_BUF_SIZE];                /* 接收缓冲区 */





/*
*****************************************************************************
* 在usart 中断 中调用
*****************************************************************************
*/
void  UART1_DataRx(u8 buffer)
{        
        g_tUART1.pRxBuf[g_tUART1.usRxWrite] = buffer;
        if (++g_tUART1.usRxWrite >= g_tUART1.usRxBufSize)
        {
                g_tUART1.usRxWrite = 0;
        }
        if (g_tUART1.usRxCount < g_tUART1.usRxBufSize)
        {
                g_tUART1.usRxCount++;
        }
}



/*
*********************************************************************************************************
*        函 数 名: UartIRQ
*        功能说明: 供中断服务程序调用,通用串口中断处理函数
*        形    参: _pUart : 串口设备,如USART1,USART2,UART3,UART7 ... ...
*        返 回 值: 无
*********************************************************************************************************
*/
static void UartIRQ(USART_TypeDef *_pUart)
{
        uint32_t isrflags   = READ_REG(_pUart->ISR);
        uint32_t cr1its     = READ_REG(_pUart->CR1);
        uint32_t cr3its     = READ_REG(_pUart->CR3);
        
        if(_pUart == USART1)
        {
                /* 处理接收中断  */
                if ((isrflags & USART_ISR_RXNE) != RESET)
                {
                        /* 从串口接收数据寄存器读取数据存放到接收FIFO */
                        uint8_t ch;

                        ch = READ_REG(_pUart->RDR);
                        UART1_DataRx( ch );
                }
        }
        
        /* 清除中断标志 */
        SET_BIT(_pUart->ICR, UART_CLEAR_PEF);
        SET_BIT(_pUart->ICR, UART_CLEAR_FEF);
        SET_BIT(_pUart->ICR, UART_CLEAR_NEF);
        SET_BIT(_pUart->ICR, UART_CLEAR_OREF);
        SET_BIT(_pUart->ICR, UART_CLEAR_IDLEF);
        SET_BIT(_pUart->ICR, UART_CLEAR_TCF);
        SET_BIT(_pUart->ICR, UART_CLEAR_LBDF);
        SET_BIT(_pUart->ICR, UART_CLEAR_CTSF);
        SET_BIT(_pUart->ICR, UART_CLEAR_CMF);
        SET_BIT(_pUart->ICR, UART_CLEAR_WUF);
        SET_BIT(_pUart->ICR, UART_CLEAR_TXFECF);
}



/*
*********************************************************************************************************
*        函 数 名: UART1_UartGetChar
*        功能说明: 从串口接收缓冲区读取1字节数据 (用于主程序调用)
*        形    参: _pUart : 串口设备
*                          _pByte : 存放读取数据的指针
*        返 回 值: 0 表示无数据  1表示读取到数据
*********************************************************************************************************
*/
static uint8_t UART1_UartGetChar(_UART1_T *_pUart, uint8_t *_pByte)
{
        uint16_t usCount;

        /* usRxWrite 变量在中断函数中被改写,主程序读取该变量时,必须进行临界区保护 */
        DISABLE_INT();
        usCount = _pUart->usRxCount;
        ENABLE_INT();

        /* 如果读和写索引相同,则返回0 */
        //if (_pUart->usRxRead == usRxWrite)
        if (usCount == 0)        /* 已经没有数据 */
        {
                return 0;
        }
        else
        {
                *_pByte = _pUart->pRxBuf[_pUart->usRxRead];                /* 从串口接收FIFO取1个数据 */

                /* 改写FIFO读索引 */
                DISABLE_INT();
                if (++_pUart->usRxRead >= _pUart->usRxBufSize)
                {
                        _pUart->usRxRead = 0;
                }
                _pUart->usRxCount--;
                ENABLE_INT();
                return 1;
        }
}



/*
uart1 串口接收函数,放在主程序里面不停的调用
*/
uint8_t UART1_GetCharEx(void)
{
        uint8_t ucData;
  uint8_t temp = 0;
//uint16_t usPos = 0;

        /* 从 UART1 模块串口读取1个字节 */
        while (1)
        {
                if (UART1_UartGetChar(&g_tUART1, &ucData))
                {
                        #if  1
                                /* 将收到的 模块数据按原样 打印到COM1 口,便于跟踪调试 */
                        
                        /* 写一个字节到USART1 */
                        USART1->TDR = ucData;
                        /* 等待发送结束 */
                        while((USART1->ISR & USART_ISR_TC) == 0)
                        {}
                                
                        #else  //把接收到的数据拷贝备份,供后续其他程序处理
                                
                        {
                                if (usPos < sizeof(g_Uart1RxBufBak))
                                {
                                        g_Uart1RxBufBak[usPos++] = ucData;
                                }
                                else
                                        usPos =0;
                        
                        }

                        #endif
                                
                                continue;        /* 可能还有数据,继续分析 */
                }

                        break;        /* 没有接收到数据,退出函数 */
        }
        
        return temp;
}



void USART1_IRQHandler(void)
{
        UartIRQ(USART1);
}




int main(void)
{
  .. ...

  while(1)
  {
    UART1_GetCharEx();
  }

}


上述程序,搞到 带 os 系统的工程里面,貌似工作非常正常,获取接收数据也是完全对的,单次数据量超过 32 byte 也不会卡死

使用特权

评论回复

相关帖子

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

本版积分规则

419

主题

419

帖子

0

粉丝