单片机实现秒表计数器
最近博主在学习单片机的课程,这快到期末考试了,老师让做个简单的课设,我看了看老师给的课题,感觉这个比较容易实现,今天下午花了两个小时左右的时间,把仿真程序电路图画好了,现在分享大家,希望大家批评改正。
实验器材:**单片机、按钮、电阻、PNP型三极管、有源蜂鸣器、共阴极数码管
实现的功能:
-
通过按键实现倒计时
-
逐秒倒计时
-
使用4为一体数码管显示时间
-
时间到发出警报声,或者在数码管闪烁显示0000
仿真电路图:推荐使用网络标号连接电路图,这样作图较为专业,适合以后的大点的作图方式。网络标号相同的即为相连接的,图貌似不是很清晰,如果看不清,评论区留言,我发给你proteus仿真文件。
程序代码:148行程序,不是太长
//尽本人最大的努力,将程序中的每条语句较为详细的讲解
#include <reg51.h>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
uchar count=0,minute=0,second=3,flag=0,stop=0;
uchar table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极
uchar disbuf[4]={0};//位选定义一个四位的数组,循环扫描显示相应的内容
sbit buzzer=P1^0;//定义单片机的相应引脚
sbit P1_1=P1^1;
sbit P1_2=P1^2;
void delay_ms(uint x) //延时消抖函数
{uint t;
while(x--) for(t = 0; t < 120; t++);
}
void display()//模块化书写函数,进行相应的调用,实现模块化编程
{
uchar i,j;
uchar sel;
disbuf[0]=second%10; //disbuf[]每一个元素赋值,对秒赋值
disbuf[1]=second/10;
disbuf[2]=minute%10;//对分钟赋值
disbuf[3]=minute/10;
P2=0XFF; //P2口接数码管的位选端,选择哪个数码管工作 共阴极数码管,位选0时有效 先置FF,使为选段为高电平,数码管不工作
sel=0x01;//定义一个扫描的位选端
for(i=0;i<4;i++)
{
j=disbuf[i]; //扫描依次显示四个数码管 上面的赋值已经将disbuf数值更改,也就是1~9
P0=table[j]; //将字形码发送到P0端口,显示位的数据
P2=(sel^0xff); // ^异或相异为1,保证每次都有一个数码管点亮
delay_ms(1); // 延时后,防止程序运行太快,跑飞
P2=0XFF;
sel=sel<<1; // 左移运算 0x01左移,1将依次在四位上循环
}
}
void modify_time()//更改计时器时间的函数,修改初始定时时间
{
if(flag==0)//修改秒
{
second++;
if(second==60)//秒的最大为60,然后会发生进位
{
second=0;
disbuf[0]=0;
disbuf[1]=0;
}
}
else//修改分钟
{
minute++;
if(minute==60)//分钟最大为60,到60以后会发生进位
{
minute=0;
disbuf[2]=0;
disbuf[3]=0;
}
}
}
void main(void)//主函数
{
TMOD=0x01;//定时器T0,工作方式1,为16位定时器
TH0=(65536-50000)/256;//高8位赋值
TL0=(65536-50000)%256;//低8位赋值
TR0=0;//默认情况下,定时器不工作,在外部的触发情况下,定时器,工作,开始减1运算
ET0=1;//打开定时器T0的中断
IT0=1;//设置外部中断0的触发方式
EX0=1;//打开外部中断的中断
IT1=1;//设置外部中断0触发方式
EX1=1;//打开外部中断1中断
EA=1;//总中断
while(1)
{
if(stop==1)//当计时倒计时完成以后,屏幕闪烁显示
{
while(1)
{
P2=~P2;
delay_ms(150);
}
}
else
display();//调用显示函数,依次减一
if(!P1_1)//判断更改时间按键是否按键 进行相应的消抖
{
while(!P1_1)
delay_ms(10);
if(P1_1)
modify_time();//调用调日期时间的函数
}
}
}
void inter1() interrupt 1//定时器T0的中断
{
count++;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
if(count==20)//50ms 20次即为1s
{
count=0;
second--;
if(second==0)//该处的程序结构应该仔细看下
{
if(minute!=0)//防止minute最后为0的时候,还执行minute--,使程序出错。
{
minute--;
second=60;
second--;
if(second==0)
{
if(minute==0)
{
second=0;
minute=0;
TR0=0;
count=0;
buzzer=0;
stop=1;
}
}
}
else
{
second=0;
minute=0;
TR0=0;
count=0;
buzzer=0;
stop=1;
}
}
}
}
void inter0() interrupt 0//外部中断0
{
flag=~flag;//flag参数的作用,是修改定时时间的时,确定是分钟位还是小时位。
}
void inter2() interrupt 2//外部中断1
{
TR0=~TR0;//按键3,奇数次按下,定时器开始工作,偶数次关闭。
}
所用器材的介绍:
PNP型三极管:判断的依据,可根据,箭头方向来判断,箭头向外NPN,箭头向内PNP
蜂鸣器:选择无源蜂鸣器 并且将电压设置为2V,如果不这样设置,可能蜂鸣器不发声。