打印

关于将状态机应用于嵌入式软件设计的问题

[复制链接]
2807|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hotpower|  楼主 | 2007-1-18 01:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在南方老树的网站里看到了一些关于将状态机应用于嵌入式软件设计的问题的转帖
也想谈些应用问题,自己也发表过I2C/TWI/USI实现状态机控制的实战例程:
I2C(TWI/SMBUS)LPC213X主机通讯例程
TWI一主多从实战程序片段

状态机在EDA中设计很普遍,有些甚至离不开它.
虽然在MCU设计中应用也很广,但有时即使可以也不得不放弃,这主要和MCU的众多因素有关.
不可否认,有时事例用状态机设计很简单,而且思路很清晰.
例如xf.zhu的状态机键盘扫描程序

但是在小容量程序空间的MCU中,可能菜农的"零耗时键盘"更能节省空间.
例如零耗时键盘各种事件及消抖处理模板裸奔程序详解

以菜农的倒塌思想去理解"状态机":
状态机就是我们预先编排的程序序列,我们设计的是如何诱导程序正常地进入此序列.
当程序不遵从序列(状态)时,将会引发错误的出现.
当程序遵从序列(状态)时,程序将根据此时的状态来安排下一步的状态(序列).

现在摘录菜农从未发表过的USI从机实战程序片段举例.

