找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7603|回复: 4
收起左侧

DS1302+数码管+矩阵键盘+温度传感器制作(c51程序)

[复制链接]
ID:72008 发表于 2015-1-11 14:47 | 显示全部楼层 |阅读模式
本帖最后由 liuyy 于 2015-1-11 14:55 编辑

1、效果图
2、矩阵键盘按键
3、代码
4、小结(矩阵键盘外部中断的小细节)

参考资料:实时时钟DS1302资料:http://www.51hei.com/bbs/dpj-22465-1.html
效果图
                                小时




                                        日期



                                                   星期与温度




矩阵键盘按键


完整程序源代码下载:http://www.51hei.com/f/shizhongcx.rar


代码:

#include <reg51.h>

//管脚声明
sbit dm = P2^0;        //段码
sbit wm = P2^1;        //位码
sbit st = P2^2;        //使能(RST)
sbit da = P2^3;        //i/o管脚(数据管脚)(i/o)
sbit cl = P2^4;        //时钟管脚(CLK)
sbit DQ = P2^5;        //定义总线的I/O管脚
sbit ZD = P3^2;

//下面是一些需要提前声明的函数(起始可以不用)

void DelayUs2x(unsigned char t);        //u延时
void DelayMs(unsigned char t);                //m延时
void x_sj();        //原始数据还原
void d_sj();        //数码管显示切换函数
void sjse();        //设置时间年月日函数
void szjia(unsigned char *ls,unsigned char j,unsigned char i,bit l);        //数值加或减函数
void sjqh(unsigned char *ls,unsigned char i,unsigned char j,unsigned char k); //设置,数码管缓存写入函数
void ntb();        //年同步函数
unsigned char jpsm();        //矩阵键盘反转扫描
void jpjm(unsigned char i);        //矩阵键盘设置函数
void sm();        //数码管扫描显示函数
void smgql();        //数码管缓存清零函数
void csh_hc();        //切换初始化数码管缓存函数(这个函数的作用就是在切换时清理数码管的缓存)
void sjse();        //设置时间年月日函数

//下面是ds1302时钟芯片的低层函数
unsigned char d_1302(unsigned char addr,unsigned char l);        //读取8个bit(参数1:地址,参数2:启用BCD处理)
void x_1302(unsigned char addr,unsigned char q,unsigned char l);        //写入8个bit(参数1:地址,参数2:数据,参数3:启用BCD处理)

//下面是ds18b20温度传感器的函数

bit d18b20_qs();        //18b20 起始
void d18b20_x(unsigned char dat); //写 8 位 数 据
unsigned char d18b20_d();        //读 8 位 数 据
unsigned int wd();        //读取温度函数
void zh(unsigned int i);         //数码管显示缓存写入函数

//下面的常量是一些寄存器的地址
#define addr_m        0x80        //秒
#define addr_f        0x82        //分
#define addr_x        0x84        //小时
#define addr_r        0x86        //日期
#define addr_y        0x88        //月
#define addr_xq 0x8a        //星期
#define addr_n        0x8c        //年
#define addr_xbh 0x8e        //写保护
#define addr_ram 0xc0        //RAM 开始地址(这款芯片有31个8位的RAM起始地址是C0)
#define addr_ram2 0xc2

//下面的是一些用到的全局变量
unsigned char sz;        //状态标志位
unsigned char hc[8];        //数码管缓存
unsigned char DM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
unsigned char WM[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};        //位码。显示的位置
unsigned char sjhc[8]={0,0,15,23,12,1,13,20};        //秒,分,小时,日期,月,星期,低位年,高位年
//unsigned char addr[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};        //秒,分,小时,日期,月,年,星期
unsigned char zt[5];        //小时,分钟,秒 与 年,月,日的数据临时变量
unsigned char shijian[8];        //全局临时变量(用来干什么都可以理论上可以节省声明数组的时间)



void csh_wbzd_0()        //初始化外部中断0
{
        IT0=0;        //外部中断0下降沿触发
        EX0=1;        //启用外部中断0
        EA=1;        //打开总中断

}
void wbzd_0() interrupt 0        //外部中断服务函数
{        

        if(!(sz & 0x80))
                sz = sz |0x80;        //有按键按下,把按键标志位 置 1

}

void DelayUs2x(unsigned char t)        //延时
{   
while(--t);
}

