找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6668|回复: 14
收起左侧

单片机电子时钟如何设置按键来控制时间的加减呢?

  [复制链接]
ID:364479 发表于 2018-7-4 08:57 | 显示全部楼层 |阅读模式
51单片机的电子时钟,如何设置按键来控制时间的加减呢?
回复

使用道具 举报

ID:320306 发表于 2018-7-4 11:26 | 显示全部楼层
设置变量,加就变量加一,减就变量减一!!!!!!!!!!!
回复

使用道具 举报

ID:364700 发表于 2018-7-4 11:44 | 显示全部楼层
要设置开关来控制
回复

使用道具 举报

ID:164602 发表于 2018-7-4 12:20 | 显示全部楼层
给你一个例子吧,虽然程序有很多BUG,但自己搞懂了,就可以变成自己的程序了。
main.c:——————————————————————
/*******************************************************************************
* 实验名                           : 万年历实验
* 使用的IO             :
* 实验效果       :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择
*选择设置加1。
*        注意                                         :
*******************************************************************************/

#include<reg51.h>
#include"lcd.h"
#include"ds1302.h"

sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;

void Int0Configuration();
void LcdDisplay();
unsigned char SetState,SetPlace;
void Delay10ms(void);   //误差 0us
/*******************************************************************************
* 函数名         : main
* 函数功能                   : 主函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void main()
{
        unsigned char i;
        Int0Configuration();
        LcdInit();
        Ds1302Init();
        while(1)
        {       
                if(SetState==0)
                {
                        Ds1302ReadTime();
                }
                else
                {
                        if(K1==0)                //检测按键K1是否按下
                        {
                                Delay10ms();        //消除抖动
                                if(K1==0)
                                {
                                        SetPlace++;
                                        if(SetPlace>=7)
                                                SetPlace=0;                                       
                                }

                                while((i<50)&&(K1==0))         //检测按键是否松开
                                {
                                        Delay10ms();
                                        i++;
                                }
                                i=0;
                        }
                        if(K2==0)                //检测按键K2是否按下
                        {
                                Delay10ms();        //消除抖动
                                if(K2==0)
                                {
                                        TIME[SetPlace]++;
                                        if((TIME[SetPlace]&0x0f)>9)                                         //换成BCD码。
                                        {
                                                TIME[SetPlace]=TIME[SetPlace]+6;
                                        }
                                        if((TIME[SetPlace]>=0x60)&&(SetPlace<2))                //分秒只能到59
                                        {
                                                TIME[SetPlace]=0;
                                        }
                                        if((TIME[SetPlace]>=0x24)&&(SetPlace==2))                //小时只能到23
                                        {
                                                TIME[SetPlace]=0;
                                        }
                                        if((TIME[SetPlace]>=0x32)&&(SetPlace==3))                //日只能到31
                                        {
                                                TIME[SetPlace]=0;       
                                        }
                                        if((TIME[SetPlace]>=0x13)&&(SetPlace==4))                //月只能到12
                                        {
                                                TIME[SetPlace]=0;
                                        }       
                                        if((TIME[SetPlace]>=0x7)&&(SetPlace==5))                //周只能到7
                                        {
                                                TIME[SetPlace]=1;
                                        }               
//                                        if(SetPlace==5)                //月只能到12
//                                        {
//                                                TIME[SetPlace]=;
//                                        }       
                                }
                               
                                while((i<50)&&(K2==0))         //检测按键是否松开
                                {
                                        Delay10ms();
                                        i++;
                                }
                                i=0;
                               
                        }                                               
                }
        LcdDisplay();       
        }
       
}
/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能                   : 显示函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void LcdDisplay()
{
        LcdWriteCom(0x80+0X40);
        LcdWriteData('0'+TIME[2]/16);                                //时
        LcdWriteData('0'+(TIME[2]&0x0f));                                 
        LcdWriteData('-');
        LcdWriteData('0'+TIME[1]/16);                                //分
        LcdWriteData('0'+(TIME[1]&0x0f));       
        LcdWriteData('-');
        LcdWriteData('0'+TIME[0]/16);                                //秒
        LcdWriteData('0'+(TIME[0]&0x0f));

        LcdWriteCom(0x80);
        LcdWriteData('2');
        LcdWriteData('0');
        LcdWriteData('0'+TIME[6]/16);                        //年
        LcdWriteData('0'+(TIME[6]&0x0f));
        LcdWriteData('-');
        LcdWriteData('0'+TIME[4]/16);                        //月
        LcdWriteData('0'+(TIME[4]&0x0f));
        LcdWriteData('-');
        LcdWriteData('0'+TIME[3]/16);                        //日
        LcdWriteData('0'+(TIME[3]&0x0f));
        LcdWriteCom(0x8D);
        LcdWriteData('0'+(TIME[5]&0x07));        //星期                         
}
/*******************************************************************************
* 函数名         : Int0Configuration()
* 函数功能                   : 配置外部中断0
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Int0Configuration()
{
        //设置INT0
        IT0=1;//跳变沿出发方式(下降沿)
        EX0=1;//打开INT0的中断允许。
        EA=1;//打开总中断       
}
/*******************************************************************************
* 函数名         : Int0()
* 函数功能                   : 外部中断0 中断函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/

void Int0() interrupt 0                 
{
        Delay10ms();
        if(K3==0)
        {
                SetState=~SetState;
                SetPlace=0;
                Ds1302Init();       
        }
}
/*******************************************************************************
* 函数名         : Delay10ms
* 函数功能                   : 延时函数,延时10ms
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
1302.c______________________
#include"ds1302.h"

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0x00, 0x00, 0x12, 0x01, 0x01, 0x02, 0x13};

/*******************************************************************************
* 函 数 名         : Ds1302Write
* 函数功能                   : 向DS1302命令(地址+数据)
* 输    入         : addr,dat
* 输    出         : 无
*******************************************************************************/

