找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1744|回复: 0
打印 上一主题 下一主题
收起左侧

STC时钟程序

[复制链接]
跳转到指定楼层
楼主
ID:314940 发表于 2018-4-23 22:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*************        本程序功能说明        **************
用STC的MCU的IO方式控制74HC595驱动8位数码管。
采用定时器0产生时钟时间
编写者:dengchao
MCU: STC12C2052AD-DIP20
OSC:11.0592MHz
实现功能:三个按键效时,可以实现加或减1;连续加减
          调整时,相应内部闪烁
特点:无需任何延时函数,
      一个定时实现按键消抖和不同时间的产生
      总只需6个IO口
程序核心思路:围绕一个1MS的核心来产生什么何时间
******************************************/
#include        "reg51.h"
//新一代 1T 8051系列 单片机系统管理特殊功能寄存器
//                                          7     6      5    4     3      2    1     0     Reset Value
//sfr PCON   = 0x87; //Power Control        SMOD  SMOD0  LVDF  POF   GF1    GF0   PD   IDL    0001,0000
//                                        7     6       5      4     3      2      1      0   Reset Value
sfr AUXR  = 0x8E; //Auxiliary Register  T0x12 T1x12 UART_M0x6 BRTR S2SMOD BRTx12 EXTRAM S1BRS  0000,0000
//-----------------------------------
sfr AUXR1 = 0xA2; //Auxiliary Register 1  -  PCA_P4  SPI_P4  S2_P4  GF2    ADRJ   -    DPS  0000,0000
/*************        本地常量声明        **************/
unsigned char code duan[]={
//         0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   消隐
        0x3F,0x06,0x5B,0x4f,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};        //段码
unsigned char code wei[]={0x01,0x02,0x04,0x08};        //位码
                                                                 //秒    分    时
unsigned char  y3,y4,y5,y6,k1,k2,k3,k4,k5,i,sec,minu,hour;
unsigned int        j,sw1,sw2;         

/*************        本地变量声明        **************/
sbit        sh_cp = P3^7;        //pin 11        SRCLK        Shift datala clock
sbit        st_cp = P3^5;        //pin 12        RCLk        store (latch) clock
sbit          ds  = P3^4;        //pin 14        SER                datala input

void display(void);                                //595驱动数码管动态显示函数
void disp595(unsigned char datal);   //写一个字节到595芯片
void display1(void);                        //显示缓冲区

sbit key1 = P3^2;  //功能设置键
sbit key2 = P3^3;  //加计数键
sbit key3 = P3^1;  //减计数键

void time_out(void);  //时、分、秒产生函数
void dinshiqi_init(void); //定时器初始化
void key1_scan(void); //三个独立按键扫描
void key2_scan(void);                 //时、分加减函数判断
void key3_scan(void);         //时、分键按一下1S后,0.2S连续加减数据
unsigned char         led_1111[4];//显示缓冲
bit        y1, y2;                        //20ms定时器标志

/******************主函数*****************/
void main(void)
{
        dinshiqi_init();   //定时器初始化
        for(i=0; i<4; i++)       
        led_1111[i] = 0x00;        //上电消隐
        y3 = 0;
        while(1)
        {
                while(!y2)        ;        //等待20ms到
                y2 = 0;
                time_out();
                display1();
                key1_scan();
        }
}

/****************定时器初始化函数******************/
void dinshiqi_init(void)
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
        TH0  = (65536 - 922) / 256;
        TL0  = (65536 - 922) % 256;
        ET0 = 1;
        TR0 = 1;
        EA  = 1;
        sec = 0;
        minu = 30;
        hour   = 12;
        sw2 = 0;
        k5 = 0;  //时、分设置切换寄存器
        y4 = 0;        //加键或减键按1S的计时寄存器
}
/*************** 秒 分 时 产生函数**************/
void time_out(void)
{
        sw1++;
        if(sw1>50)
        {
                sw1 = 0;
                sec++;           //秒
                if(sec>60)
                {
                         sec = 0;
                        minu++;          //分
                        if(minu>60)
                        {
                                 minu = 0;
                                hour++;                // 时
                                if(hour>24)
                                {
                                         hour=0;
                                }
                        }
                }
        }
  if(sw1>25)
        y1 = 1; //0.5S闪烁产生和标志位               
  else               
        y1 = 0;
}
/****************显示缓冲区函数******************/          
void display1(void)
{
        if(k5 == 0)   //k5 = 0正常显示
        {
                if(y1==1)
                {
                        led_1111[0] = duan[hour/10];  //时
                        led_1111[1] = duan[hour%10];
                        led_1111[2] = duan[minu/10];         //分
                        led_1111[3] = duan[minu%10];       
                }
                else
                {
                        led_1111[0] = duan[hour/10] ;
                        led_1111[1] = duan[hour%10] ;
                        led_1111[2] = duan[minu/10] ;
                        led_1111[3] = duan[minu%10] ;
                }
        }
        else
        {
                if(k5 == 1)  //k5 = 1 时闪烁,进入“时”加减
                {
                        if(y1==1)
                        {
                                led_1111[0] = duan[hour/10];
                                led_1111[1] = duan[hour%10];       
                        }
                        else
                        {
                                led_1111[0] = duan[hour/10]&0x00;
                                led_1111[1] = duan[hour%10]&0x00;
                        }
                        led_1111[2] = duan[minu/10];
                        led_1111[3] = duan[minu%10];
                }
                if(k5 == 2)      //k5 = 2 分闪烁,进入“分”加减       
                {
                        if(y1==1)
                        {
                                led_1111[2] = duan[minu/10];
                                led_1111[3] = duan[minu%10];       
                        }
                        else
                        {
                                led_1111[2] = duan[minu/10]&0x80;
                                led_1111[3] = duan[minu%10]&0x80;
                        }
                        led_1111[0] = duan[hour/10];
                        led_1111[1] = duan[hour%10];
                }                       
        }       
}