void DelayMs(unsigned char t)
{
     
while(t--)
{
     //大致延时1mS
     DelayUs2x(245);
         DelayUs2x(245);
}
}

bit d18b20_qs()        //18b20 起始
{
        bit dat;
        DQ = 1;        //DQ复位
        DQ = 0;        //拉低总线
        DelayUs2x(175);
        DQ = 1;        //拉高总线
        DelayUs2x(45);         //这里延时大概 45us
        dat = DQ;        //读取返回值(0:有18b20存在 1:是没有)
        DelayUs2x(20);        //这里延时大概 20us
        return dat;        //返回数值
}

void d18b20_x(unsigned char dat) //写 8 位 数 据
{
        unsigned char i;
        for(i=0;i<8;i++)        //8位计数器
        {
                DQ = 0;        //拉低总线
                DQ = dat & 0x01;        //取最低位赋值给总线
                DelayUs2x(45);        //延时45us
                DQ = 1;        //拉过总线准备写下一个数据(或者总线复位)
                dat >>= 1;        //数据右移一位
        }
}
unsigned char d18b20_d()        //读 8 位 数 据
{
        unsigned char i,dat=0;
        for(i=0;i<8;i++)        //8位计数器
        {
                DQ = 0;        //拉低总线
                dat >>= 1;        //数据右移一位
                DQ = 1;        //拉过总线(准备读取数据)
                if(DQ)        //判断是否是 1 如果是就把数据赋值给变量的高位
                        dat |= 0x80;
                DelayUs2x(25);        //这里延时大概 25us
        }
        return dat; //返回读取到数据数据
}


unsigned int wd()        //读取温度函数
{
        unsigned char i = 0;        //低8位数据
        unsigned char j = 0;        //高8位数据
        unsigned int k = 0;        //无符号16整形用来存储读回来的 16位温度数据(j和i组合后的数据)
        sm();
        d18b20_qs();        //初始化
        d18b20_x(0xCC);        //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
        d18b20_x(0x44);        //开启温度转换
        sm();
        sm();
        sm();
        d18b20_qs();        //初始化
        d18b20_x(0xCC);        //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
        sm();
        d18b20_x(0xBE);        //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
        sm();
        i = d18b20_d();        //读取低8位
        j = d18b20_d();        //读取高8位
        sm();
        k = j;               
        k <<= 8;
        k = k + i;
        sm();
        return k;        //返回读取到的16位数据
}

void zh(unsigned int i)         //数码管显示缓存写入函数
{
        unsigned char x,z;
        x = i & 0x0f;        //取出小数
        i >>=4;
        z = i & 0xff;        //取出整数
        switch(x)        //小数位写人显示缓存
        {
                case 0: hc[7]=DM[0];break;
                case 1: hc[7]=DM[1];break;
                case 2: hc[7]=DM[1];break;
                case 3: hc[7]=DM[2];break;
                case 4: hc[7]=DM[3];break;
                case 5: hc[7]=DM[3];break;
                case 6: hc[7]=DM[4];break;
                case 7: hc[7]=DM[4];break;
                case 8: hc[7]=DM[5];break;
                case 9: hc[7]=DM[6];break;
                case 10: hc[7]=DM[6];break;
                case 11: hc[7]=DM[7];break;
                case 12: hc[7]=DM[8];break;
                case 13: hc[7]=DM[8];break;
                case 14: hc[7]=DM[9];break;
                case 15: hc[7]=DM[9];break;
        }
        x = z/10;        //取出十位
        hc[5]=DM[x];//十位缓存写入
        x = z%10;        //取出个位
        hc[6] = DM[x] | 0x80;//个位缓存写入
}

/*下面这个函数是ds1302的最低层函数也是最重要的*/
void x_1302(unsigned char addr,unsigned char q,unsigned char l)        //写入8个bit(参数1:地址,参数2:数据,参数3:启用BCD处理)
{
        unsigned char i;
        if(l)        //BCD处理(处理成BCD格式)
        {
                i=q/10;
                q=q%10;
                q=q+i*16;
        }
        addr = addr & 0xFE;     //最低位置零
        cl = 0;        //拉低时钟
        da = 0;        //复位数据
        st = 1;        //使能芯片。写入开始
        for(i=0;i<8;i++)        //写入地址
        {
                addr >>= 1;
                da = CY;
                cl = 1;
                cl = 0;        
        }
        for(i=0;i<8;i++)        //写入数据
        {
                q >>= 1;
                da = CY;
                cl = 1;
                cl = 0;
        }
        st = 0;        //写入结束
}

