AVR上的DS1302程序读出来在液晶上显示错误

2019-03-24 18:19发布

为什么我的AVR上的DS1302程序读出来在液晶上显示全部都是55555 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
7条回答
南方孩子
2019-03-25 19:52
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#define uchar unsigned char
#define uint unsigned int
#define delayms(x) _delay_ms(x)
#define delayus(x) _delay_us(x)

#define rsddr        DDRD
#define rsport         PORTD
#define rspin         PIND

#define rwddr         DDRD
#define rwport         PORTD
#define rwpin         PIND

#define enddr         DDRD
#define enport         PORTD
#define enpin         PIND

#define DS1302_SECOND_WRITE 0x80
#define DS1302_MINUTE_WRITE 0x82
#define DS1302_HOUR_WRITE 0x84
#define DS1302_DAY_WRITE 0x86
#define DS1302_MONTH_WRITE 0x88
#define DS1302_WEEK_WRITE 0x8a
#define DS1302_YEAR_WRITE 0x8c

#define DS1302_YEAR_READ 0x8d
#define DS1302_MONTH_READ 0x89
#define DS1302_DAY_READ 0x87
#define DS1302_HOUR_READ 0x85
#define DS1302_MINUTE_READ 0x83
#define DS1302_SECOND_READ 0x81

#define RST PORTB
#define SCLK PORTB
#define SDA PORTC

uchar c,shi,ge;
uchar year1=0x88;
uchar year0=0x88;
uchar month1=0x88;
uchar month0=0x88;
uchar date1=0x88;
uchar date0=0x88;
uchar day1=0x88;
uchar day0=0x88;
uchar hour1=0x88;
uchar hour0=0x88;
uchar minute1=0x88;
uchar minute0=0x88;
uchar second1=0x88;
uchar second0=0x88;
uchar table[]={'0','1','2','3','4','5','6','7','8','9','0'};


void DS1302WriteByte(uchar dat)
{
        uchar i;
        SCLK &=~(1<<7);//初始时钟线置为0
        delayus(2);
        for(i=0;i<8;i++)//开始传输8字节的数据
        {
                if(dat&0x01)
                {
                        SDA|=(1<<1);
                }
                else
                {
                        SDA &=~(1<<1);
                }
        //取最低位,注意DS1302的数据和地址都是从最低位开始传输的
                delayus(2);
                SCLK|=(1<<7);//时钟线拉高,制造上升沿,SDA的数据被传输
                delayus(2);
                SCLK &=~(1<<7);//时钟线拉低,为下一个上升沿做准备
                dat>>=1;//数据右移一位,准备传输下一位数据
        }
}

uchar DS1302Write(uchar cmd,uchar dat)
{
        RST &=~(1<<4);//初始CE线置为0
        SCLK &=~(1<<7);//初始时钟线置为0
        RST|=(1<<4);//初始化CE置为1,传输开始

        DS1302WriteByte(cmd);//传输命令字,要写入的时间/日历地址
        DS1302WriteByte(dat);//写入要修改的时间/日期

        SCLK|=(1<<7);//时钟线拉高,一个上升沿写入数据
        RST &=~(1<<4);//读取结束,CE置为0,结束数据的传输
}





int DS1302ReadByte()
{       
        DDRC=0x00;////////IO口设为输入
        PORTC=0x00;//IO脚要设为高阻状态
        RST|=(1<<4);
        uchar i,dat;
        delayus(2);
        for(i=0;i<8;i++)
        {
                dat>>=1;//要返回的数据右移一位
                if(PINA|0x02)//当数据线为高时,证明该位数据为1
                {
                        dat|=0x80;//要传输数据的当前值置为1,若不是,则为0
                }
                SCLK|=(1<<7);//拉高时钟线
                delayus(2);
                SCLK &=~(1<<7);//制造下降沿,时钟下降沿才能读取数据
                delayus(2);

        }
        return dat;//返回读取出的数据
}

uchar DS1302Read(uchar cmd)
{
        DDRC=0x00;
        uchar dat;
        RST &=~(1<<4);//初始化CE线置为0
        SCLK &=~(1<<7);//初始化时钟线置为0,而且只有sclk为0时才能置rst为1
        RST|=(1<<4);//初始化CE置为1,传输开始


        DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址


        dat=DS1302ReadByte();//读取要得到的时间/日期



        SCLK|=(1<<7);//时钟线拉高
        RST &=~(1<<4);//读取结束,CE置为0,结束数据的传输
        return dat;//返回得到的时间/日期
}