void UsiObj::Start(void)
{
  set_sleep_mode(SLEEP_MODE_IDLE);
  Status = 0;//状态初始化
  USICR = (1 << USISIE) | (1 << USIOIE) | (1 << USIWM1) |(1 << USIWM0) |(1 << USICS1);// |(1 << USICS0);
  USISR = 0xf0; //清除USISIF,USIOIF,USIPF,USIDC标志和设置计数器16次即接收1个字节8位(SCL上升及下降沿都计数)
  DDRB &= ~(1 << SCL); //SCL设置为输入方式,SCL信号由主机提供
  DDRB &= ~(1 << SDA); //SDA设置为输入方式
  Count = 0;//数组指针计数器归零
}
因为在从机收到Start硬件信号后会产生中断,从机运行Usi.Start()函数.
进行状态机的初始化,即Status = 0;程序被逼迫下次中断进行芯片读写地址分析.
下次中断时运行:
void UsiObj::Exec(void)
{
unsigned char tmp;
  Count &= 0x03;//防止数组溢出
/*-------------------------------------------------------------------
优化示例:
  DDRB &= ~((1 << SCL) | (1 << SDA)); //SCL设置为输入方式,SCL信号由主机提供
上句将比下两句代码多编译2个字节
  DDRB &= ~(1 << SCL); //SCL设置为输入方式,SCL信号由主机提供
  DDRB &= ~(1 << SDA); //SDA设置为输入方式
--------------------------------------------------------------------*/
  DDRB &= ~(1 << SCL); //SCL设置为输入方式,SCL信号由主机提供
  DDRB &= ~(1 << SDA); //SDA设置为输入方式
/*-------------------------------------------------------------------
优化示例:
  while (PINB & (1 << SCL));//等待SCL=0主机处理结束
上句将比下句代码多编译16个字节
  while ((unsigned char)tmp = (PINB & (1 << SCL)));//等待SCL=0主机处理结束
--------------------------------------------------------------------*/
  while ((tmp = (PINB & (1 << SCL))) != 0);//等待SCL=0主机处理结束
  PORTB &= ~(1 << SCL);//保持低电平
  DDRB |= (1 << SCL);//占用SCL总线,以便长期处理
  switch(Status) {
    case 0: //状态TW_START,从机地址判别
        Address = USIDR;//取本机滚动地址0b0000000R/W~0b1111111R/W
        Status = ((Address & 0x01) + 1);//Status下次主发为1W,主收为2R
        Count = 0;//数组指针计数器归零
        SendAck();
        break;
    case 1: //状态TW_MT_SLA_ACK,主发从收模式
        Status = 3;//下次进入接收命令状态
        USISR = 0x00; //准备接收8位命令
        break;
    case 2: //状态TW_MR_SLA_ACK或TW_MR_DATA_ACK,主收从发模式
        Status = 4;
          USIDR = TxBuffer[Count++] ^ Address;//发送并加密8位数据1个字节
        USISR = 0x00; //继续发送8位数据
        DDRB |= (1 << SDA);//从机SDA需要输出数据,故设置为输出方式
        break;
    case 3: //状态主发从收模式(接收数据状态)
//....
因为I2C中断是有序的,即模块的状态是"有序"的,也可认为这是硬件状态机.
那么在软件状态机Status=0时,就必定要对应硬件状态TW_START.否则出错处理进入休眠;
在从机收到从机地址后,若地址的最低为D0=0(W)时,在发送ACK后下次进入主发从收模式Status=0+1=1
在从机收到从机地址后,若地址的最低为D0=1(R)时,在发送ACK后下次进入主收从发模式Status=1+1=2

依此类推,从机的接收程序被诱导入了我们实现安排好的圈套~~~
从状态图来看,它很像二叉树,故"搜索"即诱导程序序列很快,而且条理很清.

当然菜农恶搞的关于USI接口密文传送增加I2C模块拦截难度的问题就只能点到为止了~~~
否则菜农的菜碗就保不住了~~~

相关帖子

沙发
dengm| | 2007-1-18 09:47 | 只看该作者

MCU 的资源有限, 用状态机可使系统使用资源(时间也是资源

更稳定、资源利用率会更高。mcu 软件应提倡使用“状态机”、“子状态机”
的软件结构。

使用特权

评论回复
板凳
lucidmask| | 2007-1-18 09:59 | 只看该作者

请问菜农;

在AVR这块地上种C++这种菜,收程可好?

使用特权

评论回复
地板
forthlab| | 2007-1-18 12:11 | 只看该作者

我现在都是用状态机编程

我现在都是用状态机编程,包括HT48,NEC,51的。
优点很多,程序结构简洁,修改升级方便,可以实现多任务。

使用特权

评论回复
5
gtw| | 2007-1-18 12:39 | 只看该作者

便于管理

使用特权

评论回复
6
wolfererer| | 2007-1-20 11:53 | 只看该作者

怪事年年有,好文没人顶?

使用特权

评论回复
7
hotpower|  楼主 | 2007-1-20 11:58 | 只看该作者

倒塌了~~~楼主的萝卜白菜上不了席面,最多是洛阳的水席~~~

使用特权

评论回复
8
fsaok| | 2007-1-21 16:29 | 只看该作者

状态机

理论上,所有的程序都可以看成状态机的应用,不过是显式或者隐式而已。

我写程序从来不刻意用状态机方式,甚至几乎不用状态机,在51,pic等菜地里种菜,照样有收成

使用特权

评论回复
9
wolfererer| | 2007-1-21 16:45 | 只看该作者

萝卜白菜来清蒸,清爽口味才是真

使用特权

评论回复
10
forthlab| | 2007-1-23 10:29 | 只看该作者

有人继续下去么?

hotpower 多谈谈状态机编程的经验

使用特权

评论回复
11
yewuyi| | 2007-1-23 11:27 | 只看该作者

俺严重同意 fsaok观点……

很多时候在MCU编程上,使用隐式状态解析更重要

使用特权

评论回复
12
forthlab| | 2007-1-23 11:39 | 只看该作者

隐式状态解析是怎么回事?

使用特权

评论回复
13
gsnet| | 2007-1-27 16:17 | 只看该作者

好文收藏

使用特权

评论回复
14
happystar| | 2007-1-27 18:02 | 只看该作者

今天才理解了状态机概念

细想一下:自己以前写过的程序,都可以套上状态机这个概念,只是没有可以刻意往这方面想。
好贴,顶一下。那几个连接很好啊

使用特权

评论回复
15
hotpower|  楼主 | 2007-1-28 01:53 | 只看该作者

再给个状态机解码的例程

正如楼上所说的,实际上我们很多程序本来就是以状态机的概念编程的,
只是自己没留意罢了~~~
相关链接:http://www.**/blog/hotpower/15218/message.aspx

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1460

主题

21619

帖子

506

粉丝