找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于单片机驱动DS1307与数码管显示程序问题

[复制链接]
跳转到指定楼层
楼主
50黑币
最近师傅交给实时时钟学习,不讲解不提示总之自己搞定,IIC协议早期学过,可是DS1307实在是头疼得很,不知是什么原因无法在数码管显示正确的时间,资料也查了很多还是没有头绪,已陷入死胡同无法走出,已经第3天了还是束手无策,实属无奈,望各位大师给予帮助不胜感激!!!
P0数码管显示,74HC595控制数码管位码。年,月,日,时,分,秒,星期。

单片机源程序如下:
#include <reg52.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit sda=P2^0;//;模拟I2C 数据传送位
sbit scl=P2^1;//;模拟I2C 时钟控制状态标志
sbit SER  = P1^2;    //数据输入
sbit SCK  = P1^0;    //串行移位时钟
sbit RCK  = P1^1;    //锁存器时钟
sbit tiao=P1^3;  //调节键
sbit jia =P1^4;  //按键+
sbit jian=P1^5;  //按键-
uchar Hours,Minutes,Seconds,Year,Month,Date,Weeks;

uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar data dis_buf[]={0,0,0xbf,0,0,0xbf,0,0};//显示缓存

void hc595(uchar Data)//74HC595的数据串入并出子程序
{
        uchar i;            
        for(i=0;i<8;i++)        //由高位到低位发送一个字节
        {
                Data<<=1;                //左移一位,最高位溢出到位寄存器CY
                SER=CY;                        //从位寄存器的进位标志位CY读取
                SCK = 0;                        //串行移位
                SCK = 1;
        }
   RCK = 0;                         //锁存
   RCK = 1;
}

