hotpower 发表于 2007-1-18 01:13:26

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

最近在南方老树的网站里看到了一些关于将状态机应用于嵌入式软件设计的问题的转帖

也想谈些应用问题,自己也发表过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 ^ 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模块拦截难度的问题就只能点到为止了~~~

否则菜农的菜碗就保不住了~~~

chengjia535 发表于 2007-12-23 16:52:18

这个帖子竟然没人顶。

yc21 发表于 2007-12-23 17:33:54

倒塌了!
这么好的帖子竞没人顶?
帮顶!!

minier 发表于 2007-12-23 22:15:53

.

jevenhuang 发表于 2007-12-23 22:40:37

学习学习 谢谢

zhonghua_li 发表于 2007-12-24 01:38:35

哈哈,我就是这么裸奔的。

shjw 发表于 2008-1-31 12:27:02

谢谢,才发现,顶啊

jjcool 发表于 2008-1-31 13:12:16

顶,纯路过

eagle1979 发表于 2008-2-1 09:33:44

学习了

jaff 发表于 2008-2-1 12:02:45

这段时间21ic上状态机是个热门

igoal 发表于 2008-2-1 12:43:59

最近在搞IAR的visualSTATE,感觉开发挺方便的,就是不知道这个东西编出的程序效率怎么样。

y2kloach 发表于 2008-2-1 17:08:06

这个做法不错,支持!!

abcdezh 发表于 2008-2-1 17:14:49

谢谢
正在学习

elefan 发表于 2008-2-1 20:18:58

在无操作系统的情况下,是偶喜欢的编程方式,呵呵!俺住西安碑林区,呵呵!菜农在西安哪块?

xyq4513 发表于 2009-4-18 11:18:40

谢谢
正在学习

Adrian 发表于 2009-4-19 22:13:39

不顶不行

cgbabc 发表于 2009-8-14 18:07:41

要顶呀

DeKaron 发表于 2009-8-14 19:50:51

xgame 发表于 2009-8-14 20:19:45

嗯 个人风格不同

Bird 发表于 2009-8-15 21:14:35

顶一个!!

D.lovers 发表于 2009-8-15 21:45:04

顶!好东西!
按键处理,都是用状态机做的!

eduhf_123 发表于 2009-8-16 02:03:20

MARK 状态机

bijibenbenq 发表于 2009-8-28 22:37:41

学习IAR的visualSTATE

haizaolan 发表于 2009-8-29 01:23:41

学习!

xuehui869 发表于 2009-8-29 01:47:27

人工智能之父-----图灵想出来的 ,当然经典

liangbmw 发表于 2009-8-29 08:54:08

mark

bjj9217 发表于 2009-8-29 11:32:30

学习学习@!

xrwf_2009 发表于 2009-9-3 13:14:56

这里让我了结 状态机。

qzzz 发表于 2009-9-3 21:16:26

支持,帮顶

huasoft 发表于 2009-9-9 19:46:42

状态机是好东西.

强贴留名,呵呵

yuner 发表于 2009-11-19 22:43:31

ding

pengliang983 发表于 2009-11-19 22:51:18

学习。

jiangping_hbhm 发表于 2010-1-14 23:59:25

mark

D.lovers 发表于 2010-1-15 21:52:11

学习,

minier 发表于 2010-1-15 22:27:44

I2C从机只能采用状态机

sunmy 发表于 2010-1-22 09:14:03

看看!

zhames 发表于 2010-1-22 11:44:51

mark

chenloveyj 发表于 2010-1-22 17:28:34

留下脚印。。

wjy6264 发表于 2010-1-23 17:03:28

mark!

jiangping_hbhm 发表于 2010-2-7 23:33:13

MARK

sunmy 发表于 2010-2-8 08:31:21

ding!

bluelool 发表于 2010-3-2 18:47:50

mark

dujun168 发表于 2011-3-12 06:11:32

mark

luweixuan 发表于 2011-3-12 08:01:53

mark状态机

yywin 发表于 2011-3-12 08:25:26

学习

sanshui28 发表于 2011-3-14 14:38:59

mark

ieee911 发表于 2011-3-14 20:38:03

ding!ding!

newkey 发表于 2011-8-25 15:04:39

mark

wjf0509 发表于 2011-8-26 11:12:55

俺也用

wangqi509 发表于 2011-10-31 14:11:11

学习一下!

CHENXIAOTIAN 发表于 2011-10-31 23:13:06

mark 零耗时键盘 状态机

guiqiaoluo100 发表于 2011-11-1 16:21:47

mark

rubylee 发表于 2011-11-2 12:43:18

雁塔菜农 M0

xiaowenshao 发表于 2011-12-16 15:06:39

顶顶~~~

eleven_sue 发表于 2012-2-27 16:36:58

mark

gxy508 发表于 2012-2-28 11:46:13

mark

abcdzhy 发表于 2012-2-28 12:26:57

mark

henry 发表于 2012-2-28 12:50:28

这个一定要mark

vvooo2009 发表于 2012-2-28 13:11:23

回复【10楼】igoal
最近在搞iar的visualstate,感觉开发挺方便的,就是不知道这个东西编出的程序效率怎么样。
-----------------------------------------------------------------------

我在学习过程中遇到很多问题,但不知道怎样解决。

xlqiang 发表于 2014-9-2 11:26:45

下面是在网上搜到的一个针对状态机的简要总结:
“有限状态机系统优点:简单易用,状态间关系直观看到,便于编程;可以快速执行;只是通过改变输出功能来改变机器的响应。缺点:任何时刻系统只能有一个状态,无法表示并发性,不能描述异步并发系统;在系统部件多时,状态数随之增加,导致复杂性显著增长;对于大的应用系统,难于调试。 ”

感觉说的不够清楚,楼主能不能总结一下嵌入式中应用状态机的优缺点啊?

second_chan 发表于 2014-9-3 15:04:50

学习学习

lyl2022 发表于 2014-9-9 10:14:05

深入浅出啊,讲的太好了--MARK!!!硬件状态机

weiming4033 发表于 2014-9-9 10:29:23

状态机为什么这么火。。

机器人天空 发表于 2014-9-9 13:42:50

学习一下

bigwei 发表于 2016-7-13 18:55:41

学习学习
页: [1]
查看完整版本: 关于将状态机应用于嵌入式软件设计的问题