8893|18

144

帖子

2

TA的资源

一粒金砂(高级)

楼主
 

nand flash实时存储AD采集的数据和定义大数组的问题 [复制链接]

使用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]中。
比如通过以下方式:
  1. for(i=0;i<ADC_BufferLength;i++)
  2.             {
  3.               TxBuffer[i*4]   = (u8)((AD_Value[i])&0xff);
  4.               TxBuffer[i*4+1] = (u8)(((AD_Value[i])&0xff00)>>8);         //ADC1:低字
  5.                      TxBuffer[i*4+2] = (u8)(((AD_Value[i])&0xff0000)>>16);
  6.               TxBuffer[i*4+3] = (u8)(((AD_Value[i])&0xff000000)>>24);//ADC2:高字                       
  7.                  }               
复制代码
但是,这样势必影响到数据存储的速度,从而影响到实时数据的保存。该怎么办呢?
问题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。
这又该怎么办呢?

1.PNG (22.94 KB, 下载次数: 0)

在"字转字节"小程序里陷入死循环

在"字转字节"小程序里陷入死循环
此帖出自stm32/stm8论坛

最新回复

楼主你这问题解决了吗?我也在搞NAND FLASH,类似你的问题。  详情 回复 发表于 2016-5-25 16:15
点赞 关注
 

回复
举报

165

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
i不会是char吧...
此帖出自stm32/stm8论坛

点评

就是 谢谢 问题2解决了  详情 回复 发表于 2015-3-18 17:34
 
 

回复

4008

帖子

0

TA的资源

版主

板凳
 
本帖最后由 huo_hu 于 2015-3-18 16:31 编辑

1:用指针强制类型转换
TxBuffer[i*4]   =* (u32 *)(AD_Value);
2:问题没有看懂,这个和Stack_Size没有关系啊,除非你内存很吃紧了...
如果内存够就开2个缓冲区,AD和flash各访问一个,满了就换...
多于1024的数据用memory查看.
此帖出自stm32/stm8论坛

点评

图1和图2最下方的Memory2中的数据:04 08 FF 0F 01 08 FF 0F... 对应的是数组TxBuffer[0]、TxBuffer[1]、TxBuffer[2]、TxBuffer[3]、TxBuffer[4]、TxBuffer[5]、TxBuffer[6]、TxBuffer[7]...的值。 所以,如果我  详情 回复 发表于 2015-3-19 17:45
您的意思是这样吗(其中ADC_BufferLength=512[/backcolor]): (u32*)AD_Value是将AD_Value强制转换成指针,且该指针指向的数据类型是unsigner int; *((u32*)AD_Value)则是对该指针变量的引用,也就是(u32*)AD_Val  详情 回复 发表于 2015-3-19 17:38
谢谢,我会尝试一下的  详情 回复 发表于 2015-3-18 17:35
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

4
 
EETUX 发表于 2015-3-18 15:50
i不会是char吧...

就是     谢谢
问题2解决了



此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

5
 
huo_hu 发表于 2015-3-18 16:29
1:用指针强制类型转换
TxBuffer   =* (u32 *)(AD_Value);
2:问题没有看懂,这个和Stack_Size没有关系啊,除非你内存很吃紧了...
如果内存够就开2个缓冲区,AD和flash各访问一个,满了就换...
多于1024的数据用memory查看.



谢谢,我会尝试一下的
此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

6
 
