单片机程序设计中运用事件驱动机制

发布者:温馨阳光最新更新时间:2012-03-08 来源: 21IC 关键字:事件驱动  单片机  程序设计  实时响应 手机看文章 扫描二维码
随时随地手机看文章

1 传统单片机程序开发的不足

在传统的单片机程序中,通常是以“过程”和“操作”为中心的结构,程序按规定的过程顺序地执行,与外设的连接一般采用中断方式,在中断服务程序中完成外设的全部处理工作,主程序一般是初始化系统并等待中断的发生。这种结构成熟、易于理解,但有如下不足:

(1)受单片机性能的限制,容易造成系统对其它中断的响应变得迟缓,特别是对于中断源较多、中断处理耗时较多的系统(如:LED显示、键盘扫描等);

(2)中断服务程序过长,在中断服务期间系统无法响应同级的中断;

(3)可能导致代码重入,增大堆栈开销,造成难以预料的结果;

(4)程序调试时,花在各模块定时协调方面的时间、精力随系统的复杂程序大幅增加。

如果在编写单片机程序时,引入Windows程序中的事件驱动机制,把中断响应与事件处理程序分离,中断服务程序的任务只是产生一个中断发生的标志,而事件处理则由处理程序来完成,主程序则负责判断标志和调度处理程序。这样,可大幅缩短中断服务程序的长度,减少断服务程序的耗时,提高系统对多中断的响应能力,从而较好地解决上述矛盾。

2 Windows的事件驱动机制

在Windosw 系统中,程序的设计围绕事件驱动来进行。当对象有相关的事件发生时(如按下鼠标键),对象产生一条特定的标识事件发生的消息,消息被送入消息队列,或不进入队列而直接发送给处理对象,主程序负责组织消息队列,将消息发送给相应的处理程序,使相应的处理程序执行相应的动作,做完相应的处理后将控制权交还给主程序。

在这种机制中,对象的请求仅仅是向队列中添加相应的消息,耗时的处理则被分离给处理函数。这种结构的程序中各功能模块界限分明,便于扩充,能充分利用CPU的处理能力,使系统对外界响应准确而及时。

3 事件驱动的单片机程序设计

与Windows 系统相比,单片机的资源非常有限,因此,单片机程序中的事件驱动机制只能采取一种简化的方式。当某个中断发生时,中断服务程序设置相应的标志,不同的标导代表不同的中断发生的消息,而主程序不断地判别这些标志,以决定启动哪一个处理函数。相应的处理函数被启动处理完相关的任务后,清除此标志,然后把控制权交还给主程序。采用这种机制,可合理地利用有限资源,使程序调试的工作量大幅下降。对于延时、定时处理(如LED显示、键盘扫描等),更可方便地使用一定时器来完成延时、定时的任务,从而把CPU从这种耗时的任务中解放出来,确保系统对多中断有足够的响应能力。

本文以一IC卡读写机为例,说明事件驱动机制在单片机程序设计中的具体应用。

3.1 硬件结构

本系统以ATMEL公司的89C51为核心(如图1)。89C51价格低廉,性能较好,片内有4KB 的可擦写程序存储器,可满足本系统的要求。为简化硬件结构及系统能耗,键盘采用软件扫描的矩阵键盘。LED显示采用段位动态扫描,在任一时刻LED中最多只有一段被点亮。具体是在位选信号送某位LED的公共极时,每隔一个时间片依次输出该位LED的段码(含小数点),输出完成一位后,再逐闪输出下一位。从第一位至第N位LED依次分成8×N个时间片循环扫描显示。串口UART作为系统与外部数据通信的通道,IC卡的读写由MCU模拟I2C协议来实现。

3.2 事件驱动机制的单片机程序设计

中断申请标志

在系统中定义一个可位寻址的单元,在此把它命名为Message_Flag,用来记录描述中断事件发生的情况。各位的定义如下:

*Message_Flag中某位为1表示当前有相应的事件发生,为0则当有没有相应的事件发生。[page]

LED显示的实现

显示模块结构见图2。以定时器T0作为LED的动态扫描的定时基准,T0的定时时间最大值 Tseg=20ms/(8×N)(其中N为LED位数),改变 Tseg的值可改变显示的亮度。T0每隔Tseg时间向MCU申请中断,在T0的中断服务程序中置位相应的标志位(Message_Flag中的D0 位)。主程序检测到此标志位被置位后,启动显示模块实现位段的显示输出。

 

键盘输入的实现

键盘模块结构见图3。在LED动态扫描期间,只有被点亮的LED相应的位选线维持大约3ms的低电平,而在系统工作的绝大部分时间内LED的位选线(即键盘的列线)维持高电平。当有键被按下时,将把键盘的行线中某一根拉成高电平,经或非门后,向MCU 申请INT1中断,在INT1的中断服务程序中启动定时时间为20ms的定时器T1。T1的定时时间到后向MCU申请T1中断,在T1的中断服务器程序中置位相应的中断申请标志(Message_Flag中的 D1位)。主程序检测到此标志位被置位后,启动键盘扫描模块实现键盘输入。键盘输入完成(用户按“确认”键),置位键盘输入确认标志(Message_Flag中的D7位)。

