前言
前面进行了串口的收发测试,现在来实现基于环形缓冲区的串口驱动,以提供给应用层方便使用的收发接口。
设计
设计思路
设计的核心思想是,使用缓冲区,串口接收中断时往缓冲区写数据,串口读API则查询该缓冲区获取数据,以实现异步接收。
发送也可以类似,为了简单,这里发送就使用同步阻塞发送,
数据结构
缓冲区核心数据结构如下
typedef struct
{
uint32_t datalen_u32;
uint32_t maxlen_u32;
uint32_t in_u32;
uint32_t out_u32;
uint8_t* buffer_pu8;
}ring_buffer_t;
uint8_t uart_ring_buffer[128];
ring_buffer_t s_ring_buffer_t=
{
.datalen_u32 = 0,
.maxlen_u32 = sizeof(uart_ring_buffer),
.in_u32 = 0,
.out_u32 = 0,
.buffer_pu8 = uart_ring_buffer,
};
临界段处理
缓冲区在中断和API中都需要操作,所以需要临界段保护,
采用简单的开关中断方式。
DINT;
临界段代码
EINT;
串口接收中断
串口接收中断回调处理,调用uart_rx_handler将数据写入缓冲区
INTERRUPT void sciaRxIsr(void)
{
uint8_t ch;
if(SciaRegs.SCICTL2.bit.TXRDY == 1)
{
//Scia_Send(SciaRegs.SCIRXBUF.bit.RXDT);
ch = SciaRegs.SCIRXBUF.bit.RXDT;
uart_rx_handler(&ch, 1);
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
}
void uart_rx_handler(const uint8_t *buffer, uint32_t length)
{
uint32_t i;
for(i=0;i<length; i++)
{
if(s_ring_buffer_t.datalen_u32 < s_ring_buffer_t.maxlen_u32)
{
s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.in_u32] = buffer[i];
s_ring_buffer_t.datalen_u32++;
s_ring_buffer_t.in_u32++;
s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;
}
else
{
/* full */
break;
}
}
}
实现发送字节接口
查询方式发送,uart_write调用该接口循环发送
void uart_sendbyte(uint8_t ch)
{
Scia_Send(ch);
}
发送API
uart_write
int uart_write(uint8_t *buff, uint32_t len)
{
uint32_t i;
for(i=0; i<len ;i++)
{
uart_sendbyte(buff[i]);
}
return 0;
}
接收API
int uart_read(uint8_t *buff, uint32_t len)
{
uint32_t readlen = 0;
if(s_ring_buffer_t.datalen_u32 == 0)
{
return 0;
}
Enter_Critical();
uint32_t i;
for(i=0;i<len;i++)
{
if(s_ring_buffer_t.datalen_u32 > 0)
{
buff[i] = s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.out_u32];
s_ring_buffer_t.datalen_u32--;
s_ring_buffer_t.out_u32++;
s_ring_buffer_t.out_u32 %= s_ring_buffer_t.maxlen_u32;
readlen++;
}
else
{
break;
}
}
Exit_Critical();
return readlen;
}
串口初始化
使用原来的初始化
InitSciGpio();
Scia_Config(115200);
测试
uint8_t buffer[128];
for(;;)
{
int len=0;
if((len = uart_read(buffer, sizeof(buffer))) >0)
{
uart_write(buffer, len);
}
}
return 0;
使用串口调试助手自动发送,收到的和发送的完全一样,说明收发OK。