huo_hu 发表于 2015-3-18 16:29
1:用指针强制类型转换
TxBuffer   =* (u32 *)(AD_Value);
2:问题没有看懂,这个和Stack_Size没有关系啊,除非你内存很吃紧了...
如果内存够就开2个缓冲区,AD和flash各访问一个,满了就换...
多于1024的数据用memory查看.
您的意思是这样吗(其中ADC_BufferLength=512):
  1.      for(i=0;i<ADC_BufferLength;i++)
  2.             {
  3.                   TxBuffer[i*4]   = *((u32*)AD_Value);
复制代码
(u32*)AD_Value是将AD_Value强制转换成指针,且该指针指向的数据类型是unsigner int;

*((u32*)AD_Value)则是对该指针变量的引用,也就是(u32*)AD_Value所指向的值。


如果按照最初的字转字节的小程序,结果如图1所示;

按照上述代码,结果如图2所示。

可能是我还没有真正懂版主的意思,所以,麻烦再指点一下。先谢过!




1.PNG (62.25 KB, 下载次数: 0)

图1:字转字节

图1:字转字节

12.PNG (62.18 KB, 下载次数: 0)

图2:强制转换成指针

图2:强制转换成指针
此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

7
 
huo_hu 发表于 2015-3-18 16:29
1:用指针强制类型转换
TxBuffer   =* (u32 *)(AD_Value);
2:问题没有看懂,这个和Stack_Size没有关系啊,除非你内存很吃紧了...
如果内存够就开2个缓冲区,AD和flash各访问一个,满了就换...
多于1024的数据用memory查看.
图1和图2最下方的Memory2中的数据:04 08 FF 0F 01 08 FF 0F...
对应的是数组TxBuffer[0]、TxBuffer[1]、TxBuffer[2]、TxBuffer[3]、TxBuffer[4]、TxBuffer[5]、TxBuffer[6]、TxBuffer[7]...的值。

所以,如果我直接将“字转字符”的程序换成:TxBuffer[i*4]   =* (u32 *)(AD_Value);

显然是不对的,希望版主指点啊




此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

8
 
在一位坛友的帮助下,使用了共用体,union

  1. typedef union
  2. {
  3.    unsigned int Value_int[512];
  4.    unsigned char Value_char[2048];
  5. }AD_Value;
复制代码
感觉挺好的
此帖出自stm32/stm8论坛
 
 
 

回复

9790

帖子

24

TA的资源

版主

9
 
flash_write((uint8_t*)AD_Value) 这样做不需要转换也不需要额外开辟转换空间。有一个问题你考虑过没,在你存满一个缓冲区往FLASH里写的时候这段时间还要有一个缓冲区2接受ADC数据,然后交替存取才能保证采样的连续性。
此帖出自stm32/stm8论坛

点评

恩 这个我正在考虑中 谢谢提醒  详情 回复 发表于 2015-3-21 09:02
 
 
 

回复

4008

帖子

0

TA的资源

版主

10
 
这个属于C语言的问题,数组名和任何类型的指针其实是一个地址,通过地址赋值就可以实现类型转换,不过呢有个大小端也就是高位在前还是低位在前的问题.你的程序是往flash里写,读写同样的操作就不用管大小端问题了.
指针指向的数据类型是如何看待和操作地址上的数据的问题,u8dat=*(uint8 *)addr就是从地址里取一个字节u32dat=*(uint32 *)addr就是从地址去一个字32位,然后addr++的时候是和addr定义的类型有关的,如果字节类型就+1,如果字类型就+4,你也可以自定义结构类型将地址付给结构指针。。。
此帖出自stm32/stm8论坛

点评

恩 谢谢版主  详情 回复 发表于 2015-3-21 09:03
 
 
 

回复

4008

帖子

0

TA的资源

版主

11
 
你定义unsigner int  AD_Value[ADC_BufferLength]但每个数据又是32位是不是很奇怪...
AD_Value的名称也容易误解
此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

12
 
littleshrimp 发表于 2015-3-19 21:10
flash_write((uint8_t*)AD_Value) 这样做不需要转换也不需要额外开辟转换空间。有一个问题你考虑过没,在你存满一个缓冲区往FLASH里写的时候这段时间还要有一个缓冲区2接受ADC数据,然后交替存取才能保证采样的连续性。

恩  这个我正在考虑中  谢谢提醒

此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

13
 
huo_hu 发表于 2015-3-20 09:24
这个属于C语言的问题,数组名和任何类型的指针其实是一个地址,通过地址赋值就可以实现类型转换,不过呢有个大小端也就是高位在前还是低位在前的问题.你的程序是往flash里写,读写同样的操作就不用管大小端问题了.
指针指向的数据类型是如何看待和操作地址上的数据的问题,u8dat=*(uint8 *)addr就是从地址里取一个字节u32dat=*(uint32 *)addr就是从地址去一个字32位,然后addr++的时候是和addr定义的类型有关的,如果字节类型就+1,如果字类型就+4,你也可以自定义结构类型将地址付给结构指针。。。



恩  谢谢版主
此帖出自stm32/stm8论坛
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

14
 
上次定义了一个union

  1. typedef union
  2. {
  3. unsigned int Value_int[512];
  4. unsigned char Value_char[2048];
  5. }ADC_Value;
  6. ADC_Value AD1;
复制代码
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中。

用两个缓冲区交替工作来保证采集的连续性。道理是明白的,但程序实现上,还是挺茫然的。














此帖出自stm32/stm8论坛

点评

楼主你这问题解决了吗?我也在搞NAND FLASH,类似你的问题。  详情 回复 发表于 2016-5-25 16:15
 
 
 

回复

4008

帖子

0

TA的资源

版主

15
 
不知道你的flash是怎么接口的...即便是spi也可以dma的.
此帖出自stm32/stm8论坛

点评

单片机型号是stm32f103zet6,使用的外部存储器是nand flash K9F1G08,stm32与外部nand flash连接,使用了stm32的FSMC  详情 回复 发表于 2015-3-22 12:25
 
 
 

回复

144

帖子

2

TA的资源

一粒金砂(高级)

16
 
huo_hu 发表于 2015-3-22 10:53
不知道你的flash是怎么接口的...即便是spi也可以dma的.



单片机型号是stm32f103zet6,使用的外部存储器是nand flash K9F1G08,stm32与外部nand  flash连接,使用了stm32的FSMC
此帖出自stm32/stm8论坛
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

17
 
楼主您好,
我刚好也在使用这颗NAND FLASH
因我有一笔大小为384KB的数据要写入NAND FLASH中,
但我在写入后,从NAND FLASH中读取出来的数据与写入的不相同。

想问说在写入数据时,您是一页一页分开写入,
还是连续写入呢?!(意即在同一个函式下写完一页后接着填写下一页)
此帖出自stm32/stm8论坛
 
 
 

回复

483

帖子

0

TA的资源

一粒金砂(中级)

18
 
楼主你这问题解决了吗?我也在搞NAND FLASH,类似你的问题。
此帖出自stm32/stm8论坛
 
 
 

回复

483

帖子

0

TA的资源

一粒金砂(中级)

19
 
qiwan 发表于 2015-3-21 11:45
上次定义了一个union

ADC1和ADC2每采集一次,DMA就立即将该数据传输给数组AD1.Value_int,

当512个字 ...

楼主你这问题解决了吗?我也在搞NAND FLASH,类似你的问题。
此帖出自stm32/stm8论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表