[求助]
AVR上的DS1302程序读出来在液晶上显示错误
为什么我的AVR上的DS1302程序读出来在液晶上显示全部都是55555
读不出来肯定是1302没操作对。参考别人正确的例子吧。
void display()
{
c=DS1302Read(DS1302_HOUR_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
while(1);
c=DS1302Read(DS1302_MINUTE_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
c=DS1302Read(DS1302_SECOND_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
write_com(0x80+0x40);
c=DS1302Read(DS1302_DAY_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
c=DS1302Read(DS1302_MONTH_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
c=DS1302Read(DS1302_YEAR_READ);
write_data(table[c/10]);
delayus(5);
write_data(table[c%10]);
write_data(' ');
delayus(5);
write_com(0x01);
delayus(5);
}
这是我的显示程序。是不是延时太短了。。急救啊 我是一名单片机菜鸟,这个已经做了好多天了
第一段程序有个while(1);程序岂不是一直在这里死循环?
哦,谢谢,但是我改了还是不行,刚刚一直在想,发现是BCD码转换没有注意到。。。
uchar BcdToBin(uchar val)
{
val = (val >> 4) *10+(val &0x0f); ///将BCD码转换为10进制数
return val; ///返回10进制数
}
但是改了以后还是不行,这次不显示全是5了,液晶上显示3 1 7 。。。数字还是不对,完全不对。而且数字中间有空格,而我的程序里没有加空格。。。
#include
#include
#include
#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);
}
}
#include
#include
#include
#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);
}
}