OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7794|回复: 29

在操作系统下如何实现串口来数据我就把数据存到sd卡里

[复制链接]

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
发表于 2015-12-1 01:18:59 | 显示全部楼层 |阅读模式
5金钱
总体要求是串口会在系统运行的过程中发来数据,
实现串口来数据我拿到数据并存储,一个都不能丢
那么问题来了:
1、我怎么让系统一来数据就去执行最高优先级的存储任务,在跑裸奔程序的时候,
都是去判断.....BUF_STA接收完成标志位,那在UCOS下如何实现呢?
2、假如问题1解决了,那我在存储完这个数据后,如果后面没数据了,我怎样
才能让系统去执行我其他的任务呢,总不见得在存储完一个数据后加延时的吧,
加了延时的话如果在这个延时开始的一瞬间又来了一个数据怎么办?
这个问题我是这样想的,存储完一个数据,延时,切到别的任务,马上串口又来了一个数据,
切到最高优先级的存储任务,那此时是在延时处还是在这个程序的开始存储处
这样我就越想越混乱了,操作系统的本质就是不浪费时间(我的理解),有等待就调度

总而言之,怎么样才能让串口数据有条不紊得存储到SD卡里,求有经验的前辈指点一二,让我学习学习

最佳答案

查看完整内容[请看2#楼]

回复【27楼】战舰水手: --------------------------------- DMA初始化的时候不是有个传输数量值嘛,等传输数量递减到0,就会产生传输完成中断。 串口发送或是接收只有一个8bit的寄存器DR,去查阅STM32的reference manual。 DMA只是不断把DR中的一个字节按照接收顺序搬运到你指定的数组中,当DMA计数器递减到0时,传输停止,产生DMA传输完成中断 论坛里有关于串口DMA接收不定长数据的帖子 参考下 http://www.opene ...
我是一只菜鸟,但我会大鹏展翅
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-1 01:19:00 | 显示全部楼层
回复【27楼】战舰水手:
---------------------------------
DMA初始化的时候不是有个传输数量值嘛,等传输数量递减到0,就会产生传输完成中断。
串口发送或是接收只有一个8bit的寄存器DR,去查阅STM32的reference manual。
DMA只是不断把DR中的一个字节按照接收顺序搬运到你指定的数组中,当DMA计数器递减到0时,传输停止,产生DMA传输完成中断

论坛里有关于串口DMA接收不定长数据的帖子 参考下
http://www.openedv.com/posts/list/47402.htm
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-12-1 08:03:56 | 显示全部楼层
也一样的判断即可,只要有标志,就抢先处理
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

13

主题

296

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2067
金钱
2067
注册时间
2012-5-26
在线时间
292 小时
发表于 2015-12-1 09:50:57 | 显示全部楼层
串口接收中断,有做数据缓冲,等任务切换到存储任务可以继续处理
活着才是王道!健康是一切的前提!
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13129
金钱
13129
注册时间
2012-11-26
在线时间
3814 小时
发表于 2015-12-1 10:16:05 | 显示全部楼层
按照楼主这个做法,SD卡很快就坏掉了
学无止境
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-1 13:07:01 | 显示全部楼层
这个问题完全不需要用操作系统吧……
回复

使用道具 举报

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
 楼主| 发表于 2015-12-1 15:38:23 | 显示全部楼层
回复【5楼】ricefat:
---------------------------------
我还有其他任务,检测与服务器的连接状态,还要把SD卡里存储的数据发给服务器
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-1 17:27:39 | 显示全部楼层
回复【6楼】战舰水手:
---------------------------------
一定要用操作系统吗?我认为你说的那些任务都还不到必须要上操作系统的地步。
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-1 21:29:41 | 显示全部楼层
回复【7楼】ricefat:
---------------------------------
你好,我现在手上正好做楼主类似的事情,简单的说就是把串口接收到的数据写入SD卡。我现在想的是用DMA来接收串口数据,写入缓存,DMA接收完成中断中把缓存数据写入FIFO,再开启DMA接收。主循环就判断FIFO有效数据个数,达到阈值就把FIFO写入SD卡数据缓存,再进行写SD操作。写SD卡用SDIO DMA方式。
 这是我现在想的一个方法,之前用了另一种办法但是无法达到想要的高速,请问我现在的方法可行吗?或者有更好的方案吗?
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-1 21:59:00 | 显示全部楼层
回复【8楼】513393302@qq.com:
---------------------------------
中断中最好不要放需要很长时间的过程,比如软件延时,刷屏,写入数据等,防止在中断程序执行过程中被其他中断打断。在中断中设置一个标志位即可,然后在主循环中判断这个标志位并进行相应操作。
另外如果内存允许,FIFO应该尽可能大点,减少写入SD卡的次数,延长SD卡寿命。
如果对速度有更高要求,可以采用双缓冲+DMA方式。利用DMA传输过程不需要CPU参与的特性,一个缓冲接收串口数据,另外一个缓冲通过DMA向SD卡写入数据,然后交替,这样接收数据和写数据可以同时进行。
回复

使用道具 举报

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
 楼主| 发表于 2015-12-2 00:36:38 | 显示全部楼层
回复【8楼】513393302@qq.com:
---------------------------------
http://www.openedv.com/posts/list/37106.htm
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-2 21:40:36 | 显示全部楼层
回复【10楼】战舰水手:
---------------------------------
谢谢,哥们发的贴已经自己找到问题解决了。我说的方案今天已经写好了,测试通过了,在115200的波特率,通过串口发打文件,单片机把串口数据写入SD卡,再比较两个TXT文件内容,效果比较理想。只有最后很小一点数据保存到缓存中还没有写入SD卡,写入SD卡的内容与文件完全相同。
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-2 21:49:17 | 显示全部楼层
回复【9楼】ricefat:
---------------------------------
谢谢您的指点,只是我现在做的对串口数据不能丢失,如果我在DMA完成中断中设置标记,主循环扫描标记再处理,会出现数据丢失,主要是显示部分脱后腿,速度很慢。所有我现在做的是用串口DMA接收几十个字节,在DMA接收完成中断中写入FIFO,FIFO和SD卡写缓存我现在开的是一样的大小,都是1万多字节。主循环中判断FIFO有效数据数量,如果达到某个值(我现在设的是8192),则把FIFO全部的数据搬移到SD卡写缓存。SD卡的写数据就是把SD卡写缓存数据写入。我这样做虽然要用到多个缓存,但是这样就不会出现数据错误的情况而且能保持高速。今天把这个方案测试了下,效果非常满意。代码不能公开,实在抱歉
回复

使用道具 举报

0

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2015-11-24
在线时间
5 小时
发表于 2015-12-2 21:58:51 | 显示全部楼层
循环队列增强数据吞吐量
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-2 22:50:17 | 显示全部楼层
回复【12楼】513393302@qq.com:
---------------------------------
FIFO是不是可以做到读写同时进行?
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2015-12-3 10:32:35 | 显示全部楼层
回复【12楼】513393302@qq.com:
---------------------------------
你好,我想问一下你说的开的FIFO一万个多字节指的是什么意思,是在单片机内存里面定义一个一万多字节大小的循环缓冲队列的意思么?谢谢
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-3 13:13:05 | 显示全部楼层
回复【12楼】513393302@qq.com:
--------------------------------串口接收dma满,将其移动到fifo的过程中串口又来数据怎么办
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 07:38:36 | 显示全部楼层
回复【16楼】ricefat:
---------------------------------
我测试过,如果DMA中断函数处理过长,再开启DMA的时候会死掉。我现在设置的是DMA接收30个字节,DMA接收完成中断里把这个30个字节的缓存写入FIFO,在设置串口为DMA接收的时候关闭串口中断,并设置DMA接收完成中断为最高优先级,除了SDIO中断与它同级其它中断都不能打断。测试发现在115200波特率下,串口DMA接收完成中断接收50字节写入FIFO没有问题,保险起见一次只接收30字节就写入FIFO。波特率越低中断中可以写入FIFO的数据越多。
FIFO可以同时读写,只要在读写的时候先判断缓存有效数据就可以了。
测试发现,如果卡本身的读写速度较慢,数据会丢失。
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 07:44:35 | 显示全部楼层
回复【15楼】1201yuge:
---------------------------------
嗯,是的,可以实现高速与低速的兼容。FIFO相当于电路中的电容,暂时储存电能不会让电能丢失。对于SDIO方式写卡而言,串口是低速设备
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2015-12-4 09:56:56 | 显示全部楼层
回复【18楼】513393302@qq.com:
----------------------------
嗯嗯,但是有一个问题呢。就是一万多个字节的FIFO一次性写入SD卡的时候好使应该是10ms的样子(1M/s)的速度,而单片机用115200接收到30个字节中断的时间只有2-3ms,那么串口中断会不会打断SD的写入呢?假设不会,那么串口接收来的数据再放到FIFO里面,而上一次的数据还没有写完,那么会不导致数据错乱呢?
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-4 10:26:10 | 显示全部楼层
回复【17楼】513393302@qq.com:
---------------------------------
不知道你仔细考虑过没有,你现在这个方法是个单线模式,中间任何一个环节出现卡滞都会造成丢数据。
如果有更多的中断请求更多的任务,现在你这种方式可能就无法胜任了,
SDIO写入SD卡可以做到300kByte/s甚至更高,串口115200波特率只有14kByte/s,即使不用DMA 不用缓冲 也不应该出现丢数据的情况。

DMA为什么大于30字节会死
串口接收为什么使用DMA
如果串口DMA满向FIFO转移的过程中又来数据怎么办
FIFO到SD写入缓冲是不是也用了DMA
SD卡丢数据的原因是什么,是卡的问题还是你的程序出问题了

用了20多K的缓冲没法应付14K数据量

建议你考虑下上面有人提出的环形队列和我说的双缓冲
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 13:22:16 | 显示全部楼层
回复【20楼】ricefat:
---------------------------------
谢谢您的建议,我现在这个方案的确是单线模式,任何一个环节卡滞就会丢数据。
1、DMA接收完成中断里,如果处理时间过长,再来数据的时候没有没有处理完DMA就会死掉。
2、减少进串口中断次数,不用来一个数据就进一次中断,也浪费CPU资源。
3、我测试在DMA接收50字节完成后在中断中写入FIFO没有问题,测试一切正常,为留余量改为接收30字节一次。不会出现在数据到来时还没处理完的情况。
4、FIFO是一个环形列队,用DMA来实现数据转移不好管理。FIFO缓存的管理是由读指针、写指针、当前缓存有效数据数量来管理的,如果用DMA这3个变量则不好管理。
5、我之前测试了,如果用比较差的卡,在一次写很多数据时写的非常慢,FIFO会填满但是数据还没处理完的情况。

我明白这个方案很浪费RAM,但是现在暂时还没有找到其它跟有效的办法。希望您能给出建议

环形列队就是FIFO,我现在已经在采用。双缓存在F1里没有这个概率,但是对于我现在的方案能用DMA的地方我都用DMA了,串口的接收,SD的SDIO操作,FIFO缓存数据的迁移如果用DMA则不好管理。

我找时间把代码整理下,请您看看有没好的建议
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 13:51:43 | 显示全部楼层
串口DMA接收数据写入SD卡工程

串口数据接收写入SD卡.rar

1.79 MB, 下载次数: 556

回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 13:52:14 | 显示全部楼层
回复【20楼】ricefat:
---------------------------------
工程附件在21楼,请看看
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-4 14:24:56 | 显示全部楼层
回复【21楼】513393302@qq.com:
---------------------------------
main.c看了下
频繁f_open和f_close确实会让SD卡写入变慢,打开一次即可。
好久没弄STM32了,有点生疏,刚刚又看了下reference文档,双缓冲应该可行。


我提出的双缓冲主要是想起以前搞得SD卡音乐播放器
为了保证给DAC的数据不断流,需要用到两个DMA控制器
设置两个buf1和buf2。
SDIO经过DMA2读取数据到buf1,满了以后将buf1通过DMA1给连接SPI1(I2S)的DAC送数据。与此同时SDIO又通过DMA2给buf2填数据,因为DMA可以不依靠CPU自动完成传输,所以SD卡读数据和向DAC送数据可以同时进行。当buf1送完数据后,切换到buf2继续给DAC送数据,而SDIO又向buf1继续填入SD卡读取的数据。给DAC送数据的时间是可固定可计算的,通过设置合理大小的buf,使得读取SD卡时间小于给DAC送数据的时间,这样buf1和2交替可以保证给DAC数据完全不断流。当时的音频数据是44.1k 16bit数据,也就是1秒的数据量86KByte,而且这其中还包括了mp3或是flac的软解码过程,wav不需要解码,反而运行更轻松。我想这个方案也应该可以达到你这里的要求,建议尝试下。

原先我发的帖子是这个,基于F4 Discovery的
http://www.openedv.com/posts/list/21439.htm
我代码写的也不好,只是希望能给你启发
回复

使用道具 举报

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
 楼主| 发表于 2015-12-4 15:15:33 | 显示全部楼层
回复【20楼】ricefat:
---------------------------------
解疑老师您好,我现在尝试做双缓冲试下:有几个疑问
1、我把两个缓冲区的大小都设到我可能接收到的字节数以上,防止单个缓冲区满而覆盖数据
2、串口DMA接收的机制是不是串口来数据,DMA缓冲区指针递增存储数据,同时从头指针开始往内存缓冲区中搬数据,当DMA缓冲区
    中写入指针和搬运指针一样的时候停止搬运
3、我在串口中断里面使用的总线空闲中断,进中断就关闭DMA,里面的判断(判断条件是当前DMA指向的内存缓冲区)是如果中断前的内存缓冲区是A就把内存缓冲区改成B,反之则反,最后开启DMA。可能遇到的问题就是我在关闭DMA的时候,串口又来数据,并产生空闲中断,这怎么解决?
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
 楼主| 发表于 2015-12-4 15:40:09 | 显示全部楼层
回复【21楼】513393302@qq.com:
---------------------------------
http://fly-top.blog.163.com/blog/static/17275511220127823323781/
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

81

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
452
金钱
452
注册时间
2014-8-11
在线时间
87 小时
 楼主| 发表于 2015-12-4 16:05:40 | 显示全部楼层
回复【21楼】513393302@qq.com:
---------------------------------
哥们我想问你一下,在串口DMA接收数据的时候何时回产生传输完成中断,我想不明白

假如串口是一直会间断性来数据,有时候很多,有时候很少,我DMA的缓冲区的大小设到最可能数据量多的时候的大小,
那所谓的传输完成中断何时触发

DMA的数据搬运:譬如一次来了8个字节,这八个先是都缓存在了DMA中,然后dma开始往内存中搬,搬运指针偏移到第四个就是传输一半,偏移到第八个就是完成中断;假如来了六个字节,分别是3 6 产生对应中断。按我这种想法要是先来8个,然后再来六个,不就乱了

对于这种串口不间断来数据,DMA到底是怎么个搬运机制呢
我是一只菜鸟,但我会大鹏展翅
回复

使用道具 举报

3

主题

2178

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3323
金钱
3323
注册时间
2013-7-19
在线时间
195 小时
发表于 2015-12-4 16:10:17 | 显示全部楼层
回复【25楼】战舰水手:
---------------------------------
1.这个大小可以慢慢尝试
2.具体DMA的机制我没有研究过,但是串口DMA的作用就是把串口DR寄存器中的数据搬运到你指定的数组中,搬运次数就是你指定的DMA传输数量,这个过程是自动的,你不需要串口中断,只需要等待DMA计数完成产生DMA传输完成中断。
3.空闲中断是什么我没用过,你用DMA传输串口数据就不需要串口中断了,再DMA传输完成中断中切换缓冲就可以了
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-4 17:06:12 | 显示全部楼层
回复【24楼】ricefat:
---------------------------------
谢谢您的启发,这个双缓存的方式是可以测试下。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 01:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表