一种环形数据区存取机制的实现

一种随机起始地址循环连续取数据的的机制

问题描述

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 unsigned char dataBuf[3120*6];
 2 *startaddr = &dataBuf[3120];
 3 /**
 4 * @brief   : calculate next start-addr
 5 * @param   : 指向存储区所取数据得地址的地址
 6 * @retval  : none
 7 **/
 8 void addroffset(float **startaddr)
 9 {
10     u16 num, offsetnum, newnum;
11     /* 取数据至最后一包数据处,开始地址接续 */
12     if((*startaddr) > (dataBuf[0]+(3120*5) - 1))  // 判断取数据是否已到最后一包
13     {
14         offsetnum = ((dataBuf[0]+(3120*6)-1) - (*startaddr)) >> 2;
15         newnum = 3120 - offsetnum;
16         (*startaddr) = (&dataBuf[newnum]);
17         memcpy(&dataBuff[0] + newnum-1,  &dataBuf[0] +(3120*5+newnum-1),  offsetnum*4);
18     }
19     /* 取数据未到最后一包 */
20     else
21     {
22          (*paddr) += n;  // n 位算法返回值
23     }
24 }

 

 
方法二、指针描述控制法
 
1、定义指针描述控制机构
typedef struct
{
    unsigned char *pwrite;                   /* 当前数据写指针 */
    unsigned char *pread;                    /* 当前数据读指针 */
    unsigned int validDataLength =0; /* 可供读取的有效数据长度 */
}DataMemCtrl_t;
 
2、处理过程
 
1> 六种数据读取状态
 
图一为初始状态,读写指针都指向存储区起始地址 
 
图二为已写入一部分数据还未开始读取,写指针与读指针之差则为可供有效读取的数据长度                                
1.PNG                  2.PNG
                                    图一                                                                                                   图二
 
图三为在继续存数据的同时读取了一部分数据
 
图四为读取数据已至当前写数据的位置了,表示当前已无可供读取的有效数据了
3.PNG                       4.PNG
                                      图三                                                                                                    图四
 
图五为存数据已超前读数据至下一轮了,当前可供读取的有效数据为当前读指针至存储区末尾 + 存储区首地址至当前写指针
 
图六为存数据已超前读数据至下一轮了,恰好读指针在存储区末尾,可供读取的有效数据长度为写指针至数据存储区首地址
5.PNG                      6.PNG
                                      图五                                                                                                    图六
 
2> 附部分代码:
 
 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 }
原文地址:https://www.cnblogs.com/skullboyer/p/9102236.html