《基于单片机的定时报警器课程设计》

一、课题名称

        定时报警器

二、设计任务与要求

设计一个单片机控制的简易定时报警器。要求根据设定的初始值(1-59秒)进行倒计时,当计时到0时数码管闪烁“00”(以1Hz闪烁),按键功能如下:

(1)设定键:在倒计时模式时,按下此键后停止倒计时,进入设置状态;如果已经处于设置状态则此键无效。

(2)增一键:在设置状态时,每按一次递增键,初始值的数字增1。

(3)递一键:在设置状态时,每按一次递减键,初始值的数字减1。

(4)确认键:在设置状态时,按下此键后,单片机按照新的初始值进行倒计时及显示倒计时的数字。如果已经处于计时状态则此键无效。

三、设计方案

1.任务分析与整体设计思路

根据题目的要求,需要实现如下几个方面的功能:

计时功能:要实现计时功能则需要使用定时器来计时,通过设置定时器的初始值来控制溢出中断的时间间隔,再利用一个变量记录定时器溢出的次数,达到定时1秒中的功能。然后,当计时每到1秒钟后,倒计时的计数器减1。当倒计时计数器到0时,触发另一个标志变量,进入闪烁状态。

显示功能:显示倒计时的数字要采用动态扫描的方式将数字拆成“十位”和“个位”动态扫描显示。如果处于闪烁状态,则可以不需要动态扫描显示,只需要控制共阴极数码管的位控线,实现数码管的灭和亮。

键盘扫描和运行模式的切换:主程序在初始化一些变量和寄存器之后,需要不断循环地读取键盘的状态和动态扫描数码管显示相应的数字。根据键盘的按键值实现设置状态、计时状态的切换。

2.单片机型号及单片机硬件电路原理图

选用MCS-51系列单片机的AT89S51作为微控制器,因为它成本比较低,功能强,选择两个共阴极数码管组成2位显示模块,通电后系统会复位初始值,而我们的初始值设定为59秒 ,定时秒数可以通过按键来更改,所以我们配备了一个“增一”键和一个“减一”键,分别来调整时间,当时间倒计时结束时,数码显示管会闪烁,提醒倒计时已经结束。

因为键盘数量不多,所以选择独立式按键与P1口连接作为四个按键输入,没有键按下时P1.0-P1.3为高电平,当有键按下时,P1.0-P1.3相应管脚为低电平。单片机硬件电路原理图如下:

 3.程序设计

采用单片机的P1口作为按键的输入,使用独立式按键与P1.0-P1.3连接,构成四个功能按键,分别为 设置键k1、增一键k2、减一键k3、确定键k4。在计时功能中,次数为count、倒计时为countdown,在显示功能中,定义一组数组DuanMa,值为0-9数字对应的数码管7段码。还需要定义一个状态变量state用来存储当前单片机工作在哪种状态,state=1表示为设置状态,默认为state=0 表示处于倒计时状态。程序代码如下:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit k1=P1^0; // 设置键k1
sbit k2=P1^1; // 增一键k2
sbit k3=P1^2; // 减一键k3
sbit k4=P1^3; // 确定键k4
uchar code DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 段码
uchar count,shi,ge,countdown,state;
void delay(uint ms) // 延时函数
{
  uchar i;
  while(ms--)
  {
    for(i=0;i<120;i++);
  }
}
void init() // 初始化函数
{	
  P0=0x6d; // 十位显示5
  P2=0x6f; // 个位形式9
  P1=0xff; // P1口全部设置为高电平
  TMOD=0x01; // 设置定时器0的各种方式为1
  IE=0x82; // 中断允许寄存器D7置1,允许CPU中断;D1置1允许定时器0溢出中断
  TH0=(65536-50000)/256; // 设置初始值
  TL0=(65536-50000)%256; // 设置初始值
  TR0=1; // 启动定时器0
  countdown=59; // 设置倒计时为59秒
  state=0;
}
void keyboardScan()// 按键扫描函数
{
  if(k1==0)// 按下设置键k1
  {
  	delay(5);
    TR0=0; // 定时器0停止
    state=1; // 设置状态
  }
  if(state==1)// 设置状态
  {
    delay(5);
    if(k2==0) // 按下增一键k2
    {
      delay(5);
      countdown++; // 倒计时+1
      if(countdown==100)
      {
        countdown=0; // 如果倒计时大于99,重置倒计时为0
      }
      while(!k2)// 不断刷新数码管
      {
        shi=countdown/10;
        ge=countdown%10;
        P0=DuanMa[shi];
        P2=DuanMa[ge];
      }
    }
    if(k3==0)// 按下减一键k3
    {
      delay(5);
      countdown--; // 倒计时+1
      if(countdown==-1)
      {
        countdown=99; // 如果倒计时小于-1,重置倒计时为99
      }
      
      while(!k3)// 不断刷新数码管
      {
        shi=countdown/10;
        ge=countdown%10;
        P0=DuanMa[shi];
        P2=DuanMa[ge];
      }
    }
    if(k4==0)// 按下确定键盘K4
    {
      delay(5);
      TR0=1;// 启动定时器
      state=0;
    }
  }
}
void refresh() interrupt 1 // T0中断函数
{
  TH0=(65536-50000)/256;// 初始化定时器0
  TL0=(65536-50000)%256;
  count++; // 计算器+1
  if(count==20)
  {
    count=0;
	  countdown--;
  }
  if(countdown==-1)
  {
    TR0=0;// 停止定时器0
    while(k1!=0)
    {
      P0=0x00;//十位显示0
      P2=0x00;//个位显示0
      delay(500);
      P0=0xff;//十位显示8
      P2=0xff;//个位显示8
      delay(500);
    }
  }
  shi=countdown/10;
  ge=countdown%10;
  P0=DuanMa[shi];
  P2=DuanMa[ge];
}
void main() // 主函数
{
  init();// 调用初始化函数
  while(1)// 死循环
  {
	  keyboardScan();// 调用按键扫描函数
  }
}

四、结果

 五、心得体会

        单片机课程设计终于顺利完成了,其中包含着快乐,也有辛酸。我们选的设计题目是“定时报警器”,刚开始大家都觉得这个题目是比较简单的。实际做了之后,发现设计电路虽然简单,但程序设计是却漏洞百出,好在我们四人迅速分工去上网找一些相关资料,并且请教指导老师,透过不断努力,终于成功实现其功能。

        这次设计让我们受益匪浅,理解到完成一个出色的作品,单靠一个人的力量是不行的,小组成员之间必须相互配合,相互支持,相互团结,所以这也是一次锻炼我们团队合作精神的机会。

六、参考文献

[1] 张毅刚.单片机原理及应用[M].4版.北京:教育出版社,2021

[2] 张毅刚.单片机原理及应用-C51编程 + Proteus 仿真[M].2版.北京:教育出版社,2016

[3] 王幸之.AT89系列单片机原理与接口技术[M].北京:北京航空航天大学出版社,2004

物联沃分享整理
物联沃-IOTWORD物联网 » 《基于单片机的定时报警器课程设计》

发表评论