APP下载

嵌入式框架QP_nano的51单片机移植与应用

2016-01-26张东杰王俊璞

单片机与嵌入式系统应用 2015年10期
关键词:状态机

张东杰,王俊璞

(上海交通大学 仪器科学与工程系,上海 200240)



嵌入式框架QP_nano的51单片机移植与应用

张东杰,王俊璞

(上海交通大学 仪器科学与工程系,上海 200240)

摘要:本文旨在为单片机开发引入一套轻量级软件框架QPnano。首先以简易数字时钟设计为例,展示了使用QPnano的开发过程,然后详述了QPnano到Keil C51的移植,通过使用QPnano,将一些经典的软件思想和技术,如面向对象、事件驱动、状态机等,很自然地引入到单片机的软件开发中。

关键词:QPnano;事件驱动;状态机;软件框架;MCU

引言

在计算机软件开发方面,面向对象设计、UML、测试驱动开发、基于框架开发等,是比较成熟的开发方式,但它们很少被引入到传统的单片机开发领域。究其原因,除了嵌入式芯片厂家众多、软件开发与硬件耦合度过高、硬件资源有限等因素外,缺少相关领域的研究和推广也是一个主要原因。传统的中低端单片机,如8051、PIC、AVR等,因其价格低廉、结构简单、已有大批用户使用等因素,在工业、消费类电子等领域,仍占有很大的市场份额,因此提高这些单片机的开发效率和软件质量,对提高产业效率和产品质量有重要意义。

相对于传统的单片机开发使用前后台系统和多任务系统,基于框架开发在代码重用、设计简易性等方面有很大优势。作为为数不多的嵌入式软件框架,QP_nano基于UML状态机和事件驱动[1],用C语言实现,具备轻量级、便于移植等优势,特别适合嵌入式应用。

本文首先通过使用QP_nano设计数字时钟的全过程,展示QP_nano的面向对象、状态设计等应用特征给设计带来的简易性,之后详述QP_nano移植到Keil C51平台需要做的配置、代码调整以及平台相关函数的实现。

1基于QP_nano设计简易数字时钟

1.1设计方案

设计一个简易数字时钟,实现时钟的运行和设置功能设计方案如下:

① 采用24小时制,用4个数码管分别显示小时和分钟。

② 使用SET(设置键)、UP(加键)和DOWN(减键),调整时钟。

③ 数字时钟上电的时候,进入时钟运行状态;从12:00开始计时,每隔1分钟,分钟数加1;分钟数计满60后,小时数加1,分钟数清零并重新开始计时;小时数计到24时,小时数清零并重新开始计时。

④ 在时钟运行状态,按SET,进入小时设置状态,小时显示开始闪烁。

⑤ 在小时设置状态,按SET,小时数确认并进入分钟设置状态,分钟显示开始闪烁。

⑥ 在分钟设置状态,按SET,分钟数确认,并进入时钟运行状态。

⑦ 在小时或分钟设置状态,按UP或DOWN,对应的小时或分钟加1或减1,小时变化范围是0~23,分钟变化范围是0~59。

1.2硬件设计

① 搭建一个51单片机的最小系统,具体方案请参照所选芯片的数据手册。

② 添加4个数码管及相应的驱动电路到系统,采用动态刷新方式,分配4个单片机I/O口连接到数码管片选,分配8个I/O口连接到数码管段码。

③ 添加3个按键及相应的电路到系统,分配单片机3个I/O口连接到按键输入。

1.3软件设计

使用QP_nano,最重要的是划分活动对象[1],不同的活动对象负责不同的处理功能。每个活动对象都是一个状态机[1],某一时刻只能处在一个状态。活动对象和活动对象之间通过事件[1]通信,活动对象可以发送或处理事件。处理事件包括改变状态、调用一些硬件驱动函数等。使用QP_nano开发单片机应用的过程一般包括划分活动对象、定义事件信号和编写活动的状态处理函数等。

1.3.1划分活动对象

根据系统功能分解出3个活动对象:Display、Counter和Keyboard。其中,Display负责刷新数码管显示,Counter负责时钟计时和设置,Keyboard负责扫描键盘。

在动态刷新方式下,Display每隔一个Tick(系统嘀嗒)都要刷新一次,而Counter仅需要一个慢速时钟驱动,且与Display有共享显示缓冲区的需求,为简化实现,将Counter活动嵌套到Display内部,构成层次嵌套关系。因此,定义Display和Keyboard两个活动即可,代码如下:

typedef struct Display {

QActive super;

uint32_t counter;

uint16_t refreshingCtr;

uint16_t countingCtr;

uint8_t buf[4];

} Display;

typedef struct Keyboard {

QActive super;

} Keyboard;

其中,super表示活动,Display和Keyboard扩展(继承)了活动,因此可以使用向下转型(down_cast)的方式,拥有活动的响应事件等功能;counter为时钟的秒计数变量;refreshingCtr对刷新次数进行计数,每隔250个计数周期给Display活动发送计数信号;countingCtr用于对计数信号进行统计,计满4个counter加1,表示时钟前进1 s;buf表示时钟显示的缓冲区。

1.3.2定义用户信号