/*下面这个函数是ds1302的最低层函数也是最重要的*/
unsigned char d_1302(unsigned char addr,unsigned char l)        //读取8个bit(参数1:地址,参数2:启用BCD处理)
{
        unsigned char i,dat;
        addr = addr | 0x01;//最低位置高
        cl = 0;        //拉低时钟
        da = 0;        //复位数据
        st = 1;        //使能芯片,读取开始
        for(i=0;i<8;i++)        //写入地址
        {
                addr >>= 1;
                da = CY;
                cl = 1;
                cl = 0;
        }
        for(i=0;i<8;i++)        //读取数据
        {
                dat >>= 1;
                if(da)
                        dat = dat | 0x80;
                cl = 1;
                cl = 0;
        }
        st = 0;        //读取结束
        if(l)        //BCD处理(还原成10进制)
        {
                i = dat / 16;        
                dat = dat % 16;
                dat = dat +i*10;
        }
        return dat;
}

/*以下函数就是反转扫描的精华*/
unsigned char jpsm()        //矩阵键盘反转扫描
{
        unsigned char i=0;        //用于接收按键数值
        P1 = 0x0f;        //检测低4位
        if(0x0f != P1)        //检测按键是否按下
        {
                DelayMs(10);        //去抖
                if(0x0f != P1)        //在次判断按键是否真的按下而不是其他干扰
                {
                        i = P1;        //把低4位赋值给i
                        P1 = 0xf0;        //检测高4位
                        //DelayUs2x(5);        //稍微延时。。这条语句可以去掉
                        i = i | P1;        //把低4位和高4位组合成完整的按键数值
                        while( 0xf0 != P1 )        //检测按键是否松开
                        {
                                sm();
                                
                        }
                        P1 = 0xf0;        //这里是一个狠重要的经验(以为在检测低4位时赋值了0x0f,就是这个0x0f导致外部中断被无限的触发)
                        sz = sz & 0x7f;
                        return i;        //返回按键数值
                }
        }
        P1 = 0xf0;        //这里是一个狠重要的经验(以为在检测低4位时赋值了0x0f,就是这个0x0f导致外部中断被无限的触发)
        sz = sz & 0x7f;
        return 0;        //按键没有按下返回0
}

void sm()        //数码管扫描显示
{
        unsigned char i;
        for(i=0;i<8;i++)
        {
                P0 = 0;        //消影
                dm = 1;
                dm = 0;

                P0 = WM[ i];        //写入位码
                wm = 1;
                wm = 0;

                P0 = hc[ i];        //写入段码
                dm = 1;
                dm = 0;
                DelayUs2x(10);
        }
        P0 = 0;        //清空段码数据
        dm = 1;
        dm = 0;
}


