智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 2312|回复: 1
打印 上一主题 下一主题

单片机模块化编程__状态机思想资料集合

[复制链接]

5

主题

11

帖子

0

精华

高级会员

Rank: 4

积分
525
威望
258
贡献
225
兑换币
73
注册时间
2013-1-26
在线时间
21 小时
毕业学校
北京大学
跳转到指定楼层
1#
发表于 2013-8-21 22:10:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式



























摘录:
个大的单片机程序往往包含很多模块,我是这样组织的
1
。每一个C源文件都要建立一个与之名字一样的H文件,里面仅仅包括该C文件的函数的声明,其他的什么也不会有,比如变量的定义啊等等不应该有。
2
。建立一个所有的文件都要共同使用的头文件,里面当然就是单片机的管脚使用的定义,还有里面放那些需要的KEIL系统的头文件,比如#include<reg52.h>,#include<absacc.h>等等,把这个文件命名为common.h,
或者干脆就叫main.h
3
,每个C源文件应该包含自己的头文件以及那个共同的使用的头文件,里面还放自己本文件内部使用的全局变量或者以extern定义的全局变量
4
。主文件main.c里面包含所有的头文件包括那个共同使用的文件,main.c里面的函数可以再做一个头文件,也可以直接放在文件的开头部分声明就可以了,里面一般还有中断服务程序也放在main.c里面
5
。对于那些贯穿整个工程的变量,可以放在那个共同的使用的头文件里面,也可以用extern关键字在某个C源文件里面定义,哪个文件要使用就重复定义一下
6.
建立工程的时候,只要把C源文件加到工程中,把H文件直接放到相应的目录下面就可以了,不需要加到工程里。
单片机系统模块化编程的一些想法
51核类型单片机是目前应用较为广泛的一款MCU,编写单片机程序常常成为嵌入式软件开发软件入门级的训练。一般而言,51程序代码量少,考虑模块化程序相对较少。一种常规做法就是主程序采用while循环,再者通过中断中设置一些标志位;笔者在51单片机程序开发过程,发现公司的单片机程序更新很快,基本每个人都要修改一点,一段时间后原有代码想法都很难找到。还有一种是移植操作系统后,然后进行代码规范化,比如移植UCOS-ii等嵌入式操作系统,但是往往代码量增加很快,对存储容量本来就少的51单片机有较大的压力。
51模块化程序设计的最重要问题,笔者认为就是找到一种合理的程序结构,而且它能胜任实际的51单片机程序开发。考虑到文中前面提到的问题,笔者主要针对第一种主程序while循环结构进行修改。首先增加任务结构体定义,其中函数指针pFun指向实际的任务函数,nDelay表示延时时间,以ms为单位,以下涉及时间都一样的。而nRunme表示运行的次数,nPeriod表示运行的时间周期。



用状态机实现键盘消抖
用状态机做键盘消抖,很好用,不必延时等待键盘稳定,当检测到有键按下或弹起时能发出相应的键盘消息,
设置状态机有4种状态,A0,A1,A2,A3 状态转换图如下:
file:///C:\Users\Eden\AppData\Local\Temp\msohtmlclip1\01\clip_image001.giffile:///C:\Users\Eden\AppData\Local\Temp\msohtmlclip1\01\clip_image002.jpg
file:///C:\Users\Eden\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif000.jpg (12.65 KB)
2010-3-15 17:00

初始时处于A0状态,当扫描发现有键按下时,转入到A1状态。
当处于A1状态时,当扫描发现有键按下并且键值等于A1状态下的键值时,转入到A2状态,否则转入A0状态。
当处于A2状态时,当扫描发现有键按下并且键值等于A2状态下的键值时,转入到A3状态,同时发出键按下消息或将按下键的键值入队,否则转入A0状态。
当处于A3状态时,当扫描发现无键按下时,转入到A0状态。同时发出键弹起消息或弹起键的键值入队。
函数JianSaoMiao()用于键扫描的到即时键值
函数JianChuLi()用于按键处理,可放在时钟中断中调用
例:在10ms中断中扫描并处理按键只需调用:JianChuLi(JianSaoMiao());
可使调用后完成发出键按下或键弹起的消息,或者将键值送入键值队列供后续处理

#define Kong 0x00 //定义无键按下时,键扫描返回的值
#define A0 0 #define A1 1 #define A2 2
#define A3 3
struct { unsigned char JianZhi; //当前键值
unsigned char DangQianZhuangTai;//当前状态 } ZTJ;

void ZTJ_ChuShiHua(void) //状态机初始化
{
ZTJ.DangQianZhuangTai=A0; //初始状态A0 ZTJ.
JianZhi=Kong; //键值为Kong
}

uchar JianSaoMiao(void) //键值扫描
{
uchar JianZhi; //在此根据实际电路插入键值扫描程序段,键值存放到JianZhi
......
return(JianZhi);
}

void JianChuLi(uchar JZ)
{
switch(ZTJ.DangQianZhuangTai)
{
case A0:
{
if(JZ!=Kong)
{
ZTJ.DangQianZhuangTai=A1; //有键按下,状态转移
ZTJ.JianZhi=JZ; //保存当前键值
}
}
break;
case A1:
{
if(JZ==ZTJ.JianZhi)
ZTJ.DangQianZhuangTai=A2; //有键按下,且键值稳定状态转移
else ZTJ_ChuShiHua(); //键值不稳,回到初始状态A0
} break; case A2:
{
if(JZ==ZTJ.JianZhi)
{
ZTJ.DangQianZhuangTai=A3; //有键按下,且键值稳定状态转移 //在此发出键按下消息,或将键按下键值入键值队列供后续处理
......
}
else
ZTJ_ChuShiHua(); //键值不稳,回到初始状态A0
}
break;
case A3:
{
if(JZ==Kong)
{
ZTJ_ChuShiHua(); //键已弹起,回到初始状态A0 //在此发出键弹起消息,或将键弹起键值入键值队列供后续处理
......
}
}
break;
default :
{
ZTJ_ChuShiHua(); //初始状态A0
}
}
}





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

4

主题

143

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2367
威望
1143
贡献
822
兑换币
770
注册时间
2012-11-8
在线时间
201 小时
2#
发表于 2014-2-25 00:20:36 | 只看该作者
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-26 13:08 , Processed in 0.067848 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表