4.可预置起始时刻的倒计时程序
在2010 年第2 期《PIC单片机C 语言程序(5)》一文中,我们介绍了可预置起始时刻的时钟的硬件电路并给出了C 语言程序。下面要介绍的可预置起始时刻的倒计时程序,是作为日常生活中对某事件的定时之用:只要某事件由人工设置的计时时间到,倒计时电路便会发出报警声。倒计时的特点是,计时一旦达到预定值,其值就归零。利用归零条件,即可实现任意倒计时达到时的报警功能,提示人们定时已到。
本倒计时器可在0~99 分钟内任意设置计时值。
例如在厨房中,蒸大米饭(8 两米),定时33 分钟,烧开水(一壶)为20 分钟,煮胡罗卜(红色)为30 分钟等,只要设定时间一到,倒计时器即报警,使用十分方便。当然,上述倒计时值,均是事先用普通时钟确定每个事件所要花费的时间,列出相应定时标准,才能用倒记时器进行定时。
(1)硬件电路。
图6 是0~99 分钟可预置的倒计时电路。
PIC16F84A单片机④脚为手动复位端,外接R1、D0、C6、K0(微动开关)组成复位电路;③脚RA4 外接上电阻R2 和倒计时人工预置开关K1 ;⒄脚RAO 外接R0、V3 和蜂鸣器,组成倒计时值达到(归零)时的自动报警信号。电路中的两位LED 数码管和V1、V2 组成0~99 分钟可预置LED 数码显示电路,其电路原理与2009 年第12 期《PIC 单片机C 语言程序(3)》一文中图3 的起始两位计数电路相似。
( 2) 程序流程图。
图7、图8、图9 分别为0~99 分钟可预置的倒计时程序的主程序、显示函数和键值扫描程序流程图。通过流程图,读者可以加深对于倒计时程序设计原理和对2010 年第2 期《PIC 单片机C 语言程序(5)》一文中可预置时钟电路程序的理解。
图7 倒计定时主程序流程图
图8 倒计时显示函数流程图
图9 倒计时键值扫描流程图
(3)倒计时的C 程序。
根据图7~ 图9 编写的的倒计时C 程序(命名为pic06.c)清单如下:
#include<pic.h>
#define PORTAIT(add,bit)((unsigned)(&add)*8+(bit))
static bit PORTA_0 @PORTAIT(PORTA,0);
//pic16F84A
static bit PORTA_1 @PORTAIT(PORTA,1);
static bit PORTA_2 @PORTAIT(PORTA,2);
//A 口的位定义
static bit PORTA_3 @PORTAIT(PORTA,3);
static bit PORTA_4 @PORTAIT(PORTA,4);
unsigned int ttr=0;
// 无符号整形变量ttr,并赋值0
unsignedcharx=0,sign_a=0;
// 字符变量X,标志位并赋值0
void key_server(); // 键值服务函数
void display(unsigned int x);
// 带形参X 的显示函数
void display_set(unsigned int x);
// 带形参X 的键值显示函数
void delay_1m(); // 按键延时函数
void delay(unsigned long int k ) // 延时函数
{
unsigned long int i; // 无符号整形变量i
for(i=0;i<=k;i++) // for 语句
continue; // 继续循环
}
void display(unsigned int x) // 显示函数开始
{
unsigned int d=5800,unit_bit,ten_bit,
// 整型变量d 并赋值,个、十位
unsigned char SEG7[10]={0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 引用数组字符段码
unit_bit=x%10; //picc 编译器可识别的个位
ten_bit=x/10%10; // picc 可识别的十位
while(d>0) // while 语句
{
PORTA|=0x1E; // 关显示
PORTB=SEG7[unit_bit];
// 个位字段码送B 口
RA3=0; // 显示个位
delay(200); // 延时以便观察
RA3=1; // 关个位显示
delay(2); // 延时
PORTB=SEG7[ten_bit];
// 十位字段码送B 口
RA2=0; // 显示十位
delay(200); // 延时以便观察
RA2=1; // 关十位显示
delay(2); // 延时
d--; // d 从5800 开始自减量
if( PORTA_4==0) // K1 未按下
{
while(1) // 执行while 语句
{
if( PORTA_4==1) // K1 按下,执行以下程序
{
sign_a=1;
x=0;
d=0;
RA0=0;
break; // 跳出循环
}
}
}
}
}
void main( ) // 主程序开始
{
TRISB=0x00;
//16F84A口初始化,B 为输入
TRISA=0x10;// A4 输入,其余输出
PORTB=0xFF;
INTCON=0x00;
PORTA=0xFF; 关显示
RA0=0; 关报警
x=0; // 给整型变量X 赋值0
while(1) // while 循环语句开始
{
while(x>0)
{
display(x); // 调显示函数
key_server(); // 调键值服务函数
x--; // 分自减量(倒计时)
}
if (x==0) // 如果X=0
RA0=1; // RA0 赋值1(报警信号)
display_set(x); // 调键值显示函数
key_server(); // 调键值服务函数
}
}
void key_server()// 键值服务程序开始
{
unsigned int value=0; // 给存储显示值赋0
display_set(x); // 调键值显示函数
if( PORTA_4==0 ) // 如果RA4 为0
{
while(1)
{
x++; // 键值X 自增
if(x>99) // 如果键值X>99
x=0; // 给X 赋值0
display_set(x); // 调键值显示函数
delay_1m(); // 按键延时,以便观察
if(PORTA_4==1) // 如果RA4 为高电平
{
sign_a=0; // 清零设定时间标志位
RA0=0; // 给RA0 赋值0
break; // 跳出循环返回
}
}
}
}
void display_set(unsigned int x)
// 键值显示函数开始
{
unsigned int d=20,unit_bit,ten_bit,unsigned char SEG7[10]={0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unit_bit=x%10;
// 这里的注释与display 的函数相似
ten_bit=x/10%10;
while(d>0)
{
PORTA=0x1e;
PORTB=SEG7[unit_bit];
RA3=0;// 显示个位
delay(200);
RA3=1;
delay(2);
PORTB=SEG7[ten_bit];
RA2=0;// 显示十位
delay(200);
RA2=1;
delay(2);
d--;
}
}
void delay_1m()
// 按键(图6 的K1)延时函数开始
{
unsigned long int k; // 说明语句
for(k=0;k<4;k++) // for 语句
{
display_set(x); // 调用键值显示函数
}
}
说明: 上述C 程序经picc 编译后生成。hex,即可用PIC 单片机编程器将。hex 烧写到pic16F84A芯片中,再按图6 电路制成倒计时器,即可按需要使用。