void jpjm(unsigned char i)        //矩阵键盘设置函数
{
        switch(i)
        {
                case 0xe7:        //矩阵键盘按键 (切换)
                {
                        switch((sz & 0x03))
                        {
                                case 0x00:        //如果当前是时间模式则切换到日期模式模式
                                {
                                        ntb();
                                        sz++;        //把模式设置成日期格式
                                        csh_hc();        //清理数码管缓存
                                        break;
                                }
                                case 0x01:        //如果当前是日期模式则切换到时间模式
                                {
                                        sz++;        //把模式设置成时间格式
                                        csh_hc();        //清理数码管缓存
                                        break;
                                }
                                case 0x02:
                                {
                                        sz = sz & 0xfc;        //把模式设置成时间格式
                                        csh_hc();
                                        break;
                                }
                        }
                        break;
                }
                case 0xdb:
                {
                        sjse();        //调用设置函数
                        csh_hc();        //初始化数码管显示缓存
                        break;
                }
                case 0xb7:        //矩阵键盘 。还原原始时间
                {
                        x_sj();        
                        csh_hc();
                        break;
                }
        }
}
void x_sj()        //原始数据还原
{
        unsigned char i,j=addr_m;
        x_1302(addr_xbh,0,0);        //关闭写保护
        for(i=0;i<7;i++)
        {
                x_1302(j,sjhc[ i],1);
                j += 2;
        }
        x_1302(addr_ram,sjhc[7],1);        //把高2位年写入DS1302的RAM的C0地址中
        x_1302(addr_ram2,sjhc[6],1);
        x_1302(addr_xbh,0x80,0);        //打开写保护
}
void d_sj()        //数码管显示切换函数
{
        unsigned char j;
        switch((sz & 0x03))
        {
                case 0:        //显示时,分,秒
                {
                        if((j = d_1302(addr_m,1)) != zt[2])        //读取秒然后判断时间 这样来提升效率
                        {
                                zt[2] = j;        //记录秒的临时数值
                                hc[6] = DM[zt[2]/10];        //写入秒的十位数据到数码管缓存
                                hc[7] = DM[zt[2]%10];        //写入秒的个位数据到数码管缓存
                                
                                if(zt[2] == 0)        //判断秒是否是0,如果是0条件就成立就读取分钟
                                {
                                        zt[1] = d_1302(addr_f,1);        //记录分钟的临时数值
                                        hc[3] = DM[zt[1]/10];        //写入分钟的十位数据到数码管缓存
                                        hc[4] = DM[zt[1]%10];        //写入分钟的个位数据到数码管缓存
                                       
                                        if(zt[1] == 0)        //判断时钟是否是0,如果是0条件成立就读取小时
                                        {
                                                zt[0] = d_1302(addr_x,1);        //记录小时的临时数值
                                                ntb();        //每小时同步一下年
                                                hc[0] = DM[zt[0]/10];        //写入小时的十位数据到数码管缓存
                                                hc[1] = DM[zt[0]%10];        //写入小时的个位数据到数码管缓存
                                        }
                                }
                        }
                        break;
                }
                case 1:        //显示年,月,日
                {
                        if((j = d_1302(addr_r,1)) != zt[2])        //小时变化后读取月年
                        {
                                csh_hc();
                        }
                        break;
                }
                case 2:        //显示周与温度
                {
                        csh_hc();
                        break;
                }
        }

}

void csh_hc()        //切换初始化数码管缓存函数(这个函数的作用就是在切换时清理数码管的缓存)
{
        switch((sz & 0x03))
        {
                case 0x00:
                {
                        zt[2] = d_1302(addr_m,1);        //读取秒
                        zt[1] = d_1302(addr_f,1);        //读取分钟
                        zt[0] = d_1302(addr_x,1);        //读取小时
                        hc[7] = DM[zt[2]%10];        //写入秒的个位
                        hc[6] = DM[zt[2]/10];        //写入秒的十位
                        hc[5] = 0x40;        // -
                        hc[4] = DM[zt[1]%10];        //写入分的个位
                        hc[3] = DM[zt[1]/10];        //写入分的十位
                        hc[2] = 0x40;        // -                        
                        hc[1] = DM[zt[0]%10];        //写入时的个位
                        hc[0] = DM[zt[0]/10];        //写入时的十位
                        break;
                }
                case 0x01:
                {
                        zt[3] = d_1302(addr_ram,1);        //读取年的高2位(千位和百位)
                        zt[2] = d_1302(addr_r,1);        //读取日
                        zt[1] = d_1302(addr_y,1);        //读取月
                        zt[0] = d_1302(addr_n,1);        //读取年的低2位(个位和十位)
                        hc[7] = DM[zt[2]%10];        //写入日的个位
                        hc[6] = DM[zt[2]/10];        //写入日的十位
                        hc[5] = 0x80 | DM[zt[1]%10];        //写入月的个位 + "."
                        hc[4] = DM[zt[1]/10];                        //写入月的十位
                        hc[3] = 0x80 | DM[zt[0]%10];        //写入年的个位 + "."
                        hc[2] = DM[zt[0]/10];                        //写入年的十位
                        hc[1] = DM[zt[3]%10];        //写入年的百位
                        hc[0] = DM[zt[3]/10];        //写入年的千位
                        break;
                }
                case 0x02:
                {
                        zh(wd());
                        zt[3] = d_1302(addr_xq,1);
                        hc[0] = 0x40;
                        hc[1] = DM[zt[3]];
                        hc[2] = 0x40;
                        hc[3] = 0;
                        hc[4] = 0;
                        break;
                }
        }
}
void smgql()        //数码管缓存清零函数
{
        unsigned char i;
        for(i=0;i<8;i++)
                hc[ i] = 0;
}

