打印

调试W25X16意外的艰难

[复制链接]
楼主: 明月小厨
手机看帖
扫描二维码
随时随地手机跟帖
21
明月小厨|  楼主 | 2013-3-3 20:18 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
知道这些时间差和标志出现的时机,应该怎么操作就会明白一些;

使用特权

评论回复
22
明月小厨|  楼主 | 2013-3-3 20:35 | 只看该作者
描述一下读取W25X16的ID过程;
1.SPI主控使能;
2.NSS下拉;
3.写数据(0x90);
4.检测发送为空?;肯定为空;
5.再写入(0x00);(这个是伪指令,随便多少都可以)
6.检测发送为空?;肯定不空;(要等);
7.为空时再写(0x00);(这个是伪指令,随便多少都可以)
8.检测发送为空?;肯定不空;(要等);
9.为空时再写(0x00);(这个是真指令,0x00或0x01)
10.检测发送为空?;肯定不空;(要等);
11.为空时再写(0x00);这个是为了提供SCK时钟才写个数据的;随便多少都行
12.检测发送为空?;肯定不空;(要等);
13.为空时再写(0x00);这个是为了提供SCK时钟才写个数据的;随便多少都行
14.赶快读SPI接收数据寄存器(此时ID的第一个字节刚刚收到了,前面收到的都已经溢出了,不过它们没意义);
15.检测接收标志状态为空?(为空就等)
16.不空时,最后一个0x00刚刚从端口发送完毕,新收到的数据也写到接收寄存器待读;读取它;
17.SPI禁能;
18.上拉NSS,通知W25X16工作已经结束了;本描述没有经过验证(适用于STM32F103xx);

使用特权

评论回复
23
明月小厨|  楼主 | 2013-3-3 20:42 | 只看该作者
如果上面的流程不能通过验证,我将退出江湖,改行兼职做厨师;
上面写写读读比较烦,但它展示了获取ID的全过程;
W25X16上电后,或从掉电状态恢复后,有一个时间段,不接受任何操作;

使用特权

评论回复
24
明月小厨|  楼主 | 2013-3-3 20:50 | 只看该作者
如果你读取第一个数据不够及时(例如有中断发生);有可能丢数据;
解决办法:
1.DMA好象可以挂在SPI端口;当缓冲区用;
2.上述流程调整一下,最后一个0x00别急着发出去;

使用特权

评论回复
25
明月小厨|  楼主 | 2013-3-3 20:59 | 只看该作者
本帖最后由 明月小厨 于 2013-3-3 21:01 编辑

描述一下读取W25X16的ID过程;(修订版,主要是考虑系统中的中断有可能影响数据接收的及时性)
1.SPI主控使能;

2.NSS下拉;
3.写数据(0x90);
4.检测发送为空?;肯定为空;
5.再写入(0x00);(这个是伪指令,随便多少都可以)
6.检测发送为空?;肯定不空;(要等);
7.为空时,先读接收寄存器清标志,再写(0x00);(这个是伪指令,随便多少都可以)
8.检测发送为空?;肯定不空;(要等);
9.为空时,先读接收寄存器清标志,再写(0x00);(这个是真指令,0x00或0x01)
10.检测发送为空?;肯定不空;(要等);
11.为空时,先读接收寄存器清标志,再写(0x00);这个是为了提供SCK时钟才写个数据的;随便多少都行
12.检测发送为空?;肯定不空;(要等);
13.为空时,先读接收寄存器清标志,再写(0x00);这个是为了提供SCK时钟才写个数据的;随便多少都行
14.注:刚才读取的接收寄存器数据是ID的第一字节;(0xEF)

15.检测接收标志状态为空?(为空就等)
16.不空时,最后一个0x00刚刚从端口发送完毕,新收到的数据也写到接收寄存器待读;读取它;
注:此时读取的接收寄存器数据是ID的第二字节;(0x14)

17.SPI禁能;
18.上拉NSS,通知W25X16工作已经结束了;本描述没有经过验证(适用于STM32F103xx);
(修订版,主要是考虑系统中的中断有可能影响数据接收的及时性)

欢迎砖家拍砖;

使用特权

评论回复
26
明月小厨|  楼主 | 2013-3-3 21:10 | 只看该作者
本帖最后由 明月小厨 于 2013-3-3 21:11 编辑

《葵花宝典》第一页是什么?谁知道?
我只看了相关参考手册中SPI的前面一小段内容;担心被《葵花宝典》第一页误导的男性兄弟(注有的兄弟是“非男性”)可以看完全部内容;

使用特权

评论回复
27
xiaochuan610| | 2013-3-3 22:48 | 只看该作者
W25X16是非常常用的存储原件,如果你调试的这么艰辛,那么我有调试好的STM32代码~~~

使用特权

评论回复
28
明月小厨|  楼主 | 2013-3-3 23:49 | 只看该作者
多谢;共享出来,大家分享;

使用特权

评论回复
29
明月小厨|  楼主 | 2013-3-4 01:14 | 只看该作者

建立一个数组,记录每一次接收寄存器的内容;
1.先读数;数据组的第0个,没意义;此时数据还没有发送;显示的EF是上一轮测试后的残留结果;
如果发送位为空,则写发送寄存器(写0x90到发送寄存器,随后0x90进入移位寄存器);(0x90,0,0,0,0,0,0,......)
2.数据组的第1个,没意义;此时数据刚开始发送0x90;
3.数据组的第2个,没意义;此时数据刚开始发送第1个0;
4.数据组的第3个,没意义;此时数据刚开始发送第2个0;
5.数据组的第4个,没意义;此时数据刚开始发送第3个0;
  对应读ID指令0x90,0,0,0;
