层次状态机(HSM)用c语言的实现

层次状态机(HSM)用c语言的实现
层次状态机(HSM)用c语言的实现

分类:

本文讲述层次状态机实现形式中的行为继承。从行为继承与类继承之间的OO类相似来看,一个成功的层次状态机应该能够模拟下列属于C++对象模型。

?使用和维护简单

?应允许转态机拓扑容易改变,不应要求转换连接的人工代码,所需要的修

改限制在代码的一个地方。

?提供好的运行-时间效率和小的存储。

?遵守C++中的“零额外开销”原则。

为了满足上面的要求,层次状态机的实现着重于下面的主要元素:

?完全支持行为继承的层次关系

?用状态进入和退出动作实现有保证得初始化和清除

?通过类继承支持规定的状态模型

1.基本要素

(1)状态:在层次状态的情形下,状态处理器必须返回朝状态,这导致层次

状态处理特征标记的递归定义。构造这种特征标记在C++是不可能的,

于是定义下面宏来近似:

typedef void (* QPseudoState)(QEVENT const *pEvent);

typedef QPseudoState (* QState)(QEVENT const *pEvent);

(2)进入/退出动作和初始状态:这些元素是状态专有的特征,在转态中他

们被定义,而特别的是与到达状态所进过的路径无关。保留信号的转态

定义为:

typedef enum tagQSIG

{

Q_EMPTY_SIG = 1,

Q_INIT_SIG,

Q_ENTRY_SIG,

Q_EXIT_SIG,

Q_USER_SIG,

} QSIG;

状态处理机可以用一般的switch语句规定适当的用例处理这些信号,

可以自由的执行相应信号的操作。

(3)状态转换:状态处理机用Q_TRAN实现状态转换,并且在原状态的上

下文中执行动作,即:改变状态之前调用Q_TRAN(和UML规定不一致)。

#define Q_TRAN(target_) Q_TranDyc((QState)(target_))

(4)Top状态和初始伪状态:每个层次状态机都有一个Top状态,包括整

个状态的所有其它元素。Top状态没有超状态,用户也不能覆盖;Top

状态的唯一目的是提供状态层次的最高的根,使最高处理器能返回Top;

Top状态唯一能订制的是初始化。初始化伪状态处理机仅规定初始化转

换,必须指明被窃套的Top状态的状态机的缺省状态。

2.实现代码:

(1)头文件代码:

#ifndef STATE_INHERIT_H

#define STATE_INHERIT_H

typedef unsigned short QSIG;

// Define the signal of state machine

enum

{

Q_EMPTY_SIG = 0,

Q_INIT_SIG = 1,

Q_ENTRY_SIG,

Q_EXIT_SIG,

Q_USER_SIG

};

// Define the signal of state machine

typedef struct tagQEVENT

{

QSIG sig;

unsigned char *pEvent1;

unsigned char *pEvent2;

// TODO: add fields to the event

} QEVENT;

// define state data type

typedef void (* QPseudoState)(QEVENT const *pEvent); typedef QPseudoState (* QState)(QEVENT const *pEvent); typedef QPseudoState QSTATE;

#define Q_TRIGGER(state, sig) \

(QState)(*(state))((QEVENT*)&pkgStdEvt[sig])

// define a transation that don't change the state,

// just treat the pEvent with the target state.

// this is used by concurrent state

#define Q_INIT(target_) Init_((QState)(target_));

#define Q_TRAN(target_) Q_TranDyc((QState)(target_));

void Init_(QState target);

void Q_Init(QSTATE target);

void Q_Initial(QEVENT const* pQevt);

void Q_Dispatch(QEVENT const* pQevt);

void Q_TranDyc(QState target);

#endif//STATE_INHERIT_H

(2)实体代码:

#include

#include

#include "state_inherit.h"

static QStatesrcState; // source state static QStateactState; // active state static QEVENT const pkgStdEvt[] =

{

{Q_EMPTY_SIG, 0, 0},

{Q_INIT_SIG, 0, 0},

{Q_ENTRY_SIG, 0, 0},

{Q_EXIT_SIG, 0, 0}

};

void Q_Initial(QEVENT const* pQevt)

{

printf("Top_Init;");

}