IC卡的读写

IC 卡的SDA、SCL经卡座分别通过P1.0、P1.1与MCU相连。当IC卡插入卡座时,座上的微动开关使INT0变为低电平,向MCU申请INT0中断。在INT0中断服务程序中置位相应的中断申请标志(Message_Flag中的D2位),主程序检测到此标志位被置位后,启动IC卡的读模块,以软件模块I2C协议来实现读卡操作。在数据处理完成后,同样通过软件模块I2C协议来完成写卡的操作。

串口通讯

实际应用中可把UART转换成RS232C与PC相连或转换成RS485等其它协议组成单片机网。 MCU与外部的通讯采用中断方式,在串口的中断服务程序中置位相应的中断申请标志(Message_Flag中的D4位)。主程序检测到此标志位被置位后,启动串口通讯模块,实现与外部的数据通讯。

主程序的设计

综上所述,主程序首先完成系统的初始化,然后循环检测各中断的中断申请标志,如有某标志被置位,则启动相应的处理模块完成相应的任务。程序结构如下(用C51编写):

vnsigned bdata message_flag;

sbit t0_int=message_flag^0;

sbit t1_int=message_flag^1;

sbit int0_int=message_flag^2;

sbit uart_int=message_flag^4;

sbit kb_enter=message_flag^7;

unsigned char kb_buf[8];

unsigned char led_buf[8];

unsigned char ic_buf[8];[page]

unsigned char num_buf[8];

void uum_proc(void); /*数据处理模块*/

void ledbuf_write(unsigned,unsigned int); /*数据处理*/

void system_init(void); /*系统初始化*/

void uart_commune(void); /*串口通讯模块*/

void led_display(void); /*LED显示*/

void kb_scan(void); /*键盘扫描*/

void ic_reader(void); /*读IC卡*/

void ic_writer(void); /*写IC卡*/

void set_timer(unsigned int time_len,unsigned char type,unsigned char id); /*设置定时器*/

void t0_int_sever(void); /*定时器T0中断服务*/

void t1_int_sever(void); /*定时器T1中断服务*/

void int0_int_sever(void); /*INT0中断服务*/

void int1_int_sever(void); /*INT1中断服务*/

void uart_int_sever(void); /*串口中断服务*/

void main(void)

{

system_init();

while(1) {

if (t0_int) led_display();

if (int0_int) ic_reader();

if (t1_int) kb_scan();

if (uart_int) uart_commune();

if (kb_enter){

num_proc();

ic_writer();

ledbuf_write(num_buf,8);

}

}

}

事件驱动的单片机程序设计是通过在中断服务程序中置位相位标志,把耗时的中断服务中的处理部分分离出来,中断返回后,再由主程序根据标志启动相应的处理模块。在任务处理完成后,清除相应的标志。由于中断服务程序短小,所以一般能实时地响应各种中断;而处理程序之间不会被相互调用,所以不会产生代码重入;各模块界限分明,给程序中各模块的统调带来很大的方便。

实践证明,运用事件驱动机制来纺织单片机程序,即使对于要求定时准,耗时多的多中断、多模块系统,也可轻松地完成。

关键字:事件驱动  单片机  程序设计  实时响应 引用地址:单片机程序设计中运用事件驱动机制

上一篇:Keil Monitor-51仿真板的制作与使用
下一篇:Linux PC和51系列单片机串行通信的设计

推荐阅读最新更新时间:2024-03-16 12:54