uchar Decimal_to_BCD(uchar temp)//十进制转换成BCD码
{
uchar a,b,c;
        a=temp;
        b=0;
        while(a>=10)
                {
                        a=a-10;
                        b=b+16;
                        c=a+b;
                        temp=c;
                }         
        return temp;
}
uchar BCD_to_Decimal(uchar temp)//BCD码转换成十进制
{
        uchar a,b,c;
        a=temp;
        b=0;
        while(a>=16)
                {
                        a=a-16;
                        b=b+10;
                        c=a+b;
                        temp=c;
                }         
        return temp;
}
void delay_5us()//5us延时
{
        _nop_();
        _nop_();
        _nop_();
}
void star_1307()//开始
{
        sda=1;
        delay_5us();//5us延时
        scl=1;
        delay_5us();//5us延时
        sda=0;
        delay_5us();//5us延时
}
void stop_1307()//停止
{
        sda=0;
        delay_5us();//5us延时
        scl=1;
        delay_5us();//5us延时
        sda=1;
        delay_5us();//5us延时
}
void ack_1307()//应答
{
uchar z=0;
        while((sda==1)&&(z<50))z++;//条件判断, sda=1,则没有应答。如果没有应答则延时:z<50,z++;后返回
        scl=0;
        delay_5us();//5us延时
}
void write_1307(uchar slave_write_address,uchar byte_address,uchar data_data)//写一个数据
{
uchar temp,temp1,i,ii;
        star_1307();                                //开始
        for(ii=0;ii<3;ii++)//根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,数据
        {
                if(ii==0)
                {
                        temp=slave_write_address;//送 器件写地址
                        temp1=slave_write_address;
                }
                else if(ii==1)
                {
                        temp=byte_address;//送 字节地址
                        temp1=byte_address;
                }
                else if(ii==2)
                {
                        temp=data_data;//送 数据
                        temp1=data_data;
                }
                for(i=0;i<8;i++)
                {
                        scl=0;
                        delay_5us();//5us延时
                        temp=temp1;
                        temp=temp&0x80;//相 与 后,把不相关的位清零
                        if(temp==0x80)//根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1                        
                                sda=1;
                        else
                                sda=0;
                        
                        delay_5us();//5us延时
                        scl=1;
                        delay_5us();//5us延时
                        scl=0;
                        delay_5us();//5us延时
                        temp1=temp1<<1;//向左移出1位
                        
                }
                sda=1;
                delay_5us();//5us延时
                scl=1;
                delay_5us();//5us延时
                ack_1307();
        }
        stop_1307();//停止
}
uchar read_1307(uchar slave_write_address,uchar byte_address,uchar slave_read_address)  //读一个数据
{
uchar temp,temp1,i,ii,x,data_data;
        star_1307();         //开始
        for(ii=0;ii<3;ii++)  //根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,器件读地址
        {
                if(ii==0)
                        {
                        temp=slave_write_address;  //送 器件写地址
                        temp1=slave_write_address;
                        }
                else if(ii==1)
                        {
                        temp=byte_address;        //送 字节地址
                        temp1=byte_address;
                        }
                else if(ii==2)
                        {
                        star_1307();              //开始
                        temp=slave_read_address;  //送 器件读地址
                        temp1=slave_read_address;
                        }
                for(i=0;i<8;i++)              //开始读数据
                        {
                                scl=0;
                                delay_5us();          //5us延时
                                temp=temp1;
                                temp=temp&0x80;       // 相 与 后,把不相关的位清零
                                if(temp==0x80)        //根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1
                                
                                sda=1;
                                else
                                sda=0;
                                
                                delay_5us();          //5us延时
                                scl=1;
                                delay_5us();          //5us延时
                                scl=0;
                                delay_5us();          //5us延时
                                temp1=temp1<<1;       //向左移出1位
                        }
                sda=1;
                delay_5us();                 //5us延时
                scl=1;
                delay_5us();                 //5us延时
                ack_1307();                  //应答
        }
        for(x=0;x<8;x++)
        {
                data_data=data_data<<1;     //向左移入1位
                sda=1;
                delay_5us();                //5us延时
                scl=0;
                delay_5us();                //5us延时
                scl=1;
                delay_5us();                //5us延时
                if(sda==1)                  //判断 数据线是否是高电平
                data_data|=0x01;            //把读到的数据 或 0X01
        }
        ack_1307();                     //应答
        stop_1307();                    //停止
        return data_data;               //返回读到的数据
}
void init_1307()                    //初始化
{
        Hours=23;
        Minutes=14;
        Seconds=11;
        Year=17;   
        Month=11;
        Date=24;
        Weeks=5;        
        Seconds=Decimal_to_BCD(Seconds);  //十进制转换成BCD码
        Minutes=Decimal_to_BCD(Minutes);  //十进制转换成BCD码
        Hours=Decimal_to_BCD(Hours);      //十进制转换成BCD码
        Date=Decimal_to_BCD(Date);        //十进制转换成BCD码
        Year=Decimal_to_BCD(Year);        //十进制转换成BCD码
        Month=Decimal_to_BCD(Month);      //十进制转换成BCD码

        write_1307(0xd0,0x00,Seconds);    //写入秒
        write_1307(0xd0,0x01,Minutes);    //写入分
        write_1307(0xd0,0x02,Hours);      //写入时
        write_1307(0xd0,0x03,Weeks);      //写入星期
        write_1307(0xd0,0x04,Date);       //写入日期
        write_1307(0xd0,0x05,Month);      //写入月         
        write_1307(0xd0,0x06,Year);       //写入年
}
void read_time_1307()
{
        Seconds=read_1307(0xd0,0x00,0xd1);          //读秒
        Seconds=BCD_to_Decimal(Seconds);     //BCD码转换成十进制
        Minutes=read_1307(0xd0,0x01,0xd1);          //读分
        Minutes=BCD_to_Decimal(Minutes);     //BCD码转换成十进制         
        Hours=read_1307(0xd0,0x02,0xd1);          //读时
        Hours=BCD_to_Decimal(Hours);         //BCD码转换成十进制

        Year=read_1307(0xd0,0x06,0xd1);          //读年
        Year=BCD_to_Decimal(Year);           //BCD码转换成十进制
        Date=read_1307(0xd0,0x04,0xd1);          //读日
        Date=BCD_to_Decimal(Date);           //BCD码转换成十进制
        Month=read_1307(0xd0,0x05,0xd1);     //读月
        Month=BCD_to_Decimal(Month);         //BCD码转换成十进制
        Weeks=read_1307(0xd0,0x03,0xd1);         //读周
}



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

