在发布了单通道实现篇之后,继续整理并记录在完成项目中测试硬件、调试代码的思路。上一篇文章是我第一次在CSDN发文,没想到第一次就上了最佳新人榜。基于STM32F103RC1的多通道ads1015通讯详细实现(单个通道实现篇)http://t.csdnimg.cn/8PvAAhttp://t.csdnimg.cn/8PvAA 实现篇是我对实现主机与ads1015通信的较为详细与系统的思路,而调试篇则是包含了我在实现项目过程中遇到的问题和它们的现象,我遇到这些现象后查找问题根源,解决问题的思考。
一、硬件简单介绍
在单个通道ads1015阶段,整个模块由两块板子,一根RS232信号线,一根供电导线组成。
第一块板子是数据采集板,一块数据采集板上附带两块ads1015,ads1015有四个ad转换通道,我们的设计是一ads1015上的两个AIN采集电压,另外两个AIN采集电流,另外数据采集板上还能连接两个mlx90614进行温度检测。ads1015与主机的通信是通过I2C协议,一块数据采集板上有两块ads1015,这就是上一篇文章中我介绍的ads1015用电阻将addr与不同的引脚连接后,可以完成对从机地址的选择。而mlx90614通过SMBus协议(SMBus是I2C协议的一个子集)与主机进行通信,为了避免太多系统资源被浪费。两块ads1015共用一根I2C总线,两块mlx90614共用一根SMBus总线,他们一起占用了RS232串口上的四个引脚(I2C_SCL、I2C_SDA、SMBus_SCL、SMBus_SDA),并通过RS232与主机进行通信。
第二块板子是状态监测板(主机),主要用于接收并处理从多个数据采集板处通过RS232传输的数据,同时为数据采集板提供电源。
二、硬件问题排查
1、检查供电是否正常
这个步骤需要借助万用表来辅助完成。主机使用STLink烧录程序并且提供3.3v的电源。首先要把电压调至20v量程,对板子上的电压进行测量(红表笔接VCC,黑表笔接GND)可以得到板子的电压数据。
这个步骤有时候能帮你发现一些匪夷所思的问题。在某个寒风凛冽的早晨,当我来到实验桌前准备开始继续程序的调试,却发现主机无法通过STLink烧录程序。
遇到这个问题我一开始想的是不是因为无意间把配置了特殊引脚的代码烧录了进去,导致STLink无法再进行烧录。在这里我简单介绍一下这种情况把!
在配置引脚时,要注意引脚定义表上的特殊引脚,某些特殊IO口(如JTAG、SWD)被占用后,烧录一次程序后将不能继续烧录。在keil中可能会有以下弹窗报错:
解决方法也很简单:
1、按住Reset按键,再点击烧录,烧录更换了正确引脚的代码
2、尝试用STM32 ST-LINK Utility连接主机,然后擦除烧录的代码
3、用串口连接主机,再使用FlyMCU连接主机,清楚芯片内容
在尝试以上方式无果后,我只能果断求助师兄。师兄测得主机上的电压异常,本应该为3.24V的工作电压受到异常分压只剩下1.6V左右。然而奇怪的是,把监测板对数据采集板的供电断开后,程序又能正常烧录了。后面我把供电恢复正常,打算一步步排查到底是哪个部位出了问题,程序还是能够正常烧录..........
后面我还是再次遇到了这种情况,这次我从数据采集板的ads1015开始一个个开始拆,拆下一个ads1015芯片后,仍无法烧录,然后我把它装了回去,又能正常烧录了。后面每次遇到这种情况都先拆再装,就能解决这个问题。。。
说完上面这个令人无语的,甚至带点恶趣味的问题。接下来继续检查其余的硬件。
当确认ST-LINK给监测板的供电,以及监测板自身工作电压正常之后,就要检查监测板给采集板的供电是否正常了。
监测板对采集板供电的供电导线包含四个引脚(+15V、-15V、GND、3.3V),因为我们目前使用的是3V3供电,所以要测试这个3v3是否正常供应。
首先可以用万用表测试电源线两端是否导通,然后测试电源线互相之间有没有短路的情况发生(就是测试几个引脚的线有没有交缠在一起导致短路)。
后面就可以着手测试ads1015芯片上的数据了,
把ads1015与 主机连接上后,便可以测试VDD是否正常供电3.3V。然后根据自己的电路设计和选择收据数据的AIN口,在对应的AIN口上进行电压的测量。假如我要收集电压数据,待测电源3v3进入电路,在电路中有两个相同电阻进行分压,导致A0端的电压理论上只有待测电源的一半。先用万用表在A0上测一下电压,得到1.62V左右说明硬件电路是没有问题的。
三、I2C通信调试
在初步完成上一篇文章的实现代码后,才发现通信根本不能正常进行。然而这是最让人头疼的,代码这么多,谁知道错在哪一步哪一行呢?这时候通常有三个好用的工具:示波器,逻辑分析仪,串口。这里就讲讲我用到的串口和逻辑分析仪吧。
1、串口
先讲大伙最熟悉的串口吧!这里的串口主要指的是通过主机的串口,连接usb to ttl模块把自己想看的数据打印在串口助手上。
我在该实验中的多处都使用串口打印信息来提示具体是哪个函数出现问题,比如写config register部分,写地址指针寄存器部分等。
在这里,如果主机向从机发送一个字节,且从机没有回复,那么函数会返回一。串口就会打印出init PointRegister error,我们很容易看出是指针寄存器这部分的问题了。
2、逻辑分析仪
用逻辑分析仪可以抓取主机与ads1015通信中SCL和SDA的波形,同时可以利用解码功能得到这两条线组合代表的数据。
下面是对单通道ads1015通信时抓取的完整波形:
正如上一篇文章所述,这是I2C通信的主设备发送流程,主机发送起始信号后开始发送从机地址呼叫从机,最后一位为W位,表示要写从机寄存器。从机应答后,主机先写指针寄存器0x01,指向config register,表示记下来要写配置寄存器(16bit),接下来的两个字节都是对config register的配置,从机一一应答后,主机发送停止信号。
这里则是完整的读时序,具体的步骤详细解析也可以参考上一篇文章。
逻辑分析仪既然可以抓取完整的波形,自然也可以抓取部分波形或者通讯失败的波形来判断是什么地方出现问题导致了通信的失败,或者数据丢失等问题。
比如用逻辑分析仪连接主机端的SCL、SDA线,查看接受的波形,如果收到的波形都是start、start repeat。那是正常的,因为主机没有连接从机,从机再怎么喊启动也没从机会动,主机只有喊了再喊。
在这里要特别主要RS232中引脚较多,而我们之前一根RS232里也只用了四个引脚,比较容易配置错误。可以直接用杜邦线把逻辑分析仪与RS232的引脚相连,更方便查找出有无配置错误。
同样也可以直接把逻辑分析仪连接到正在通信的总线上,仔细观察SCL、SDA的波形与产品说明书的通信时序或者通信协议是否相符,不同的地方在哪,这样可以更精确地找到问题所在。
四、Keil 5调试
使用keil5进行调试也是非常重要的一步。结合串口部分定位到的错误代码段落,在keil5中可以给这个函数加上一个断电,然后可以全速运行到断点的位置,然后逐步运行代码,查看参数传递是否正确,进而一步步发现代码中存在的错误。
如果keil5在你打了断点后全速运行的时候卡住不运行代码了,说明在走到你打上断点的函数之前就有错误导致程序卡死了。你可以一步一步往先运行的函数身上打断点,然后全速运行,这样不断地排查。
在使用keil5进行调试的期间,偶然蹦出过一个硬件错误中断(HardFault_Handle) 。引起HardFault_Handle的原因可以参考其他同学的文章,我也是偶然因为因为没有初始化结构体,导致传入结构体的值错误,触发了这个中断。执行了这个中断之后,他会一直在while{}里面呆住不出来,所以学长告诉我我们一般可以在这个循环里面加入某个led的闪烁,用来提示程序出现了一些硬件不知道如何处理的问题,触发了这个中断。