笔者在用ADI一款SPI接口的ADC(模数转换)芯片,该芯片内置高精度基准源,也可以配置为外部基准,三通道采样,可配置1-128倍增益。通过配置相关寄存器便可以在通道和增益之间随意切换,官方提供了驱动程序源码,修改通信驱动(Communication Driver)部分后可以移植到任何处理器。

图:AD驱动程序框架

开发者需要根据所选择的Microcontroller(微控制器)修改Communication Driver(通讯驱动)程序即可,具体来说就是实现SPI_Init(SPI接口初始化)、SPI_Write(SPI发送数据)和SPI_Read(SPI接收数据)即可,ADI Driver部分理论上不用修改,ADI Part部分的核心就是SPI接口的ADC芯片。笔者将之前验证过的SPI接口的读写程序放到Communication Driver的三个驱动函数,编写上Demo 测试函数,分成以下几步,逐步测试驱动程序中的接口函数:第一步能识别芯片ID,验证通信接口驱动Communication Driver;第二步设置通道采集数据,验证SetChannel接口函数,第三步设置增益采集数据,验证SetGain,最后一步任意切换通道和增益采集数据,将芯片彻底“俘获”。第一步实现至关重要,一旦识别成功,就说明SPI底层程序没有问题,就算成功了一半,甚至后面的试验都能水到渠成。想想,还有点小激动呢。

上电,下载,运行一气呵成,坐等握手成功识别芯片ID的好消息,竟然没有回复,一定是我打开的方式不对,重新上电,依旧没有收到识别成功的消息。好吧,不要骗自己了,驱动程序拿来就用,而且是不加修改跟中彩票的几率一样,就是真中奖,还要仔细阅读源码,是否有Bug,生怕是个陷阱。几番折腾遍后,笔者确认是ADI Driver部分出了问题。阅读官方提供的驱动程序,ADI Driver可读性很高,层层封装。底层通信驱动由所选的微处理器提供,进一步封装成设置和读写芯片寄存器的功能函数,要控制芯片还需要读写寄存器相互配合,进一步地封装读写寄存器的功能函数,完成应用级别的封装,实现对芯片真正地控制,芯片的使用就变成了函数的调用,这是驱动程序要达成的最终目标。

但现实往往是骨感的,仔细阅读官方驱动的同时一一对应芯片的数据手册,索性将整个官方应用驱动的工程文件下载下来研读。发现SPI读写程序的第一个字节是芯片的片选信号控制位;所以SPI读写数据的第一个字节不能发送,而要根据其值转变成片选信号来控制芯片是否选中,这个很容易实现,第一个字节判断一下即可,分分钟解决这个问题。上电,下载,运行等待握手成功的消息,果然识别了芯片ID,握手成功!

图:SPI发送字节(读字节)流程图

慢着,为什么只是握手成功,芯片采集数据读不上来,难道是总线失去了同步?失去同步官网的解决方案是复位芯片的通信接口,那就握手成功后加入复位芯片通信接口的操作,依旧只能收到握手成功的消息,看来没有想地那么顺利。继续研究官网的驱动程序,底层驱动之上,封装的是寄存器读写操作,八成问题出在这里,这是后知后觉,最初发现问题可是Debug到怀疑世界的才最终定位到寄存器读写出了问题,短短几行代码,浅显易懂。先读取寄存器的值,控制命令通过宏定义转换为控制代码,将控制代码写入读到的寄存器的指定位置,把芯片的片选信号,修改过控制代码的寄存器值依次写入缓冲区,调用底层SPI_Write将缓冲区数据发送即可。问题出在哪儿,且慢,为什么写入缓冲区的数据是从最后一个字节开始呢,将数据顺序颠倒了。是不是问题出在了这里,那么是不是读数据的时候顺序就是颠倒的,然后在这里颠倒回去,负负得正。需要返回去查看读寄存器的封装,然而这里并没有颠倒,问题来了,为什么呢?显然这个驱动程序在官方评估板上是没问题的。就是不同平台原因导致的。在评估板上,如果能,不,是肯定能运行,这个字节存储是高字节在前,这是,是典型的小端模式。这样解释了为什么来个字节倒置。问题找到了,改掉而后快。

图:设置寄存器流程(包含字节颠倒的操作)

继续重复,上电、下载、运行但愿能一气呵成吧。握手成功,数据读取成功,读取的数据随着外部电压信号而变化,每个通道都是这样,短路输出几乎为零,符合预期但是测量范围太小了,显然是最大增益,就是说修改增益没有成功,依然是默认的增益。至此驱动程序没有问题了,那就是调用时出现了问题,参考官方例程一一对比芯片初始化的步骤,缺少了一项设置参考电压,因为寄存器默认就是内部参考电压,所以就没有另外设置,但这是唯一的区别了,福尔摩斯说过,当你排除了所有可能的情况后,剩余的那种情况尽管显得多么不可能,那就是真相。加上一行代码,上电,下载,运行,握手成功,通道和增益都设置生效了,测量范围也变宽了。看来确是缺少设置参考电压导致的。芯片已经摸索得差不多了,可以展开进一步应用了。

图:芯片初始化操作

不急,官网驱动虽然可读性较高,但是过多的调用和封装占用内存资源过多何不进行整合将SPI驱动调整至设置寄存器中,减少不必要的调用,删去没有必要的接口函数。仅修改驱动程序情况下,数据空间和代码空间都有不同程度地减小,小中见大,如果调用次数增加,或者程序更加复杂,那么节省的资源将更多,至此芯片探索告一段落。

图: 程序优化前后数据空间和程序空间对比

虽然是由程序Bug导致的但是没有找到就是开发者的问题了。驱动程序无疑是离硬件最近的软件,其优劣直接影响硬件性能地发挥,驱动被封装和调度,归操作系统管理,操作系统之上再运行各种应用软件。软件工程师无论是使用何种编程语言,都是在调用操作系统的各种接口,最终是跑在硬件之上。但是软件越庞大,软件开发者离硬件越远,分工也越明确。高质量的软件绝不是单纯的算法,都有不同程度针对于硬件的优化。如老牌的PDF文件阅读器Adobe Reader文件打开速度总是快于其他软件;PhotoShop有针对显卡的硬件加速;WPS对于大文件编辑能力不及Microsoft Word;基于Chromium内核的浏览器总是快于其他内核的;华为的GPU Turbo技术;Google设计Nexus One就是为了了解手机的设计和制造流程,以便优化Android系统;更不用说苹果手机就是从硬件做到了软件的封闭生态,将硬件的性能发挥到极致。软件的优化一定程度上是面向硬件编程,处理器速度提升遇到瓶颈和摩尔定律接近失效,拉近软硬件的距离,最大效率发挥硬件的性能,成为提升用户体验和降低成本的不错途径。

People who are really serious about software should make their own hardware–Alan Kay

真正热爱软件的人应该自己制作硬件

                                                                                    –阿伦·凯

发表评论

邮箱地址不会被公开。 必填项已用*标注