南邮单片机实验小型定时开关控制系统设计.docx
- 文档编号:12005882
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:38
- 大小:6.37MB
南邮单片机实验小型定时开关控制系统设计.docx
《南邮单片机实验小型定时开关控制系统设计.docx》由会员分享,可在线阅读,更多相关《南邮单片机实验小型定时开关控制系统设计.docx(38页珍藏版)》请在冰豆网上搜索。
南邮单片机实验小型定时开关控制系统设计
实验报告
(2017/2018学年第学期)
课程名称
单片机原理及应用
实验名称
小型定时开关控制系统设计
实验时间
年
月
日
指导单位
指导教师
学生姓名
班级学号
学院(系)
专业
实验报告
实验名称
小型定时开关控制系统设计
指导教师
实验类型
课内实验
实验学时
2
实验时间
一、实验目的和要求
1.掌握行列式键盘、LED、数码管、蜂鸣器、继电器等人机接口和机电设备的工作原理,以及使用单片机C语言对其进行控制的方法;
2.掌握基于状态转移及定时调度的系统分析方法,并使用此方法对系统软件结构进行分析和设计,实现所要求的功能;
3.掌握使用集成开发环境Keil进行单片机程序的设计、开发及调试的方法和过程。
二、实验要求
1.通过单片机的IO端口控制人机接口及机电设备,完成一个定时开关的设计;
2.定时开关的工作方式可设置为定时开或定时关;
3.系统通过行列式键盘接受用户的按键输入,设置工作方式和定时时长;
4.系统通过控制LED、数码管及蜂鸣器对用户的操作提供反馈和提示;
5.当用户控制计时启动时,系统对用户设定的时长进行倒计时;
6.如用户设置系统工作在定时开方式,则倒计时结束(计数到0)时控制继电器吸合;
7.如用户设置系统工作在定时关方式,则倒计时开始时继电器吸合,倒计时结束(计数到0)时继电器断开。
三、实验环境(实验设备)
PC机、KeilC51集成开发环境、STC增强型51单片机,继电器。
图3.1硬件实物图
四、实验原理及内容
4.1程序主体流程分析
●程序分析
程序可以分为两个大循环,一个是main函数的循环,一个是定时器1的定时中断任务(T0ISR函数)。
Main函数的任务主要有3个:
1、完成系统初始化。
2、处理定时中断传来的按键任务。
3、处理定时结束的事件(开关继电器、蜂鸣器)。
定时中断任务主要有5个(1ms的定时时长):
1、根据任务减小当前剩余时间。
2、刷新键盘。
3、刷新数码管。
4、响蜂鸣器.5、刷新led灯
main函数和定时中断的流程如下:
图4.1.1主函数和定时中断函数流程图
●代码设计
Main函数代码:
voidmain()
{
//1、初始化2、处理按键3、处理定时结束事件
Init();
while
(1)
{
if(keysolved==0)//有按键要处理
{
solveKey();
keysolved=1;//已处理
}
if(TimeOut==1)//定时事件结束
{
if(Timetype==0)//定时开
{
Open();
}
elseif(Timetype==1)//定时关
{
Close();
}
TimeOut=0;
Laststate=0;
}
}
}
定时中断服务程序代码如下,其中XXTH通过宏定义为0xFC,XXTL通过宏定义为0X18:
voidT0ISR()interrupt1//1ms一次
{
//1、根据任务减当前剩余时间2、刷新键盘3、刷新显示器4、蜂鸣器
TH0=XXTH;
TL0=XXTL;
cnt++;
if(beepOn==1)//如果蜂鸣器开,响蜂鸣器
{
beep=~beep;
}
if(cnt==1000)
{
cnt=0;
if(state==2||state==3)
{
second--;
if(second<0)
{
minite--;
second+=60;
if(minite<0)
{
hour--;
minite+=60;
if(hour<0)
{
TimeOut=1;//通知主程序处理
Laststate=state;//保存上一个状态,供主程序处理
state=0;
hour=minite=second=0;
}
}
}
}
}
RefreshKey();
RefreshBoard();
RefreshLedState();//刷新led
}
4.2系统初始化
●初始化分析
系统初始化主要为初始化定时器,打开定时器中断,初始化相关字段:
1、上一次的键盘按压状态和本次键盘按压状态为0xf0。
键盘有没有按压是通过相邻两次定时中断的过程中,如果上一次定时中断没有检测到键盘按压,而本次定时中断服务程序检测到了键盘的按压,则认为键盘被按压了。
有没有检测到键盘的按压是通过采集键盘的输入线状态来实现的,输入线为P0口的高4位。
如果P0口高4位全1,则没有按压,如果高4位有一个是0,则键盘被按压。
采集P0口的时候注意屏蔽低4位,通过与0xf0相与实现屏蔽低4位。
2、系统的初始化状态。
刚刚进入系统后,系统初始化为状态0.也就是空闲状态。
3、定时任务完成标识TimeOut。
此标识当定时任务计时完成后置1(在中断服务程序内).main函数不断检测此标志,当TimeOut为1的时候,检测当前是定时开还是定时关,并启动相应的函数。
函数执行完成后,置TimeOut为0,表示定时任务处理完成。
4、Keysolved标志,即当前按键已处理完成标志。
在定时中断服务程序中,通过相邻两次的键盘输入线扫描结果是否相同来判断有没有按键按下,一旦有按键按下,则扫描当前行线,采集按键,将按键代码保存到keycode全局变量中,并将Keysolved设置为0,通知主程序处理。
主程序main函数中不断检测keysolved变量是不是0,来判断当前有没有新的按键要处理,如果keysolved为0,则启动按键处理函数。
程序开始的时候keysolved应该被设置为1.
●初始化程序代码
其中,XXTH通过宏定义为0xFC,XXTL通过宏定义为0X18:
voidInit()
{
TH0=XXTH;
TL0=XXTL;
TMOD=0x01;
ET0=1;
TR0=1;
EA=1;
lastKeyState=0xf0;
nowkeyState=0xf0;
state=0;//初始化为空闲状态
TimeOut=0;
keysolved=1;
}
●定时器初值计算
定时器采用定时器0的方式1,即16位定时器。
不具备自动重装功能,所以每次在中断服务程序中首先要软件重设定时器初值。
定时器的初值可根据定时公式计算,由于定时器为对机器周期递增计数,定时时长公式可表示如下:
由上式解出初值N为:
其中,定时时长设置为1ms,晶振频率为12MHZ,所以机器周期为1us。
初值N计算过程如下:
所以,定时器高8位TH0位FCH,低8位TL0位18H。
4.3系统状态介绍
系统中一共设置了4种状态,通过state全局变量进行记录。
各个状态以及对应的数值如下:
State==0:
状态0,空闲状态
State==1:
状态1,设置状态
State==2:
状态2,定时开(正在运行)
State==3:
状态3,定时关(正在运行)
各个状态的切换条件如下:
图4.3.1系统模式切换条件
4.4按键处理
按键的检测是在定时器0的中断服务程序中进行的,中断服务程序通过调用RefreshKey函数(后面介绍)实现。
当有按键按下的时候,定时中断服务程序通过keycode全局变量记录下当前的按键代码。
通过keysolved设置为0表明当前按键还没被处理过。
Main函数一旦检测到keysolved为0,即调用solveKey()函数处理当前按键。
并在处理完成后,设置keysolved为1,表明当前keycode里面的按键代码已经被处理过了。
系统的按键采用矩阵键盘,连接在P1端口。
键盘的电路图如下(按键获取查看4.7节)
图4.4.1矩阵键盘电路图
各个按键定义的功能如下:
图4.4.2按键对应功能
●相关细节设计
按键操作限制:
每个按键只有在特定的系统状态下才可以被按下,例如+1s按键只能在系统设置状态下被按下,如果不在系统设置状态而被按下,蜂鸣器会发出0.1s的响声提示用户错误操作。
确认键的两个功能:
确认键除了在设置状态确认后进入定时状态,还有个功能是在定时结束后关闭的提醒用户的蜂鸣器。
加1与减1的进位与借位:
加1s和减1s,加1分,减1分,都要考虑到进位和借位的问题,即59秒加一秒后变为00秒,并且分钟+1,59分+1分后,变为00分,并且小时加1,。
减一的时候同理。
且要考虑到小时数大于99或者小于0(由于借位或者本身减去)的时候要提醒用户错误操作(通过蜂鸣器),并设置为临界值(大于99设置为99,小于0设置为0)。
●程序代码
voidsolveKey()
{
if(keycode==0x11)//加1s
{
if(state==1)//只有设置状态才可以+1s
{
second++;
if(second>=60)
{
second-=60;
minite++;
if(minite>=60)
{
minite-=60;
hour++;
if(hour>=99)
{
hour=99;
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
}
}
else//操作错误,响蜂鸣器提示
{
beepcnt=BEEPLEN;
}
}
elseif(keycode==0x12)//减1s
{
if(state==1)//只有设置状态才可以-1s
{
second--;
if(second<0)
{
second+=60;
minite--;
if(minite<0)
{
minite+=60;
hour--;
if(hour<0)//出现错误,蜂鸣器相
{
hour=0;
beepcnt=BEEPLEN;
}
}
}
}
else
{
beepcnt=BEEPLEN;
}
}
elseif(keycode==0x21)//+1分钟
{
if(state==1)//只有设置状态才可以+1分钟
{
minite++;
if(minite>=60)
{
minite-=60;
hour++;
if(hour>=99)
{
hour=99;
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
}
else
{
beepcnt=BEEPLEN;
}
}
elseif(keycode==0x22)//-1分钟
{
if(state==1)//只有设置状态才可以-1分钟
{
minite--;
if(minite<0)
{
minite+=60;
hour--;
if(hour<0)//出现错误,蜂鸣器提示
{
hour=0;
beepcnt=BEEPLEN;
}
}
}
else
{
beepcnt=BEEPLEN;
}
}
elseif(keycode==0x31)//+1小时
{
hour++;
if(hour>=99)
{
hour=99;
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
elseif(keycode==0x32)//-1小时
{
hour--;
if(hour<0)
{
hour=0;
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
elseif(keycode==0x13)//切换系统状态,只有空闲状态和设置状态可以互相切换,定时状态要在设置状态下按下确认键进入
{
if(state==0||state==1)
{
state++;
if(state==2)
{
state=0;
}
}
else
{
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
elseif(keycode==0x14)//确认
{
if(state==1)//设置状态可以确认
{
if(Timetype==0)//定时类型0--定时关
{
state=3;
}
else//1--定时开
{
state=2;
}
}
elseif(state==0)//定时完成跳转到空闲状态,并蜂鸣器报警,按下确认键关闭蜂鸣器
{
beepOn=0;
}
else
{
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
elseif(keycode==0x23)//切换定时开还是定时关
{
if(state==1)//设置状态可以互相切换
{
Timetype++;
if(Timetype==2)
{
Timetype=0;
}
}
else
{
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
elseif(keycode==0x24)//取消当前定时
{
if(state==2||state==3)//定时状态才可以取消
{
state=0;
}
else
{
beepcnt=BEEPLEN;//操作错误,蜂鸣器提示
}
}
else//按键按错了,蜂鸣器提醒
{
beepcnt=BEEPLEN;
}
}
4.5蜂鸣器的用户错误操作提醒功能
●蜂鸣器错误提醒的设计思路
此功能借助定时器实现,如果当前需要通过蜂鸣器提醒用户按下了错误的按键,则将一个全局变量beepcnt设置为BEEPLEN,BEEPLEN通过宏定义定义为100.在定时器0的定时中断服务程序T0ISR函数中,由于T0ISR函数每1ms执行一次,则执行的时候检测beepcnt是不是大于0,如果大于0,则将beepcnt减一,并将beep取反。
此处beep为蜂鸣器的引脚定义。
通过100次间隔1ms的取反操作实现蜂鸣器的提醒功能。
●相关代码
RefreshKey()函数在T0ISR每次执行的时候都会调用一次,所以这个过程放在了RefreshKey()函数内。
voidRefreshKey()
{
...
if(beepcnt>0)//错误的按键按下时,响固定时长的蜂鸣器,提高用户体验
{
beep=~beep;
beepcnt--;
}
...
}
在需要响蜂鸣器的地方添加一句即可响一下蜂鸣器:
beepcnt=BEEPLEN;
4.6数码管显示
●显示格式
数码管一共8位,在空闲状态显示全0。
在设置状态和定时状态显示当前的时-分-秒。
设置和定时状态下显示格式如下:
图4.6.1设置和定时状态下的数码管显示
上图中,从左向右依次为时分秒。
在空闲状态下显示全0,如下图所示:
图4.6.2空闲状态数码管显示
●硬件电路
数码管的段选接在P0端口(中间接入74HC245总线收发器进行驱动),位选通过3-8译码器接在P2口的2-4位。
电路图如下图所示:
图4.6.3数码管电路图
上图中的LED1~LED8的位选信号接入74138译码器,74138译码器的输入端为P2.2到P2.4。
138译码器电路如下图所示:
图4.6.4与位选信号相连接的138译码器
数码管采用动态显示。
刷新操作放在了定时中断服务程序中。
定时中断程序通过调用RefreshBoard()函数实现数码管刷新显示。
因为定时中断程序每1ms执行一次,数码管有8位,所以刷新率为
。
数码管为共阴极数码管,输出1驱动某一段的显示。
定义的全局变量段码如下:
unsignedcharcodeseg[]={0x3f,0x06,0x5B,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
●程序设计思路
Ø段码的确定
进入RefreshBoard()函数后,首先判断当前系统状态:
1、如果是空闲状态,则显示全0。
即向P0口输出“0”的段码。
2、如果是设置状态或者计时状态,则按照图4.6.1的格式输出时、分、秒。
中间以短横线隔开。
根据课本181页图,可以确定短横线的段码为0x40.在设置状态或者计时状态下显示时、分、秒的时候,需要将当前的时、分、秒分成两位显示,即需要进行取余确定个位,除以10确定十位。
Ø位码的确定
每执行一次定时中断服务程序的时候,只显示一位。
通过上面的方法确定段码后,还需要确定位选。
定义一个全局变量nowwei来表示当前的位选,取值为0~7。
然后138译码器并不能输入10进制数字,所以需要将nowwei的2进制代码中的低3位输出到138译码器。
可以通过分别与4、2、1相与的方式确定低3位的01值。
定义接入138译码器的输入端ABC引脚的变量如下:
sbitG1=P2^2;//数码管位选接入3-8译码器,此为3-8译码器最低位
sbitG2=P2^3;
sbitG3=P2^4;//数码管位选接入3-8译码器,此为3-8译码器最高位
则,在RefreshBoard()函数中,通过下面的方法确定G1、G2、G3的数值:
G3=(nowwei&4)==0?
0:
1;
G2=(nowwei&2)==0?
0:
1;
G1=(nowwei&1)==0?
0:
1;
位选计算完成后,需要将nowwei变量+1,以便下次定时中断调用RefreshBoard()刷新数码管的时候显示下一位。
要注意+1后如果是8要置0,形成循环。
●数码管代码
voidRefreshBoard()//数码管刷新
{
if(state==0)//空闲状态,显示全0
{
P0=seg[0];
}
else
{
if(nowwei==2||nowwei==5)
{
P0=0x40;//显示一个横线
}
else
{
if(nowwei==0)
{
inttmp=second%10;
P0=seg[tmp];
}
elseif(nowwei==1)
{
inttmp=second/10;
P0=seg[tmp];
}
elseif(nowwei==3)
{
inttmp=minite%10;
P0=seg[tmp];
}
elseif(nowwei==4)
{
inttmp=minite/10;
P0=seg[tmp];
}
elseif(nowwei==6)
{
inttmp=hour%10;
P0=seg[tmp];
}
elseif(nowwei==7)
{
inttmp=hour/10;
P0=seg[tmp];
}
}
}
G3=(nowwei&4)==0?
0:
1;//位选,接入3-8译码器
G2=(nowwei&2)==0?
0:
1;
G1=(nowwei&1)==0?
0:
1;
nowwei++;
if(nowwei==8)nowwei=0;
}
4.7矩阵键盘
键盘为4*4的矩阵键盘,键盘的硬件电路如图4.4.1所示。
●按键的检测与消抖
由于矩阵键盘存在抖动现象,需要消抖。
由于本程序包含一个T0的中断程序,所以可以借助T0的中断服务进行消抖。
每当当前中断服务程序检测到了键盘按下,而上一个中断服务程序没有检测到按下,就认为键盘按下,从而实现了消抖。
关键代码如下:
if(lastKeyState==0xf0&&nowkeyState!
=0xf0)//有新的按键按下
键盘的检测,检测输入线,此单片机学习板中为P1的高4位。
当P1高4位全为1,则表示没有键按下,否则有键按下。
关键代码如下:
nowkeyState=P1&0xf0;
一旦检测到有新的按键按下后,则开始逐行扫描。
将输出线逐位置低,然后读取输入线状态。
当读入的某位输入线为低,结合输出线即可确定按键位置。
●按键代码的保存与通知
一旦检测到新的按键,即将当前按键码保存到keycode变量中,并将keysolved变量置0,表示当前按键没有处理。
Main函数检测到keysolved的为0,即开始处理新的按键。
●按键程序代码
RefreshKey()函数被中断服务程序T0ISR调用。
voidRefreshKey()
{
ucharkey,i,line;
lastKeyState=nowkeyState;
P1=0xf0;
nowkeyState=P1&0xf0;//读入矩阵键盘输入线状态(P1高4位为输入线)
if(beepcnt>0)//错误的按键按下时,响固定时长的蜂鸣器,提高用户体验
{
beep=~beep;
beepcnt--;
}
if(lastKeyState==0xf0&&nowkeyState!
=0xf0)//有新的按键按下
{
for(i=0;i<4;i++)
{
P1=0xff;
line=0x01;
line<<=i;
line=~line;
P1&=line;
key=P1&0xf0;
switch(key)
{
case(0xe0):
keycode=0x40|(4-i);
break;
case(0xd0):
keycode=0x30|(4-i);
break;
case(0xb
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 实验 小型 定时 开关 控制系统 设计