C51单片机实现数字秒表计时(分段计时,LCD1602显示,总计时),误差精度在1s之内

一、设计题目:数字秒表设计

二、课程设计内容及要求

        基本要求:

        1.按键2个,一个用于计时开始/停止,一个用于数字清零

        2.数码管显示,数码管初始显示00-00-00(分-秒-毫秒)

        3.基本功能,按计时开始/停止键,数码管从当前计时数字累加,精度为10ms,计时10分钟误差补超过2秒,再按计时开始/停止键,数码管停止计时,按数字清零键,数码管恢复初始显示,重  新计时

        扩展功能:

        1.显示更换为1602液晶屏显示

        2.实现分段计时和总计时两个模式

此次设计实现了基本功能和拓展功能。

三、明确用户需求,根据设计需求绘制原理图(K4键可删掉):

原理图

四、代码解析

第一步:根据原理图定义引脚信息,及相关控制位、标志位、以及需要用到的延时函数



//定义引脚
sbit LCD_RS = P1^0;   
sbit LCD_RW = P1^1;
sbit LCD_E = P2^5;

sbit K1 = P3^6;    //定时开始、暂停键
sbit K2 = P3^7;    //定时清零键
sbit K3 = P3^4;    //显示分段计时键
uint keyCount = 0;    //按键次数标志
uint flag1 = 0;       //计时时的时间是否显示
uint time[] = {0x00,0x00,0x00,0x00,0x00,0x00};    //用来存放计时所产生的时间
uint temp[] = {0x00,0x00,0x00,0x00,0x00,0x00};    //用于计算、并time数组时间的时、分、秒
uchar msg[] = {"     round"};    //提示界面
uchar wname[] = {"welcome"};     //友好界面

uchar all_time[4][6];            //存放分段计时所产生的时间

uint flag = -1;        //作为向all_time数组保存时间的数组下标
//延时函数delay_nops()
void delay_nops(){
    _nop_();
    _nop_();
    _nop_();
    _nop_();
}
//延时函数Delay(uint num)
void Delay(uint num)
{
  while( --num );
}
//延时函数delay1(int ms)
void delay1(int ms)
{
   unsigned char n;
   while(ms--)
   {
     for(n = 0; n<250; n++)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
   }
}

第二步:LCD1602显示部分

//在对LCD1602进行写操作(包括写命令和写数据)的时候(读操作不需要),需要检查“忙”标志位,不“忙”即可写入
int LCD_BUSY(){
    bit isBusy;
    LCD_RS = 0;    //设置RS为命令寄存器
    LCD_RW = 1;    //设置RW为读操作,读busy位
    LCD_E = 1;     //设置E(使能端)为1,进行读操作
    delay_nops();    //延时
    isBusy = (bit)(P0&0X80);    //根据原理图引脚信息及LCD1602文档,busy位对应P1^7口,从P1^7读出端口的状态
    LCD_E = 0;     //恢复使能标志
    return  isBusy;    //返回busy位状态信息
}
//LCD1602 写命令操作
void LCD_WCMD(uchar cmd){
    while(LCD_BUSY());    //对LCD1602进行写操作前,要检查“忙”标志位,不“忙”即可继续写操作
    LCD_RS = 0;           //设置RS为命令寄存器
    LCD_RW = 0;           //设置RW为写操作
    LCD_E = 0;            //设置使能E为低电平,后续给予高电平,即形成一个正脉冲,完成写操作
    _nop_();              //延时一个空操作时间,保证引脚初始状态正确赋值
    _nop_();              //延时一个空操作时间,保证引脚初始状态正确赋值
    P0 = cmd;             //向P0口写入命令,16进制
    delay_nops();         //延时若干个空操作
    LCD_E = 1;            //给予E高电平,形成正脉冲,完成写操作
    delay_nops();         //延时若干个空操作,保证命令正确写入   
    LCD_E = 0;            //恢复使能E为低电平
    Delay(10);            //延时
}
//LCD1602 写数据操作,与LCD1602写命令操作类似,但又有不同之处,不同之处在下面代码中标出
void LCD_WDATA(uchar dat){
    while(LCD_BUSY());    
    LCD_RS = 1;    //将RS设置为数据寄存器
    LCD_RW = 0;
    LCD_E = 0;
    P0 = dat;      //向P0口写入数据
    delay_nops();
    LCD_E = 1;
    delay_nops();
    LCD_E = 0;
    Delay(5);
}
//设置LCD1602 的显示位置,以标准 0x80+RAM 地址方式写入命令,具体LCD1602RAM地址映射图如下
void LCD_POS(uchar pos){
    LCD_WCMD(pos | 0x80);    //根据下面RAM地址映射图,举例,例如:LCD_WCMD(0x00 | 0x80);即显示在LCD1602的第一行,从第一个单元开始显示、LCD_WCMD(0x40 | 0x80);即显示在LCD1602的第二行,从第一个单元开始显示
}

        LCD1602 RAM地址映射图:

 

