AD采集到的实时数据全部存入nand flash和定义大数组的问题

2019-08-23 14:40发布

使用STM32ADC1ADC2同步采集2路外部信号,且定时器中断(TIM2_CC2,每0.01ms采集一次,即采样率为100ksps)触发ADC1ADC2同时采集。
其中ADC1采集的数据保存在ADC_DR的低16位,ADC2采集的数据保存在ADC_DR的高16位。
然后将ADC1ADC2采集的数据通过DMA方式将ADC_DR中的字数据传输至数组 unsigner int  AD_Value[ADC_BufferLength]中,最后将保存在数组
 AD_Value中的数据写入nand flash中保存起来。
现在主要有两个问题:
问题1:由于数组AD_Value中保存的是数据,而目前所使用的nand  flash K9F1G08U0E8位的,因此,在将数组AD_Value中的数据写入flash 之前,需要先将数组AD_Value数据分解字节数据,并将这些字节数据保存在字节数组unsigner char TxBuffer[ADC_BufferLength*4]中。
比如通过以下方式:
[mw_shl_code=c,true] for(i=0;i<ADC_BufferLength;i++) { TxBuffer[i*4] = (u8)((AD_Value)&0xff); TxBuffer[i*4+1] = (u8)(((AD_Value)&0xff00)>>8); //ADC1:低字 TxBuffer[i*4+2] = (u8)(((AD_Value)&0xff0000)>>16); TxBuffer[i*4+3] = (u8)(((AD_Value)&0xff000000)>>24);//ADC2:高字 } [/mw_shl_code] 但是,这样势必影响到数据存储的速度,从而影响到实时数据的保存。该怎么办呢?
问题2:两路AD同步采集,且采集速率都是100ksps,而nand  flash的页编程时间一般为300us~700us,那么,在flash的页编程时间里,2路AD采集
到的数据量=2*100k*700us*2Byte(每个AD采集数据为2个字节)=280Byte,因此,为了能够保证保存AD采集的全部实时数据,那么缓冲区的大小
就至少为280Byte。
于是我就将ADC_BufferLength定义为128:#define ADC_BufferLength  128
这样一来,缓冲区的实际大小就是128*4=512Byte,这是满足要求的。
程序编译通过了,nand  flash的读写也是正确的。
但考虑到nand flash的一页是2k=2048个字节,于是,将于是我就将ADC_BufferLength定义为512,即2048个字节,恰好是falsh一页的大小。
编译能够通过,但是程序却一直在“字转字节”的小程序中循环:
我尝试着将堆区扩大,将Stack_Size      EQU     0x00000800 改成 Stack_Size      EQU     0x00008000
结果依然是:在”字转字节“的小程序中死循环,全速运行,也不会到达断点处;
然后我将数组unsigner char TxBuffer[ADC_BufferLength*4]由局部变量改成全局变量,
结果依然是:在”字转字节“的小程序中陷入了死循环,即使全速运行,也不能到达断点处,当停止全速运行时,通过memory窗口
查看数组TxBuffer中数据时,发现,只能看到数据的前1024个数据,即TxBuffer[0]~TxBuffer[1023],之后的1024个数据则全部为
0x00。
这又该怎么办呢?

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
tuy0326
1楼-- · 2019-08-23 17:07
直接强转成u8的指针,然后保存,然后按u8读,都出来直接再强转回来即可
miaoguoqiang
2楼-- · 2019-08-23 17:07
 精彩回答 2  元偷偷看……
Mobile1991
3楼-- · 2019-08-23 17:57
回复【2楼】miaoguoqiang:
---------------------------------
是的  很抱歉   犯了这种不该犯的错误,不过还是感谢您的提醒
Mobile1991
4楼-- · 2019-08-23 18:41
在一位坛友的帮助下,使用了共用体结构(union)
typedef union
{
  unsigned int Value_int[512];
  unsigned char Value_char[2048];
}AD_Value;
挺好用的。谢谢这位坛友,也谢谢坛友的热心帮忙!
Mobile1991
5楼-- · 2019-08-23 23:39
上次说使用了uinon结构,
typedef union
{
 unsigned int Value_int[512];
 unsigned char Value_char[2048];
} AD_Value;
AD_Value AD;
ADC1和ADC2每采集一次,DMA就立即将该数据传输给数组AD1.Value_int,
当512个字全部传输完毕,进入DMA中断;
DMA中断程序主要是将刚刚采集到的512个字,即2048个字节写入flash中。
关于“在DMA中断函数中完成写flash”,这是我自己比较惆怅的地方:
之所以很难保证AD采集数据的完整性,flash的存储速度跟不上就是主要的原因。
而现在在中断程序中完成flash写操作,除去flash页编程的时间不说,还有额外的进入中断和
退出中断的时间。这无疑是雪上加霜啊。   
ADC1和ADC2的同步采集是由定时器2中断(IM2_CC)触发的,采样率控制为100ksps,也就是    
说,采样的时间间隔是10us。
而当开始第一次采集到一次写flash完成的时间,设为T,则     
T=AD采集时间+DMA传输时间(虽然时间很短很短)+进入DMA中断时间+在中断中写flash时间+退出DMA中断时间。
T应该是大于10us,所以实际写入flash的数据不是AD第一次采集的数据。因为AD1_Value_int中的数据每10us就会改变一次,而T却比10us大,所以,实际写入flash的数据也不知道是AD第几次采集的。
除非一进入DMA中断,就关闭定时器或者关闭DMA传输,那么写入flash的数据则是关闭定时器之前时AD采集的数据。
但是这样的话,AD的采集频率就不再是100ksps,肯定比100ksps小。
所以,我现在在考虑:
(1)不要在DMA中断函数中完成flash写操作,但不在DMA中断函数中写,又该怎么弄呢?
(2)坛友提到的“双缓冲模式”,定义两个缓冲区,一个缓冲区存满之后,就存第二个缓冲区,同时将第一个缓冲区中数据写入flash中;等第二个缓冲区满了,重新回来存第一个缓冲区,同时,将第二个缓冲区中的数据写入flash中。                  
用两个缓冲区交替工作来保证采集的连续性。道理是明白的,但程序实现上,还是挺茫然的。
yanhongqiuhe
6楼-- · 2019-08-24 01:56
楼主,你后来解决了没?我现在遇到的问题几乎跟你是一样的,能否赐教,谢谢。

一周热门 更多>