环形缓冲区--串口专用

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();
	}

}

 

 

posted on 2019-10-24 10:02  lizhuohui  阅读(131)  评论(0编辑  收藏  举报

导航