裸机下获取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 也不会卡死 |