单片机学习3
寻址方式与指令系统 通过前面的学习,我们已经了解了单片机内部的结构,并且也已经知道,要控制单片机,让它为我们干学,要用指令,我们已学了几条指令,但很零散,从现在开始,我们将要系统地学习8051的指令部份。 一、概述 1、指令的格式 我们已知,要让计算机做事,就得给计算机以指令,并且我们已知,计算机很 笨 ,只能懂得数字,如前面我们写进机器的75H,90H,00H等等,所以指令的第一种格式就是机器码格式,也说是数字的形式。但这种形式实在是为难我们人了,太难记了,于是有另一种格式,助记符格式,如MOV P1,#0FFH,这样就好记了。这两种格式之间的关系呢,我们不难理解,本质上它们完全等价,只是形式不一样而已。 2、汇编 我
[单片机]
MSP430单片机FLASH读写操作例子
//****************************************************************************** // MSP430F149 // M. Mitchell // Texas Instruments Inc. // Feb 2005 // Built with IAR Embedded Workbench Version: 3.21A //****************************************************************************** #include MSP430x14x.h char value;
[单片机]
最简洁的单片机状态机模型(X-状态机)
单片机如果控制的设备趋向复杂,使用状态机模式写程序会更清晰,但是网上讲的状态机图晦涩难懂,实际状态机就是一张表,并且这张表对应单片机的输入输出引脚就能完成大部分状态罗列。 看问题看本质,单片机内部运行的程序用户不关心,但是单片机显示、发声、按键操作、控制设备是最关注的。 把输入组合作为条件,输出仅做动作,就是最简洁的单片机状态机。 为了与通常所讲的状态机模型区分,个人给这个状态机模型起个名字: X-状态机 (X-FSM) 输入可以是传感器、按键、开关信号等 输出可以是开关信号、数码管显示、LCD显示、蜂鸣器、语音喇叭发声、指示灯等。 一图胜万言,一表见真章: 表一(行输出,列输入) 表二 有限状态机FS
[单片机]
STC12C2052AD单片机做的红外学习遥控器
// 中断函数注意养成指定寄存器组的习惯 //不同优先级的中断程序绝对不能使用同一组寄存器 /*****编程时防止中断把寄存器中的数据改变的解决方法是给中断指定寄存器, 同优先级的使用同一组没事。 1、写中断程序一定要用using语句指定寄存器组。第1、2、3组都可以,不能是0. 2、51单片机的中断有两个优先级。一个中断不会打断另一个相同优先级的中断。 这样相同级别中断可以使用同一个组。比如:低优先级的中断函数都 用 using 1,高优先级的中断都用 using 2 。这样不会冲突。 下面是一个正常的例子: C程序: void int0() interrupt 0 using 1 默
[单片机]
STC12C2052AD<font color='red'>单片机</font>做的红外学习遥控器
基于MCU和FPGA的LED图文显示屏控制系统
  引言   目前,市场上的中小规模LED显示系统,一般采用传统的单片机作为主控芯片。对LED大屏幕显示屏来说,由于数据传输量大,要求扫描速度快,而单片机内部的资源较少、运行速度较慢,难于满足系统要求。以FPGA作为控制器,一方面,FPGA采用软件编程实现硬件功能,速度较快;另一方面,它的引脚资源丰富,可扩展性强。因此,用单片FPGA和简单的外围电路就可以实现大屏幕LED显示屏的控制,无需另外设计汉字库,具有集成度高、稳定性好、设计灵活和效率高等优点。   1 系统总体结构   LED大屏幕显示系统由上位机(PC机)、单片机系统、FPGA控制器、LED显示屏的行列驱动电路等模块组成,如图1所示。上位机负责汉字、
[单片机]
基于<font color='red'>MCU</font>和FPGA的LED图文显示屏控制系统
STC15W408AS单片机白光T12控制器
自己 设计和制作的stc白光,附上原理图,洞洞板走线图和源代码。 只实现了简单的温控,短按一下编码器快速设定温度为300℃,双击一下编码器快速设定为10℃(相当于短暂休眠 代码注释还是很详细的,适合初学者学习。 单片机源程序如下: /** 布满星星的天空 CZS 编写 */ #include STC15.h #include intrins.h #include math.h sbit t12 = P3 ^ 7; //T12控制 sbit encoderb = P1 ^ 0; //编码器的b脚 sbit encodera = P1 ^ 1; //编码器的a脚 sbit encod
[单片机]
STC15W408AS<font color='red'>单片机</font>白光T12控制器
单片机笔记】NodeMcu入坑—局域网通信
先上源码 --wifi_light.lua wifi.setmode(wifi.STATION) wifi.sta.config( wifi_ssid , wifi_psw ) print(wifi.sta.getip()) led1 = 0 gpio.mode(led1, gpio.OUTPUT) srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on( receive , function(client,request) local buf = ; local _, _, method, path, vars = string.fi
[单片机]
【<font color='red'>单片机</font>笔记】NodeMcu入坑—局域网通信
MCU 面临 800V 电动汽车牵引逆变器的 3 种挑战
电动汽车 (EV) 牵引逆变器是电动汽车的核心。它将高压电池的直流电转换为多相(通常是三相)交流电来驱动牵引电机并控制制动能量的再生。电动汽车电子设备正在从 400V 架构转向 800V 架构,这正在逐步现实、普及,更高的电压会带来至少三个好处: - 快速充电 - 在相同电流下提供双倍的电量。 - 通过使用碳化硅 (SiC) 提高效率和功率密度。 - 通过使用更细的电缆来减轻重量,从而减少 800V 相同额定功率所需的电流。 在牵引逆变器中,微控制器(MCU)是系统的大脑,通过模数转换器(ADC)执行电机控制、电压和电流采样,使用磁芯计算磁场定向控制(FOC)算法,使用脉宽调制 (PWM) 信号驱动功率场效应晶体管
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved