如需要源文件可以添加qq群聊获取:662177587
概要
实际设计图
设计内容
设计一个单片机控制的简易定时报警器。要求根据设定的初始值(1-59秒)进行倒计时,当计时到0时数码管闪烁“00”(以1Hz闪烁),按键功能如下:
(1)设定键:在倒计时模式时,按下此键后停止倒计时,进入设置状态;如果已经处于设置状态则此键无效。
(2)增一键:在设置状态时,每按一次递增键,初始值的数字增1。
(3)递一键:在设置状态时,每按一次递减键,初始值的数字减1。
(4)确认键:在设置状态时,按下此键后,单片机按照新的初始值进行倒计时及显示倒计时的数字。如果已经处于计时状态则此键无效。
整体架构流程
根据题目的要求,需要实现如下几个方面的功能。
计时功能:要实现计时功能则需要使用定时器来计时,通过设置定时器的初始值来控制溢出中断的时间间隔,再利用一个变量记录定时器溢出的次数,达到定时1秒中的功能。然后,当计时每到1秒钟后,倒计时的计数器减1。当倒计时计数器到0时,触发另一个标志变量,进入闪烁状态。
显示功能:显示倒计时的数字要采用动态扫描的方式将数字拆成“十位”和“个位”动态扫描显示。如果处于闪烁状态,则可以不需要动态扫描显示,只需要控制共阴极数码管的位控线,实现数码管的灭和亮。
键盘扫描和运行模式的切换:主程序在初始化一些变量和寄存器之后,需要不断循环地读取键盘的状态和动态扫描数码管显示相应的数字。根据键盘的按键值实现设置状态、计时状态的切换。
技术细节
- 主函数.c
#include <STC89C5xRC.H>
#include "Timer0.h"
#include "Nexie.h"
unsigned char startnum=1; //³õÖµ£¬³õʼֵΪ1
unsigned char long_flag=0,long_flag1=0;//ÓÃÓÚ¼Ó¼õ5µÄÅжϱê־λ
bit set_flag=1;
bit zero_flag=0;
bit show_flag=1;
/**
* @brief °´¼üɨÃè
* @param ÎÞ
* @retval ÎÞ
*/
void Key_Loop()
{
static unsigned char count,count1,count2,count3;
if(set_flag==1) //ÅжÏÊÇ·ñΪÉèÖÃģʽ,·ñÔò¼Ó¼õ°´¼üʧЧ
{
if(P32==0)
{
count++;
if(count>100) //˵Ã÷Êdz¤°´
{ //Ö´ÐмӼõ5µÄ²Ù×÷
long_flag=1;
count--; //ΪÁ˲»ÈüÆÊýÖµ³¬¹ý·¶Î§
}
}
if(P32==1)
{
if(count>2) //˵Ã÷Ö»Êǵ¥»÷
{ //Ö´ÐмӼõ1µÄ²Ù×÷
startnum++;
if(startnum>59) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{startnum=1;}
}
long_flag=0;
count=0;
}
if(P33==0)
{
count1++;
if(count1>100) //˵Ã÷Êdz¤°´
{ //Ö´ÐмӼõ5µÄ²Ù×÷
long_flag1=2;
count1--; //ΪÁ˲»ÈüÆÊýÖµ³¬¹ý·¶Î§
}
}
if(P33==1)
{
if(count1>2) //˵Ã÷Ö»Êǵ¥»÷
{ //Ö´ÐмӼõ1µÄ²Ù×÷
startnum--;
if(startnum<1) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{startnum=59;}
}
long_flag1=0;
count1=0;
}
}
if(P30==0)//¸Ã°´¼üΪÉèÖð´¼ü
{
count2++;
}
if(P30==1)
{
if(count2>2) //˵Ã÷Ö»Êǵ¥»÷
{
if(zero_flag==1)//Èç¹û0µÄ±ê־λÖÃ1
{startnum=1;} //Ôò°´Ï°´¼üµÄ»°°Ñ¼ÆÊýÖµÖÃ1
set_flag=1; //°ÑÉèÖñê־λÖÃ1£¬±íʾĿǰΪÉèÖÃģʽ
zero_flag=0; //°Ñ0±ê־λÖÃ0ΪÏ´ε¹¼Æʱ׼±¸
show_flag=1; //ÏÔʾ±ê־λÖÃ1±íʾÏÔʾ
}
count2=0;
}
if(P31==0)//¸Ã°´¼üΪȷÈÏ°´¼ü
{
count3++;
}
if(P31==1)
{
if(count3>2) //˵Ã÷Ö»Êǵ¥»÷
{
set_flag=0; //°ÑÉèÖñê־λÖÃ1£¬±íʾĿǰΪ¼Æʱģʽ
}
count3=0;
}
}
/**
* @brief ÊýÂë¹ÜÊý×ÖÏÔʾ
* @param ÎÞ
* @retval ÎÞ
*/
void num_show()
{
if(show_flag==1)//Èç¹ûÊÇÏÔʾ£¬ÔòÏÔʾÊý¾Ý
{
Nixie_SetBuf(1,startnum/10%10);
Nixie_SetBuf(2,startnum%10);
}
else //·ñÔòÏÔʾϨÃð
{
Nixie_SetBuf(1,10);
Nixie_SetBuf(2,10);
}
}
void main()
{
Timer0_Init(); //¶¨Ê±Æ÷0³õʼ»¯
while(1)
{
num_show();
}
}
/**
* @brief ¶¨Ê±Æ÷0µÄÏà¹Ø²Ù×÷
* @brief ¶¨Ê±Æ÷0Ϊģʽ1,16Ϊ²»×Ô¶¯ÖØÔØ,1msÖжÏ
* @param ÎÞ
* @retval ÎÞ
*/
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count0,T0Count1,T0Count2,T0Count3,T0Count4;//¶¨Ê±Æ÷Ïà¹Ø±äÁ¿
TL0 = 0x18; //ÉèÖö¨Ê±³õʼֵ
TH0 = 0xFC; //ÉèÖö¨Ê±³õʼֵ
T0Count0++;T0Count1++;T0Count2++;T0Count3++;T0Count4++;//ÿ1ms½øÐÐÒ»´Î++£»
if(T0Count0>=10)//10msµ÷ÓÃÒ»´ÎKey_Loop()º¯Êý
{
T0Count0=0;
Key_Loop();
}
if(T0Count1>=2)//2msµ÷ÓÃÒ»´ÎNixie_Loop()º¯Êý
{
T0Count1=0;
Nixie_Loop();
}
if(T0Count2>=250)//µ÷½Ú¸ÃÖµ¿É¸Ä±ä¼Ó¼õ5µÄËÙ¶È
{
T0Count2=0;
if(long_flag==1)
{
startnum+=5;
if(startnum>59) //ÏÞÖÆ·¶Î§Îª1-59
{startnum=1;}
}
if(long_flag1==2)
{
startnum-=5;
if(startnum>59) //ÏÞÖÆ·¶Î§Îª1-59
{startnum=59;}
}
}
if(T0Count3>=1000)//1sµ¹¼Æʱ
{
T0Count3=0;
if(set_flag==0)
{
if(zero_flag==0)//Èç¹ûÉèÖúÍ0±ê־λ¶¼Îª0£¬Ôò½øÐÐÊý×ֵĵ¹¼Æʱ
{
startnum--;
}
if(startnum==0)//Èç¹ûÉèÖñê־λΪ0ºÍÊý×Ö¼õÉÙµ½0£¬Ôò¹ÒÆð0±ê־λ
{
zero_flag=1;
}
}
}
if(T0Count4>=500)//µ÷½Ú¸ÃÖµ¿É¸Ä±äÉÁ˸ƵÂÊ
{
T0Count4=0;
if(zero_flag==1) //½øÐÐÉÁ˸ÏÔʾ
{
show_flag=!show_flag;
}
else
{
show_flag=1;
}
}
}
- 数码管.c
#include <STC89C5xRC.H>
#include "Delay.h"
unsigned char Nixie_Buf[4]={0,10,10};//0ÊÇΪÁËÕÕÓ¦loopÖÐi=1
unsigned char NixieNumb[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};
/**
* @brief Íⲿµ÷ÓöÔÊý×éNixie_Buf[4]¸³Öµ
* @brief ʹµÃloopº¯ÊýÑ»·¶Ôscanº¯Êý¸³ÖµÊ±¶Áµ½ÏàÓ¦Êý¾Ý
* @brief δ¸³ÖµµÄÊý×éλ¼´Îª10£»¶ÔÓ¦NixieNumb[]ÖеÄ0£»
* @param Table,NumberÔÚNixie_BufÊý×éµÄÏÂ±ê ¸³µÄÖµ£¨¸ÃÖµ¼´¶ÔÓ¦NixieNumb[]ÖеÄÖµ£©
* @retval ÎÞ
*/
void Nixie_SetBuf(unsigned char Table,Number)
{
Nixie_Buf[Table]=Number;
}
/**
* @brief ÊýÂë¹ÜÏÔʾ
* @param Table,NumberÏÔʾµÄλÖà ÏÔʾµÄÊý×Ö
* @param Á½²ÎÊýÓɶ¨Ê±Æ÷°´ÖÜÆÚɨÃèʱ¸ø¶¨
* @retval ÎÞ
*/
void Nixie_Scan(unsigned char Table,Number)
{
P0=0x00;//ÏûÒþ
switch(Table)
{// P2_4=C-4,P2_3=B-2;P2_2=A-1
case 1:P24=1;P23=1;P22=1;break;
case 2:P24=1;P23=1;P22=0;break;
}
P0=NixieNumb[Number];//²»ÓÃdelayÔÙÏûÒþ£¬ÒòΪ¶¨Ê±Æ÷½øÀ´ÓÐʱ¼ä¼ä¸ô
}
/**
* @brief ¶¨Ê±Æ÷µ÷Óõĺ¯Êý
* @param ÎÞ
* @retval ÎÞ
*/
void Nixie_Loop(void)//¶¨Ê±Æ÷ÿ½øÒ»´Î¾Íµ÷ÓÃÒ»´Îscanº¯Êý
{ //ʹµÃ3¸öÊýÂë¹ÜÒÀ´Î¿ìËÙÏÔʾ
static unsigned char i=1;
Nixie_Scan(i,Nixie_Buf[i]);
i++;
if(i>=3)i=1;
}
- 数码管.h
#ifndef __NEXIE_H__
#define __NEXIE_H__
void Nixie_Scan(unsigned char Table,Number);
void Nixie_Loop(void);
void Nixie_SetBuf(unsigned char Table,Number);
#endif
- 定时器.c
#include <STC89C5xRC.H>
/**
* @brief ¶¨Ê±Æ÷³õʼ»¯
* @param ÎÞ
* @retval ÎÞ
*/
void Timer0_Init(void) //100us@12.000MHz
{
TMOD &= 0xF0; //¶¨Ê±Æ÷ʱÖÓ12Tģʽ
TMOD |= 0x01; //ÉèÖö¨Ê±Æ÷ģʽ
TL0 = 0x18; //ÉèÖö¨Ê±³õʼֵ
TH0 = 0xFC; //ÉèÖö¨Ê±³õʼֵ
TF0 = 0; //Çå³ýTF0±êÖ¾
TR0 = 1; //¶¨Ê±Æ÷0¿ªÊ¼¼Æʱ
ET0=1;
EA=1;
PT0=0;
}
- 定时器.h
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0_Init(void);
#endif
小结
设计一个单片机控制的简易定时报警器。要求根据设定的初始值(1-59秒)进行倒计时,当计时到0时数码管闪烁“00”(以1Hz闪烁)
如需要源文件可以添加qq群聊获取:662177587
希望对你有所帮助!