/***************595驱动数码管动态显示函数*******************/
void disp595(unsigned char datal)        //发送一个字节
{               
        unsigned char        i;
        for(i=0; i<8; i++)
        {
                if(datal & 0x80)
                ds = 1;
                else                       
                ds = 0;
                sh_cp = 1;
                sh_cp = 0;
                datal = datal << 1;
        }
}

/****************显示扫描函数******************/
void display(void)       
{       
        if(y1==1)
        {
               
                 disp595(wei[y3]|0x20);                        //共阴        输出位码
        }
        else
        {
               
                 disp595(wei[y3]|0x00);                        //共阴        输出位码
        }
        disp595(~led_1111[y3]);        //共阴        输出段码
//        disp595(wei[y3]);                                //共阳        输出位码
//        disp595(~duan[LED8[y3]]);        //共阳        输出段码
        st_cp  = 1;
        st_cp  = 0;
        y3++;
        if(y3>3)
        {
                y3 = 0;
        }

}
/**************T0定时器函数****************/
void timer0 (void) interrupt 1        //Timer0 1ms中断函数
{
        TH0  = (65536 - 922) / 256;        //重装定时值
        TL0  = (65536 - 922) % 256;
        display(); //采用定时器0  1MS接一个数码管,实现动态显示
        sw2++;
        if(sw2>19)
        {
                sw2 = 0;
                y2 = 1;                //20ms标志
        }
}

/******************三个独立按键扫描*****************/
void key1_scan(void)
{
        if(key1==0) k2 = 1;         //功能键按下k2 = 1
        if(key2==0) k2 = 2;         //加键按下k2 = 2
        if(key3==0) k2 = 3;         //减键按下k2 = 3

        if(key2&key3&key1) //三个按键都不按时,40MS后所有跟按键有关的寄存器清0
        {
                k4++;
                if(k4>2) //40MS后所有跟按键有关的寄存器清0
                {
                        k4 = 0;
                        k2 = 0;
                        k3 = 0;
                        y4 = 0;
                        y5 = 0;
                }       
        }
        else
        {
                if(k2!=k3)  //k3 为按键消抖寄存器
                {
                        k3 = k2;
                        if(k2==1)
                        {
                                k5++;
                                if(k5==3)
                                {
                                        k5 = 0;
                                        sec = 0;       
                                }
                        }
                        key2_scan(); //按一次响应一次
                }
            key3_scan();        //加键或减键按1S后连续加或减数据
        }       
}

/*********** 时、分 键按一下1S后,0.2S连续加减数据**********/
void key3_scan(void)
{
        if(y5==0)
        {       
                if((k2==2)|(k2==3))
                {
                        y4++;
                        if(y4>50)
                        {
                                y4 = 0;
                                y5 = 1;       
                        }
                }
        }
        if(y5==1) //1S到后,进入0.2s加减数据
        {
                y6++;
                if(y6>10)
                {
                        y6=0;
                        key2_scan();
                }       
        }               
}

/****************** 时、分 加减函数判断****************/
void key2_scan(void)
{
        if(k5==1)
        {       
                if(k2==2)
                {
                        hour++;
                        if(hour>23)         //时
                        hour = 0;       
                         
                }
                if(k2==3)         
                {
                         if(hour==0)
                         hour = 23;
                        else
                        {
                                hour--;
                        }                
                }
        }
        if(k5==2)
        {       
                if(k2==2)
                {
                        minu++;
                        if(minu>59)            //分
                        minu = 0;       
                         
                }
                if(k2==3)         
                {
                         if(minu==0)
                         minu = 59;
                        else
                        {
                                minu--;
                        }                
                }
        }       
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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