void Ds1302Write(uchar addr, uchar dat)
{
        uchar n;
        RST = 0;
        _nop_();

        SCLK = 0;//先将SCLK置低电平。
        _nop_();
        RST = 1; //然后将RST(CE)置高电平。
        _nop_();

        for (n=0; n<8; n++)//开始传送八位地址命令
        {
                DSIO = addr & 0x01;//数据从低位开始传送
                addr >>= 1;
                SCLK = 1;//数据在上升沿时,DS1302读取数据
                _nop_();
                SCLK = 0;
                _nop_();
        }
        for (n=0; n<8; n++)//写入8位数据
        {
                DSIO = dat & 0x01;
                dat >>= 1;
                SCLK = 1;//数据在上升沿时,DS1302读取数据
                _nop_();
                SCLK = 0;
                _nop_();       
        }       
                 
        RST = 0;//传送数据结束
        _nop_();
}

/*******************************************************************************
* 函 数 名         : Ds1302Read
* 函数功能                   : 读取一个地址的数据
* 输    入         : addr
* 输    出         : dat
*******************************************************************************/

uchar Ds1302Read(uchar addr)
{
        uchar n,dat,dat1;
        RST = 0;
        _nop_();

        SCLK = 0;//先将SCLK置低电平。
        _nop_();
        RST = 1;//然后将RST(CE)置高电平。
        _nop_();

        for(n=0; n<8; n++)//开始传送八位地址命令
        {
                DSIO = addr & 0x01;//数据从低位开始传送
                addr >>= 1;
                SCLK = 1;//数据在上升沿时,DS1302读取数据
                _nop_();
                SCLK = 0;//DS1302下降沿时,放置数据
                _nop_();
        }
        _nop_();
        for(n=0; n<8; n++)//读取8位数据
        {
                dat1 = DSIO;//从最低位开始接收
                dat = (dat>>1) | (dat1<<7);
                SCLK = 1;
                _nop_();
                SCLK = 0;//DS1302下降沿时,放置数据
                _nop_();
        }

        RST = 0;
        _nop_();        //以下为DS1302复位的稳定时间,必须的。
        SCLK = 1;
        _nop_();
        DSIO = 0;
        _nop_();
        DSIO = 1;
        _nop_();
        return dat;       
}

