历史上的今天
今天是:2025年08月06日(星期三)
2021年08月06日 | 基于51单片机的电子秒表设计
2021-08-06 来源:eefocus
设计要求:
最多可记录十组数据
可删除其中多组数据
可上下查阅所记录的数据
数据通过lcd1602显示
计时精度到0.01s
由于并没有使用24c02,导致程序去数据较大,仿真可能不行。实际验证通过
程序界面如图:

仿真界面如图:

如果编译出错,将keil按如图参数设置:

以下为程序代码:
包括两个文件,主程序里面是:
#include<1602.h>
#include #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif /*按键定义*/ /*开始键,计数键,停止计数键或者清零键,上下查阅键,删除数据键*/ sbit key_start=P1^0; sbit key_count=P1^1; sbit key_stop=P1^2; sbit key_up=P1^3; sbit key_down=P1^4; /*变量定义*/ int count=0;//计数器 uint i,j,state,k=0,countnum,m,delete; /*设置标志位*/ char flag; char maxflag; char clearflag; char turnflag; // char upflag; //为1时可以继续上翻 char minflag=0; //为0时可以继续下翻 char downflag; /*定义数组 */ unsigned char str[] = "time:"; unsigned char str2[]= "num:"; unsigned char str3[]="...press start.."; unsigned char str4[]="....counting...."; unsigned char str5[]=".. press count.."; unsigned char str6[]="press up or down"; unsigned char str7[]="..overcounting.."; int number[10]=0; int num2[5]=0; void keyscan(); void init(); void main() { InitLcd1602(); init(); /*以下为调试程序段*/ LcdShowStr(0,0,str3); // LcdShowStr(0,1,str2); // LcdWriteCom(0x91); // LcdWriteData('0'+1); // LcdWriteCom(0x90); // LcdWriteData('0'+1); /*以上为调试程序段*/ while(1) { //LcdShowStr(0,1,str4); //测试 keyscan(); Lcd1602_Delay1ms(50); } } void init() { IT0=0; EX0=0; TMOD=0x01; TH0=(65536-10000)/256; TL0=(65536-10000)%256; EA=0; //开总中断 // key_count=0; // key_stop=0; // key_up=0; // key_down=0; // key_delete=0; flag=0; //标志位为0时代表未计时状态,为1时代表为计时状态 i=0; maxflag=0;//定时标志位,为1时代表定时已满 clearflag=0;//清除标志位 turnflag=0;//为1时可以上下翻页显示 downflag=0; upflag=1; } void keyscan() { if((key_start==0)&&(flag==0)) //防抖处理 { Lcd1602_Delay1ms(10); //防抖处理 if((key_start==0)&&(flag==0))//防抖处理 { while((!(key_start==0)&&(flag==0)));//防抖处理 InitLcd1602(); EA=1;//检测到开始按键按下后,启动定时器 ET0=1; //计时器0开启 TR0=1; //计时器打开 flag=1;//设置标志位为计时状态 LcdShowStr(0,0,str4); LcdShowStr(0,1,str5); } } if((key_count==0)&&(flag==1)&&(maxflag==0)) { Lcd1602_Delay1ms(50); if((key_count==0)&&(flag==1)&&(maxflag==0)) { while(!((key_count==0)&&(flag==1)&&(maxflag==0))); InitLcd1602(); LcdShowStr(0,0,str); LcdShowStr(0,1,str2); number[i]=count; LcdWriteCom(0xC7); LcdWriteData('0'+i+1); LcdWriteCom(0xC6); LcdWriteData('0'); if(i==9) { LcdWriteCom(0xC7); LcdWriteData('0'); LcdWriteCom(0xC6); LcdWriteData('0'+1); } num2[0]=number[i]/10000; num2[1]=number[i]/1000%10; num2[2]=number[i]/100%10; num2[3]=number[i]/10%10; num2[4]=number[i]%10; LcdWriteCom(0x86); LcdWriteData('0'+num2[0]); LcdWriteCom(0x87); LcdWriteData('0'+num2[1]); LcdWriteCom(0x88); LcdWriteData('0'+num2[2]); LcdWriteCom(0x89); LcdWriteData('.'); LcdWriteCom(0x8A); LcdWriteData('0'+num2[3]); LcdWriteCom(0x8B); LcdWriteData('0'+num2[4]); LcdWriteCom(0x8D); LcdWriteData('S'); i++; state=i; if(i==10) { maxflag=1; } } } if(key_stop==0) { Lcd1602_Delay1ms(50); if(key_stop==0) { while(!(key_stop==0)); if(clearflag==0) { TR0=0; //关定时器,查阅时定时就停止 EX0=1; //开外部中断,保证只有在上下翻阅时才能触发外部中断 count=0;//计数清零 clearflag=1;//清除标志位打开,也就是说再按一下这个按键所有制清零 turnflag=1; minflag=0; } else if(clearflag==1)//此块执行清除任务 { InitLcd1602(); number[10]=0; clearflag=0; LcdShowStr(0,0,str3); turnflag=0; maxflag=0; flag=0; i=0;//将数组计数给清零 } } } if(key_up==0) { Lcd1602_Delay1ms(50); if(key_up==0) { while(!(key_up==0)); if(upflag==0) { InitLcd1602(); LcdShowStr(0,0,str); LcdShowStr(0,1,str2); minflag=0;//只要上翻过后都可以下翻 state++; if(state==10) { LcdWriteCom(0xC7); LcdWriteData('0'); LcdWriteCom(0xC6); LcdWriteData('0'+1); } else { LcdWriteCom(0xC7); LcdWriteData('0'+state); LcdWriteCom(0xC6); LcdWriteData('0'); } m=state-1; delete=m; /*显示时间*/ num2[0]=number[m]/10000; num2[1]=number[m]/1000%10; num2[2]=number[m]/100%10; num2[3]=number[m]/10%10; num2[4]=number[m]%10; LcdWriteCom(0x86); LcdWriteData('0'+num2[0]); LcdWriteCom(0x87); LcdWriteData('0'+num2[1]); LcdWriteCom(0x88); LcdWriteData('0'+num2[2]); LcdWriteCom(0x89); LcdWriteData('.'); LcdWriteCom(0x8A); LcdWriteData('0'+num2[3]); LcdWriteCom(0x8B); LcdWriteData('0'+num2[4]); LcdWriteCom(0x8D); LcdWriteData('S'); if(state==10) { upflag=1; } } } } if(key_down==0) { Lcd1602_Delay1ms(50); if(key_down==0) { while(!(key_down==0)); if((turnflag==1)&&(minflag==0)) { InitLcd1602(); LcdShowStr(0,0,str); LcdShowStr(0,1,str2); /*显示组号*/ state--; LcdWriteCom(0xC7); LcdWriteData('0'+state); LcdWriteCom(0xC6); LcdWriteData('0'); k=state-1; delete=k; /*显示时间*/ num2[0]=number[k]/10000; num2[1]=number[k]/1000%10; num2[2]=number[k]/100%10; num2[3]=number[k]/10%10; num2[4]=number[k]%10; LcdWriteCom(0x86); LcdWriteData('0'+num2[0]); LcdWriteCom(0x87); LcdWriteData('0'+num2[1]); LcdWriteCom(0x88); LcdWriteData('0'+num2[2]); LcdWriteCom(0x89); LcdWriteData('.'); LcdWriteCom(0x8A); LcdWriteData('0'+num2[3]); LcdWriteCom(0x8B); LcdWriteData('0'+num2[4]); LcdWriteCom(0x8D); LcdWriteData('S'); if(state==1) { minflag=1; } upflag=0; } } } } void timer0() interrupt 1 { TH0=(65536-10000)/256; TL0=(65536-10000)%256; count++; if(count==6000) { count=0; ET0=0; //计时器0关闭 TR0=0; //计时器关闭 turnflag=1; EX0=1; InitLcd1602(); LcdShowStr(0,0,str6); LcdShowStr(0,1,str7); } } void counter0(void) interrupt 0 using 1 { number[delete]=0; LcdWriteCom(0x86); LcdWriteData('0'); LcdWriteCom(0x87); LcdWriteData('0'); LcdWriteCom(0x88); LcdWriteData('0'); LcdWriteCom(0x89); LcdWriteData('.'); LcdWriteCom(0x8A); LcdWriteData('0'); LcdWriteCom(0x8B); LcdWriteData('0'); LcdWriteCom(0x8D); LcdWriteData('S'); } 然后是lcd的驱动程序: #include<1602.h> void Read_Busy() //忙检测函数,判断bit7是0,允许执行;1禁止 { unsigned char sta; // LCD1602_DB = 0xff; LCD1602_RS = 0; LCD1602_RW = 1; do { LCD1602_EN = 1; sta = LCD1602_DB; LCD1602_EN = 0; //使能,用完就拉低,释放总线 }while(sta & 0x80); } void Lcd1602_Write_Cmd(unsigned char cmd) //写命令 { Read_Busy(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD1602_EN = 1; LCD1602_EN = 0; } void Lcd1602_Write_Data(unsigned char dat) //写数据 { Read_Busy(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD1602_EN = 1; LCD1602_EN = 0; } void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示 { unsigned char addr; if(y == 0) addr = 0x00 + x; else addr = 0x40 + x; Lcd1602_Write_Cmd(addr|0x80); } void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串 { LcdSetCursor(x,y); //当前字符的坐标 while(*str != '