void szjia(unsigned char *ls,unsigned char j,unsigned char i,bit l)        //数值加或减函数
//参数1:数据,参数2:传送要设置的位置,参数3:传送模式,参数4:(0是:减,1是:加)
{
        switch((sz & 0x03))        //区分时间,日期,周
        {
                case 0:        //时间(从switch1:分支1)
                {
                        switch(j)        //区分 秒,分钟,小时
                        {
                                case 1:        //秒
                                {
                                        if(l)        //判断是加还是减
                                        {
                                                ls[0]++;
                                                if( 60 <= ls[0] )
                                                        ls[0] = 0;
                                        }
                                        else
                                        {
                                                if( 0 >= ls[0])
                                                        ls[0]=59;
                                                else
                                                        ls[0]--;
                                        }
                                        sjqh(ls,6,0,1);        
                                        break;
                                }
                                case 2:        //分钟
                                {
                                        if(l)        //判断是加还是减
                                        {        
                                                ls[1]++;
                                                if( 60 <= ls[1] )
                                                        ls[1] = 0;
                                        }
                                        else
                                        {
                                                if( 0 >= ls[1])
                                                        ls[1]=59;
                                                else
                                                        ls[1]--;
                                        }
                                        sjqh(ls,3,1,1);
                                        break;
                                }
                                case 3:        //小时
                                {
                                        if(l)        //判断是加还是减
                                        {
                                                ls[2]++;
                                                if( 24 <= ls[2] )
                                                        ls[2] = 0;
                                        }
                                        else
                                        {
                                                if(0 >= ls[2])
                                                        ls[2]=23;
                                                else
                                                        ls[2]--;
                                        }
                                        sjqh(ls,0,2,1);
                                        break;
                                }
                        }
                        break;
                                                        
                }
                case 1:        //日期(从switch2:分支1)
                {
                        switch(j)        //区分 日期,月份,年
                        {
                                case 1:        //日期
                                {
                                        if(l)        //判断是加还是减
                                        {
                                                ls[3]++;
                                                if( i <= ls [3])        //这里的i放在右移的按键里面处理,
                                                        ls[3] = 1;
                                        }
                                        else
                                        {
                                                if(1 >= ls[3])
                                                {
                                                        ls[3]= i-1;
                                                }
                                                else
                                                {
                                                        ls[3]--;
                                                }
                                        }
                                        sjqh(ls,6,3,1);
                                        break;
                                }
                                case 2:        //月份
                                {
                                        if(l)
                                        {
                                                ls[4]++;
                                                if(13 <= ls[4])        
                                                        ls[4] = 1;
                                        }
                                        else
                                        {
                                                if(1 >= ls[4])
                                                        ls[4] = 12;
                                                else
                                                        ls[4]--;
                                        }
                                        sjqh(ls,4,4,1);
                                        break;
                                }
                                case 3:        //年
                                {
                                        if(l)
                                        {
                                                ls[6]++;
                                                if( 100 <= ls[6])
                                                {
                                                        ls[6] = 0;
                                                        ls[7]++;
                                                        if( 100 <= ls[7] )
                                                                ls[7] = 0;
                                                }
                                        }
                                        else
                                        {
                                                if( 0 >= ls[6] )
                                                {
                                                        ls[6] = 99;
                                                        ls[7]--;
                                                        if( 0 >= ls[7] )
                                                        {
                                                                ls[7] = 99;
                                                        }
                                                }
                                                else
                                                        ls[6]--;
                                        }
                                        sjqh(ls,0,7,2);
                                        break;
                                }
                        }
                        break;
                }
                case 2:        //周(从switch3:分支3)
                {
                        if(l)
                        {
                                ls[5]++;
                                if( 8 <= ls[5] )
                                {
                                        ls[5] = 1;
                                }
                        }
                        else
                        {
                                if( 1 >= ls[5])
                                        ls[5] = 7;
                                else
                                        ls[5]--;
                        }
                        sjqh(ls,0,0,10);
                        break;
                }
        }

}

