单片机控制的简易定时报警器电路设计(含电路图和程序)

2011-08-27 16:53:03来源: 互联网

设计一个单片机控制简易定时报警器。要求根据设定的初始值(1-59秒)进行倒计时,当计时到0时数码管闪烁“00”(以1Hz闪烁),按键功能如下:
(1)设定键:在倒计时模式时,按下此键后停止倒计时,进入设置状态;如果已经处于设置状态则此键无效。
(2)增一键:在设置状态时,每按一次递增键,初始值的数字增1。
(3)递一键:在设置状态时,每按一次递减键,初始值的数字减1。
(4)确认键:在设置状态时,按下此键后,单片机按照新的初始值进行倒计时及显示倒计时的数字。如果已经处于计时状态则此键无效。
3.1.2 模块1:系统设计
(1)任务分析与整体设计思路
根据题目的要求,需要实现如下几个方面的功能。
计时功能:要实现计时功能则需要使用定时器来计时,通过设置定时器的初始值来控制溢出中断的时间间隔,再利用一个变量记录定时器溢出的次数,达到定时1秒中的功能。然后,当计时每到1秒钟后,倒计时的计数器减1。当倒计时计数器到0时,触发另一个标志变量,进入闪烁状态。
显示功能:显示倒计时的数字要采用动态扫描的方式将数字拆成“十位”和“个位”动态扫描显示。如果处于闪烁状态,则可以不需要动态扫描显示,只需要控制共阴极数码管的位控线,实现数码管的灭和亮。
键盘扫描和运行模式的切换:主程序在初始化一些变量和寄存器之后,需要不断循环地读取键盘的状态和动态扫描数码管显示相应的数字。根据键盘的按键值实现设置状态、计时状态的切换。
   (2)单片机型号及所需外围器件型号,单片机硬件电路原理
选用MCS-51系列AT89S51单片机作为微控制器,选择两个四联的共阴极数码管组成8位显示模块,由于AT89S51单片机驱动能力有限,采用两片74HC244实现总线的驱动,一个74HC244完成位控线的控制和驱动,另一个74HC244完成数码管的7段码输出,在输出口上各串联一个100欧姆的电阻对7段数码管限流。
由于键盘数量不多,选择独立式按键与P1口连接作为四个按键输入。没有键按下时P1.0-P1.3为高电平,当有键按下时,P1.0-P1.3相应管脚为低电平。电路原理图如图3-1所示。

图3-1 定时报警器电路原理图
(3)程序设计思路,单片机资源分配以及程序流程
 ①单片机资源分配
采用单片机的P3口作为按键的输入,使用独立式按键与P3.0-P3.3连接,构成四个功能按键。
在计时功能中,需要三个变量分别暂存定时器溢出的次数(T1_cnt)、倒计时的初始值(init_val)以及当前倒计时的秒数(cnt_val)。
按键扫描功能中,需要两个变量,一个变量(key_val_new)用来存储当前扫描的键值(若无按键按下则为255),另一个变量(key_val_old)用来存储上一次扫描的键值。只有这两个变量值不一样时,才能说明是一次新的按键按下或弹起了,同时将新的键值赋给key_val_old变量。
在显示功能中,需要定义一组数组(code类型),值为0-9数字对应的数码管7段码。还需要定义一个变量(show_val)暂存要显示的数据,用于动态扫描显示中。
在整个程序中,定义了一个状态变量(state_val)用来存储当前单片机工作在哪种状态。
②程序设计思路
鉴于题目要求,存在三种工作模式:初始值设置模式、倒计时模式、计时到0时的闪烁模式。变量state_val为0时,处于倒计时模式。变量state_val为1时,处于初始值设置模式。变量state_val为2时,处于闪烁模式。这些状态的切换取决于按下哪一个键以及是否计时到0。状态的切换图如图3-2

 图3-2 状态的切换
