今天打算总结下最近受命开发的一个定制产品,是基于AD芯片的一个采样卡。
不做太多的铺垫,直接上干货!
本文中主要涉及到的是在调试和开发过程中遇到的几个问题和探索过程,尝试过的办法和思路,以及最终解决问题的方法,解决方法很简单,但是我个人觉得探索过程中的思路更重要一点,如果是单纯寻求解决方法可以直接跳转。
涉及的元器件:
SGM4518的AD采样芯片
LPC1765 主CPU芯片
模拟开关**
先说下本文中要提到的几个问题:
- IIC的通讯波形中出现的“台阶”形状
- SGM4518的连续模式配置及思路
- SGM4518的DATARegister在切换通道过程中出现的读取错误
问题1:
先给一张直观图,先用示波器抓出SDA和CLK的波形,会出现如下的台阶形状:
就是如下那个台阶,其实在研发的过程中发现这个数据位永远是0,并不影响使用功能,但是出于复杂环境的考虑(比如极端条件下,磁暴环境下会让这个点产生不可预计的影响),还是要把它消掉。
原因: iic是半双工的通讯方式,所以在这个第八位,由于我模拟iic的原因(估计是哪里配置的不好),在第八位数据位的时候,与SGM的ack回应信号(ack为一个回应高电平信号)发生对撞,所以我本身发出的是一个0,结果撞到了ack的1,就产生了一个半高的台阶信号。
进一步原因的发现,是我移植前SC32的芯片的代码在第八位数据后是要将SDA的gpio转为input,用来接收这个ack信号,结果LPC没来得及切过来,所以产生了对撞。
解决方法:在我这个案例中,将原来移植代码中的SDA管脚提前转input,这样就不会发生对撞,在正确的位置接收到ack信号。
解决后的波形如图:
总结思路: 由于IIC半双工通讯,所以不太能单步调试的方式去抓波形,当时用触发式去抓波形常常都是只能抓到一个沿,所以比较费神,需要一个一个的比特位去查看代码和实际波形。
当时在不断尝试发不同的数据的时候,发现当发出最后一位是高电平的时候,不会有台阶出现,所以想到了可能是有ack的对撞,由于我本身就要发送高电平(第八位高)的时候,ack也是高,所以哪怕我的SDA切input的时候有点慢,但是就没有台阶了,于是想到会不会是有信号的对撞。
调试过程中,本以为可以通过修改CLK的脉宽来达到将这个对撞分离,但是显然,我还是太天真了一点,延长了CLK信号,台阶也跟着被等比放大了(现在回头想,真的像个憨憨一样的操作,难以原谅自己…不敢让领导知道我干了这种蠢操作来尝试debug,实属憨批)。
找到了对撞的这个问题,就开始思考如何产生的对撞,显然,我们将SDA切input这个步骤,讲道理是不会有多少延时的,代码运行速度是非常快的,没有任何条件和循环语句及其他嵌套,再排除了中断的影响可能性,有了一个想法,就是会不会我这个LPC模拟IIC的切换速度有点跟不上,哪怕是一丢丢,运气不错,尝试了一下确实是这个原因,将原来的代码中SDA切换的代码位置提前了一下,所以这个问题暂时就fixed。
(题外话,图中还有一个黄色小凸起,我还没消掉,但是迫于项目进度,先暂时没有处理,因为这个点位时有时无的,在其他的卡上也有类似,但是出现的频率不一,暂时考虑是硬件原因,先搁置,欢迎联系我讨论这个小凸起)
问题2&3:
先说下这个场景: 我之前做的都是用AD转换芯片做一些比较不吃速度的卡件,这次是应用户需求,需要响应100ms的信号变化,因此需要配置和开发一个转换速度比较快的代码。
SGM主要配置:
这里如图,是一部分我在这个项目中配置的部分。
首先,要提高速度,那么原先的代码中是单次采样后切换采样通道,因此以前是选用单次模式。这次我选用的是连续模式,也就是说,芯片完成底层配置一次以后,没有问题就连轴转。
另一个区别是在采样速度,也就是SPS参数,SGM4518的最高SPS是960,这个参数在不同的选型中的有所不同,但都是可配的。
SPS的全称找了一些地方没找到(大胆猜测Serial Per Second?),哈哈哈大概是这个意思,我的理解就是每秒发出串行数据的比特位频率。SPS960就很容易计算,1000ms除以960等于1.04。
这里我想讲讲我自己对这个采样速度的理解,由于这款LPC芯片的SPS960在使用手册中注明是SINC4的数字滤波模式,而这个SINC4是不可配的,被芯片锁定的一个参数,所以当我们把SPS配好以后,就是完成了cfg寄存器的全部配置了。
那么这个采样速度要达到100ms的响应,应该如何理解和如何考量呢?
有几个关键点就是(借鉴下图),
- 黄色的部分每一个下降点(RDY信号)就是SGM发回的信号,表明在这个RDY信号后的数据被更新了,通知MCU来DataRegister取数据。
- SINC4的意思就是,在SGM在某时刻采样点抓到的信号(取名SIGNAL_1),那么这个S1将在4个RDY信号后的第一个RDY信号时候转换出来并提供给MCU。还有一个很重要的点,就是在4个RDY信号期间,AD都在采样同一个点,所以这个期间内进行切换通道的话,肯定是会出错的!所以简单来理解,SINC4的意思是 对一个数据的转化时间是需要4个Rdy信号的,也就是我们前面对SPS960的计算结果,因此最快的一个通道采样完成的时间就是 4 * 1.04了,那么你有多少通道,理论值上耗时计算就是通道数 * 4 * 1.04了,当然,这不包括模拟开关的切换时间(我自己这个模拟开关的一次耗时大概是24us左右)。
- 图中翠绿色的波形,前四个方波就是向DataRegister索取了四次 某1个通道的 采样值,显然第五个RDY信号的时候出现了空缺,这个空缺是我的一个bug,因为一开始发现这样采样好像也没问题,但是当我将耗时压缩的时候,发现当第五个RDY读取数据的时候,数据明显是错误的,于是就有了后面的解决思路。
前面说到这第五个RDY期采样的问题,我发现有点问题,于是将第五次的RDY填补了进来,如下图:
图中我标记了一下,前4RDY是对第一个通道的采样,那么按理来说第5至8RDY应该是采第二通道了没错,可是实际中是错误的数据,而且导致后面的数值都有问题。
这个问题困扰了我很久,因为单从IIC通讯SGM来说,这样的配置和波形是没有问题的,尝试N多种办法(没办法,第一次接触这个芯片,只能不断尝试摸索),我发现了一个问题,就是以前的AD用于它自己的AD内部通道切换,所以每次都要初始化,而初始化以后,就不会像我现在这样是一个连续的RDY了,也就是说,以前的单次采样方案,其实是有点漏洞的(但是也确实是不会影响任何使用),因为他们每次配置以后,SGM都会以新的RDY发送新的数据,而不像连续采样(可以将连续采样当成是一种有着自己时钟信号的发送数据方式,它可不会管你什么时候来读取,它就只管自己发,反正你只配置了一次而已)。
于是我去把第二通道的电平信号给抓了出来:
果然
抓出来一看波形就很直观了,红色的蓝线的下降是我切换到第二通道以后,产生的新的数据,这个数据在黄色的1RDY才被SGM拿走,经历过黄色的4个RDY信号以后,才会被SGM计算出来给MCU,而青色的第二个读取数据,就错开了。每个通道采样都偏移,那么问题可相知。
这个大坑,最大的原因就是以前的AD芯片每次都要配置(配置很费时间的),所以他们的代码是不会有连续的读取,也就不用考虑黄色RDY这种情况了。
问题找到了,解决起来就很舒服了,把以前的代码中切换通道的位置修改到读取第一个通道信号发出去之前就可以了:
以前顺序是 1-2-3,我这里需要改成 -1-获得RDY,-3- 切换到第二通道 ,-2- 读取第一通道值,这样一来,波形看一下:
正确读取。
美如画,问题完美解决,又多积累一些思路和方法。
现在每个通道都能正确在第一个RDY信号周期中的第一时间去获取数据了,至于里面要不要再读取其他3个RDY,我是为了提高性能,就没去读取。