`/* PIC16F630为核心的厨房定时器 注:所有的I/O口都用完
* 功能:倒(正)计时1秒-99分59秒
* 显示:数码管显示分钟和秒钟;双色LED秒闪显示秒状态;两种LED分别显示功能状态:倒计 时橙色灯和正计时绿色灯显示。
* 提示音:1、计时结束:嘟嘟嘟连续响五次;2、正计时逢5分钟提示一个长音:嘟;3、正计时逢10分钟提示两个半长音:嘟-嘟
* 人机交互:五个按键分别是启动/停止;正/倒计时;加十分;加1分;加1秒/暂停/继续
* 电源开启:默认倒计时状态-加分加秒-启动
* 计时精度依赖于PIC16F630内部振荡器(4M)的精度和程序设计定时器初值的设定
*/
/* 本程序已经成功制作出成品,外壳使用的是银行点钞机外显示外壳
#include
__CONFIG(0x3184); //配置:禁止数据和程序的代码保护;禁止低电压检测;RA3作为普通I/O口
;上电复位开;看门狗关闭;使用内部振荡器。
//输入键:RA3,RC1,RC3,RC4,RC5。其余键均为输出
#define BZZP RC2 //蜂鸣器接口
#define CLK RA5 // 74HC164时钟输入
#define DAT RA4 // 74HC164数据端口
#define WEI3 RA0 // 秒十位
#define WEI4 RA1 // 秒个位
#define WEI1 RA2 // 分十位
#define WEI2 RC0 // 分个位
#define QID RC1 //启动/停止键
#define ZDAO RC3 //正/倒计时
#define JSHF RC4 //加十分
#define JGOF RC5 //加个分
#define JMIAO RA3 //加秒
#define uchar unsigned char
#define uint unsigned int
uchar timecnt = 0,fs=0,fg=0,ms=0,mg=0;
bit zhengdao,qidong,zhantin;
//mss:秒闪烁;zdjs:正倒计时0倒1正;qdtz:启动停止0停1动;ztjx暂停/继续 0暂停 1继续
const unsigned char LED[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//0-9十个数值的编码(共阴数码管)
void delay(uint);//延时函数
void dududu(void);//嘟嘟嘟
void changdu(void);//长嘟
void dudu(void);//嘟嘟
void smduan(uchar);//写串行数据入164
void keytest(void); //键扫描函数
void Init(void); //初始化子函数
void zhengjishi(void); //正计时函数
void daojishi(void); //倒计时函数
void interrupt ISR(void) //PIC单片机的所有中断都是这一个入口
{
if(TMR1IF==1) //需要进一步判断是否是T1中断
{
TMR1H=0x0B; //重置初值
TMR1L=0xEA; //重置初值 E9
TMR1IF=0; //清中断标志位,以备下次中断
//***此处用户自行添加定时器T1中断处理程序***
timecnt++;
if(timecnt==2)
{timecnt=0;
if(qidong==1)
{ if(zhengdao==1) zhengjishi();
else daojishi();
}
}
}
}
main()
{
uchar x;
Init();
while(1)
{
keytest();
if(fs>0)
{smduan(LED[fs]);
WEI1=0;
delay(3);
WEI1=1;
}
if(timecnt==1) x=LED[fg]+0x80;
else x=LED[fg];
smduan(x);
WEI2=0;
delay(3);
WEI2=1;
if(zhengdao==0) x=LED[ms]+0x80;
else x=LED[ms];
smduan(x);
WEI3=0;
delay(3);
WEI3=1;
if(zhengdao==1) x=LED[mg]+0x80;//正计时灯亮
else x=LED[mg];
smduan(x);
WEI4=0;
delay(3);
WEI4=1;
}
}
void zhengjishi(void) //正计时函数
{
mg++;
if(mg==10)
{ mg=0;
ms++;
if(ms==6)
{
ms=0;
fg++;
if(fg==5) changdu();
if(fg==10)
{
fg=0;
fs++;
dudu();
if(fs==10)
fs=0;
}
}
}
}
void delay(uint x) //延时函数
{
uint a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
void dududu(void) //连续三声嘟
{
uchar i,j;
for(j=5;j>0;j--)
{for(i=3;i>0;i--)
{
BZZP=1;
delay(200);
BZZP=0;
delay(30);
}
delay(300);
}
}
void changdu(void) //长嘟
{
BZZP=1;
delay(300);
BZZP=0;
}
void dudu(void) //两声嘟
{
uchar i;
for(i=2;i>0;i--)
{
BZZP=1;
delay(200);
BZZP=0;
delay(20);
}
}
//按键处理程序
void keytest(void)
{
if(QID==0)
{
while(QID==0) //按键去抖
{ delay(100);}
qidong=!qidong;
if(qidong==0)
{
TMR1ON=0; //关闭定时器1
fs=fg=ms=mg=0;
zhengdao=0; //停止时默认倒计时
}
else TMR1ON=1; //启动定时器1
}
///////////////// 正倒计时转换
if(ZDAO==0)
{
while(ZDAO==0) //按键去抖
{ delay(100);}
if(qidong==0) //停止状态有效
zhengdao=!zhengdao;
}
//////////////// 加分十位
if(JSHF==0)
{
while(JSHF==0) //按键去抖
{ delay(100);}
if(zhengdao+qidong==0) // 倒计时和停止状态下才能运行
{
fs++;
if(fs==10) fs=0;
}
}
/////////////////
if(JGOF==0)
{
while(JGOF==0) //按键去抖
{ delay(100);}
if(zhengdao+qidong==0) // 倒计时和停止状态下才能运行
{
fg++;
if(fg==10) fg=0;
}
}
////////////////
if(JMIAO==0)
{
while(JMIAO==0) //按键去抖
{ delay(100);}
if(zhengdao+qidong==0) // 倒计时和停止状态下才能运行
{
mg++;
if(mg==10)
{
mg=0;
ms++;
if(ms==6) ms=0;
}
}
if(qidong==1) //暂停与继续
{
zhantin=!zhantin;
if(zhantin==0)
TMR1ON=0; //暂停:关闭定时器1
else
TMR1ON=1; //继续:开启定时器1
}
}
}
void Init(void) //主函数初始化
{
OPTION=0b10000000; //禁止弱上拉
WPUA= 0x00; //关闭弱上拉
TRISA=0B00001000; //RA3 口做输入,且只能作为输入
TRISC=0B00111010; //RC5,4,3,2做输入,RC0,2做输出
PORTA=0B00001000;
PORTC=0B00111010;
//INTCON=0; //关中断
CMCON=0x07; // 设置全部为普通数字IO口 关闭所有比较器
PIE1 = 0X01; //T1溢出中断使能位
PIR1 = 0X00; //T1溢出标志位,每次溢出都要软件清0
T1CON = 0X05; //设置T1中断参数
//***定时器TMR1初始化***
TMR1CS=0; //TMR1时钟源选择内部指令周期时钟(Fosc/4)
T1CKPS0=1; //1:8预分频比,T1CKPS0=1
T1CKPS1=1; //1:8预分频比,T1CKPS1=1
TMR1H=0x0B; //定时62500×8微秒,置初值为65536-62500+13
TMR1L=0xEA; //定时62500×8微秒,置初值为65536-62500+13
TMR1ON=0; //启动定时器T1(暂停)
TMR1IF=0; //清除T1的中断标志
TMR1IE=1; //T1中断允许
PEIE=1; //外设中断允许,TMR1属于外设中断范围
//**********************
//***开全局中断设置****
//定时器T1设置了中断允许,此处要开全局中断
GIE=1;
WEI1=1;
WEI2=1;
WEI3=1;
WEI4=1;
zhantin=1;
}
void smduan(uchar udata) //向164传输段码
{
uchar i;
for (i=0;i<8;i++)
{
if(udata&0x80)
DAT=1;
else
DAT=0;
CLK=0;
asm("NOP");
asm("NOP");
CLK=1;
udata = udata<<1;
CLK=0;
}
}
void daojishi(void) //倒计时函数
{
if(fs+fg+ms+mg>0)
{
if(mg>0) mg--;
else
{
if(ms>0)
{
ms--;
mg=9;
}
else
{
if(fg>0)
{
fg--;
ms=5;
mg=9;
}
else
{
if(fs>0)
{
fs--;
fg=9;
ms=5;
mg=9;
}
}
}
}
}
else
{dududu(); //倒计时}时间到,蜂鸣器工作
zhengdao=1; //正计时开始
}
}
电路图:
正计时状态:
倒计时状态:
|