使用
STM32的ADC1和ADC2同步采集2路外部信号,且定时器中断(TIM2_CC2,每0.01ms采集一次,即采样率为100ksps)触发ADC1和ADC2同时采集。
其中
ADC1采集的数据保存在ADC_DR的低16位,ADC2采集的数据保存在ADC_DR的高16位。
然后将
ADC1和ADC2采集的数据通过DMA方式将ADC_DR中的字数据传输至数组 unsigner int AD_Value[ADC_BufferLength]中,最后将保存在数组
AD_Value
中的数据写入nand flash中保存起来。
现在主要有两个问题:
问题
1:由于数组AD_Value中保存的是字数据,而目前所使用的
nand flash K9F1G08U0E是8位的,因此,在将数组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。
这又该怎么办呢?
---------------------------------
是的 很抱歉 犯了这种不该犯的错误,不过还是感谢您的提醒
typedef union
{
unsigned int Value_int[512];
unsigned char Value_char[2048];
}AD_Value;
挺好用的。谢谢这位坛友,也谢谢坛友的热心帮忙!
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中。
用两个缓冲区交替工作来保证采集的连续性。道理是明白的,但程序实现上,还是挺茫然的。
一周热门 更多>