今天一天解决了一个问题.
在Wince下与设备通过SPI通讯,过程如下:
1. 给设备发Reset信号
2. 检查数据是否Ready
3. SPI通讯
为了具体化,我列出程序的伪代码:
1. 拉高Reset脚
2. Sleep 1毫秒(给出的规格是最少Delay 10us)
3. 拉低Reset脚
4. 检查Ready脚是否为高
5. SPI采集数据
Bug的表现是这样的:
a. 有时候测不到Ready信号
b. 有时候能取到正常的数据,大部分时候数据完全不对,偶尔前半部分数据对.
c. 为了模块化,我改了一版封装比较好的版本,就是把混在一起的语句用几个函数包装了起来.测试时发现封装好的版本大部分时候检测不到信号,而且取得错误数据的几率高很多.
请电子工程师检查代码,认为逻辑是对的,没问题.然后开始怀疑取数据时SPI速度太快,改了之后没任何改善.
逐行比较两个版本的代码,改成几乎完全一致,唯一不同是多了函数封装.结果还是封装版本出错的几率高.开始怀疑函数调用产生了开销,导致时序不正确.检查了各个关键点,没发现特别耗时的操作.有点走头无路,就差察看汇编代码了.
我还用延时代替Ready信号的检查,再SPI切换片选信号前后加延时,加大Reset信号为高电平的时间.所有的办法都试了.
只有...,只有...,只有没把Wince里等待1毫秒的函数Sleep(1)换掉.因为Sleep最小就是1ms.
因为改过系统自带的SPI驱动,怀疑驱动没正确加载,上午的时候尝试过用GPIO软模拟SPI.后来发现模拟出来的CLOCK信号频率太低,遂放弃.
抱着试试看的态度,把Sleep(1)换成了for循环.
居然成功了,那一刻,我觉得自己是成功人士.
设备检测到FIFO_RESET的上升沿,就开始设置READY信号,接着自动通过SPI丢数据上来.因为Sleep太久,就错过了这精彩的一幕幕,只抓到个尾巴.
结论:
1. 设备代码不OK,检查READY信号的逻辑不合理,或者,至少说明多久时间内要检查;还有,FIFO_RESET延时没有给出上限.
2. 这类开发中,所有偶发的Bug都与时间有关.
3. CSDN的博客还是很烂.中途我丢失一部分内容,重新排了一次版,因为段落的距离太大大大大了