标题:
带详细注释的51单片机电子秒表程序
[打印本页]
作者:
帅气的小哥哥
时间:
2021-12-16 10:39
标题:
带详细注释的51单片机电子秒表程序
基于单片机电子秒表设计的一些程序编程
//包含头文件
#include <reg52.h>
//宏定义
#define uc unsigned char
#define ui unsigned int
void display(); //声明显示函数
// 0 1 2 3 4 5 6 7 8 9
uc code tab[]={0x5f,0x44,0x9d,0xd5,0xc6,0xd3,0xdb,0x45,0xdf,0xd7,0x00}; //数字对应显示码表
uc code tab1[]={0x7f,0x64,0xbd,0xf5,0xe6,0xf3,0xfb,0x65,0xff,0xf7}; //带小数点的数字码表
uc code index[]={0x7f,0xbf,0xdf,0xef}; //每位数字对应数码管显示位置
uc num[8]; //num【0】-num【3】是计时用数组,4-7是范围计时用(设置10s,计时到10秒报警)
uc val[10][4]; //存储的记录 [10]为记录序列,[4]为每组记录中的数字
char val_index; //记录序列标志位
uc set_index,ok_flag,timing; //set_index:设置的位。ok_flag:设置状态标志,=0时是正常状态,=1是设置状态。timing:显示状态标志:=0正常显示,=1闪烁设置位
bit mode=1; //运行模式,1为正向计数,0为反向计数。
bit fin_flag=0; //完成标志位,当反向计数结束时,此位为高电平,触发蜂鸣器
bit set_shan;
uc count,beep_stop;
sbit beep=P3^2; //蜂鸣器
sbit key1=P3^3; //功能1:开始&停止计时;//功能2:倒计时数值设置位加1(倒计时数值设置模式下操作闪烁位);
sbit key2=P3^4; //功能1:记录时间点(计时进行中按下记录,停止计时后按下回看);//功能2:倒计时数值设置位切换(倒计时数值设置模式下操作);
sbit key3=P3^5; //功能:计时值归零(随时操作)
sbit key4=P3^6; //功能:正/倒计时模式切换(计时停止状态下操作)
sbit key5=P3^7; //功能:倒计时数值设置模式(计时停止状态下操作)
void delay(ui z) //延时函数,大约延时z ms
{
ui i,j;
for(i=0;i<z;i++)
for(j=0;j<121;j++);
}
void init() //初始化
{
TMOD=0x11; //工作方式
TH0=0x3c;
TL0=0xb0; //定时器0赋初值
TH1=0x3c;
TL1=0xb0; //定时器1赋初值
ET1=1; //允许中断
TR1=1; //定时开关
ET0=1;
TR0=0;
EA=1; //中断总开关
val_index=0; //清零
}
void clr() //清除函数
{
uc i;
for(i=0;i<8;i++) //将存储的数据清零 for循环8次
num[i]=0;
}
void setup() //设置函数
{
ok_flag=0xff; //ok_flag赋值1
set_index=0; //设置位置0
while (ok_flag) //进入设置后,循环,直到ok_flag为0
{
display(); //调用显示函数
if(key1==0) //按动KEY1设置值加1
{
delay(5); //延时去抖
if(key1==0)//再次判断按键是否按下
{
if ((set_index==0)|(set_index==2)|(set_index==4)|(set_index==6))//设置个位数据时
{
num[set_index]++; //数据加
if(num[set_index]==10) //加到10
num[set_index]=0; //清零
}
else if((set_index==1)|(set_index==3)|(set_index==5)|(set_index==7))//设置十位数据时
{
num[set_index]++; //数据加
if(num[set_index]==6) //加到6时
num[set_index]=0; //清零
}
while(!key1) display(); //按键释放
}
}
if(key2==0) //按动KEY2设置位置加1
{
delay(5);//延时去抖
if(key2==0)//再次按下按键
{
set_index++; //设置位置加
if(set_index==8)//设置位置加到最后一位时
{
set_index=0;//设置位置到0
}
while(!key2) display();//按键释放
}
}
if(key5==0) //按动KEY5设置结束
{
delay(5);//延时去抖
if(key5==0)//再次判断按键是否按下
{
ok_flag=0x00;//ok_flag清零
if((num[4]!=0)||(num[5]!=0)||(num[6]!=0)||(num[7]!=0)) //如果计时时间上限设置数据不都为0时
{
num[0]=0;num[1]=0;num[2]=0;num[3]=0;mode=1;//将正计时时间清零,Mode置1,正计时
}
else if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0))//如果计时时间上限设置数据都为0时
{
if((num[0]==0)&&(num[1]==0)&&(num[2]==0)&&(num[3]==0))//判断计时时间都为0
mode=1; //正计时模式
else if((num[0]!=0)||(num[1]!=0)||(num[2]!=0)||(num[3]!=0))//判断计时时间有不为0
mode=0; //倒计时模式
}
while(!key5) display(); //按键去抖
}
}
}
}
void display()
{
uc i;
if(ok_flag!=0xff) //不是设置状态时
{
if(timing==0)
{
for(i=0;i<4;i++)
{
P0=0xff; //清显示
P2=index[i]; //选中位
if(i==2) //如果是第二位时
P0=tab1[num[i]];//显示有小数点的数据
else //不是第二位时
P0=tab[num[i]]; //正常显示数据
delay(2); //修改此参数可修改刷新频率
}
}
else //设置时 闪烁相应位
{
if(set_shan==0)
{
for(i=0;i<4;i++)
{
P0=0xff;
P2=index[i];
P0=tab[10]; //熄灭
delay(2); //修改此参数可修改刷新频率
}
}
else if(set_shan==1)
{ //点亮显示
for(i=0;i<4;i++)
{
P0=0xff;
P2=index[i];
if(i==2)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
}
}
}
}
else //设置时
{
if(set_shan==0)
{
if(set_index==0) //设置不同位时,闪烁相应位
{
for(i=0;i<4;i++)
{
if(i==0)
{
P2=index[0];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i];
if(i==2)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==1)
{
for (i=0;i<4;i++)
{
if(i==1)
{
P2=index[1];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i];
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==2)
{
for (i=0;i<4;i++)
{
if(i==2)
{
P2=index[2];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i];
if(i==2)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==3)
{
for (i=0;i<4;i++)
{
if(i==3)
{
P2=index[3];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i];
if(i==2)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==4)
{
for (i=4;i<8;i++)
{
if(i==4)
{
P2=index[0];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i-4];
if(i==6)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==5)
{
for (i=4;i<8;i++)
{
if(i==5)
{
P2=index[1];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i-4];
if(i==6)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==6)
{
for (i=4;i<8;i++)
{
if(i==6)
{
P2=index[2];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i-4];
if(i==6)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
else if(set_index==7)
{
for (i=4;i<8;i++)
{
if(i==7)
{
P2=index[3];
P0=tab[10];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
else
{
P2=index[i-4];
if(i==6)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
}
else
{
if(set_index<4)
{
for (i=0;i<4;i++)
{
P2=index[i];
if(i==2)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
else
{
for (i=4;i<8;i++)
{
P2=index[i-4];
if(i==6)
P0=tab1[num[i]];
else
P0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
P0=0xff;
}
}
}
}
}
void alarm()
{
if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0)) //计时时间到0时
{
timing=0;
}
else
{
if((num[4]==num[0])&&(num[6]==num[2])&&(num[5]==num[1])&&(num[7]==num[3])) //设置上限模式时,计时时间到
{
timing=1;
TR0=0; //停止计时,并闪烁显示
}
}
}
void main()
{
uc h,g,k;
init();
clr();
while(1)
{
display(); //刷屏显示数码管
alarm();
if(key1==0) //开始/暂停按钮
{
delay(5);
if(key1==0)
{
TR0=~TR0;
while(!key1) display();
}
}
if(key2==0) //记录按钮
{
delay(5);
if(key2==0)
{
if(TR0==1)//当在运行中按下记录键则存储记录
{
for(g=1;g<10;g++)
{
for(k=0;k<4;k++)
{
val[g-1][k]=val[g][k]; //低位存储的数据向高位移一位
}
}
for(h=0;h<4;h++)
{
val[9][h]=num[h];//将当前时间存储
}
}
else//在停止状态下按下记录键查看记录,按动一次序列递减一次,即查看上一次记录
{
for(h=0;h<4;h++)
num[h]=val[val_index][h];//将当前时间存储
val_index--;
if(val_index<0)
val_index=9;
}
while(!key2) display(); //按键释放
}
}
if(key3==0) //复位按钮
{
delay(5);
if(key3==0)
{
clr(); //将数据清零
while(!key3) display(); //按键释放
}
}
if((key4==0)&&(TR0==0)) //模式选择按钮,仅在停止状态下有效
{
delay(5);
if(key4==0)
{
mode=~mode; //正计时倒计时切换
while(!key4) display();
}
}
if((key5==0)&&(TR0==0)) //时间设置,仅在停止状态下有效
{
delay(5);
if(key5==0)
{
while(!key5)
display();
setup(); //调用设置函数
}
}
}
}
void T0_time() interrupt 1
{
uc m;
TH0=0x3c; //12M晶振定时器定时时间为50ms
TL0=0xb0;
m++;
if(m==20)
{
m=0;
if(mode==1) //正向计数
{
num[0]++; //秒个位加
if(num[0]==10) //秒个位加到10时
{
num[0]=0; //个位清零
num[1]++; //秒十位加
if(num[1]==6) //秒十位加到6时
{
num[1]=0; //秒十位清零
num[2]++; //分个位加
if(num[2]==10) //分个位加到10时
{
num[2]=0; //分个位清零
num[3]++; //分十位加
if(num[3]==10)//分十位加到10时
num[3]=0; //分十位清零
}
}
}
}
else
{
num[0]--; //秒个位减
if(num[0]>9) //小于0时,该数字的最高位会变1,所以判断是否大于9 下同
{
num[0]=9;
num[1]--;
if(num[1]>5)
{
num[1]=5;
num[2]--;
if(num[2]>9)
{
num[2]=9;
num[3]--;
if(num[3]>9)
{
num[3]=0;
TR0=0;
fin_flag=1;
clr();
}
}
}
}
}
}
}
void T1_time() interrupt 3 //定时器1的工作函数
{
uc shan,beep_stop;
TH1=0x3c;
TL1=0xb0; //重新赋初值
shan++; //闪烁变量加
if(shan==10) //加到10时(500ms)
{
shan=0; //清零
set_shan=~set_shan; //设置的闪烁变量取反
if((fin_flag)||(timing)) //当反向计数完成时 或计时时间到时
{
beep_stop++;
beep=~beep; //蜂鸣器闪烁响
if(beep_stop==10) //蜂鸣器响五声停止
{
fin_flag=0;
timing=0;
num[4]=0;num[5]=0;num[6]=0;num[7]=0;
beep_stop=0;
beep=1;
}
}
}
}
复制代码
作者:
sanye凉风
时间:
2022-4-13 15:33
有没有仿真图片可以图文来讲解一下吗?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1