环形缓冲区--串口专用
cpp:
#pragma once
class CRcvQueue
{
#define RCV_QUEUE_MAX_SIZE 4096
unsigned char m_Buf[RCV_QUEUE_MAX_SIZE+1]; // 如果不加1,最后一位数据会出错。
unsigned int m_Push_i;
unsigned int m_Pop_i;
public:
CRcvQueue(void){m_Push_i = 0;m_Pop_i = 0;}
~CRcvQueue(void){}
void push(unsigned char ch){m_Buf[m_Push_i] = ch; if (++m_Push_i > RCV_QUEUE_MAX_SIZE)m_Push_i = 0;} // 将x添加到队列的末尾
bool empty(void){return m_Push_i == m_Pop_i;}
unsigned char front(void) {return empty() == false ? m_Buf[m_Pop_i] : 0;}// 访问队头元素:push进,这里出,实现先过后出就靠这个了。
void pop(void){if (empty() == false){if (++m_Pop_i > RCV_QUEUE_MAX_SIZE)m_Pop_i = 0;}} // 弹出队列的第一个元素(队头元素)
};
C语言时:
rcv_queue.h
#pragma once
#include <stdio.h>
#define RCV_QUEUE_MAX_SIZE 4096
extern unsigned char m_Buf[]; // 如果不加1,最后一位数据会出错。
extern unsigned int m_Push_i;
extern unsigned int m_Pop_i;
#define RX_PUSH(ch) do {m_Buf[m_Push_i] = ch; if (++m_Push_i > RCV_QUEUE_MAX_SIZE)m_Push_i = 0;} while (0) // 将x添加到队列的末尾
#define RX_IS_EMPTY() (m_Push_i == m_Pop_i)
#define RX_FRONT() (RX_IS_EMPTY() == false ? m_Buf[m_Pop_i] : 0) // 访问队头元素:push进,这里出,实现先过后出就靠这个了。
#define RX_POP() do {if (RX_IS_EMPTY() == false){if (++m_Pop_i > RCV_QUEUE_MAX_SIZE)m_Pop_i = 0;}} while (0) // 弹出队列的第一个元素(队头元素)
rcv_queue.c
#include "rcv_queueh.h"
unsigned char m_Buf[RCV_QUEUE_MAX_SIZE+1]; // 如果不加1,最后一位数据会出错。
unsigned int m_Push_i = 0;
unsigned int m_Pop_i = 0;
在灵动微单片机上的一次实际使用:
// rcv_queue.c //
#define RCV_QUEUE_MAX_SIZE 100//4096
unsigned char m_Buf[RCV_QUEUE_MAX_SIZE+1]; // 如果不加1,最后一位数据会出错。
unsigned int m_Push_i = 0;
unsigned int m_Pop_i = 0;
#define RCV_QUEUE_PUSH(ch) do {m_Buf[m_Push_i] = ch; if (++m_Push_i > RCV_QUEUE_MAX_SIZE)m_Push_i = 0;} while (0) // 将x添加到队列的末尾
#define RCV_QUEUE_IS_EMPTY() (m_Push_i == m_Pop_i)
#define RCV_QUEUE_FRONT() (RCV_QUEUE_IS_EMPTY() == false ? m_Buf[m_Pop_i] : 0) // 访问队头元素:push进,这里出,实现先过后出就靠这个了。
#define RCV_QUEUE_POP() do {if (RCV_QUEUE_IS_EMPTY() == false){if (++m_Pop_i > RCV_QUEUE_MAX_SIZE)m_Pop_i = 0;}} while (0) // 弹出队列的第一个元素(队头元素)
#include "HAL_uart.h"
extern "C" void UART2_IRQHandler( void )
{
static unsigned char temp = 0;
if( UART_GetITStatus( UART2, UART_IT_RXIEN ) != RESET )
{
UART_ClearITPendingBit( UART2, UART_IT_RXIEN );
temp = UART_ReceiveData( UART2 );
RCV_QUEUE_PUSH(temp);
}
}
void SendToPc(unsigned char *buf, int len)
{
for (int i=0; i<len; i++)
{
UART_SendData(UART2,(uint16_t)buf[i]);
while(1)
{
if(UART_GetITStatus(UART2, UART_IT_TXIEN))
{
UART_ClearITPendingBit(UART2, UART_IT_TXIEN);
break;
}
}
}
}
void SendToPc(char *buf){SendToPc((unsigned char *)buf, strlen(buf));}
void Rcv_Command_do(char *buf, unsigned int size);
char g_CommandRcvBuf[RCV_QUEUE_MAX_SIZE+1] = {0};
unsigned int g_Command_size = 0;
void Rcv_Command_Analysis(void)
{
static unsigned long TickOld = 0;
while (RCV_QUEUE_IS_EMPTY() == false)
{
TickOld = GetTickCount();
g_CommandRcvBuf[g_Command_size++] = RCV_QUEUE_FRONT();
RCV_QUEUE_POP();
}
if (GetTickCount() - TickOld > 2) // 间隔 n 毫秒就算不同的帧了。
{
if (g_Command_size > 0)
{
Rcv_Command_do(g_CommandRcvBuf, g_Command_size);
memset(g_CommandRcvBuf, 0, RCV_QUEUE_MAX_SIZE+1);
g_Command_size = 0;
}
}
}
void Rcv_Command_do(char *buf, unsigned int size)
{
if (size >= 2 && buf[0] == 'A'&& buf[1] == 'T' && buf[2] == 0)
{
SendToPc("SIM_1.0\n");
}
else
{
SendToPc("No Support Command: ");
SendToPc((unsigned char *)buf, size);
SendToPc("\n");
}
}
void main(void)
{
cli();
BSP_SysInit();
sei();
while (1)
{
Rcv_Command_Analysis();
}
}