//配置完LCD1602引脚和端口信息,以及LCD1602相关函数后,根据LCD1602使用手册进行LCD1602的初始化
void LCD_INIT(){
    LCD_RW = 0;         //设置LCD1602中RS为命令寄存器
    delay1(15);         //延时
    LCD_WCMD(0x01);     //写入命令,清屏,清除LCD的显示内容
    LCD_WCMD(0x38);     //16*2显示,5*7点阵,8位数据
    delay1(5);          //延时,保证正确写入,下方延时函数功能皆是如此
    LCD_WCMD(0x38);     //重复写入,保证正确写入
    delay1(5);
    LCD_WCMD(0x38);    
    delay1(5);
    LCD_WCMD(0x38);
    delay1(5);
    LCD_WCMD(0x0c);     //开显示,不显示光标     
    delay1(5);
    LCD_WCMD(0x01);     //清除LCD的显示内容
    delay1(5);
}
//LCD1602 显示部分
void display(){
    uchar i;
    for(i = 0;i<6;i++){
        temp[i] = time[i] + 0x30;    //这里是把time数组(定时器T0计时产生的时间),进行赋值给temp数组,便于后期进行时、分、秒拆分显示
    }

    
    LCD_POS(0x45);    //设置LCD1602上显示为第二行第6个单元开始,具体请看上面提到的RAM地址映射图
    LCD_WDATA(temp[5]);    //显示定时器T0产生的 分(十位)
    LCD_WDATA(temp[4]);    //显示定时器T0产生的 分(个位)
    LCD_WDATA(0x3a);       //显示“:”

    LCD_WDATA(temp[3]);    //显示定时器T0产生的 秒(十位)
    LCD_WDATA(temp[2]);    //显示定时器T0产生的 秒(个位)
    LCD_WDATA(0x3a);       //显示“:”

    LCD_WDATA(temp[1]);    //显示定时器T0产生的 0.1s
    LCD_WDATA(temp[0]);    //显示定时器T0产生的 0.01s
   
    
}

第三步:主函数部分

