找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+8位数码管显示时钟程序 无法读取ds1302时间

[复制链接]
跳转到指定楼层
楼主
本人初学单片机,想用8位数码管和ds1302做个简单的时钟,折腾了很久,死活读取不了ds1302的时间,时分秒都一直显示0,请各位高手不吝赐教,谢谢!

单片机源程序如下:
/*******************************************************************************
*  标题:  8位数码管显示时钟                                                   *
*                                                                                                                                                                                                *
*                                                                                    *
********************************************************************************/
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char

sbit SCK=P3^6;        //时钟
sbit SDA=P3^4;        //数据
sbit RST = P3^5;// DS1302复位

void main (void);                                        // 主函数
void LED4_Display (void);                        // LED显示
void LED_OUT(uchar X);                                // LED单字节串行移位函数

unsigned char code LED_0F[];                // LED字模表

sbit DIO = P1^0;                                //串行数据输入
sbit RCLK  = P1^1;                                //时钟脉冲信号——上升沿有效
sbit SCLK = P1^2;                                //打入信号————上升沿有效

//-----------------------------------------------------------------------------
// 全局变量

unsigned char LED[8] = {0,0,12,15,5,3,8};        //用于LED的8位显示缓存
bit ReadRTC_Flag;//定义读DS1302标志

unsigned char l_tmpdate[7]= {0,0,12,15,5,3,8}; //秒分时日月周年08-05-15 12:00:00
unsigned char l_tmpdisplay[8];

