基于表驱动状态机方法的DS18B20驱动库设计
lbing7
(四川托普信息技术职业学院 实训中心)
[摘 要]表驱动状态机的方法可以让DS18B20在工作的时候解放MCU,让系统更有效地分配和利用MCU的运算资源。提高应用了DS18B20温度传感器的系统的平均响应时间,拓宽DS18B20温度传感器的应用范围,使DS18B20与系统的接口更加自由、方便。
[关键词]状态机、传感器、DS18B20、微控制器、库
A DS18B20's Driver Library Based on FSMTable
lbing7
(SichuanTOP Vocational Institute of Information Technology)
[ABSTRACT] Table-drivenFSM can free the MCU when DS18B20 is workingand allowing system toutilize MCU resources more effectively. It improves theaverage responsetime for systems using DS18B20, widens the application ofDS18B20, andmakes the interface between DS18B20 and system more freelyandconvenient.
[KEY WORDS]FSM; Sensor; DS18B20;MCU;Library
1 引言
一个有限状态机(简称状态机)是一个特殊的有向图,它包括一些状态(节点)和连接这些状态的有向弧。每一个有限状态机都有一个启始状态和一个终止状态和若干中间状态。每一条弧上带有从一个状态进入下一个状态的条件[1]。状态机是非常有效地面向对象的建模工具,它把问题看成一个整体(对象),把问题某些特定的时期特性看成状态,把触发这些特性发生改变的因素看成事件。因此,它就能非常紧密地贴近问题,把各种交错复杂的问题清晰地分解开,提供更加漂亮的解决思路。在编译原理、通信协议及游戏设计等领域中状态机都得到非常广泛的应用。将其引入单片机软件开发,必定能为这个领域带来更加广阔的解决思路及优雅的编码。
DS18B20温度传感器是常见的温度传感器,由于它采用独特的“一线总线”接口,在MCU与之通信的时候仅需要一个数字IO即可。这为MCU系统节省了有限的IO资源,但是由于它完成一次温度转换的时间较长,且当前普遍采用阻塞式的驱动方式(即:MCU被迫停下来等待它完成温度转换),这使得它的应用受到了极大的限制。一般仅用到系统平均响应时间要求较低的场合,比如说:初学者学习,简易电子温度计等。本文结合状态机思想提出一种新的驱动方法,并设计成库以改进DS18B20的驱动方法,不采用阻塞方式,而让DS18B20进行温度转换的时候MCU可以腾出“手”来去做别的事。
2 状态机的驱动方式
状态机的驱动一般有三种方式:switch-case方式、表驱动方式和状态模式。前两种方式比较常见,状态模式由于完全抽象于面向对象的思想,需要面向对象设计语言的支持,在MCU软件开发领域目前几乎没有面向对象语言的应用,在此不做讨论。
2.1 switch-case方式
switch-case方式抽象于面向过程设计的思想,贴近状态切换过程,本质上每进行一次switch-case解析都是状态的迁移。在对应的case状态中处理状态中的信息,并依据当时条件迁移到下一个状态。在状态较少以及状态间迁移的边数较少的时候,这种方式比较有效。如果状态过多或迁移的边数较多的情况,则可能需要一个庞大的switch-case代码块,这会给编码、开发带来很大的麻烦。
2.2 表驱动方式
2.2.1伪码
//定义状态机及初始化
FSM Wfsm = START;
//状态1
void STATE1(void)
{
//状态处理
//状态迁移
Wfsm = NEXT;
}
//状态1(2)
void STATE2(void)
{
//状态处理
//状态迁移
Wfsm = START;
}
//建立状态表
void (*STATETABLE[])(void)= {STATE1, STATE2};
while (1){
//表驱动状态机
(*STATETABLE[Wfsm])();
}
2.2.2 简述
表驱动方式抽象于面向对象的设计的思想,它把每一个状态(包括它的迁移边)看成一个对象,用一个函数去表达这个“对象”。然后把这些“对象”放到一个函数表里,以状态机作为函数表的索引。通过修改索引去调用不同的函数,达到状态迁移的目的。
2.3 表驱动方式的优势
1.switch-case方式源于面向过程设计的思想,它关注状态的迁移,使程序员花费较多的精力于状态机的转换逻辑,而分散其于状态机功能实现这个本质要解决的问题上的精力。表驱动方式源于面向对象设计的思想,它把各个状态都看成了“对象”。把状态的迁移也封装到了“对象”里面。让程序员更加关注状态本身的功能实现。
2.switch-case方式在进行状态解析的时候会用到一组switch-case语句,若状态机中状态较多,迁移的边数较多的情况,可能需要一个庞大的switch-case代码块,这会给编码、开发带来很大的麻烦。表驱动方式仅仅需要更改状态机以决定去调用哪个状态的函数,在状态机处理的地方仅需要1行代码即可,代码非常简洁。
3.switch-case方式的代码会被编译器编译成一系列地比较、跳转指令,这些指令会造成比较大的CPU运算资源花销。表驱动状态机方式仅需要通过下标在函数表里索引找到对应的函数进行调用即可,几乎没有太多地系统资源浪费。因此,它更适合用在系统资源更弱的MCU上。
4.switch-case方式如果要进行维护(如:添加或删除状态)那必须在switch-case代码块中删除或添加相应的状态,以及到其它的状态处理的case代码里去删除或添加相应的状态迁移条件,这给修改代码带来了很大的麻烦,很容易让程序员淹没在茫茫的代码海洋里。表驱动状态机方式仅需要在状态机类型中添加一个新的状态,然后实现新的状态的处理函数,然后到相关的状态处理函数里修改迁移条件即可。由于各种迁移条件都被封装到状态处理函数里,在修改起来就很清晰,不会出现switch-case那样的问题。
3 表驱动状态机方法于MSP430单片机驱动DS18B20上的应用
3.1 DS18B20简介
DS18B20由美国DALLAS半导体公司的数字化温度传感器,它是世界上第一片支持“一线总线”接口的温度传感器,主要特性:
独特的“一线总线”接口,仅需一个端口引脚进行通讯
3.0V到5.5V宽电压工作
测温范围-55℃至+125℃,在-10℃到+85℃间误差为:±0.5℃。
温度可选以9位至12位数字量分辨率
温度数字量最长转换时间750毫秒
应用于包括温度控制、工业系统、消费品、温度计或任何热感测系统
3.2 对DS18B20温度转换过程建模
下载 (19.8 KB)
3 小时前
图表 1:DS18B20状态图
针对DS18B20的特性,结合实际系统应用将其工作状态如上图所划分:
开始状态:这个状态用于DS18B20上电后的复位,重新配置寄存器,进入就绪状态。等用户给一个开始转换指令。
开始温度转换状态:原本这只是一个很快的过程,只是MCU给DS18B20发一个开始转换指令而已,按理是应该作为一个事件看待,但是,为了让DS18B20连续地工作,保证循环工作地逻辑连接的持续性及语义的正确性。也把它独立成一个状态了,这让这整个状态机更加切实丰满。
转换中状态:这个是此设计的闪光点,一般来说DS18B20在接到开始温度转换指令之后,它就开始温度转换。这个过程它是阻塞式的,也就是说在它完成转换之前,对它的任何操作都是没有意义的。在此状态中,利用定时器中断中计数,以达到等待其相应延时的目的。转换结束后自动进入读取温度值状态。相当于在中断服务中以状态机的方式开启了一个智能的“进程”,由它自动地去启动、等待和读取DS18B20。解放了MCU,更合理地分配MCU资源。
读取温度值状态:把传感器转换完成的温度值从传感器里面读回MCU中,再根据用户的指令,来确定是进入开始温度转换状态还是结束状态。
结束状态:DS18B20停止工作。
3.3 DS18B20驱动库3.3.1
DS18B20驱动库结构DS18B20的单总线接口,需要在IO上加一个1千欧姆的上拉电阻。利用定时器中断提供的“死循环”,为驱动状态机提供服务。在状态机的各个状态中,运用到了单总线接口协议去操作DS18B20按要求完成其温度转换的功能。在用户接口上,采用类似“消息”的机制去传递完成转换后的温度值。由于没有实时操作系统的支持,因此,只能让用户去查询消息标志。另外,向用户开发了控制状态机启停的两个控制标志,以方便用户更加灵活地使用DS18B20。
下载 (27 KB)
3 小时前
图表 2DS18B20驱动库结构图
3.3.2 DS18B20驱动库的核心及接口
3.3.2.1 DS18B20状态实现
DS18B20具体三个核心的状态,用一个枚举类型表示,如下:
/*
DS18B20操作时序状态机
START,DELAY和READDATA分别对应开始温度转换,转换中和读取温度值状态。
*/
typedef enum {
START = 0,
DELAY,
READDATA,
}tmpsensorFSM;
//定义状态机及初始化状态机
tmpsensorFSMDS18B20FSM = START;
/*
DS18B20启动温度转换
*/
voidDS18B20START(void){
PowerOnDs18b20();//复位DS18B20
WriteDS18B20(0xcc);//跳过ROM指令
WriteDS18B20(0x44);//开始转换
}
//等待计数器
unsigned intWaitDS18B20Times = 0;
//最长等待时间
#defineMICROMINITE750 7
/*
DS18B20转换中状态
*/
voidDS18B20Delay(void){
if (WaitDS18B20Times < MICROMINITE750)
{
WaitDS18B20Times++;//步进计数
DS18B20FSM--;//把状态机拉回来
}
else
{
WaitDS18B20Times = 0;
}
}
/*
DS18B20读取温度
*/
voidDS18B20ReadData(void){
unsigned char H = 0;
unsigned char L = 0;
PowerOnDs18b20();//复位DS18B20
WriteDS18B20(0xCC); //跳过ROM指令
WriteDS18B20(0xBE); //读数据
L = ReadDS18B20();
H = ReadDS18B20();
TmpCTLState.TmpDecimalH = DecimalH[L &0x0f];//处理数据
TmpCTLState.TmpDecimalL = DecimalL[L &0x0f];
TmpCTLState.TmpInteger = ((H << 4) | (L>> 4));
TmpCTLState.Begin = 0;
TmpCTLState.DataReady = 1;
}
//建立状态表:
void (*P[])(void) ={DS18B20START, DS18B20Delay, DS18B20ReadData};
3.3.2.2驱动库接口
按常理,应该对用户有所隐藏,把必要的控制变量用函数进行封装起来。但为了不占用更多的MCU本就有限的处理器资源,因此,不过多地进行封装,直接向用户开放控制接口所用到的控制结构。
/*
TmpCTLState传感器控制结构
*/
typedef struct {
//最近一次转换完成的温度值
unsigned char TmpInteger;
unsigned char TmpDecimalH;
unsigned char TmpDecimalL;
unsigned char Stop;//stop:停止转换,值为1停止,反之为0。
unsigned char Begin;// begin:开始转换
unsigned char DataReady; //缓冲区中数据状态,数据准备好值为1,反之为0
}CTLstate;
CTLstateTmpCTLState = {0};
3.3.2.3库的使用示例
#pragma vector =TIMERA0_VECTOR__interrupt voidTIMER0ISR(void){
//模糊定时器中断
//如果传感器结构被启动
if (TmpCTLState.Stop == 0)
{
//若上次数据没有处理
if (TmpCTLState.DataReady == 1)
{
return;
}
//若没有开始
if (TmpCTLState.Begin == 0)
{
DS18B20FSM = START;
TmpCTLState.Begin = 1;
}
//运行状态机(表驱动方式)
(*P[DS18B20FSM++])();
}
}
int main()
{
...//其它代码
//启动传感器控制状态机
TmpCTLState.Stop= 0;
if(TmpCTLState.DataReady == 1)
{
//操作温度
DrawTemperatrue(TmpCTLState.TmpInteger);
//更新温度控制状态机
TmpCTLState.DataReady = 0;
}
//关闭温度控制状态机
TmpCTLState.Stop= 1;
...//其它代码
return 0;
}
4 结束语
这套库引入了状态机设计思想,解决了传统方法在驱动DS18B20时必须花费高昂代价的问题,扩展了DS18B20的应用范围。但它也有不足的地方,比如,要占用一个时钟中断,由于要在中断中处理各种状态,会造成定时中断的不确定,因此,它不能用于一个精确定时的时钟。就于目前所有的驱动DS18B20的方式来说,这个库不论是从用户接口,资源占用还是可移植性都算上乘。本文也表达了这样的一种思想:在MCU资源越来越充足的今天,如果能很好地利用高层次软件开发的思想改进传统MCU底层的软件开发,将能获得更好的系统性能,更低的系统维护代价以及更优雅的代码和设计。
参考文献:
[1] 发表者:吴军,Google 研究员
数学之美 系列十
有限状态机和地址识别
http://www.googlechinablog.com/2006/07/blog-post.html
2006年7月5日上午 09:09:00
[2] http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf
[作者简介]lbing7,四川托普信息技术职业学院实训中心实验室管理员。