int main(){
    uchar i;
    TMOD = 0X01;    //选择T0工作方式1
    TH0 = 0XDC;    //10ms触发一次中断
    TL0 = 0X00;    //10ms触发一次中断
    EA = 1;        //开启中断总开关
    ET0 = 1;        //开启定时中断T0

    LCD_INIT();    //LCD1602初始化
    LCD_POS(0X00);    //设置LCD1602 显示位置为第一行第一个单元
     
    for(i = 0;i<7;i++){
        LCD_WDATA(wname[i]);    //友好界面
    }
    delay1(100);
    while(1){
       if(K1 == 0){    //判断按键K1是否按下,按下则进行计时,或者暂停(根据keyCount判断)
            keyCount++;    
            delay1(100);
            switch(keyCount){
                case 1:
                    TR0 = 1;    //打开定时器T0,开始
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X31);    //显示这是第几轮计时
                    break;
                case 2:
                    TR0 = 0;    //关闭定时器T0,暂停
                    flag++;saveTime();    //在暂停的时候进行时间保存,即达到分段计时的效果
                    break;
                case 3:
                    TR0 = 1;    //打开定时器T0,开始
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X32);
                    break;
                case 4:
                    TR0 = 0;    //关闭定时器T0,暂停
                    flag++; saveTime();
                    break;
                case 5:
                    TR0 = 1;    //打开定时器T0,开始
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X33);
                    break;
                case 6:
                    TR0 = 0;    //关闭定时器T0,暂停
                    flag++;saveTime();
                    break;
                case 7:
                    TR0 = 1;
                   
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X34);
                    break;
                case 8:
                    TR0 = 0;
                    flag++;saveTime();
                    break;
                default:
                    TR0 = 0;
                    flag = -1;    
                    break;
            }
            delay1(10);
       }
       if(K2==0){    //定时时间清零键
            TR0=0;
            keyCount = 0;
            flag=3;
            delay1(10);
            flag=3;
            delay1(10);
            flag=3;
            delay1(10);
            for(i=0;i<6;i++){    //对在中断处理函数中保存在time中的时间进行清零
                time[i] = 0;
            }
       }
       if(K3==0){    //显示分段计时,所存储的时间段
            TR0 = 0;
            flag1 = 1;
            display1(flag);    //显示分段时间段
            flag1 = 0;    //显示完自动隐式退出
            delay1(10);     
       }  
       if(flag1==0){      // 当flag1==0,即自动退出“显示分段计时”后,显示计时页面
            display();    //显示计时页面
       } 
        
    }
}

        定时中断处理函数:

//定时器T0的中断处理函数,time数组用来保存定时器T0计时所产生的时间

void timer0() interrupt 1{
    TH0 = 0XDC;    //重新装入初值
    TL0 = 0X00;
    time[0]++;   //保存0.01s
    if(time[0]==10){  
        time[1]++;  //保存0.1s
        time[0] = 0;
    }
    if(time[1]==10){  
        time[2]++;   //保存1s
        time[1] = 0;
    }
    if(time[2]==10){  
        time[3]++;  //保存10s
        time[2] = 0;
    }
    if(time[3]==6){   
        time[4]++;  //保存1min
        time[3] = 0;
    }
    if(time[4]==10){  
        time[5]++;   //保存10min
        time[4] = 0;
    }
    if(time[5]==6){
        time[5] = 0;
    }
}

      LCD1602 显示时间函数(循环显示):

//LCD1602 显示函数 时分秒函数
void display1(uint m){

    uchar i;
    uint t = 0x31;
    for(i = 0;i<=m;i++){
            LCD_WCMD(0X01);
            LCD_POS(0X00);
            LCD_WDATA(0X3C);
            LCD_WDATA(t++);
            LCD_WDATA(0X3E);
            LCD_POS(0x45);
            LCD_WDATA(all_time[i][5] + 0x30);
            LCD_WDATA(all_time[i][4] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][3] + 0x30);
            LCD_WDATA(all_time[i][2] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][1] + 0x30);
            LCD_WDATA(all_time[i][0] + 0x30);
            delay1(500);
            
    }

}

      在main函数中调用的保存分段时间函数:

//保存时间段
void saveTime(){
    uchar j = 0;
    if(flag != -1){
       for(j = 0;j<6;j++){
          all_time[flag][j] = time[j];    //保存每次暂停所产生的时间段,即分段计时功能
       }
    }
}

        在main函数中调用的显示分段时间的函数:

//显示分段计时存储的时间信息,类似前面的display()函数
void display1(uint m){

    uchar i;
    uint t = 0x31;
    for(i = 0;i<=m;i++){
            LCD_WCMD(0X01);    
            LCD_POS(0X00);
            LCD_WDATA(0X3C);
            LCD_WDATA(t++);
            LCD_WDATA(0X3E);
            LCD_POS(0x45);
            LCD_WDATA(all_time[i][5] + 0x30);    //这里加上0x30是根据单片机系统自带字符库编码方式
            LCD_WDATA(all_time[i][4] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][3] + 0x30);
            LCD_WDATA(all_time[i][2] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][1] + 0x30);
            LCD_WDATA(all_time[i][0] + 0x30);
            delay1(500);
            
    }

}