code unsigned char write_rtc_address[7]= {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位读写位
code unsigned char read_rtc_address[7]= {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//码表
unsigned char code LED_0F[] =
{   // 0         1          2           3        4         5          6           7        8         9          A           b        C    d          E    F    -
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf
};
code unsigned char table[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
//共阳数码管

/******************************************************************/
/*                    函数声明                                    */
/******************************************************************/
void Write_Ds1302_byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);//read RTC
void Set_RTC(void); //set RTC
void InitTIMER0(void);//inital timer0
/******************************************************************/
/*                   主函数                                       */
/******************************************************************/
void main(void)
{
    InitTIMER0();          //初始化定时器0
    //Set_RTC();             //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽

    while(1)
    {
        if(ReadRTC_Flag)
        {
            ReadRTC_Flag=0;
            Read_RTC();

            LED[0]=l_tmpdate[2]/16;                        //数据的转换,因我们采用数码管0~9的显示,将数据分开
            LED[1]=l_tmpdate[2]&0x0f;
            LED[2]=16;                                                    //加入"-"
            LED[3]=l_tmpdate[1]/16;
            LED[4]=l_tmpdate[1]&0x0f;
            LED[5]=16;
            LED[6]=l_tmpdate[0]/16;
            LED[7]=l_tmpdate[0]&0x0f;

        }
    }
}
/******************************************************************/
/*                   定时器0初始化                                */
/******************************************************************/
void InitTIMER0(void)
{
    TMOD|=0x01;//定时器设置 16位
    TH0=0xef;//初始化值
    TL0=0xf0;
    ET0=1;
    TR0=1;
    EA=1;
}


/******************************************************************/
/*                   写一个字节                                   */
/******************************************************************/
void Write_Ds1302_Byte(unsigned  char temp)
{
    unsigned char i;
    for (i=0; i<8; i++)             //循环8次 写入数据
    {
        SCK=0;
        SDA=temp&0x01;     //每次传输低字节
        temp>>=1;                  //右移一位
        SCK=1;
    }
}
/******************************************************************/
/*                  写入DS1302                                    */
/******************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
    RST=0;
    _nop_();
    SCK=0;
    _nop_();
    RST=1;
    _nop_();                    //启动
    Write_Ds1302_Byte(address);        //发送地址
    Write_Ds1302_Byte(dat);                //发送数据
    RST=0;                              //恢复
}
/******************************************************************/
/*                   读出DS1302数据                               */
/******************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
    unsigned char i,temp=0x00;
    RST=0;
    _nop_();
    _nop_();
    SCK=0;
    _nop_();
    _nop_();
    RST=1;
    _nop_();
    _nop_();
    Write_Ds1302_Byte(address);
    for (i=0; i<8; i++)                 //循环8次 读取数据
    {
        if(SDA)
            temp|=0x80;                        //每次传输低字节
        SCK=0;
        temp>>=1;                        //右移一位
        _nop_();
        _nop_();
        _nop_();
        SCK=1;
    }
    RST=0;
    _nop_();                          //以下为DS1302复位的稳定时间
    _nop_();
    RST=0;
    SCK=0;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    SCK=1;
    _nop_();
    _nop_();
    SDA=0;
    _nop_();
    _nop_();
    SDA=1;
    _nop_();
    _nop_();
    return (temp);                        //返回
}
/******************************************************************/
/*                   读时钟数据                                   */
/******************************************************************/
void Read_RTC(void)                //读取 日历
{
    unsigned char i,*p;
    p=read_rtc_address;             //地址传递
    for(i=0; i<7; i++)                  //分7次读取 秒分时日月周年
    {
        l_tmpdate[ i]=Read_Ds1302(*p);
        p++;
    }
}
/******************************************************************/
/*                  设定时钟数据                                  */
/******************************************************************/
void Set_RTC(void)                    //设定 日历
{
    unsigned char i,*p,tmp;
    for(i=0; i<7; i++) {    //BCD处理
        tmp=l_tmpdate[ i]/10;
        l_tmpdate[ i]=l_tmpdate[ i]%10;
        l_tmpdate[ i]=l_tmpdate[ i]+tmp*16;
    }
    Write_Ds1302(0x8E,0X00);

    p=write_rtc_address;        //传地址
    for(i=0; i<7; i++)                //7次写入 秒分时日月周年
    {
        Write_Ds1302(*p,l_tmpdate[ i]);
        p++;
    }
    Write_Ds1302(0x8E,0x80);
}
/******************************************************************/
/*                   定时器中断函数                               */
/******************************************************************/
void tim(void) interrupt 1 using 1
//中断,用于数码管扫描
{

    static unsigned char i,num;
    uchar code *led_table;          // 查表指针
        
    TH0=0xf5;
    TL0=0xe0;
    //uchar i;
    //显示第1位
    LED4_Display();
    i++;
    if(i==8)
    {
        i=0;
        num++;
        if(10==num)       //隔段时间读取1302的数据。时间间隔可以调整
        {
            ReadRTC_Flag=1; //使用标志位判断
            num=0;
        }
    }
}

void LED4_Display (void)
{
    uchar code *led_table;          // 查表指针
    uchar i;
    //显示第1位
    led_table = LED_0F + LED[0];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x01);

    RCLK = 0;
    RCLK = 1;
    //显示第2位
    led_table = LED_0F + LED[1];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x02);

    RCLK = 0;
    RCLK = 1;
    //显示第3位
    led_table = LED_0F + LED[2];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x04);

    RCLK = 0;
    RCLK = 1;
    //显示第4位
    led_table = LED_0F + LED[3];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x08);

    RCLK = 0;
    RCLK = 1;
    //显示第5位
    led_table = LED_0F + LED[4];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x10);

    RCLK = 0;
    RCLK = 1;
    //显示第6位
    led_table = LED_0F + LED[5];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x20);

    RCLK = 0;
    RCLK = 1;
    //显示第7位
    led_table = LED_0F + LED[6];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x40);

    RCLK = 0;
    RCLK = 1;
    //显示第8位
    led_table = LED_0F + LED[7];
    i = *led_table;

    LED_OUT(i);
    LED_OUT(0x80);

    RCLK = 0;
    RCLK = 1;
}

void LED_OUT(uchar X)
{
    uchar i;
    for(i=8; i>=1; i--)
    {
        if (X&0x80) DIO=1;
        else DIO=0;
        X<<=1;
        SCLK = 0;
        SCLK = 1;
    }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:155507 发表于 2020-6-15 09:55 | 只看该作者
你这个程序没错,估计其他地方错了,硬件搭建有错漏。

没有原理图、没有实物,谁能知道怎么来找问题
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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