思路
圆形缓冲区的实现用处很多,比如一个屏幕的显示中可以认为是一个二维的,当屏幕需要动态的不断更新数据,并且还是动态的显示波形,但是显示的宽度却是一定的,这时候一般采用给一定宽度的数组添加一个,随即删除一个,此时就是动态的。
简而言之:
数组长度固定,删除最前面的数据,然后在最后面添加一个新数据
思路:
申请一个全局数组,但是要比需要的长度长2;
其中一个用来存放起始地址,另一个用来存放结束地址
起始地址方便我们进行数据的读取;
结束地址方便我们进行数据存入;
源码
//圆形缓冲区
uint16_t circle_array[12] ; //实际只使用10个长度
/*
名:圆形缓冲区的实现
功能:传入一个数组名,数据组大小,选择添加的单个数据
参数:数组地址、数组中数据大小、数据
注意:数组大小默认大两个,一个是当前起始地址,然后是当前尾部地址
【0】【1】【2】【3】【4】【5】【6】、、、【n】【起始偏移地址】【尾部偏移地址】
尾部指针指向下一个空房间
*/
void array_to_add(uint16_t *array_x,uint16_t array_length , uint16_t *data_to_array)
{
uint16_t start = array_x[array_length];
uint16_t end = array_x[array_length+1];
//first chache
if(end == 0 && start == 0){
end = array_length-1;
array_x[end] = data_to_array[0];
}
//not first
else{
start += 1;
end += 1;
//state of end is bigest
if(end == array_length)
end = 0;
if(start == array_length)
start = 0;
array_x[end] = data_to_array[0];
}
array_x[array_length] = start;
array_x[array_length+1] = end;
}
测试代码
//以起始地址开始打印,里面的10代表的是数据长度为10
void circle_printf_data(){
for (int j = 0;j<10;j++){
if (circle_array[10]+j < 10)
printf("%d ",circle_array[circle_array[10]+j]);
else
printf("%d ",circle_array[circle_array[10]+j-10]);
}
}
//以数组起始开始打印,里面的10代表的是数据长度为10
void forward_printf_data(){
for (int j = 0;j<10;j++){
printf("%d ",circle_array[j]);
}
}
//无限制的添加i,并且i是不断递增的
void array_test(){
uint16_t i=0;
while (1){
HAL_Delay(1000);
array_to_add(circle_array,10,&i);
i++;
circle_printf_data();//本次测试的是圆形打印
//顺便将起始和结束地址打印出来
printf("\tstart = %4d , end = %4d",circle_array[10],circle_array[11]);
printf("\n");
}
}
结果
扩展
//圆形缓冲区以起始地址读至数组
//参数:圆形缓冲区、正常数组、圆形缓冲区数据大小
void circle_array_to_normal_array(uint16_t *circle , uint16_t *normal ,uint16_t data_length ){
uint16_t start;
for(int i=0;i<data_length;i++){
start = i + circle[data_length];
if(start >= data_length)
start -= data_length;
normal[i] = circle[start];
}
}