/*******************************************************************************
* 函 数 名         : Ds1302Init
* 函数功能                   : 初始化DS1302.
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302Init()
{
        uchar n;
        Ds1302Write(0x8E,0X00);                 //禁止写保护,就是关闭写保护功能
        for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
        {
                Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);       
        }
        Ds1302Write(0x8E,0x80);                 //打开写保护功能
}

/*******************************************************************************
* 函 数 名         : Ds1302ReadTime
* 函数功能                   : 读取时钟信息
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302ReadTime()
{
        uchar n;
        for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
        {
                TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
        }
               
}
1302.h______________________________
#ifndef __DS1302_H_
#define __DS1302_H_

//---包含头文件---//
#include<reg51.h>
#include<intrins.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif

//---定义ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;

//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();

//---加入全局变量--//
extern uchar TIME[7];        //加入全局变量

#endif
LCD.c________________________________
#include"lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能                   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
        for (; c>0; c--)
        {
                 for (b=199;b>0;b--)
                 {
                          for(a=1;a>0;a--);
                 }      
        }
           
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能                   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
#ifndef         LCD1602_4PINS         //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com)          //写入命令
{
        LCD1602_E = 0;     //使能
        LCD1602_RS = 0;           //选择发送命令
        LCD1602_RW = 0;           //选择写入
       
        LCD1602_DATAPINS = com;     //放入命令
        Lcd1602_Delay1ms(1);                //等待数据稳定

        LCD1602_E = 1;                  //写入时序
        Lcd1602_Delay1ms(5);          //保持时间
        LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com)          //写入命令
{
        LCD1602_E = 0;         //使能清零
        LCD1602_RS = 0;         //选择写入命令
        LCD1602_RW = 0;         //选择写入

        LCD1602_DATAPINS = com;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;         //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;

//        Lcd1602_Delay1ms(1);
        LCD1602_DATAPINS = com << 4; //发送低四位
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;         //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能                   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/                  
#ifndef         LCD1602_4PINS                  
void LcdWriteData(uchar dat)                        //写入数据
{
        LCD1602_E = 0;        //使能清零
        LCD1602_RS = 1;        //选择输入数据
        LCD1602_RW = 0;        //选择写入

        LCD1602_DATAPINS = dat; //写入数据
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;   //写入时序
        Lcd1602_Delay1ms(5);   //保持时间
        LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)                        //写入数据
{
        LCD1602_E = 0;          //使能清零
        LCD1602_RS = 1;          //选择写入数据
        LCD1602_RW = 0;          //选择写入

        LCD1602_DATAPINS = dat;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;          //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;

        LCD1602_DATAPINS = dat << 4; //写入低四位
        Lcd1602_Delay1ms(1);

        LCD1602_E = 1;          //写入时序
        Lcd1602_Delay1ms(5);
        LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能                 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/                  
#ifndef                LCD1602_4PINS
void LcdInit()                                                  //LCD初始化子程序
{
        LcdWriteCom(0x38);  //开显示
        LcdWriteCom(0x0c);  //开显示不显示光标
        LcdWriteCom(0x06);  //写一个指针加1
        LcdWriteCom(0x01);  //清屏
        LcdWriteCom(0x80);  //设置数据指针起点
}
#else
void LcdInit()                                                  //LCD初始化子程序
{
        LcdWriteCom(0x32);         //将8位总线转为4位总线
        LcdWriteCom(0x28);         //在四位线下的初始化
        LcdWriteCom(0x0c);  //开显示不显示光标
        LcdWriteCom(0x06);  //写一个指针加1
        LcdWriteCom(0x01);  //清屏
        LcdWriteCom(0x80);  //设置数据指针起点
}
#endif
LCD.h_________________________________
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);   //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/       
void LcdWriteData(uchar dat)        ;
/*LCD1602初始化子程序*/               
void LcdInit();                                                  

#endif

评分

参与人数 1黑币 +80 收起 理由
admin + 80 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:364770 发表于 2018-7-4 13:38 | 显示全部楼层
电子时钟用单片机控制
回复

使用道具 举报

ID:280206 发表于 2018-7-4 14:15 | 显示全部楼层
我是这样做的

1893878478.jpg
1894796573.jpg
1891574732.jpg

评分