void Q_Dispatch(QEVENT const* pQevt)

{

for (srcState = actState; srcState;

srcState = (QState)(*srcState)(pQevt)) {}

}

void Init_(QState target)

{

actState = target;

}

void Q_Init(QSTATE target)

{

register QState s;

actState = (QState)target;

srcState = (QState)Q_Initial;

s = actState; // save actState in a temporary

(*(QPseudoState)srcState)((QEVENT*)0); // top-most initial tran.

// initial transition must go one level deep

s = actState; // update the temporary

Q_TRIGGER(s, Q_ENTRY_SIG); // enter the state while (0 == Q_TRIGGER(s, Q_INIT_SIG))

{

// init handled

// initial transition must go one level deep

s = actState;

Q_TRIGGER(s, Q_ENTRY_SIG); // enter the substate

}

}

void Q_TranDyc(QState target)

{

QStateentry[8], p, q, s, *e, *lca;

for (s = actState; s != srcState; )

{

QState t;

t = Q_TRIGGER(s, Q_EXIT_SIG);

if (t)

{

// exit action unhandled, t points to superstate

s = t;

}

else

{

// exit action handled, elicit superstate

s = Q_TRIGGER(s, Q_EMPTY_SIG);

}

}

*(e = &entry[0]) = 0;

*(++e) = target; // assume entry to target

// (a) check source == target (transition to self)

if (srcState == target)

{

Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source goto inLCA;

}

// (b) check source == target->super

p = Q_TRIGGER(target, Q_EMPTY_SIG);

if (srcState == p) goto inLCA;

//(c) check source->super == target->super (most common)

q = Q_TRIGGER(srcState, Q_EMPTY_SIG);

if (q == p)

{

Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source goto inLCA;

}

// (d) check source->super == target

if (q == target)

{

Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source

--e; // not enter the LCA goto inLCA;

}

// (e) check rest of source == target->super->super... hierarchy

*(++e) = p;

for (s = Q_TRIGGER(p, Q_EMPTY_SIG); s; s = Q_TRIGGER(s, Q_EMPTY_SIG)) {

if (srcState == s)

{

goto inLCA;

}

*(++e) = s;

}

Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source // (f) check rest of source->super == target->super->super...

for (lca = e; *lca; --lca)

{

if (q == *lca)

{

e = lca - 1; // do not enter the LCA

goto inLCA;

}

}

// (g) check each srcState->super->super..for each target...

for (s = q; s; s = Q_TRIGGER(s, Q_EMPTY_SIG))

{

for (lca = e; *lca; --lca)

{

if (s == *lca)

{

e = lca - 1; // do not enter the LCA

goto inLCA;

}

}

Q_TRIGGER(s, Q_EXIT_SIG); // exit s

}

assert(0); // malformed HSM

inLCA: // now we are in the LCA of srcState and target

assert(e <&entry[sizeof(entry) / sizeof(*entry)]); // entry fits while (s = *e--)

{

// retrace the entry path in reverse order

Q_TRIGGER(s, Q_ENTRY_SIG); // enter s

}

actState = target; // update current state while (0 == Q_TRIGGER(target, Q_INIT_SIG))

{

// initial transition must go one level deep

assert(target == Q_TRIGGER(actState, Q_EMPTY_SIG));

target = actState;

Q_TRIGGER(target, Q_ENTRY_SIG); // enter target }

3.范例:

(1)范例状态图

(2)范例代码

#include

#include "state_inherit.h"

QSTATE s0(QEVENT const *e);

QSTATE s1(QEVENT const *e);

QSTATE s2(QEVENT const *e);

QSTATE s11(QEVENT const *e);

QSTATE s21(QEVENT const *e);

QSTATE s211(QEVENT const *e);

QSTATE Q_Top(QEVENT const *e);

static void Initial(QEVENT const *e);

static bool bFoo;

enum QSignals {

A_SIG = Q_USER_SIG,

B_SIG, C_SIG, D_SIG, E_SIG, F_SIG, G_SIG, H_SIG

};

static const QEVENT testQEvt[] =

{

{A_SIG, 0, 0}, {B_SIG, 0, 0}, {C_SIG, 0, 0}, {D_SIG, 0, 0}, {E_SIG, 0, 0}, {F_SIG, 0, 0}, {G_SIG, 0, 0}, {H_SIG, 0, 0} };

int main()

{

printf("Hiberarchy state machine testing\n");

Initial(0); // trigger initial transition for (;;)

{

char c;

printf("\nSignal<-");

c = getc(stdin);

getc(stdin); // discard '\n'

if (c < 'a' || 'h' < c) {

return 0;

}

Q_Dispatch(&testQEvt[c - 'a']); // dispatch

}

return 0;

}

static QSTATE Q_Top(QEVENT const *e)

{

return 0;

}

void Initial(QEVENT const *e)

{

bFoo = false;

Q_Init((QSTATE)s0);

}

QSTATE s0(QEVENT const *e) {

if (e != NULL)

{

switch (e->sig)

{

case Q_ENTRY_SIG: printf("s0-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s0-EXIT;"); return 0;

case Q_INIT_SIG: printf("s0-INIT;"); Q_INIT(s1); return 0;

case E_SIG: printf("s0-E;"); Q_TRAN(s211); return 0; }

}

return (QSTATE)Q_Top;

}

QSTATE s1(QEVENT const *e) {

switch (e->sig) {

case Q_ENTRY_SIG: printf("s1-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s1-EXIT;"); return 0;

case Q_INIT_SIG: printf("s1-INIT;");Q_INIT(s11); return 0;

case A_SIG: printf("s1-A;"); Q_TRAN(s1); return 0;

case B_SIG: printf("s1-B;"); Q_TRAN(s11); return 0;

case C_SIG: printf("s1-C;"); Q_TRAN(s2); return 0;

case D_SIG: printf("s1-D;"); Q_TRAN(s0); return 0;

case F_SIG: printf("s1-F;"); Q_TRAN(s211);return 0;

}

return (QSTATE)s0;

}

QSTATE s11(QEVENT const *e) {

switch (e->sig) {

case Q_ENTRY_SIG: printf("s11-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s11-EXIT;"); return 0;

case G_SIG: printf("s11-G;"); Q_TRAN(s211); return 0;

case H_SIG: // internal transition with a guard if (bFoo)

{ // test the guard condition

printf("s11-H;");

bFoo = false;

return 0;

}

break;

}

return (QSTATE)s1;

}

QSTATE s2( QEVENT const *e) {

switch (e->sig) {

case Q_ENTRY_SIG: printf("s2-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s2-EXIT;"); return 0;

case Q_INIT_SIG: printf("s2-INIT;");Q_INIT(s21); return 0;

case C_SIG: printf("s2-C;"); Q_TRAN(s1); return 0;

case F_SIG: printf("s2-F;"); Q_TRAN(s11); return 0;

}

return (QSTATE)s0;

}

QSTATE s21(QEVENT const *e) {

switch (e->sig) {

case Q_ENTRY_SIG: printf("s21-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s21-EXIT;"); return 0;

case Q_INIT_SIG:printf("s21-INIT;");Q_INIT(s211);return 0;

case B_SIG: printf("s21-C;"); Q_TRAN(s211);return 0;

case H_SIG: // self transition with a guard if (!bFoo)

{ // test the guard condition

printf("s21-H;");

bFoo = true;

Q_TRAN(s21); // self transition

return 0;

}

break; //break to return the superstate }

return (QSTATE)s2;

}

QSTATE s211(QEVENT const *e) {

switch (e->sig) {

case Q_ENTRY_SIG: printf("s211-ENTRY;"); return 0;

case Q_EXIT_SIG: printf("s211-EXIT;"); return 0;

case D_SIG: printf("s211-D;"); Q_TRAN(s21); return 0;

case G_SIG: printf("s211-G;"); Q_TRAN(s0); return 0;

}

return (QSTATE)s21;

}

(3)输出结果:

Hiberarchy state machine testing

Top_Init;s0-ENTRY;s0-INIT;s1-ENTRY;s1-INIT;s11-ENTRY;

Signal<-a

s1-A;s11-EXIT;s1-EXIT;s1-ENTRY;s1-INIT;s11-ENTRY;

Signal<-e

s0-E;s11-EXIT;s1-EXIT;s2-ENTRY;s21-ENTRY;s211-ENTRY;

Signal<-e

s0-E;s211-EXIT;s21-EXIT;s2-EXIT;s2-ENTRY;s21-ENTRY;s211-ENTRY; Signal<-a

Signal<-h

s21-H;s211-EXIT;s21-EXIT;s21-ENTRY;s21-INIT;s211-ENTRY;

Signal<-h

Signal<-x

说明:上面功能都是通过C语言实现的,大家可以将其用C++实现,共享一下。

状态机讲义

Digital System Design 大部分数字系统都可以划分为控制单元和数据单元(存储单元)两个组成部分,通常,控制单元的主体是一个状态机,它接收外部信号以及数据单元产生的状态信息,产生控制信号序列。 1 2011/6/21Computer Faculty of Guangdong University of Technology

Digital System Design 有限状态机特别适合描述那些发生有先后顺序或者有逻辑规律的事情(其实这就是状态机的本质)。状态机的本质就是对具有逻辑顺序或时序规律事件的一种描述方法,即“逻辑顺序”和“时序规律”就是状态机所要描述的核心和强项,换言之,所有具有逻辑顺序和时序规律的事情都适合用状态机来描述。 2 2011/6/21Computer Faculty of Guangdong University of Technology

Digital System Design 1、基本概念 有限状态机(Finite State Machine,FSM)是表示实现有限个离散状态及其状态之间的转移等行为动作的数学模型。(关注Matlab的Stateflow) (1)状态:也叫状态变量。在逻辑设计中,使用状态划分逻辑顺序和时序规律。 状态名称、状态编码、进入/退出操作、内部转移、子状态、延迟事件 3 2011/6/21Computer Faculty of Guangdong University of Technology

Digital System Design (2)转移:指两个状态之间的关系,表示当发生指定事件且满足指定条件时,第一个状态中的对象将执行某些操作并进入第二个状态,即“触发”了转移。将触发转移之前的状态定义为“源”状态(初始状态),而触发转移之后的状态定义为“目标”状态(次态)。 初始状态、转移条件、警戒条件、转移操作、目标状态 4 2011/6/21Computer Faculty of Guangdong University of Technology

状态机设计

集成电路实验 状态机设计实验报告 专业:电子信息工程 姓名:江燕婷 学号:2011301200025

状态机设计(实验五)实验报告 一.实验目的 1. 掌握状态机设计的基本方法 2.学习利用状态机的方法实现控制电路 二.实验原理 有限状态机(Finite State Machine FSM)是时序电路设计中经常采用的一种方式,尤其适合设计数字系统的控制模块,在一些需要控制高速器件的场合,用状态机进行设计是一种很好的解决问题的方案,具有速度快、结构简单、可靠性高等优点。有限状态机非常适合用FPGA器件实现,用Verilog HDL的case 语句能很好地描述基于状态机的设计,再通过EDA工具软件的综合,一般可以生成性能极优的状态机电路,从而使其在执行时间、运行速度和占用资源等方面优于用CPU实现的方案。 有限状态机一般包括组合逻辑和寄存器逻辑两部分,寄存器逻辑用于存储状态,组合逻辑用于状态译码和产生输出信号。根据输出信号产生方法的不同,状态机可分为两类:米里型(Mealy)和摩尔型(Moore)。摩尔型状态机的输出只是当前状态的函数,如图1-1所示;米里型状态机的输出则是当前状态和当前输入的函数,如图1-2所示。米里型状态机的输出是在输入变化后立即变化的,不依赖时钟信号的同步,摩尔型状态机的输入发生变化时还需要等待时钟的到来,必须在状态发生变化时才会导致输出的变化,因此比米里型状态机要多等待一个时钟周期。 图1-1 摩尔型状态机图1-2 米里型状态机 状态机在硬件描述语言实现上,可使用单过程、双过程或三过程等不同的结构实现。状态机的状态实现上,可采用符号编码或显式数字编码。编码方式有顺序编码(自然二进制编码),一位热码(one-hot encoding),格雷(gray code)码等。顺序编码,简单状态寄存器占用少;一位热码输出译码电路简单;在状态顺序变化时,格雷码每次只有一位变化,避免产生输出信号毛刺。

空调系统有限状态机的设计

空调系统有限状态机的设计 摘要:空调系统状态机自动控制是以可编程逻辑为核心,配以各种传感器,电机驱动,状态机,变频器等实现自动控制,能确保空调末端温度供给,降低系统运行费用和时间,从而节约资源,它必将日趋成熟,在人类的生活中大显身手。一直以来,环保问题时世界关注的焦点,各种替代能源动力车的出现,为空调业提出来新的课题与挑战。现代家用也得发展成为人们生活的追求,空调已成为人们的必备品。 关键字:FPGA,空调系统状态机,自动控制。

一、设计分析: 1.课程设计目的: 本课程设计的目的是在掌握EDA实验开发的初步使用基础上,了解EDA技术,对空调系统进一步了解,掌握其状态机的工作原理,掌握用Verilog实现状态机的方法。通过本课程的设计,更好的巩固加深基础知识的理解,独立完成仿真过程,增强理论联系实际,提高电路分析能力,为日后的学习奠定基础。 2.课程设计要求: 试设计一个空调系统状态机,它两个输入端A和B分别与传感器相连(用两位拨码开关模拟),用于检测室内温度。如果室内温度正常,则A和B均为0。如果室内温度过高,则A为“1”,B为“0”。如果室内温度过低,则A为“0”,B为“1”。根据A和B的值来判断当前的状态,如太热,则在液晶上显示TOO-HOT,并将输出端COOL 置为“1”,并显示,表明现在开始制冷;如太冷,则在液晶上显示TOO-COLD,并将输出端HEAT置为“1”,并显示,表明现在开始加热;如适中,则在液晶上显示JUST-RIGHT,COOL和HEAT都为“0”。 要求一: 由传感器检测室内温度,并将采集来的数据传输到控制系统的预处理单元,在预处理单元将采集来的温度信号与设定值相比较,来判断当前的状态 (太热、太冷或适中),然后将处理结果传输到控制单元,最后由执行机构接受控制单元输出的控制信号,控制

空调系统有限状态自动机的设计

1 引言 1.1课程设计的背景 空调的发明已经列入20世纪全球十大发明之一,它首次向世界证明了人类对环境温度、湿度、通风和空气品质的控制能力。19世紀,英国科学家及发明家麦克·法拉第(Michael Faraday),发现压缩及液化某种气体可以將空气冷冻,当时其意念仍流于理论化。二十世纪六七十年代美国为解决干旱缺水地区的冷热源问题而率先研制出风冷式冷水机,用空气散热代替冷却塔,其英文名为Air cool chiller, 简称Chiller。之后,设备设计和制造技术在90年代被转让到中国[1]。 随着人们生活水平的逐渐提高,空调产品也将由“生活奢侈品”逐渐转变为日常生活用品。在空调健康、节能功能以及外观设计上,国内企业也经过引进、消化、吸收,技术水平及产品质量都在不断趋于完善,我国已经发展成为世界空调产业重要的研发和生产基地。随着经济的发展,空调已成为必备的家用电器,对空调的设计更加重要。随着社会需求的变化,空调朝着节能、环保及智能化方向发展。 1.2课程设计的目的 本课程设计的目的是在掌握EDA实验开发系统的初步使用基础上,了解EDA技术,对空调系统进一步了解,掌握其有限状态自动机工作原理。通过本次课程设计更好地巩固和加深对基础知识的理解,学会设计中小型数字系统的方法,独立完成仿真过程,增强理论联系实际的能力,提高电路分析和理解能力。为日后的学习和工作奠定基础。 1.3课程设计的任务 本课程设计任务是通过设计空调系统有限状态自动机的基本方法学习硬件设计的基本思想和基本流程,采用Max+plus2等软件为开发工具。通过对计算机硬件和软件解决方案的论证,对应用领域进行调查分析,参考各种资料和进行硬件开发实践。在指导老师的帮助下,已经基本上成功地实现了设计任务书的要求。 1.4课程设计的内容 本课程设计主要完成基于VHDL的空调系统的设计与实现。本文运用有限状态自动机的方法,设计了状态机进程与信号控制进程相互配合。在状态机进程中定义了6个

相关文档
最新文档