void sjqh(unsigned char *ls,unsigned char i,unsigned char j,unsigned char k) //设置,数码管缓存写入函数
        //参数1:数据,参数2:缓存开始地址(0~7),参数3:写入缓存的数据,参数4:写入数据的个数
{
        if(k<10)
                for(;k>0&&i<8&&j<8;k--)
                {
                        hc[ i]= DM[ls[j]/10];
                        i++;
                        if(i<8)
                                hc[ i]= DM[ls[j]%10];
                        j--;i++;
                }
        else
        {
                hc[0]=0x40;
                hc[1]=DM[ls[5]];
                hc[2]=0x40;
        }
}

void sjse()        //设置时间年月日函数
{
        unsigned char ls[8],i,j=0x80;
        unsigned int n;        //保存年(计算闰年要用到)
        for(i=0;i<7;i++)        //读取寄存器的所有数值
        {
                shijian[ i]=d_1302(j,1);        //读取数据
                ls[ i] = shijian[ i];        //赋值给临时设置数组
                j += 2;        //地址指针移动到下一个地址
        }
        shijian[7]=d_1302(addr_ram,1);        //读取高2位年。地址是0xc0
        ls[7] = shijian[7];//赋值给临时设置数组
        j = 3;        //初始化位置
        smgql(); //数码管缓存清零
        switch((sz & 0x03))
        {
                case 0:sjqh(ls,0,2,1);break;        //把小时写入数码管缓存
                case 1:sjqh(ls,0,7,2);break;        //把年写入缓存
                case 2:sjqh(ls,0,0,10);        //星期
        }
        while(i)
        {
                if((sz & 0x80))        //这里是判断是否有按键按下。
                {
                        sz = sz & 0x7f;        //按键标志位置0
                        switch (jpsm())        //按下的按键区分(主switch)
                        {
                                case 0xdd: //6 数值加(主switch:分支1)
                                {
                                        szjia(ls,j,i,1);        //写入数码管显示缓存
                                        break;
                                }
                                case 0xeb:        //*        左移(主switch:分支2)
                                {
                                        smgql(); //数码管缓存清零
                                        if( 1 < j )
                                                j--;
                                        else
                                                j=3;
                                        switch((sz & 0x03))
                                        {
                                                case 0:        //时间左移
                                                {
                                                        switch(j)        //区分移动标志的数值
                                                        {
                                                                case 1:        //移动标志1是6~7数码管显示
                                                                {
                                                                        sjqh(ls,6,0,1);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                                case 2:
                                                                {
                                                                        sjqh(ls,3,1,1);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                                case 3:
                                                                {
                                                                        sjqh(ls,0,2,1);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                        }
                                                        break;
                                                }
                                                case 1:        //日期左移 >>
                                                {
                                                        //标志1
                                                        switch(j)
                                                        {
                                                                case 1:
                                                                {
                                                                        switch(ls[4])        //设置每个月天数的上限
                                                                        {
                                                                                case 2:
                                                                                {
                                                                                        n = ls[7];
                                                                                        n = n*100+ls[6];
                                                                                        if( n % 400 ==0 ||((n%4) ==0 && (n%100)))        //能被400整除与能被4整除且不能被100整除
                                                                                                //四年一闰,百年不闰,四百年再闰
                                                                                                i = 29;
                                                                                        else
                                                                                                i = 28;
                                                                                        break;
                                                                                }
                                                                                case 4: i=30;break;
                                                                                case 6: i=30;break;
                                                                                case 9: i=30;break;
                                                                                case 11: i=30;break;
                                                                                default : i = 31;
                                                                        }
                                                                        i++;
                                                                        sjqh(ls,6,3,1);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                                case 2:
                                                                {
                                                                        sjqh(ls,4,4,1);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                                case 3:
                                                                {
                                                                        sjqh(ls,0,7,2);        //写入数码管显示缓存
                                                                        break;
                                                                }
                                                        }
                                                        break;
                                                }
                                                case 2: sjqh(ls,0,0,10);break;
                                        }
                                        break;
                                }
                                case 0xdb:        //9        设置或者确定(主switch:分支3)
                                {
                                        j=0x80;
                                        x_1302(addr_xbh,0,0);
                                        for(i=0;i<7;i++)
                                        {
                                                if( shijian[ i] != ls[ i] )
                                                {
                                                        x_1302(j,ls[ i],1);
                                                }
                                                j += 2;
                                        }
                                                x_1302(addr_ram,ls[7],1);
                                                x_1302(addr_ram2,ls[6],1);
                                       
                                        x_1302(addr_xbh,0x80,0);
                                        i=0;
                                        break;
                                }
                                case 0xbb:        //8 右移(主switch:分支4) <<
                                {
                                        smgql(); //数码管缓存清零
                                        if(j>=3)
                                                j=1;
                                        else
                                                j++;
                                        switch( (sz & 0x03) )
                                        {
                                                case 0:        //时间
                                                {
                                                        switch(j)
                                                        {
                                                                case 1: sjqh(ls,6,0,1);break;
                                                                case 2: sjqh(ls,3,1,1);break;
                                                                case 3: sjqh(ls,0,2,1);break;
                                                        }
                                                        break;
                                                }
                                                case 1:        //日期
                                                {
                                                        switch(j)
                                                        {
                                                                case 1: sjqh(ls,6,3,1);break;
                                                                case 2: sjqh(ls,4,4,1);break;
                                                                case 3: sjqh(ls,0,7,2);break;
                                                        }
                                                        break;
                                                }
                                                case 2:        sjqh(ls,0,0,10);break;
                                        }
                                        break;
                                }
                                case 0xd7:        //= 数值减(主switch:分支5)
                                {
                                        szjia(ls,j,i,0);
                                        break;
                                }
                                case 0xe7:        //设置切换
                                {        
                                        j=3;
                                        smgql(); //数码管缓存清零
                                        if((sz & 0x03) == 2)
                                                sz = sz & 0xfc;
                                        else
                                                sz++;
                                        switch((sz & 0x03))
                                        {
                                                case 0:sjqh(ls,0,2,1);break;
                                                case 1:sjqh(ls,0,7,2);break;
                                                case 2:sjqh(ls,0,0,10);break;
                                        }
                                        break;
                                }
                                case 0xb7: i=0;break;        //.取消设置
                        }
                        
                }
                sm();        //扫描显示数码管
        }
}

void ntb()        //年同步函数
{
        shijian[5] = d_1302(addr_n,1);
        shijian[6] = d_1302(addr_ram2,1);
        if(shijian[6] != shijian[5])
        {
                if( shijian[6] == 99)
                {
                        shijian[7] = d_1302(addr_ram,1);
                        if(shijian[7] != 99)
                                shijian[7]++;
                        else
                                shijian[7]=0;
                        x_1302(addr_xbh,0,0);
                        x_1302(addr_ram2,0,1);
                        x_1302(addr_ram,shijian[7],1);
                        x_1302(addr_xbh,0x80,0);
                }
                else
                {
                        x_1302(addr_xbh,0,0);
                        x_1302(addr_ram2,shijian[5],1);
                        x_1302(addr_xbh,0x80,0);
                }
        }
}

void main()        //主函数
{
        
        sz = 0;
   csh_hc();
        csh_wbzd_0();        //外部中断初始化
        ntb();
        P1 = 0xf0;        //这个是用于检测矩阵键盘是否按下的(外部中断需要的)
        while(1)
        {
                d_sj();
                if((sz&0x80))        //这里是判断是否有按键按下。
                /*注:这里加这个判断是因为键盘解码后需要执行的函数打乱主函数中断 d_sj()
                函数造成数据有时无法写入DS1302芯片*/
                {
                        jpjm(jpsm());
                        
                }
                sm();        //扫描显示数码管
        }
        
}

代码中关于ds18b20部分原理详见:http://www.51hei.com/bbs/dpj-22807-1.html
注:代码写的狠垃圾。。根本没有算法可言而且BUG很多 。。
       没有改的BUG有。在设置日期时存在日期可以设置成 2月31号的错误

矩阵键盘的外部中断问题
       1,如果矩阵键盘检测按键完毕后 ,如果P1口的数值是 0x0f就会导致外部中断
            无限触发。
      
         这里P1口的数值要结合电路图来判断。
回复

使用道具 举报

ID:73463 发表于 2015-2-10 08:27 | 显示全部楼层
老师,这是个万年历吗?
回复

使用道具 举报

ID:73868 发表于 2015-3-19 22:03 | 显示全部楼层
亲,能否给出电路图
回复

使用道具 举报

ID:640928 发表于 2019-11-23 20:07 来自手机 | 显示全部楼层
为什么下载不了
回复

使用道具 举报

ID:640928 发表于 2019-11-23 20:47 来自手机 | 显示全部楼层
我试了一下什么反映也没有呀
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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