参与人数 1黑币 +90 收起 理由
admin + 90 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:280206 发表于 2018-7-4 14:17 | 显示全部楼层

                   ;电子钟程序
                   ;
                          ;STC12C5A60S2  12MC  12T
                          ;
                          ;
                          ;以下定义中断向量地址
ORG 0000H
LJMP CHUSI
ORG 0003H
RETI
ORG 000BH         ;定时器0中断向量
LJMP DSQ0      
ORG 0013H
RETI
ORG 001BH
RETI
ORG 0023H
RETI
ORG 002BH         ;定时器2中断向量
RETI
NOP
        NOP
        NOP
        NOP
        ORG 0064H
                          ;初始化和定义寄存器用途
CHUSI: CLR A             ;清零
MOV 87H,A         ;置CPU功率方式
MOV IE,A          ;禁止中断
MOV IP,A          ;禁止中断优先控制
MOV SCON,A        ;关闭串行控制
MOV TMOD,A        ;计数器控制
MOV TCON,A        ;计数器控制
MOV SP,#080H      ;设置栈底
                   ;
MOV P0,#0FFH      ;显示划驱动低有效
        MOV P2,#0FFH      ;显示位驱动,低有效
        MOV P3,#0FFH      ;按键,低电平有效
   MOV 21H,#0        ;62.5mS计数器
        MOV 22H,#0        ;
MOV 23H,#0        ;秒计数暂存位
MOV 24H,#10        ;分计数暂存位
MOV 25H,#9        ;时计数暂存位
MOV 26H,#2       ;日计数暂存位,上电为16
        MOV 27H,#7       ;月计数暂存位,上电为7
        MOV 28H,#1        ;星期计数器
   CLR 0H            ;时间/日期标志,0=时间,1=日期
        MOV 30H,#0        ;
        MOV 31H,#0        ;
        MOV 32H,#0        ;
        MOV 33H,#0H       ;
                          ;设置定时器0为16位计数器方式(65536-62500)
        MOV TL0,#213      ;重装定时器0寄存器低位(T0=62.5毫微秒)
        MOV TH0,#0BH      ;重装定时器0高位重装入寄存器
        NOP               ;
                                 ;
        NOP               ;   TMOD       GATE  C/T M1 M0 GATE C/T M1 M0
        MOV TMOD,#01H     ;定时/计数       0     0  0  0   0    0  0  1
                          ;
NOP               ;   TCON       TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
        MOV TCON,#00H     ;启动定时器0    0   0   0   0   0   0   0   0
                          ;
                          ;
        MOV IP,#0H        ;中断优先控制  X  X  PT2  PS  PT1  PX1  PT0  PX0   
                          ;              0  0   0   0   0    0    0    0
                          ;
                    ;中断控制   EA -- ET2 ES ET1 EX1 ET0 EX0
        MOV IE,#10001010B;             1     0  0   1   0   1   0
        LJMP XIANSHI
        NOP
        NOP
        ORG 0100H                            ;
XIANSHI:NOP
        JNB P3.2,AJS4      ;查询按键 显示日期
        MOV A,23H          ;23H里有秒计数器
        CJNE A,#5,M6       ;每分钟第5秒到第10秒显示日期
        SETB 0H
        LJMP D1
M6:     CJNE A,#6,M7
        SETB 0H
        LJMP D1
M7:     CJNE A,#7,M8
        SETB 0H
        LJMP D1
M8:     CJNE A,#8,M9
        SETB 0H
        LJMP D1
M9:     CJNE A,#9,M10   
        SETB 0H
        LJMP D1
M10:    CLR 0H            ;非5 6 7 8 9 显示时间
        LJMP D1            ;S4=1 没按
AJS4:   SETB 0H            ;S4=0 按下
        SETB TR0           ;启动用
D1:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第一位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ1        ;BIT0为1显示日期
        MOV B,#10         ;小时计数器0-23
        MOV A,25H         ;小时计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        CJNE A,#0,SWW0    ;十位为0不显示
        LCALL YSQ1        ;调用延时器1
        LJMP D2