用户信号用来标记事件的类型,即确定事件的含义。数字时钟共定义了4个信号,代码如下:

enum ClockSignals {

CLOCK_COUNT_SIG = Q_USER_SIG, //计数信号

CLOCK_SET_SIG, //设置信号

CLOCK_UP_SIG, //加信号

CLOCK_DOWN_SIG, //减信号

};

1.3.3活动顺序图

QP_nano活动之间的通信关系,用UML顺序图描述。数字时钟的顺序图如图1所示,QP_nano每隔一个Tick(配置为1 ms)发送一个TIME_OUT事件(系统保留)给Keyboard和Display;Keyboard每计满10个TIME_OUT,扫描一次键盘,连续两次发现有键按下就发送对应的键盘事件给Display;Display每收到一个TIME_OUT就刷新一次数码管,并同时对该事件计数,计满250个后给自身发送CLOCK_COUNT事件,并更新一次显示缓冲区,如果在计时状态,累加4次后,时钟变量加1 s;如果在设置状态,则切换消隐(清空显示缓冲区)和正常显示,实现闪烁功能(为简便起见,信号末尾未加_SIG,下同)。

图1 活动顺序图

1.3.4活动状态图

活动和活动之间的通信关系由活动顺序图展现,而活动内部的状态及运行情况则通过UML状态图描述。

图2 Keyboard状态图

活动Keyboard的状态图如图2所示,Scanning状态用于扫描键盘,Keyboard由初始状态转换到该状态后,一直运行于该状态。

图3 Display状态图

活动Display的状态图如图3所示,Refreshing状态用于刷新数码管,Counting状态用于时钟计数,Set_Hour状态用于调整小时,Set_Min状态用于调整分钟;Display从初始状态进入Refreshing状态,又继续进入Counting状态;在Counting状态、Set_Hour状态和Set_Min状态下,若收到TIME_OUT事件,则自动返回到Refreshing状态处理。

1.3.5编写活动的状态处理函数和硬件驱动函数

活动状态图中的每一个状态都对应一个状态处理函数处理事件,如Keyboard的Scanning状态响应TIME_OUT事件(计数满10个,调用键盘扫描函数),Display的Counting状态响应CLOCK_SET事件(转换到Set_Hour状态)。

硬件驱动函数用来初始化和控制外设,本测试中定义了bsp_init()、bsp_keyboard()和bsp_display()三个硬件相关函数。其中,bsp_init()用于初始化芯片时钟、键盘和显示I/O口状态,在启动QP_nano运行前调用;bsp_keyboard()用于键盘扫描,即读取键盘I/O口的状态,在Keyboard的Scanning状态调用;bsp_display()用于刷新一位数码管,在Display的Refreshing状态调用。

1.3.6主程序

基于QP_nano的主程序简单,只需调用活动的构造函数及硬件初始化函数,然后启动QP_nano内核即可。数字时钟的主程序如下:

intmain(void) {

Display_ctor();

Keyboard_ctor();

bsp_init();

return QF_run();

while(1);

}

1.3.7文件部署

数字时钟的文件部署如下(.表示项目路径,main()函数在clock.c定义):

./boot/startup.a51

./bsp/bsp.c,bsp_display.c,bsp_keyboard.c,bsp.h,bsp_display.h,bsp_keyboard.h

./nano_51/qepn.c,qfn.c,qepn.h,qfn.h,qassert.h

./obj

./usr/clock.uvproj,qpn_port.h,clock.c,display.c,keyboard.c,clock.h,display.h,keyboard.h

最后编译结果显示,ROM空间使用约11 KB,RAM空间使用约170 B。

2移植QP_nano到Keil C51

2.1获取QP_nano的代码文件

访问网站http://www.state-machine.com/psicc2/,点击 QP_nano的资源链接,转到sourceforge网站下载安装文件或压缩包(本文使用的是2014年发布的5.3.0版),安装或解压的默认路径是c:qp。需要移植的文件包括:

① qpn_port.h:QP_nano和平台相关的声明,都要在此文件声明(如QP_nano使用的数据类型,typedef int int16_t)或包含(如#include "qassert.h")。在安装例程位置拷贝一个做模版,比如C:qpqpnexamplesmsp430iarlinky_eZ430qpn_port.h。

② qp_nano的实现头文件:QP_nano的实现声明,位于C:qpqpninclude目录下,包括qassert.h、qepn.h、qfn.h、和qkn.h。

③ qp_nano的实现文件:QP_nano的实现代码,位于C:qpqpnsource目录下,包括qepn.c、qfn.c、qfn_init.c和qkn.c。

2.2Keil配置

2.2.1修改启动文件STARTUP.A51

本文测试使用外部RAM作为可重入堆栈,需对启动文件做如下配置:

① XDATALEN:外部RAM的尺寸,与所选芯片匹配,如果是1 KB, 则为3FFH;

② XBPSTACK:设为1,标记外部RAM作为可重入堆栈;

③ XBPSTACKLEN:配置堆栈栈顶,与芯片匹配,如果是1 KB,则为3FFH+1;

2.2.2菜单配置

① 在目标配置窗口目标选项卡(Flash->Configure-Target)选择内存模型为大模式。

② 在目标配置窗口C51选项卡,添加包含文件的路径(根据文件部署添加)。

2.3QP_nano文件调整

由于部分函数传递参数较多,必须加reentrant关键字,告诉编译器要使用堆栈传递参数。为了减轻工作量,本文测试中所有函数的声明和定义都添加了reentrant关键字。

2.4实现QP_nano平台相关函数

QP_nano只需要平台提供几个函数就可以工作了,本文测试创建了一个 bsp.c文件来实现这些函数,内容包括:

① 定时器中断函数:用来调用QP_nano的Tick函数QF_tickXISR(0),驱动QP_nano工作。

② 启动QP_nano框架的函数void QF_onStartup(void):在该函数中启动定时器。

③ 空闲函数void QF_onIdle(void):没有事件发生时被框架调用。

④ QP_nano的断言函数 void Q_onAssert():打印出错信息,并停止程序运行。

2.5demo的文件部署

本文仿照qpn提供的一个demo例程blinky(模拟发光二极管以1 Hz频率闪烁),移植到Keil C51后的文件部署如下所示(.表示项目路径,main()函数位于blinky.c):

./nano/qepn.c, qfn.c

./include/qassert.h,qepn.h,qfn.h,qkn.h

./user/blinky.uvproj, blinky.c,bsp.c,startup.a51, blinky.h, bsp.h, qpn_port.h

./obj

2.6编译结果

blinky移植成功后,编译结果显示,ROM空间使用约9 KB,RAM约120 B。

结语

参考文献

[1] Miro Samek.Practical UML STATECHARTS in C/C++,Event-Driven Programming for Embedded Systems[M].Second Edition.Amstel dam:Elsevier Inc,2008.

张东杰(工程硕士),研究方向为智能仪器;王俊璞(助理研究员),研究方向为导航制导与控制。

Atmel携手Intel 提升物联网应用安全水平

Atmel公司与英特尔公司合作,推出更加安全的物联网(IoT)应用。通过此次合作,Atmel将在所有Atmel SmartConnect无线解决方案中支持英特尔增强隐私身份(Intel EPID)技术。随着物联网市场的迅猛发展,智能联网设备数量不断增加,在物联网节点与云之间实现相互身份验证,提升云部署的安全性变得日益重要。

到2020年,全球联网设备数量将达到数百亿台。为了在边缘节点与云之间达成无缝连接,安全成为其中一项关键因素。为此,Atmel提供了完整的物联网解决方案,整合了Atmel|SMART微控制器(MCU),支持Wi-Fi、802.15.4和蓝牙的Atmel SmartConnect无线技术以及Atmel的安全产品。与英特尔的携手合作,使得采用Atmel无线解决方案的开发者可以在自己的解决方案当中应用值得信任的英特尔EPID身份识别标准。Atmel公司副总裁兼无线解决方案部门总经理Kaivan Karimi表示:“英特尔EPID技术的应用,为物联网设计者提供了一个真正无缝的边缘节点对云物联网平台。该平台具有值得信赖的安全性能,并且拥有Atmel广泛的物联网产品组合。Atmel的SmartConnect无线和物联网解决方案从现在起可以支持英特尔EPID技术,该技术的安全性已经在过去5年得到了充分验证。”

英特尔EPID是一项用于身份验证和隐私保护的ISO标准,该标准自2011年以来一直运用于英特尔平台。这项技术能够提供硬件可信根,并兼容公钥基础设施(PKI)。采用英特尔EPID技术,设备身份将可得到验证,并在经过验证的设备之间建立安全的通信链路。并且,可在避免暴露具体平台身份的条件下确定设备组成员身份,再添一层安全保护。同时,英特尔EPID技术还可以动态分配取消单个组成员身份,且符合内容和数据保护协议对保护密钥传送的最新要求。

Porting and Application of Embedded Frame QP_nano on 51 MCU

Zhang Dongjie,Wang Junpu

(Department of Instrument Science and Engineering,Shanghai Jiao Tong University,Shanghai 200240,China)

Abstract:This article introduces QPnano to MCU,which is a light weight software framework.Firstly,taking a simple digital clock design as an example,the process of develement using QPnano is described,then the porting QPnano to Keil C51 is described in detail.So some classic software concepts and technologies such as object oriented programming,event driven and state machine are brought into the software development of MCU naturally.

Key words:QPnano;event driven;state machine;software framework;MCU

收稿日期:(责任编辑:薛士然2015-05-12)

中图分类号:TP368

文献标识码:A

猜你喜欢

状态机
基于Verilog 的有限状态机编程方式及研究
FPGA状态机综合可靠性探究 ①
基于有限状态机的交会对接飞行任务规划方法
在硬件课程设计中引入Quartus Ⅱ状态机编辑器的探索与实践
基于状态机学习算法的TLS实现库安全性分析
基于Spring StateMachine的有限状态机应用研究
高性能云工作流状态机的原理与实现①
三段式状态机在单片机中的实现
基于量子平台状态机的桥式起重机控制系统软件设计
双口RAM读写正确性自动测试的有限状态机控制器设计方法