void initDS1302(void)
{
        DDRA=0xff;
        DS1302Write(0x8e,0x00);//写保护关
        DS1302Write(DS1302_SECOND_WRITE,0x00);//初始化秒值为0
        DS1302Write(DS1302_MINUTE_WRITE,0x20);//初始化分钟值为0
        DS1302Write(DS1302_HOUR_WRITE,0x09);//初始化为24小时模式 初始化时间为9点
        DS1302Write(DS1302_DAY_WRITE,0x23);//2010年1月1日 星期6   25
        DS1302Write(DS1302_MONTH_WRITE,0x04);//12月
        DS1302Write(DS1302_YEAR_WRITE,0x95);//10年
//        DS1302Write(DS1302_WEEK_WRITE,0x00);
//        DS1302Write(DS1302_SECOND_WRITE,0x06);
        DS1302Write(0x90,0x01);//充电
        DS1302Write(0xc0,0xf0);//初始化一次标示
        DS1302Write(0x8e,0x80);//写保护开
}


////液晶显示程序
void write_com(uchar com)
{       
        rsddr|=(1<<0);
        rsport &=~(1<<0);
        DDRA=0xff;//液晶端口
        PORTA=com;
        delayms(3);

        enddr|=(1<<2);
        enport|=(1<<2);
        delayms(3);
        enport &=~(1<<2);       
}
void init()
{
        rwddr|=(1<<1);
        rwport &=~(1<<1);       
        enddr|=(1<<2);
        enport &=~(1<<2);
        write_com(0x38);//显示模式
        write_com(0x0e);//开显示 显示光标
        write_com(0x06);//当读或写一个字符后地址指针加一
        write_com(0x01);//数据指针清零
        write_com(0x80);//数据指针初始化       
}

void write_data(uchar date)
{
        rsddr|=(1<<0);
        rsport|=(1<<0);
        DDRA=0xff;//液晶端口
        PORTA=date;//液晶端口
        delayms(3);

        enddr|=(1<<2);
        enport|=(1<<2);
        delayms(3);
        enport &=~(1<<2);       
}

///////液晶显示程序


void display()
{
        c=DS1302Read(DS1302_HOUR_READ);
        hour0=c&0x0f;
        hour1=(c>>4)&0x03;
        delayms(10);
        write_data(table[hour1]);
        delayms(5);
        write_data(table[hour0]);
//        write_data(' ');
        delayms(5);

        c=DS1302Read(DS1302_MINUTE_READ);//分
        minute0=c&0x0f;
        minute1=(c>>4)&0x07;
        delayms(10);
        write_data(table[minute1]);
        delayms(5);
        write_data(table[minute0]);
//        write_data(' ');
        delayms(5);

        c=DS1302Read(DS1302_SECOND_READ);//秒
        second0=c&0x0f;
        second1=(c>>4)&0x07;
        delayms(10);
        write_data(table[second1]);
        delayms(5);
        write_data(table[second0]);
//        write_data(' ');
        delayms(5);

        write_com(0x80+0x40);

        c=DS1302Read(DS1302_DAY_READ);//日
        date0=c&0x0f;
        date1=(c>>4)&0x03;//只可能是1-3
        delayms(10);
        write_data(table[date1]);
        delayms(5);
        write_data(table[date0]);
//        write_data(' ');
        delayms(5);

        c=DS1302Read(DS1302_MONTH_READ);//月
        month0=c&0x0f;//个位
        month1=(c>>4)&0x01;//十位只可能是1
        delayms(10);
        write_data(table[month1]);
        delayms(5);
        write_data(table[month0]);
//        write_data(' ');
        delayms(5);

        c=DS1302Read(DS1302_YEAR_READ);//年
        year0=c&0x0f;//!!!!读到的数的前四位是十位,后四位是个位
        year1=c>>4;
        delayms(10);
        write_data(table[year1]);
        delayms(50);
        write_data(table[year0]);
//        write_data(' ');
        delayms(5);

        write_com(0x01);//清屏!!!
        delayms(50);

}


int  main()
{
       
        DDRB=0xff;
        rsddr|=(1<<0);
        rwddr|=(1<<1);
        enddr|=(1<<2);
        DDRA=0xff;       
        init();//初始化液晶1602
        sei();//开总中断
        initDS1302();
        while(1)
        {
                display();
                delayms(500);
        }       

}

一周热门 更多>