XSRQ1:  MOV B,#10         ;月份计数器1-12
        MOV A,27H          ;月份计数器计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        CJNE A,#0,SWW0    ;十位为0不显示
        LCALL YSQ1        ;调用延时器1
        LJMP D2
SWW0:   LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.0          ;显示第一位   
        LCALL YSQ1        ;调用延时器1
        NOP   
        NOP
        NOP
D2:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第二位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ2        ;BIT0为1显示日期
        MOV B,#10         ;小时计数器0-23
        MOV A,25H          ;小时计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        MOV A,B           ;个位数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.1          ;显示第二位
        LCALL YSQ1        ;调用延时器1
        LJMP D3
XSRQ2:  MOV B,#10         ;月份计数器1-12
        MOV A,27H          ;月份计数器计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        MOV A,B           ;个位数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.1          ;显示第二位
        LCALL YSQ1        ;调用延时器1
        NOP
        NOP
        NOP
D3:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第三位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ3        ;BIT0为1显示日期
        MOV A,#0BFH        ;中间划
        MOV P0,A          ;显示划驱动
        CLR P2.2          ;显示第三位
        LCALL YSQ1        ;调用延时器1
        LJMP D4
XSRQ3:  MOV A,#0F7H       ;下边划
        MOV P0,A          ;显示划驱动
        CLR P2.2          ;显示第三位
        LCALL YSQ1        ;调用延时器1
        NOP   
        NOP
        NOP
D4:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第四位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ4        ;BIT0为1显示日期
        MOV B,#10         ;分位计数器0-59
        MOV A,24H          ;分计数器
        DIV AB            ;分计数器除10,商在A,余数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.3          ;显示第四位
        LCALL YSQ1        ;调用延时器1
        LJMP D5
XSRQ4:  MOV B,#10         ;日期计数器1-31
        MOV A,26H          ;日期计数器计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        CJNE A,#0,SWW4    ;十位为0不显示
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.3          ;显示第四位
        LCALL YSQ1        ;调用延时器1
        LJMP D5
SWW4:   LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.3          ;显示第位
        LCALL YSQ1        ;调用延时器1
        NOP   
        NOP
        NOP
D5:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第五位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ5         ;BIT0为1显示日期
        MOV B,#10         ;小时计数器0-23
        MOV A,24H          ;小时计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        MOV A,B           ;个位数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.4          ;显示第五位
        LCALL YSQ1        ;调用延时器1
        LJMP D6
XSRQ5:  MOV B,#10         ;月份计数器1-12
        MOV A,26H          ;月份计数器计数器
        DIV AB            ;小时计数器除10,商在A,余数在B
        MOV A,B           ;个位数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.4          ;显示第五位
        LCALL YSQ1        ;调用延时器1
        NOP
        NOP
        NOP
D6:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第六位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ6        ;BIT0为1显示日期
        MOV A,#0BFH        ;中间划
        MOV P0,A          ;显示划驱动
        CLR P2.5          ;显示第六位
        LCALL YSQ1        ;调用延时器1
        LJMP D7
XSRQ6:  MOV A,#0F7H       ;下边划
        MOV P0,A          ;显示划驱动
        CLR P2.5          ;显示第六位
        LCALL YSQ1        ;调用延时器1
        NOP   
        NOP
        NOP
D7:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第七位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ7        ;BIT0为1显示日期
        MOV B,#10         ;秒计数器0-59
        MOV A,23H          ;秒计数器
        DIV AB            ;秒计数器除10,商在A,余数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.6          ;显示第七位
        LCALL YSQ1        ;调用延时器1
        LJMP D8
XSRQ7:  MOV A,#0F7H       ;星期计数器
        MOV P0,A          ;显示划驱动
        CLR P2.6          ;显示第七位
        LCALL YSQ1        ;调用延时器1
        NOP
        NOP
D8:     MOV P0,#0FFH      ;关闭显示划驱动,准备显示第八位
        MOV P2,#0FFH      ;关闭显示位驱动
        JB 0,XSRQ8        ;BIT0为1显示日期
        MOV B,#10         ;秒计数器0-59
        MOV A,23H         ;秒计数器
        DIV AB            ;秒计数器除10,商在A,余数在B
        MOV A,B           ;个位数在B
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.7          ;显示第八位
        LCALL YSQ1        ;调用延时器1
        LJMP XIANSHI