6.数据组的第5个,没意义;此时数据刚开始发送第4个0;//此时W25X16开始送0xEF到STM32F103,数据正在线上;
7.数据组的第6个,正是0xEF;此时数据刚开始发送第5个0;//此时W25X16开始送0x14到STM32;数据正在传送中;
8.数据组的第7个,正是0x14;此时数据刚开始发送第6个0;
......

使用特权

评论回复
30
明月小厨|  楼主 | 2013-3-4 01:21 | 只看该作者
8.数据组的第7个,正是0x14;此时数据刚开始发送第6个0;
说明;最后一个0可以不发送,但需要判断接收标志位,要查询接收缓冲区是否有新数据(正在传输中的0x14收到了没有)?

记录全过程;STM32没出问题;W25X16也没出问题;
但是你这一轮的操作,影响仍在继续;如接收寄存器有数据时,一直都在;和SPI是否使能无关;同时标志位也不受SPI是否使能影响;

使用特权

评论回复
31
明月小厨|  楼主 | 2013-3-4 01:30 | 只看该作者
所以,
每次传输数据的时候,一边发送,一边接收;是同步完成;(全双工)
每一次操作的结果,如果没有处理完成,将持续影响下一次的STM32F103的传输;
如果二次操作间有足够的空闲时间,数据传输肯定是结束了(自然结束或强制结束);

但接收数据的标志位和接收的数据仍有效(不为空);
我原以为只要禁止SPI,所有的状态将自动清除;看来错的离谱了;

使用特权

评论回复
32
明月小厨|  楼主 | 2013-3-4 01:37 | 只看该作者
发送标志为空,并不是指数据发送已经完成;
发送空是指发送寄存器的数据已经送入移位寄存器;移位寄存器的数据有可能刚开始发送至总线;
如果移位寄存器的数据正在发送中,此时禁止SPI(主控);不知道会有什么结果;不过NSS上拉随后进行,总线是否立即进入空闲状态已经不重要了;

使用特权

评论回复
33
dong_abc| | 2013-3-4 01:48 | 只看该作者
新塘MO的BSP包里有W25X16样例。

使用特权

评论回复
34
明月小厨|  楼主 | 2013-3-4 01:57 | 只看该作者
上面测试时每次都是先读数据(不一定要判断标志位);然后判断写为空否;为空则写数据;
这样处理的理由:
如果是先写,再读;基本上是能读到的;万一此时有中断发生,等中断处理完再返回来的时候,待读的数据有可能早就被破坏掉了;
你可以查溢出标志位做判断;有溢出说明你没及时读取;

就算是先读,仍然不能保证数据不丢失(最多只丢一个);

看来万无一失只能是用DMA缓存了;

使用特权

评论回复
35
明月小厨|  楼主 | 2013-3-4 02:04 | 只看该作者
可以在传输过程中插入延时,看数据接收的过程;
如果是这样;数据到移位寄存器,此时接收寄存器有数没有读,则等待;没有则写入接收寄存器;这样的话,上面的方案成立;
难怪调试时我看过程,结果和预想有差距;

使用特权

评论回复
36
明月小厨|  楼主 | 2013-3-4 02:06 | 只看该作者
不成立,移位寄存器的数据也有可能被破坏掉了;

使用特权

评论回复
37
明月小厨|  楼主 | 2013-3-4 04:53 | 只看该作者
本帖最后由 明月小厨 于 2013-3-4 04:56 编辑



SPI
写数据寄存器

SPI
发送移位寄存器
正在总线上的数据
(发送)

W25X16
正在接收的数据

W25X16返写
正在总线上的数据

SPI
接收移位寄存器
正在总线上的数据
(接收)

SPI
接收数据寄存器

过程1

=>0x90

-

-

-

-

-

过程2

=>0A

0x90 --->

---> 0x90

-

-

-

过程3

=>0B

0A--->

---> 0A

-

-

-

过程4

=>0C

0B--->

---> 0B

-

-

-

过程5

=>0D

0C--->

---> 0C

-

-

-

过程6

=>0E

0D--->

---> 0D

0xEF --->

--->正在收0xEF

=>读空后弃掉

过程7



0E--->

---> 0E

0x14 --->

--->正在收0x14

=>0xEF保存

过程8











=>0x14保存

使用特权

评论回复
38
明月小厨|  楼主 | 2013-3-4 04:53 | 只看该作者
因SPI的发送移位寄存器为空,所以过程1很快结束;过渡到过程2;......
根据这个表,写SPI的数据寄存器,只要发送TXE标志有效,就连续写;一直写到过程6,此时读空接收寄存器;
即写最一个0(编号E)时,立即读空接收数据寄存器(不用查看标志),读完弃掉;然后等待;
只要有新的数据收到就立即读,这次读到的是0xEF;
只要有新的数据收到就读(不需要立即读,不急了),这次读到的是0x14;
每一个过程从SPI写数据开始;到SPI读结束(前几个阶段不需要读)

使用特权

评论回复
39
明月小厨|  楼主 | 2013-3-4 05:24 | 只看该作者
没有版权限制,但初始化SPI的部分不在文档中;
我自己验证过;没一点点小问题(注意中断导致读数据丢失,一旦丢失会死机的);

读W25X16的ID.zip

3.53 KB

使用特权

评论回复
40
明月小厨|  楼主 | 2013-3-4 05:37 | 只看该作者
下一个测试项目,在发送数据的过程中,强制中断停止,再重新启动SPI总线;
测试目的,观察总线是否在SPI失能后同步中止并进入空闲状态;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则