单片机复位之后,默认处于倒计时模式,启动定时器,定时器每隔250us溢出一次,根据定时器溢出次数来计时,到1秒时将时间的计数器减1。当“设置键”按下时,变量state_val由0变为1,切换到设置模式。可以使用“递增键”“递减键”对计时初始值进行修改。按下“确认键”时,回到计时模式开始以新的初始值进行倒计时。当倒计时到0时,变量state_val由1变为2,处于闪烁状态,在这种状态下,根据按键的情况分别又切换到计时和设置状态。
③程序流程
主程序首先需要初始化定时器的参数和一些变量,然后进入一个循环结构,在循环中始终只做两件事,一是键盘的扫描,二是数码管的动态扫描。
在扫描键盘后,根据前一次按键的结果是否与本次键值相同。如果不同,表示有键按下或弹起,同时用本次按键值更新上一次的按键值。这样设计旨在避免一个按键长时间按下时被重复判为有新键按下,使得当前按下的键只有松开后,下一次按下时才算为一次新的按键。
根据按键的值分别改变变量(state_val)的值或者在设置状态时的倒计时初始值。完整的主程序图如图3-3所示。

 图3-3 主程序的流程图
    在定时器的参数中,选择定时器T1的8位自动装载模式,每250us产生一次溢出中断,中断服务程序如图3-4所示。

中断服务程序流程图

(4)软硬件调试方案
     软件调试方案:伟福软件中,在“文件新建文件”中,新建C语言源程序文件,编写相应的程序。在“文件新建项目”的菜单中,新建项目并将C语言源程序文件包括在项目文件中。
 在 “项目编译”菜单中将C源文件编译,检查语法错误及逻辑错误。在编译成功后,产生以 “*.hex”和“*.bin” 后缀的目标文件。
硬件调试方案:在设计平台中,将单片机的P3.0-P3.3分别与独立式键盘的相应位通过插线连接起来。
在伟福中将程序文件编译成目标文件后,运行MCU下载程序,选择相应的flash 数据文件,点击“编程”按钮,将程序文件下载到单片机的Flash中。
然后,上电重新启动单片机,检查所编写的程序是否达到题目的要求,是否全面完整地完成试题的内容。