XSRQ8:  MOV A,28H         ;星期计数器计数器
        LCALL YMQ         ;调用译码器      
        MOV P0,A          ;显示划驱动
        CLR P2.7          ;显示第八位
        LCALL YSQ1        ;调用延时器1
        LJMP XIANSHI
        NOP
        NOP
        NOP
        LJMP XIANSHI
        LJMP XIANSHI      
DSQ0:   PUSH PSW          ;程序状态字入栈
        PUSH ACC          ;累加器入栈
        NOP               ;空操作 每插入一个操作可增大每日误差115.2毫秒 每8天一秒
        NOP               ;
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        MOV TL0,#197      ;重装定时器0寄存器低位(T0=62.5毫秒)( 减小变慢 增大变快)
        MOV TH0,#0BH      ;重装定时器0高位重装入寄存器(每调整一个数日误差1.3824秒)
        SETB TR0          ;启动定时器0
        INC 21H           ;定时器0的第1计数器(62.5mS)
        LCALL S30         ;查询调秒按键
        MOV A,21H         ;62.5毫秒+1
        CJNE A,#8,P16     ;不到8 半秒则返回
        LCALL AJ          ;到半秒查询调时分键
        LJMP DSQ0W
P16:    CJNE A,#16,DSQ0W  ;不到整秒时间则返回
        MOV 21H,#0        ;62.5毫秒重新计数
        INC 23H           ;分计数+1
        LCALL AJ          ;调用按键
        MOV A,23H         ;比较
        CJNE A,#60,DSQ0W ;60秒吗
        MOV 23H,#0       ;秒重新计数
        INC 24H          ;分计数
        MOV A,24H         ;
        CJNE A,#60,DSQ0W ;不到时间则返回
        MOV 24H,#0       ;分重新计数
        INC 25H          ;小时计数
        MOV A,25H         ;
        CJNE A,#24,DSQ0W  ;24吗
        MOV 25H,#0       ;重新计数
        INC 28H          ;星期加1
        MOV A,28H
        CJNE A,#7,RQJS   ;每星期7天 显示 0 1 2 3 4 5 6
        MOV 28H,#0
RQJS:   INC 26H          ;日期计数
   MOV DPTR,#TSZS   ;设置每月天数指示
        MOV A,27H        ;把当前月数送A
MOVC A,@A+DPTR   ;读取该月应有天数
        CJNE A,26H,DSQ0W ;比较,如相等,满月了,否则从中断返回
        MOV 26H,#1       ;日寄存器置1
        INC 27H          ;月寄存器加1
        MOV A,27H
CJNE A,#13,DSQ0W; 如等于13,月寄存器置1,否则从中断返回
        MOV 27H,#1         ;
DSQ0W:  POP ACC           ;程序状态字出栈
  POP PSW           ;累加器出栈
       RETI              ;从定时器0中断返回
        NOP
        NOP   
        NOP
YMQ:    MOV DPTR,#YMSJ    ;设置译码数据地址指针
       MOVC A,@A+DPTR    ;读取译码数据
        RET
        RET
YMSJ:   DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0
        NOP
        NOP
        RET                ;返回
        NOP
YSQ1:   CLR P3.1
        MOV 30H,#255       ;延时3
YSQ:    NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        DJNZ 30H,YSQ       ;5
        SETB P3.1
        RET
TSZS:   DB 0H,32,29,32,31 ;月中天数数据(+1)
        DB 32,31,32,32,31
        DB 32,31,32
        NOP
        NOP
        NOP
AJ:     NOP                ;查询按键程序
        JNB P3.3,S1        ;查询按键 小时 月
        JNB P3.6,S2        ;查询按键 分钟 日
        JNB P3.7,S3        ;查询按键 秒 星期
        RET                ;没有按键  返回     
S1:     JNB P3.2,S14       ;检查日期显示键 如有效调月份
        MOV A,25H          ;读取小时到A
        CJNE A,#24,XY23    ;小于23吗
        MOV 25H,#0         ;23+1=24(0)
        RET
