一种环形数据区存取机制的实现
一种随机起始地址循环连续取数据的的机制
问题描述
1) 需要开辟一片缓存区以存储 ADC 采集的数据,数据连续不间断存储,按首地址--->末地址--->首地址的存储顺序。
2) 数据算法要对采集后的数据做处理,也是按照ADC数据的存储顺序做循环取数据的,要求每次取一包数据 (长度3120byte) 做处理,数据处理后会返回一个数值 n,该数值 n 作为下一包取数据的起始地址偏移量,且该数值n每次返回值随机,由算法得出。
3) 从数据缓存区取出的数据必须是有效数据,即取数据时存数据已存超过 3120 个点,这一要求可通过当前存地址与当前取地址做差 >= 3120 来保证。
解决方法
方法一、搬移数据接续法
使用场合:尤其适用于某个算法函数只需接收起始地址这一个参数,而进行的数据块读取,这个起始地址在外部通过搬移数据接续法计算获得
方法二、指针描述控制法
使用场合:设某个算法函数需要数据块读取,则要求其需要拿到读写指针参数进行数据块读取实现,即算法函数本身兼具指针描述控制法读数据功能
具体实现
方法一、搬移数据接续法
1、 如下图所示开辟 6 包(3120个点/包) 数据大小的缓存区
2、 ADC 采集数据的存储首地址从包2起始,以包6为末地址终止, 数据存满包6后跳转至包2开启新一轮数据存储,以此形成环形缓存区机制
3、 从首地址包 2 开始取数据,按首地址--->add1(3119-n1)--->addr2(add1+3119-n2)--->addrn 模式取数据,当下一次读取数据的地址 addrn+3119 > 包 6末地址,即剩余数据不够 3120 个点,需要切换至地址头包2读取剩余的数据。设本次数据读取至地址 addrn 为包 6 的 P 地址处,P 地址处距包6首的的偏移为 offsetnum = addrn - 包 5 末地址,要做的就是将 P地址处往后直到包 6 末尾的剩余数搬移到包 1 缓存中,以接续包2中的数据,搬移数据在包 1 中的存放位置也是距包 1 首地址偏移 offsetnum 处,这样就保证了读取数据的连续性。
附部分代码:
1 uint8_t **startAddr; 2 uint8_t dataBuf[3120*6]; 3 *startAddr = &dataBuf[3120]; 4 /** 5 * @brief : calculate next start-addr 6 * @param : 指向存储区所取数据得地址的地址 7 * @retval : none 8 */ 9 void AddrOffset(uint8_t **addr) 10 { 11 uint16_t offsetNum, newNum; 12 /* 取数据至最后一包数据处,开始地址接续 */ 13 if((*addr) > (dataBuf[0]+(3120*5) - 1)) // 判断取数据是否已到最后一包 14 { 15 offsetNum = ((dataBuf[0]+(3120*6)-1) - (*addr)) >> 2; 16 newNum = 3120 - offsetNum; 17 (*addr) = (&dataBuf[newNum]); 18 memcpy(&dataBuff[0] + newNum-1, &dataBuf[0] +(3120*5+newNum-1), offsetNum*4); 19 } 20 /* 取数据未到最后一包 */ 21 else 22 { 23 (*addr) += n; // n 位算法返回值 24 } 25 }
1 unsigned char dataBuf[3120*6]; 2 DataMemCtrl_t data_mem_ctrl; 3 int data_process(unsigned char * buf, int length) 4 { 5 unsigned short temp =0; 6 unsigned int dataBuf_len =sizeof(dataBuf); 7 /* 有效数据长度不够读 */ 8 if(data_mem_ctrl.validDataLength < length) 9 { 10 return -1; 11 } 12 /* 读指针与写指针同在一轮数据中 */ 13 if(data_mem_ctrl.pread < data_mem_ctrl.pwrite) 14 { 15 memcpy(buf, &dataBuf[0]+data_mem_ctrl.pread, length); 16 /* 更新读指针 */ 17 data_mem_ctrl.pread +=length; 18 /* 读数据至末尾,读指针归0 */ 19 if(data_mem_ctrl.pread == dataBuf_len) 20 { 21 data_mem_ctrl.pread=0; 22 } 23 /* 计算可待读数据长度 */ 24 data_mem_ctrl.validDataLength -=length; 25 return length; 26 } 27 /* 写指针已超前读指针至一轮 */ 28 else if(data_mem_ctrl.pread > data_mem_ctrl.pwrite) 29 { 30 /* 计算可待读取的数据长度 */ 31 temp =dataBuf_len - data_mem_ctrl.pread; 32 /* 数据长度够本次读取 */ 33 if(temp >= length) 34 { 35 memcpy(buf, &dataBuf[0]+data_mem_ctrl.pread, length); 36 data_mem_ctrl.pread +=length; 37 } 38 /* 数据长度不够本次读取 */ 39 else 40 { 41 /* 读取该轮中可读取的数据 */ 42 memcpy(buf, &dataBuf[0]+data_mem_ctrl.pread, temp); 43 /* 在下一轮中读取剩余的数据 */ 44 memcpy(buf+temp, &dataBuf[0]+data_mem_ctrl.pread, length-temp); 45 data_mem_ctrl.pread =length -temp; 46 } 47 /* 数据读指针恰好已至末尾 */ 48 if(data_mem_ctrl.pread == dataBuf_len) 49 { 50 data_mem_ctrl.pread =0; 51 } 52 data_mem_ctrl.validDataLength -=length; 53 return count; 54 } 55 /* 读写指针位置一致,无数据可读 */ 56 else 57 { 58 return 0; 59 } 60 }