问题描述:
读出来时钟的时间 在LCD1602上显示都是85 请教大侠帮吗解答疑问!真诚的谢谢!!!下面附有仿真的PROTEUS图片。
/*******************************
date:2011/11/2
time:20:45
write by:一棵小草
********************************/
/*------------------------------------------------------------------------
对1602的操作如下:
1、读状态,输入:RS=L,RW=H,E=H。 输出:D0~D7=状态字
2、写指令,输入:RS=L,RW=L,D0~D7=指令,E=高脉冲。输出:无
3、读数据,输入:RS=H,RW=H,E=H。输出:D0~D7=数据
4、写数据,输入:RS=H,RW=L,D0~D7=数据,E=高脉冲。输出:无
-------------------------------------------------------------------------*/
#include<avr/io.h>
#define uint unsigned int
#define uchar unsigned char
//液晶相关宏定义
#define RS PD0
#define RW PD1
#define EN PD2
#define LCD_Data PORTC
//DS1302相关宏定义
#define RST PA0
#define SCLK PA1
#define IO PA2
#define DS1302_Sec 0x80 //秒寄存器地址
#define DS1302_Min 0x82 //分寄存器地址
#define DS1302_Hour 0x84 //时寄存器地址
#define DS1302_Day 0x86 //日寄存器地址
#define DS1302_Month 0x88 //月寄存器地址
#define DS1302_Week 0x8a //周寄存器地址
#define DS1302_Year 0x8c //年寄存器地址
#define DS1302_Control 0x8e //控制寄存器
#define DS1302_Charger 0x90 //涓流充电
#define DS1302_Clkburst 0xbe //时钟多字节
void delay_ms(uint z);//1ms delay
void LCD_1602_init();
void write_com(uchar com); // 写指令
void write_data(uchar date); //写数据
void port_init(void);//端口初始化
void busy_check();
void write_ds1302(uchar addr,uchar data);
uchar read_ds1302(uchar addr);
//void ds1302_SetTime();
//void ds1302_GetTime();
//void trans();
void write_sfm(uchar add,uchar dat);
void init_1302();
uchar shi,fen,miao;
//uchar table1[]="time:21:01";
//uchar table2[]="date:2011-09-02";
//uchar table_time[8]={0,0,10,0,0,10,0,0}; //时间
//uchar time[7]={0,00,0,00,0,0,0};
//uchar table_num[]="0123456789:- ";
int main(void)
{
// uchar i,j;
port_init();
LCD_1602_init();
// ds1302_SetTime();
init_1302();
while(1)
{
miao=read_ds1302(0x81);
fen=read_ds1302(0x83);
shi=read_ds1302(0x85);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
}
}
void port_init(void)
{
// DDRA = 0XFF;
// DDRB = 0XFF;
DDRC = 0XFF;
DDRD = 0XFF;
// PORTA = 0X00;
// PORTB = 0X00;
PORTC = 0X00;
PORTD = 0X00;
}
void delay_ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=419;y>0;y--);
}
void LCD_1602_init()
{
write_com(0x38);//显示模式设置
write_com(0x08);//关闭显示
write_com(0x01);//清屏
write_com(0x0c);//开显示
write_com(0x06);//显示光标移动设置
}
void write_com(uchar com)
{
busy_check();
DDRC = 0Xff;
PORTD &= ~_BV(RS);
PORTD &= ~_BV(RW); //RW=0;
PORTD &= ~_BV(EN); //EN=0;
PORTC = com;
PORTD |= _BV(EN); //EN=1;
delay_ms(10);
PORTD &= ~_BV(EN); //EN=0;
PORTD |= _BV(RS); //RS=1;
PORTD |= _BV(RW); //RW=1
}
void write_data(uchar date)
{
busy_check();
DDRC = 0Xff;
PORTD |= _BV(RS); //RS=1;
PORTD &= ~_BV(RW); //RW=0;
PORTD &= ~_BV(EN); //EN=0;
PORTC = date;
PORTD |= _BV(EN); //EN=1;
delay_ms(10);
PORTD &= ~_BV(EN); //EN=0;
PORTD &= ~_BV(RS);
PORTD |= _BV(RW); //RW=1
}
void busy_check()
{
DDRD |= 0X07;
DDRC = 0X00;
PORTD &= ~_BV(EN); //EN=0;
PORTD |= _BV(RW); //RW=1;
PORTD &= ~_BV(RS);
PORTD |= _BV(EN); //EN=1;
while(LCD_Data&&0x80==1);
PORTD &= ~_BV(EN); //EN=0;
delay_ms(3);
}
/********写一个字节*********************/
void write_ds1302(uchar addr,uchar data)
{
uchar i;
DDRA |= _BV(IO);//I/O set output
PORTA &= ~_BV(SCLK);
PORTA |= _BV(RST);
addr&=0xfe;
for(i=0;i<8;i++) //写地址、命令字节,上升沿有效
{
PORTA &= ~_BV(SCLK);
if(addr&0x01) //判断地址字节的最低位
PORTA |= _BV(IO);
else
PORTA &= ~_BV(IO);
PORTA |= _BV(SCLK);
addr>>=1; //先发送低位
}
for(i=0;i<8;i++)//写数据
{
PORTA &= ~_BV(SCLK);
if(data&0x01) //判断数据字节的最低位
PORTA |= _BV(IO);
else
PORTA &= ~_BV(IO);
PORTA|=_BV(SCLK);
data>>=1;
}
PORTA &= ~_BV(RST);
}
/***************从DS1302中读一个字节******************/
uchar read_ds1302(uchar addr)
{
uchar i,data,temp,temp1,temp2;
DDRA |= _BV(IO); //设置IO为输出
PORTA &= ~_BV(SCLK);
PORTA |= _BV(RST);
addr|=0x01; //地址字节的LSB设置为逻辑1
for(i=0;i<8;i++) //写地址、命令字节,上升沿有效
{
PORTA &= ~_BV(SCLK);
if(addr&0x01) //字节地址的LSB是否为1
PORTA |= _BV(IO);
else
PORTA&=~_BV(IO);
PORTA |= _BV(SCLK);
addr>>=1;
}
DDRA &= ~_BV(IO); //改变IO为输入状态
PORTA &= ~_BV(IO);
for(i=0;i<8;i++) //读数据字节,下降沿有效
{
PORTA |= _BV(SCLK);
if(PINA&_BV(IO)) data|=0x80; //判断PINA的IO位是否为1,是则读1
PORTA &= ~_BV(SCLK);
data>>=1;
}
PORTA &= ~_BV(RST); //拉低RST信号,读一个字节结束
temp1 = data/16;
temp2 = data%16;
temp = temp1*10+temp2;
return (temp); //返回数据
}
/*void ds1302_SetTime()
{
uchar i,add;
add=0x80;
write_ds1302(0x8e,0x00); //允许写入
for(i=0;i<7;i++)
{
write_ds1302(add,time[i]);
add+=2;
}
write_ds1302(0x90,0xa6); //写充电控制寄存器.
write_ds1302(0x8e,0x80); //禁止写入
}*/
//-------------------------------
//---- 获取DS1302时间 --------
//---- 在主函数中调用 --------
//-------------------------------
/*void ds1302_GetTime()
{
uchar i,add=0x81;
write_ds1302(0x8e,0x00); //允许向DS1302写入数据
for(i=0;i<7;i++)
{
time[i]=read_ds1302(add); //获得的数据已转换为十进制
add+=2;
}
write_ds1302(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠
}*/
/*void trans()
{
table_time[0]=time[2]/10; //小时十位
table_time[1]=time[2]%10; //小时个位
table_time[3]=time[1]/10; //分十位
table_time[4]=time[1]%10; //分个位
table_time[6]=time[0]/10; //秒十位
table_time[7]=time[0]%10; //秒个位
}*/
void init_1302()
{
write_ds1302(0x8e,0x00);
write_ds1302(DS1302_Sec,0X31);
write_ds1302(DS1302_Min,0X14);
write_ds1302(DS1302_Hour,0X09);
write_ds1302(0x8e,0x80);
}
void write_sfm(uchar add,uchar dat) //往1602中写数据(即时间)
{
uchar shi,ge;
shi=dat/10;
ge=dat%10;
write_com(0x80+add);
write_data(0x30+shi);
write_data(0x30+ge);
} |