XY23:   INC 25H            ;
        RET
        NOP
S14:    MOV A,27H          ;读取月份到A
        CJNE A,#12,XY12    ;小于12吗
        MOV 27H,#1         ;12+1=1
        RET
XY12:   INC 27H            ;
        RET
        RET
        RET                ;
        NOP
S2:     JNB P3.2,S24       ;检查日期显示键 如有效调月份
        MOV A,24H          ;读取分到A
        CJNE A,#59,XY59    ;小于23吗
        MOV 24H,#0         ;59+1=60(0)
        RET
XY59:   INC 24H            ;
        RET
        NOP
S24:    MOV DPTR,#TSZS   ;设置每月天数指示
        MOV A,27H        ;把当前月数送A
MOVC A,@A+DPTR   ;读取该月应有天数
        DEC A
        CJNE A,26H,XYDQY ;比较,如相等,满月了,
        MOV 26H,#1        ;12+1=1
        RET
XYDQY:  INC 26H            ;
        RET
        RET
        RET                ;
S3:     JNB P3.2,S34       ;检查日期显示键 如有效调月份
        RET
S34:    MOV A,28H          ;读取星期到A
        CJNE A,#6,XY6      ;小于6吗
        MOV 28H,#0         ;6+1=0
        RET
XY6:    INC 28H            ;
        RET
        RET
        RET                ;
        NOP
S30:    JB P3.7,AJFH       ;查询按键 秒 星期
        JNB P3.2,AJFH      ;检查日期显示键 如有效调月份
S31:    MOV A,23H          ;读取秒到A
        CJNE A,#30,XY33    ;等于30吗
S331:   MOV 23H,#0         ;等于30退到0
        MOV 21H,#0
        RET
XY33:   JC S331
        MOV 23H,#0
        MOV 21H,#0
        INC 24H          ;分计数
        MOV A,24H         ;
        CJNE A,#60,AJFH  ;不到时间则返回
        MOV 24H,#0       ;分重新计数
        INC 25H          ;小时计数                    ;
AJFH:   RET
        NOP
        RET
        RET
        RET                ;
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        END

回复

使用道具 举报

ID:364810 发表于 2018-7-4 14:45 | 显示全部楼层
先通过按键加减来设置好变量参数,然后将数值通过写入函数写入时钟芯片
回复

使用道具 举报

ID:358998 发表于 2018-7-4 14:49 | 显示全部楼层
按键 长按 触发 功能 是怎么完成的
回复

使用道具 举报

ID:16255 发表于 2018-7-4 14:55 | 显示全部楼层

评分

参与人数 1黑币 +70 收起 理由
admin + 70 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:365230 发表于 2018-7-4 22:46 | 显示全部楼层
同求个电子钟程序
回复

使用道具 举报

ID:280206 发表于 2018-7-5 14:12 | 显示全部楼层
回复11楼 求知心  ,7楼是完整的51系列单片机作时钟的程序,用两组端口扫描方式驱动8只数码管,用四个端口作校时控制,利用内部定时器0,分频定时,中断计数,程序支持8051系列40脚的系列,我用的是STC12C560S2,试验通过,日误差能控制到0.125秒
回复

使用道具 举报

ID:363756 发表于 2018-7-5 14:33 | 显示全部楼层
写一个延时函数通过按键改变延时函数参数就行
回复

使用道具 举报

ID:111634 发表于 2018-7-7 16:14 | 显示全部楼层
实例94  模拟电子钟(由80C51定时器产生秒时基)
Proteus仿真一下,确认有效。
实例94 模拟电子钟(由80C51定时器产生秒时基).rar (43.05 KB, 下载次数: 5)
回复

使用道具 举报

ID:111634 发表于 2018-7-7 16:16 | 显示全部楼层
本帖最后由 zl2168 于 2018-7-7 16:21 编辑

实例93  具有校正功能的时钟1302(LED数码管显示)
Proteus仿真一下,确认有效。
实例93 带校正时分秒的时钟1302(6位LED数码管显示).rar (732.75 KB, 下载次数: 5)

评分

参与人数 1黑币 +5 收起 理由
乐呵呵的小鹏 + 5

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表