第四步:实物连接

 

完整代码:

#include<reg51.h>
#include<intrins.h>

#define uchar unsigned char
#define uint  unsigned int

sbit LCD_RS = P1^0;
sbit LCD_RW = P1^1;
sbit LCD_E = P2^5;

sbit K1 = P3^6;
sbit K2 = P3^7;
sbit K3 = P3^4;
uint keyCount = 0;
uint flag1 = 0;
uint time[] = {0x00,0x00,0x00,0x00,0x00,0x00};
uint temp[] = {0x00,0x00,0x00,0x00,0x00,0x00};
uchar msg[] = {"     "};
uchar wname[] = {"welcome"};

uchar all_time[4][6];

uint flag = -1;
void delay_nops(){
    _nop_();
    _nop_();
    _nop_();
    _nop_();
}
void Delay(uint num)
{
  while( --num );
}
void delay1(int ms)
{
   unsigned char n;
   while(ms--)
   {
     for(n = 0; n<250; n++)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
   }
}
int LCD_BUSY(){
    bit isBusy;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_E = 1;
    delay_nops();
    isBusy = (bit)(P0&0X80);
    LCD_E = 0;
    return  isBusy;
}
void LCD_WCMD(uchar cmd){
    while(LCD_BUSY());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_E = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delay_nops();
    LCD_E = 1;
    delay_nops();
    LCD_E = 0;
    Delay(10);
}
void LCD_WDATA(uchar dat){
    while(LCD_BUSY());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_E = 0;
    P0 = dat;
    delay_nops();
    LCD_E = 1;
    delay_nops();
    LCD_E = 0;
    Delay(5);
}




