话说小时候总盼着放假,一年只有寒假暑假可放,而其中寒假因为带着春节,尤其热闹,更是盼望。小学班主任知道孩子贪玩,到了年底就更没心思好好上课了,提醒我们:“同学们,要是这几天不好好上课,那就是‘一年到头调皮捣蛋’了啊,注意啊!”所以后来我养成个习惯,就是每年末的最后一天也要学点、做点什么,这样可以跟人吹嘘“ouba一年到头刻苦style”。
——2012年12月31日 写完了I2C接口的飞思卡尔MPL115A2气压传感器cookie的驱动,第一版
这还要从2012年末说起。当时CooCox还是非著名组织,推出了个叫做Cookie的开发板,用的是著名的新塘的32位mcu,兼容著名的Arduino。兴趣所致,上网狂搜,发现他们竟然用雷军卖小米的办法卖板子,饥饿营销啊。
之后出于对开源的推崇和对CooCox的兴趣,参与了CooCox的开发开源驱动的活动,本来准备做PCD8544的驱动,把手册翻了n遍,觉得胸有成竹才去申请,没想到Walter竟然早了半天捷足先登,于是乎转而承揽了飞思卡尔MPL115A压力传感器。
飞思卡尔MPL115A压力传感器是一款测量气压的传感器,这个系列有2个型号,分别是串口的MPL115A1和I2C的MPL115A2,拿到手册之后发现2款只有协议和引脚定义略有区别,使用流程和算法是一样的。
先说使用流程,首先要保证!SHDN为高电平,然后读取几个参数,然后启动转换,再后面是读取气压、温度原始标量,最后是按照规定算法计算出实时气压值。这里后来发现有几个问题:一是使用I2C协议时,由于MPL115A2的地址固定为0x60,所以如果一条总线上要用多个MPL115A2,必须要有多个!SHDN才行;二是传感器参数并不是像我开始设想的那样,是出厂配置不会变,所以只好每次量气压前再读一次;三是得到的是格式不同的定点数,不好计算,这个后面会提到。
再说算法,算式很简单:
Pcomp= a0+(b1+c12×Tadc)×Padc+b2×Tadc
Pressure(kPa) = Pcomp × (115-50)/1023+ 50
但是做起来就费劲了。首先遇到的问题是:传感器上的6个数据是长度不等、小数位各异的。最开始用2个函数来做转换,实验代码如下:
#define MY_DEBUG printf
#include "stdio.h"
float getFloatByBIN(signed short intB,unsigned short iShift)
{
float f=0.0;
f+=intB;
f/=(1<);<>
return f;
}
float calcMACs(float a,float b,float x){
return a+b*x;
}
void main()
{
float a0 ,b1 ,b2 ,c12 ;
unsigned short padc,tadc;
a0 = getFloatByBIN(0x3ECE,3);
b1 = getFloatByBIN(0xB3F9,13);
b2 = getFloatByBIN(0xC517,14);
c12 = getFloatByBIN(0x33C8,2+9+13,2);
padc=0x6680>>6;
tadc=0x7EC0>>6;
MY_DEBUG("%f,%f,%f,%f,%d,%d\n",a0 ,b1 ,b2 ,c12,padc,tadc);
MY_DEBUG("%f\n",calcMACs(50, calcMACs( calcMACs( a0,calcMACs(b1,c12,tadc) ,padc) ,b2,tadc) ,(115-50)/1023.0));
}
其间发现手册有“印刷错误”(不知道这个典故的可以去找老罗语录),不过经认真比对之后还是不难搞定滴:p
虽然实现了功能,但是效率不怎么样,而且浮点数是会损失精确度的,需要修改!
正在苦B的写定点数转换算法时,发现飞思卡尔有一份应用笔记,里面有详细的算法,简直是定点数计算的极好教材,果断收下。
总结起来基本上是以下几点:
1】正负问题交给语言去解决
2】注意小数点对齐
3】及时清理压缩数据的容器,当然,这需要准确掌握计算结果的长度和实际值域,比如[m,n]+[j,k]的长度是[max(m,j),max(n,k)],[m,n]×[j,k]的长度是[m+j,n+k]。
4】把 65/1023 改成成 1041>>14 简直是位于牛A与牛C之间的极品,深受触动,大受启发。
搞定算法后开始拿板子调试接口,先做MPL115A2,所以启用I2C——把板上跳线A4,A5跳到23,然后就开始写协议代码了。由于当时coIDE和coocox的库还在升级中,偶尔会出现示例不能用之类的情况,不过在coocox的liam帮助下,还是搞明白了I2C的用法,后来就是调试了。没想到启动转换的命令0x12发送后就飞了,后来发现,在命令后还要跟一个0x00——看手册不仔细害死人啊。
启动转换没问题了,可是取气压温度原始数据时又出问题了——虽然调试的时候有时能正常,但一旦开跑,每次取出来的都是0,这个问题直到31日晚上才解决:当时手册已经看到第n次方遍了,快崩溃了,正要关机歇业,下年再说,突然灵机一动,把等待adc的延时加大了,然后就洗具了。这才踏踏实实过了年。
2012年就这么过去了,2013年赶紧把驱动传给liam看,结果发现一堆问题,主要是不符合coocox的文档规范。coocox的文档除了在程序文本中要加入doxygen语法外,还对预定义的格式等有严格要求。虽然学习过doxygen,不过有些东西还是做得不到位啊。后来liam提出的问题全部解决,顺手着还发现、处理了几个结构上不够紧凑的毛病。
MPL115A2做完之后,该做MPL115A1了,这个是SPI协议,用的也是cox的库来做的,相比做MPL115A1容易了一些,但调底层时还是遇到了一个问题:必须要用xSPISSSet对spi进行使能。当时参考了Walter的方法,不成功,后来参数改用xSPI_SS_SOFTWARE才调通,又发现每次发送前都要重新做一次xSPISSSet才可以,不知是否MPL115A1会自动拉高?总之,MPL115A1也搞定了。
都搞定后,liam告诉我,还要上传一套用于介绍组件的主页,这样使用者就可以从主页上大概了解这个组件有什么功能、如何使用。手册翻了那么多遍,这个很好写了。写好后,问了问如何写sample文件、如何上传等等,最后就毫无悬念的上传了,这是上传之后的部分截图:
文章评论(0条评论)
登录后参与讨论