3.1.3 程序设计(仅供参考的C语言源程序)
//晶振:11.0592M  T1-250微秒 按键P10 P11 P12 P13
/*变量的定义:
  show_val:     显示的值0-59
  init_val:     初始值
  state_val:    状态值 0-计数状态;1-设置状态;2-闪烁状态
  shan_val:
  key_val1:     四个按键的值 255-无键;1-设置键  2-增一键  3-减一键  4-确定键
  T1_cnt:       定时器计数溢出数
  cnt_val:      倒计时的数值
  led_seg_code:数码管7段码
*/
#include "reg51.h"     //包含文件
sbit     P1_0=P1^0;    //设置键
sbit     P1_1=P1^1;    //增一键
sbit     P1_2=P1^2;    //减一键
sbit     P1_3=P1^3;    //确定键
unsigned char data shan_val;  //闪烁时LED的开/关状态
unsigned char data cnt_val;   //保存倒计数的当前值
unsigned int  data T1_cnt;    //保存定时器溢出次数
unsigned char data key_val_new,key_val_old;//存放当前扫描的键和前一次按下的键值
unsigned char data state_val; //状态值
unsigned char data show_val;  //存放需要在数码管显示的数字
unsigned char data init_val;  //暂存倒计数的初始值
char code led_seg_code[10]={0x3f,0x06,0x05b,0x04f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//----------延时--------------
void delay(unsigned int i)   //大约延时i*2个微秒
{  while(--i);}
//-----------按键扫描-------------
unsigned char scan_key()
{  unsigned char i;
   i=P1&0x0f;
   delay(100);           //延时,去抖动
   if (i==(P1&0x0f))
   { if (P1_0==0)
     {  i=1;    }
     else
     { if (P1_1==0)
       { i=2;}
       else
       { if (P1_2==0)
          { i=3;}
          else
          { if (P1_3==0)
            { i=4;} }
       }  }  }
   else
   {  i=255; }
   return i;
}
//---------数码管显示---------------
void led_show(unsigned int v)
{
 unsigned char i;
 if (state_val!=2)     //动态扫描
 {i=v%10;              //取要显示的数的个位
  P0=led_seg_code[i];  //转换为7段码
  P2=0xfe;             //显示个位
  delay(15);           //延时
  i=v%100/10;          //取十位
  P0=led_seg_code[i];  //转换为7段码
  P2=0xfd;             //显示十位
  delay(5);            //延时
 }
 else
 { P0=led_seg_code[0]; //处于闪烁状态
   if (shan_val)
   { P2=0xff; }        //将数码管的关闭
   else
   { P2=0xfc; }         //将数码管的打开
 }
}
//----------定时器T1中断服务程序---------------
void  timer1() interrupt 3     //T1中断,250us中断一次
{ T1_cnt++;
  switch (state_val)
   { case 0:
         if(T1_cnt>3999)       //如果计数>3999, 计时1s
         {  T1_cnt=0;
            if(cnt_val!=0)
            { cnt_val--;}
            else
            {state_val=2;}     //定时计数到0时,切换状态
            show_val=cnt_val;
          }
          break;
      case 2:
         if(T1_cnt>1999)        //如果计数>1999, 计时0.5s
         { T1_cnt=0; shan_val=!shan_val; } //闪烁状态
         break;
     }
}
//---------主程序----------------
main()
{init_val=59;         //初始化各变量
 cnt_val=init_val;
 show_val=cnt_val;
 state_val=0;
 key_val_old=255;
 T1_cnt=0;
 shan_val=0; //初始化51的寄存器
TMOD=0x20;  //用T1计时 8位自动装载定时模式
 TH1=0x19;   //250微秒溢出一次;   250=(256-x)*12/11.0592 -> x= 230.4
 TL1=0x19;
 EA=1;       //打开总中断允许
 ET1=1;      //开中断允许
 TR1=1;      //开定时器T1
while(1)
{  key_val_new=scan_key();         // 255表示无键按下
   if (key_val_new!=key_val_old)
{ // 只有当前扫描的键值与上次扫描的不同,才判断是有键按下
     key_val_old=key_val_new;
     switch (key_val_new)
     { case 1: //设置键
               state_val=1;        //处于设置状态
               TR1=1;              //停止计时
               show_val=init_val;  //显示原来的倒计数初始值
               break;
       case 2: if(state_val==1)    //只有在设置状态,增1键才有用
               { if (init_val>0)   //更改原来的倒计数初始值
                 {init_val--; }
                 else
                 {init_val=59;}
                 show_val=init_val;//显示更改后的倒计数初始值
               }
               break;
       case 3: if(state_val==1)    //只有在设置状态,减1键才有用
               {  if (init_val<59) //更改原来的倒计数初始值
                 {init_val++; }
                 else
                 {init_val=0;}
                 show_val=init_val; //显示更改后的计数初始值
               }
               break;
       case 4: if(state_val!=0)     //如果已处于计数模式,确认键不起作用
               { cnt_val=init_val;  //将初始值赋给计数变量
                 show_val=cnt_val;  //将计数变量的数字显示
                 TR1=1;             //启动定时器T1
                 state_val=0;       //将状态切换为计数模式
               }
               break;
      }
   }
   led_show(show_val);              //动态扫描
}
}

关键字:单片机  控制  简易  报警器

编辑:eeleader 引用地址:http://www.eeworld.com.cn/gykz/2011/0827/article_8323.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
论坛活动 E手掌握
微信扫一扫加关注
论坛活动 E手掌握
芯片资讯 锐利解读
微信扫一扫加关注
芯片资讯 锐利解读
推荐阅读
全部
单片机
控制
简易
报警器

小广播

独家专题更多

TTI携TE传感器样片与你相见,一起传感未来
TTI携TE传感器样片与你相见,一起传感未来
TTI携TE传感器样片与你相见,一起传感未来
富士通铁电随机存储器FRAM主题展馆
富士通铁电随机存储器FRAM主题展馆
馆内包含了 纵览FRAM、独立FRAM存储器专区、FRAM内置LSI专区三大部分内容。 
走,跟Molex一起去看《中国电子消费品趋势》!
走,跟Molex一起去看《中国电子消费品趋势》!
 
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2016 EEWORLD.com.cn, Inc. All rights reserved