수신된 데이터를 처리할 때 링 버퍼는 처리할 데이터를 저장하는 데 사용되는 경우가 많으며, 특히 메모리가 본질적으로 작은 단일 칩 마이크로컴퓨터에서는 메모리 사용량을 절약할 필요가 있습니다.
링 버퍼의 사용은 데이터 헤드와 테일의 포인터 오프셋을 통해 데이터를 쓰고 읽는 것입니다.
예를 들어, 이제 외부에서 데이터를 수신하고 이를 링 버퍼에 저장한 다음 링 버퍼에서 데이터를 읽고 일부 프레임 형식 및 데이터 확인 작업을 수행한 다음 링에서 데이터를 읽는 직렬 포트가 있습니다. 버퍼 직렬 포트가 전송됩니다.
다음으로 두 가지 방법으로 링 버퍼를 도입합니다.
1. 간단한 링 버퍼 사용 - 단일 바이트 쓰기 및 읽기
1. 링 버퍼의 구조 정의
버퍼 길이는 처리해야 하는 데이터 양의 크기에 따라 정의할 수 있습니다.
헤드(Head): 다음에 읽어올 데이터의 첫 번째 주소인 현재 큐의 헤드는 데이터의 접근 상태에 따라 동적으로 변경된다.
Tail: 현재 Queue의 tail, 즉 다음 데이터가 기록될 때의 첫 번째 주소는 데이터의 접근 상태에 따라 동적으로 변경됩니다.
길이 : 현재 버퍼에 저장된 데이터의 길이, 즉 Head와 Tail 사이의 데이터 길이
Ring_Buff : 데이터를 저장하는 메모리 영역
#define RINGBUFF_LEN 10240 //定义最大接收字节数 10240
//环形buffer结构体
typedef struct
{
uint32_t Head;
uint32_t Tail;
uint32_t Length;
uint8_t Ring_Buff[RINGBUFF_LEN];
} RingBuff_t;
2. 링 버퍼 데이터를 쓰는 코드
/**
*功能:数据写入环形缓冲区
*入参1:要写入的数据
*入参2:buffer指针
*返回值:buffer是否已满
*/
uint8_t Write_RingBuff(volatile uint8_t data, RingBuff_t *ringBuff)
{
if(ringBuff->Length >= RINGBUFF_LEN) //判断缓冲区是否已满
{
//如果buffer爆掉了,清空buffer,进行重新初始化
memset(ringBuff, 0, RINGBUFF_LEN);
RingBuff_Init(ringBuff);
return 1;
}
//将单字节数据存入到环形buffer的tail尾部
ringBuff->Ring_Buff[ringBuff->Tail]=data;
//重新指定环形buffer的尾部地址,防止越界非法访问
ringBuff->Tail = ( ringBuff->Tail + 1 ) % RINGBUFF_LEN;
//存入一个字节数据成功,len加1
ringBuff->Length++;
return 0;
}
3. 링 버퍼의 데이터를 읽습니다.
/**
*功能:读取缓存区整帧数据-单字节读取
*入参1:存放提取数据的指针
*入参2:环形区buffer指针
*返回值:是否成功提取数据
*/
uint8_t Read_RingBuff_Byte(uint8_t *rData, RingBuff_t *ringBuff)
{
if(ringBuff->Length == 0)//判断非空
{
return 1;
}
//先进先出FIFO,从缓冲区头出,将头位置数据取出
*rData = ringBuff->Ring_Buff[ringBuff->Head];
//将取出数据的位置,数据清零
ringBuff->Ring_Buff[ringBuff->Head] = 0;
//重新指定buffer头的位置,防止越界非法访问
ringBuff->Head = (ringBuff->Head + 1) % RINGBUFF_LEN;
//取出一个字节数据后,将数据长度减1
ringBuff->Length--;
return 0;
}
4. 직렬 포트를 사용하여 데이터 테스트를 보내고 받는 경우 다음과 같이 직렬 포트 인터럽트 중에 수신된 데이터를 링 버퍼에 써야 합니다.
extern RingBuff_t ringBuff0; //实例化一个环形buffer对象
/**
*功能:串口0中断接收函数
*/
void USART0_IRQHandler(void)
{
volatile uint16_t data;
if( usart_interrupt_flag_get(USART0,USART_INT_FLAG_RBNE) != RESET)
{
data = usart_data_receive(USART0); //接收串口数据
Write_RingBuff(data, &ringBuff0); //将窗口数据写入环形buffer
}
}
5. 메인 메인 스레드에서는 다음과 같이 while 루프를 통해 링 버퍼의 데이터를 읽고 직렬 포트에서 보냅니다.
uint8_t read_data = 0; //存放读取环形buffer的数据
RingBuff_t ringBuff0; //实例化一个环形buffer对象
int main(void)
{
/* configure systick */
systick_config();
//初始化环形buffer以及所有外设资源
all_peripheral_init();
while(1){
//开发板测试:USART0接收,USART0发送
ret = Read_RingBuff_Byte(&read_data, &ringBuff0);
if(ret == 0){
//将读取的环形buffer数据通过串口发送出去
uart_send_byte(USART0, read_data);
}
}
}
/**
*功能:串口数据发送函数
*入参1:串口号
*入参2:要发送的字节数据
*/
void uart_send_byte(uint32_t com, uint8_t ch)
{
while(usart_flag_get(com, USART_FLAG_TBE) == RESET );
usart_data_transmit(com, ch);
}
좋아요, 즐겨찾기, 팔로우 부탁드려요! ! ! ヾ(o◕∀◕)ノ