void LCD_INIT(){
    LCD_RW = 0;
    delay1(15); 
    LCD_WCMD(0x01);
    LCD_WCMD(0x38);
    delay1(5);
    LCD_WCMD(0x38);
    delay1(5);
    LCD_WCMD(0x38);
    delay1(5);
    LCD_WCMD(0x38);
    delay1(5);
    LCD_WCMD(0x0c);
    delay1(5);
    LCD_WCMD(0x01);
    delay1(5);
}
void LCD_POS(uchar pos){
    LCD_WCMD(pos | 0x80);
}
void display(){
    uchar i;
    for(i = 0;i<6;i++){
        temp[i] = time[i] + 0x30;
    }

    
    LCD_POS(0x45);
    LCD_WDATA(temp[5]);
    LCD_WDATA(temp[4]);
    LCD_WDATA(0x3a);

    LCD_WDATA(temp[3]);
    LCD_WDATA(temp[2]);
    LCD_WDATA(0x3a);

    LCD_WDATA(temp[1]);
    LCD_WDATA(temp[0]);
   
    
}
void saveTime(){
    uchar j = 0;
    if(flag != -1){
       for(j = 0;j<6;j++){
          all_time[flag][j] = time[j];
       }
    }
}
void display1(uint m){

    uchar i;
    uint t = 0x31;
    for(i = 0;i<=m;i++){
            LCD_WCMD(0X01);
            LCD_POS(0X00);
            LCD_WDATA(0X3C);
            LCD_WDATA(t++);
            LCD_WDATA(0X3E);
            LCD_POS(0x45);
            LCD_WDATA(all_time[i][5] + 0x30);
            LCD_WDATA(all_time[i][4] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][3] + 0x30);
            LCD_WDATA(all_time[i][2] + 0x30);
            LCD_WDATA(0x3a);
        
            LCD_WDATA(all_time[i][1] + 0x30);
            LCD_WDATA(all_time[i][0] + 0x30);
            delay1(500);
            
    }

}
int main(){
    uchar i;
    TMOD = 0X01;
    TH0 = 0XDC;
    TL0 = 0X00;
    EA = 1;
    ET0 = 1;

    LCD_INIT();
    LCD_POS(0X00);
    P3 = 0XC0 | P3;
    
    LCD_POS(0X00);
    for(i = 0;i<7;i++){
        LCD_WDATA(wname[i]);
    }
    delay1(100);
    while(1){
       if(K1 == 0){
            keyCount++;
            delay1(100);
            switch(keyCount){
                case 1:
                    TR0 = 1;
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X31);
                    break;
                case 2:
                    TR0 = 0;
                    flag++;saveTime();
                    break;
                case 3:
                    TR0 = 1;
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X32);
                    break;
                case 4:
                    TR0 = 0;
                    flag++; saveTime();
                    break;
                case 5:
                    TR0 = 1;
                   
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X33);
                    break;
                case 6:
                    TR0 = 0;
                    flag++;saveTime();
                    break;
                case 7:
                    TR0 = 1;
                   
                    LCD_POS(0x00);
                    for(i = 0;i<10;i++){
                        LCD_WDATA(msg[i]);
                    }
                    LCD_WDATA(0X34);
                    break;
                case 8:
                    TR0 = 0;
                    flag++;saveTime();
                    break;
                default:
                    TR0 = 0;
                    flag = -1;
                    break;
            }
            delay1(10);
       }
       if(K2==0){
            TR0=0;
            keyCount = 0;
            flag=3;
            delay1(10);
            flag=3;
            delay1(10);
            flag=3;
            delay1(10);
            for(i=0;i<6;i++){
                time[i] = 0;
            }
       }
       if(K3==0){
            TR0 = 0;
            flag1 = 1;
            display1(flag);
            flag1 = 0;
            delay1(10);     
       }  
       if(flag1==0){
            display();
       } 
        
    }
}
void timer0() interrupt 1{
    TH0 = 0XDC;
    TL0 = 0X00;
    time[0]++;   //0.01s
    if(time[0]==10){  
        time[1]++;  //0.1s
        time[0] = 0;
    }
    if(time[1]==10){  
        time[2]++;   //1s
        time[1] = 0;
    }
    if(time[2]==10){  
        time[3]++;  //10s
        time[2] = 0;
    }
    if(time[3]==6){   
        time[4]++;  //1min
        time[3] = 0;
    }
    if(time[4]==10){  
        time[5]++;   //10min
        time[4] = 0;
    }
    if(time[5]==6){
        time[5] = 0;
    }
}

  • 18
    点赞
  • 182
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
#include<reg51.h> #define ulong unsigned long char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90}; char tab_dp[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x58,0x00,0x10}; #define LED P0 //P0 为数码管的段选 #define WS P1 //P1 为数码管的位选 sbit time_shift=P3^0; //P3^0 为"移位"按键 sbit time_set=P3^1; //P3^1 为"修改"按键 sbit set_inc=P3^2; //P3^2 为"增加"按键 sbit time_run=P3^3; //P3^3 为"计时开始暂停"按键 sbit LIGHT=P2^0; sbit SPEAKER=P2^7; unsigned char sec,min,sec_ge,sec_shi,min_ge,min_shi,t; //定义秒,分,,秒的个位,十位,分的个位,十位 int state; //秒表状态指示 0-计时暂停 1-正在倒计时 2-计时间参数修改 int flag; //秒表修改数据指示 0-分钟十位 1-分钟个位 2-秒钟十位 3-秒钟个位 int blink; //-------------------------------------------------------------------- void init(); void display_run(); void display_pause(); void delay(int); void time_modify(); //-------------------------------------------------------------------- void main() { init(); state=0; flag=0; blink=1; t=0; LIGHT=1; SPEAKER=1; min=5; sec=0; sec_ge=0; //秒的个位和十位 sec_shi=0; min_ge=5; //分的个位和十位 min_shi=0; while(1) { if(time_set==0) //如果"调"按键按下 { delay(5); //延去抖 if(time_set==0) state=2; } if(state==0) { TR0=0; TR1=0; display_pause(); } if(state==1) { TR0=1; TR1=0; display_run(); } if(state==2) { TR1=1; time_modify(); } } } //-------------------------------------------------------------------- void init() { TMOD=0x11; EA=1; ET0=0; ET1=0; TH0=0x4d; TL0=oxfc; //开总中断 //定义定器 0 工定器 1 作与方式 1 //定器 0 赋初值 TH1=15536/256; TL1=15536%256; //中断初始化 EX0=1; PX0=0; IT0=1; EX1=1; PX1=1; //定器 1 赋初值 IT1=1; } //外中断 1 void INT_1() interrupt 2 using 0 { if( time_run==0)//表示按钮有按下 { delay(20); //延 if(time_run==0) { state=(state+1)%2; LIGHT=1; SPEAKER=1; } } } //外中断 0 void INT_0() interrupt 0 using 1 { if( set_inc==0)//表示按钮有按下 { delay(20); //延去抖 if(set_inc==0) { switch(flag) //分支结构,根据 flag 的值来判断哪一位加 1 { case 0: { min=(min+10)%60; break; } case 1: { min=(min+1)+min/10*10; break; } case 2: { sec=(sec+10)%60; break; } case 3: { sec=(sec+1)+sec/10*10; break; } default:break; } } } } //--------------------------------延子函数----------------------------------- void delay(int x) { int i,j; for(i=x; i>0l; i--) for(j=255; j>0; j--) ; } //-------------------------------显示子函数-------------------------------------- void display_run() { if(TF0==1) //如果定器溢出 { TF0=0; //清中断标志位 t++; if(t==20) { t=0; if(min==0&&sec==0) { min=60; } if(sec==0) { sec=59; min--; } else sec--; if(min==0&&sec>56) { SPEAKER=0; delay(20); SPEAKER=1; } if(min==0&&sec==0) { LIGHT=0; SPEAKER=0; delay(20); SPEAKER=1; delay(240); SPEAKER=0; delay(20); SPEAKER=1; delay(240); SPEAKER=0; delay(20); SPEAKER=1; delay(240); SPEAKER=0; delay(20); SPEAKER=1; delay(240); SPEAKER=0; delay(20); SPEAKER=1; state=4; min=5;//回归初始化 sec=0; sec_ge=0; //秒的个位和十位 sec_shi=0; min_ge=5; //分的个位和十位 min_shi=0; } } } sec_ge=sec; //秒的个位和十位 sec_shi=sec/10; min_ge=min; //分的个位和十位 min_shi=min/10; WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); WS=0xfd; LED=tab[sec_shi]; delay(1); WS=0xfb; LED=tab_dp[min_ge]; delay(1); WS=0xf7; LED=tab[min_shi]; delay(1); } void display_pause() { WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); WS=0xfd; LED=tab[sec_shi]; delay(1); WS=0xfb; LED=tab_dp[min_ge]; delay(1); WS=0xf7; LED=tab[min_shi]; delay(1); } void time_modify() { //修改位的闪烁状态 if(TF1==1) { TF1=0; blink=(blink+1)%2; } //修改具体哪个数码管指示 if(time_shift==0) { delay(60); if(time_shift==0) flag=(flag+1)%4; } // 修改状态下的数码管显示 switch(flag) //分支结构,根据 flag 的值来决定扫描状态 { case 0: { sec_ge=sec; //秒的个位和十位 sec_shi=sec/10; min_ge=min; //分的个位和十位 min_shi=min/10; WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); WS=0xfd; LED=tab[sec_shi]; delay(1); WS=0xfb; LED=tab_dp[min_ge]; delay(1); if(blink==1) { WS=0xf7; LED=tab[min_shi]; delay(1); } break; } case 1: { sec_ge=sec; //秒的个位和十位 sec_shi=sec/10; min_ge=min; //分的个位和十位 min_shi=min/10; WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); WS=0xfd; LED=tab[sec_shi]; delay(1); if(blink==1) { WS=0xfb; LED=tab_dp[min_ge]; delay(1); } WS=0xf7; LED=tab[min_shi]; delay(1); break; } case 2: { sec_ge=sec; //秒的个位和十位 sec_shi=sec/10; min_ge=min; //分的个位和十位 min_shi=min/10; WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); if(blink==1) { WS=0xfd; LED=tab[sec_shi]; delay(1); } WS=0xfb; LED=tab_dp[min_ge]; delay(1); WS=0xf7; LED=tab[min_shi]; delay(1); break; } case 3: { sec_ge=sec; //秒的个位和十位 sec_shi=sec/10; min_ge=min; //分的个位和十位 min_shi=min/10; if(blink==1) { WS=0xfe; //循环扫描 LED=tab[sec_ge]; delay(1); } WS=0xfd; LED=tab[sec_shi]; delay(1); WS=0xfb; LED=tab_dp[min_ge]; delay(1); WS=0xf7; LED=tab[min_shi]; delay(1); break; } default:break; } }
很高兴为您解答!关于C51单片机lcd实现数字秒表计时的问题,您可以参考以下代码: ``` #include<reg52.h> #include<intrins.h> sbit RS=P2^0; //定义LCD的RS接口 sbit RW=P2^1; //定义LCD的写入接口 sbit E=P2^2; //定义LCD的使能接口 void DelayUs2x(unsigned char t); void DelayMs(unsigned char t); void LcdWriteCmd(unsigned char cmd); void LcdWriteDat(unsigned char dat); void LcdInit(); void TimerInit(); void Display(); void Int0Init(); //按键中断初始化 unsigned char code table[]="1234567890"; //定义计数器显示数字 unsigned char cnt=0; //计数器变量 unsigned int count=0; //计数变量,最大为65535 void main() { LcdInit(); //初始化LCD TimerInit(); //初始化计数器 Int0Init(); //初始化按键中断 while(1) //循环体 { Display(); //调用显示函数 } } void DelayUs2x(unsigned char t) { while(--t); } void DelayMs(unsigned char t) { while(t--) { DelayUs2x(245); DelayUs2x(245); } } void LcdWriteCmd(unsigned char cmd) //写入指令 { RS=0; RW=0; P0=cmd; DelayUs2x(5); E=1; DelayUs2x(5); E=0; } void LcdWriteDat(unsigned char dat) //写入数据 { RS=1; RW=0; P0=dat; DelayUs2x(5); E=1; DelayUs2x(5); E=0; } void LcdInit() //LCD初始化 { LcdWriteCmd(0x38); //8位数据接口,双行显示,5x7点阵 LcdWriteCmd(0x0c); //显示开,无光标 LcdWriteCmd(0x06); //地址自动加1,不移屏 LcdWriteCmd(0x01); //清屏 } void TimerInit() //计数器初始化 { TMOD=0x01; TH0=(65535-50000)/256; TL0=(65535-50000)%256; TR0=1; ET0=1; EA=1; } void Display() //显示计数器的值 { unsigned char i; unsigned char str[7]={"00:00:"}; unsigned int c; c=count; //读取计数变量的值 str[6]=table[cnt%10]; //个位 str[5]=table[(cnt/10)%10]; //十位 str[3]=table[(c/360000)%10]; //小的十位 str[4]=table[(c/36000)%10]; //小的个位 str[1]=table[(c%36000)/6000]; //分钟的十位 str[2]=table[(c%6000)/1000]; //分钟的个位 LcdWriteCmd(0x80); //第1行第1个字符开始显示 for(i=0;i<7;i++) LcdWriteDat(str[i]); } void Int0Init() //按键中断初始化 { IT0=1; EX0=1; } void Int0() interrupt 0 //按键中断函数 { TR0=~TR0; //计数器开关 if(TR0) EA=1; else EA=0; if(!TR0) cnt=0; IE0=0; //清除中断标志位 DelayMs(20); //消抖 IE0=1; //重新使能中断 } void Timer0() interrupt 1 //计数器中断函数 { TH0=(65535-50000)/256; TL0=(65535-50000)%256; count++; if(count==8640000) //计数器累计1天停止计数 TR0=0; cnt++; } ``` 此代码使用了C51单片机和LCD,实现数字秒表计时的功能。 如果需要更加详细的解释,请提出您的疑问,我会给您详细的解答。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

密斯der~.Tang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值