使用道具 举报

沙发
ID:332444 发表于 2020-9-25 10:26 | 只看该作者
问题描述不是很清楚,通常写程序或调试程序是这样的,首先用某固定值去调好数码管,因为是人机交互的界面,调好数码管显示无误后才去调要显示的内容,也就是分步设计或调试。
回复

使用道具 举报

板凳
ID:332444 发表于 2020-9-25 10:28 | 只看该作者
也就是功能要一块一块的完成,已经完成了的功能就不用去考虑有问题出现。
回复

使用道具 举报

地板
ID:709561 发表于 2020-9-25 11:14 | 只看该作者
xianfajushi 发表于 2020-9-25 10:26
问题描述不是很清楚,通常写程序或调试程序是这样的,首先用某固定值去调好数码管,因为是人机交互的界面, ...

是的,就是调试的时候数码管不是没有显示就是乱码,还是DS1307与数码管程序衔接的问题是自己没有办法解决,理解的不够透彻,才导致问题产生无法解决,是否有文献或参考类给予借鉴,不胜感激!!!
回复

使用道具 举报

5#
ID:332444 发表于 2020-9-25 11:29 | 只看该作者
DS1307我自己没用过,摆渡资料看也不是很理解什么叫做闰年补偿,这个闰年补偿是指阴历?看资料也没提到阴历,若是指阳历阳历闰年是固定的没什么好补偿的,不是很了解这块芯片。我说过了先用固定值去调试数码管,完成数码管功能块后再去调试读取。DS1307电路图摆渡有,需要我帮你搜索?
回复

使用道具 举报

6#
ID:332444 发表于 2020-9-25 11:43 | 只看该作者
其实我认为蛋骗鸡只要提供标准的秒信号就可以了,目前蛋骗鸡使用中断作为计时器会受影响,因此,要外部芯片;
我的思路是蛋骗鸡可设计一功能提供一不受任何影响的秒信号存储空间,调用时就是读取秒数据,可预制秒内容,其他的分,时,星期,日,月,年都可写程序实现。
回复

使用道具 举报

7#
ID:96682 发表于 2020-9-25 15:27 来自手机 | 只看该作者
阳历的闰年只是多天,农历就不同了几年会多一个闰月。楼主说的乱码是否用错数码管?。
回复

使用道具 举报

8#
ID:709561 发表于 2020-9-25 16:00 | 只看该作者
wc86110 发表于 2020-9-25 15:27
阳历的闰年只是多天,农历就不同了几年会多一个闰月。楼主说的乱码是否用错数码管?。

数码管是对的我确定没有使用错误,就是提取DS1307的时间年月日就是无法显示正确
回复

使用道具 举报

9#
ID:709561 发表于 2020-9-25 16:02 | 只看该作者
xianfajushi 发表于 2020-9-25 10:28
也就是功能要一块一块的完成,已经完成了的功能就不用去考虑有问题出现。

是的,就是调试到数码管与DS1307衔接的程序,无论如何改写都无法显示正确???
回复

使用道具 举报

10#
ID:332444 发表于 2020-9-25 16:13 | 只看该作者
那就先测试读芯片一个值测试通讯是否正确。
回复

使用道具 举报

11#
ID:213173 发表于 2020-9-26 09:26 | 只看该作者
这是在本坛找的帖子,是一个DS1307.H文件,经移植仿真测试原作者的源码写得很好。只要添加按键和显示函数就能成为一个万年历。链接http://www.51hei.com/bbs/dpj-152422-1.html

测试程序 仿真.zip (153.83 KB, 下载次数: 25)





回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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