ds1302 在液晶1602上显示的问题

kangyonghui 2010-05-25 06:48:51
#include<msp430x24x.h>
#include"1602.h"
uchar year,yue,ri,shi,fen,miao,aa,t,t1,t2,t3,t4;
/*******************宏定义*******************/
#define REST_OUT P2DIR|=BIT4
#define REST_IN P2DIR&=~BIT4
#define REST_H P2OUT|=BIT4
#define REST_L P2OUT&=~BIT4

#define SCLK_OUT P2DIR|=BIT5
#define SCLK_IN P2DIR&=~BIT5
#define SCLK_H P2OUT|=BIT5
#define SCLK_L P2OUT&=~BIT5

#define IO_OUT P2DIR|=BIT6
#define IO_IN P2DIR&=~BIT6
#define IO_H P2OUT|=BIT6
#define IO_L P2OUT&=~BIT6

#define IO_date (P2IN&BIT6)


/**********以下代码为切换成XT2高频振荡器****************/


void reset_ds1302(void)
{

REST_OUT; //设为输出状态
SCLK_OUT; //输出状态
SCLK_L; // SCLK=0;
REST_L;
delay_lcd();
SCLK_H; //sclk=1
}


void write_ds(uchar add) //写字节
{
uchar i,temp;
IO_OUT; //对外写,输出状态
REST_H;
temp=add;
for(i=0;i<8;i++)
{

SCLK_L;
if(temp&0x01) IO_H; //写的时候低字节在前 与IIC不同
else IO_L;

delay_lcd();
SCLK_H;
temp=temp>>1;

}


}
uchar read_ds() //读字节
{ IO_IN;
REST_H;
uchar a,temp=0x00;
for(a=0;a<8;a++)
{

SCLK_H;
delay_lcd();
SCLK_L;
delay_lcd();
temp=temp>>1;
if(IO_date) temp|=0x80;
}

return temp;

}
void wr_ds1302(uchar add,uchar date)
{
SCLK_L;
REST_L;

REST_H;
write_ds(add);
write_ds(date);
REST_L;
SCLK_H;
}
uchar rd_ds1302(uchar add)
{
uchar m;
REST_L;
SCLK_L;
delay_lcd();
REST_H;
write_ds(add);
delay_lcd();
m=read_ds();
delay_lcd();
SCLK_H;
REST_L;
return m;

}
void Init_DS1302(void)
{
wr_ds1302(0x8e,0x00); //根据写状态寄存器命令字,写入不保护指令
wr_ds1302(0x80,0x46); //根据写秒寄存器命令字,写入秒的初始值
wr_ds1302(0x82,0x46); //根据写分寄存器命令字,写入分的初始值
wr_ds1302(0x84,0x46); //根据写小时寄存器命令字,写入小时的初始值
//wr_ds1302(0x86,0x22); //根据写日寄存器命令字,写入日的初始值
//wr_ds1302(0x88,0x04); //根据月寄存器命令字,写周的初始值
wr_ds1302(0x8c,0x10); //根据写年时寄存器命令字,写入年的初始值

}

void write_sfm(uchar add , uchar date)
{
uchar ge ,shi;
shi=date/10;
ge=date%10;
LcdWriteCommand(0x80+0X40+add); //显示地址。
LcdWriteData(shi+0x30); //+0X30是为了转换成ASCCII, 相差0X40.

LcdWriteCommand(0x80+0X40+add+1); //显示地址。
LcdWriteData(ge+0x30);

}
void write_nyr(uchar add,uchar date)
{
uchar ge ,shi;
ge=date%10;
shi=date/10;
LcdWriteCommand(0x80+add);
LcdWriteData(shi+0x30);

LcdWriteData(ge+0x30);

}

void main(void)
{
WDTCTL = WDTPW+WDTHOLD;
P2DIR=0X70;
Lcdinit();
Init_DS1302();
reset_ds1302();

while(1)
{

wr_ds1302(0x8f,0x01);
aa=rd_ds1302(0x81); //秒寄存器 读操作
miao=((aa)>>4)*10+(aa&0x0f);

t=rd_ds1302(0x83); //分寄存器 读操作
fen=(t>>4)*10+(t&0x0f);


t1=rd_ds1302(0x85); //时寄存器 读操作
shi=(t1>>4)*10+(t1&0x0f);


t2=rd_ds1302(0x8d); //年寄存器 读操作

year=(t2>>4)*10+(t2&0x0f);

write_sfm(13,miao);
write_sfm(6,fen);
write_sfm(3,shi);
write_nyr(2,year);

LcdWriteCommand(0x80);









}

}

#include<1602.h>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar ta××e[]=" 20 -03-23";
uchar ta××e1[]=" ";
uchar num, num1;
/***************宏定义**************************/
#define DataDir P4DIR
#define DataPORT P4OUT //输出。
#define Busy 0x80
#define CtrLDDir P3DIR
#define CLR_RS P3OUT&=~BIT0; //RS=P3.0 0
#define SET_RS P3OUT|=BIT0; // 1
#define CLR_RW P3OUT&=~BIT1; //RW=P3.1 0
#define SET_RW P3OUT|=BIT1; // 1
#define CLR_EN P3OUT&=~BIT2; //EN=P3.2 0
#define SET_EN P3OUT|=BIT2; // 1
/***********************************************/
uchar m,n,i=0;
void delay_lcd(void)
{

for(i=0;i<200;i++);
}
/***************检测忙信号*********************/
void WaitForEna××e(void)
{
DataDir &=0X00; //将P4口切换到输入状态
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();

while((P4IN & Busy) != 0); //检测忙标志
CLR_EN;
P4DIR|=0XFF; //将P4口切换到输出状态
}

/***************写指令*********************/
void LcdWriteCommand(uchar cmd)
{

CLR_RS;
CLR_RW;
_NOP();
DataPORT=cmd; //将命令写入数据端口。
_NOP();
SET_EN //产生使能脉冲信号。
_NOP();
_NOP();
CLR_EN;

}

/***************写数据*********************/
void LcdWriteData(uchar Data)
{

SET_RS ;
CLR_RW;

DataPORT=Data; //数据写入数据端口。
_NOP();
SET_EN //产生使能脉冲信号。
_NOP();
_NOP();
CLR_EN;
}
/***************LCD初始化*********************/
void Lcdinit(void)
{
CtrLDDir|=0x07; // 控制I0口为输出模式
DataDir|=0xff; //数据端口为输出
CLR_EN ;
CLR_RS ;
CLR_RW ;
LcdWriteCommand(0x38); //显示模式设置
LcdWriteCommand(0x06); //读写字符时,地址指针加1 ,整体不移动。
LcdWriteCommand(0x0c); //显示开,不开光标,不闪烁
LcdWriteCommand(0x08); //关闭显示
LcdWriteCommand(0x01); //清显示,光标复位到地址00H

LcdWriteCommand(0x80);
for(num=0;num<15;num++)
{
LcdWriteData(ta××e[num]) ;
delay_lcd();
delay_lcd();

}
LcdWriteCommand(0xc0);
for(num=0;num<15;num++)
{
LcdWriteData(ta××e1[num]) ;
delay_lcd();
delay_lcd();
}


}
我的这个显示的时候只显示 个位。 比如初始化时间为 23秒 秒只会显示3.
依次类推。
检查了很久,感觉没错呀。
我的初始化是 06 :46:54 但是显示只是: 6 :6 :4
走时 是对的。
...全文
475 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
liuhan33025 2011-05-14
  • 打赏
  • 举报
回复
嗯,支持楼上的!!
空影 2010-05-26
  • 打赏
  • 举报
回复
用LCD_set_position先设好位置,就可以写数据了
空影 2010-05-26
  • 打赏
  • 举报
回复
试试这个,在protues上可以用的
#define LCD_GO_HOME 0x02 //AC=0,光标、画面回HOME位

//输入方式设置
#define LCD_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一
#define LCD_AC_AUTO_DECREASE 0x04 //数据读、写操作后,AC自动减一
#define LCD_MOVE_ENABLE 0x05 //数据读、写操作,画面平移
#define LCD_MOVE_DISENABLE 0x04 //数据读、写操作,画面不动

//设置显示、光标及闪烁开、关
#define LCD_DISPLAY_ON 0x0C //显示开
#define LCD_DISPLAY_OFF 0x08 //显示关
#define LCD_CURSOR_ON 0x0A //光标显示
#define LCD_CURSOR_OFF 0x08 //光标不显示
#define LCD_CURSOR_BLINK_ON 0x09 //光标闪烁
#define LCD_CURSOR_BLINK_OFF 0x08 //光标不闪烁

//光标、画面移动,不影响DDRAM
#define LCD_LEFT_MOVE 0x18 //LCD显示左移一位
#define LCD_RIGHT_MOVE 0x1C //LCD显示右移一位
#define LCD_CURSOR_LEFT_MOVE 0x10 //光标左移一位
#define LCD_CURSOR_RIGHT_MOVE 0x14 //光标右移一位

//工作方式设置
#define LCD_DISPLAY_DOUBLE_LINE 0x38 //两行显示
#define LCD_DISPLAY_SINGLE_LINE 0x30 //单行显示
void LCD_cls(void);
void LCD_write_data(unsigned char);
void LCD_initial(void);
void LCD_set_position(unsigned char);
void LCD_prints(unsigned char *);
void LCD_printc(unsigned char);
void LCD_check_busy(void) //检测LCD状态,看它是不是还在忙呢
{
while(1)
{
LCD_EN=0;
LCD_RS=0;
LCD_RW=1;
LCD_DATA=0xff;
LCD_EN=1;
if(!LCD_BUSY)break;
}
LCD_EN=0;
}

void LCD_cls(void) //LCD清屏
{

LCD_check_busy();
LCD_RS=0;
LCD_RW=0;
LCD_DATA=1;
LCD_EN=1;
LCD_EN=0;

}

void LCD_write_instruction(unsigned char LCD_instruction) //写指令到LCD
{
LCD_check_busy();
LCD_RS=0;
LCD_RW=0;

LCD_DATA=LCD_instruction;
LCD_EN=1;
LCD_EN=0;
}

void LCD_write_data(unsigned char LCD_data) //输出一个字节数据到LCD
{
LCD_check_busy();
LCD_RS=1;
LCD_RW=0;

LCD_DATA=LCD_data;
LCD_EN=1;
LCD_EN=0;
}

void LCD_set_position(unsigned char x) //LCD光标定位到x处
{
LCD_write_instruction(0x80+x);
}

/*
void LCD_go_home(void) //LCD光标归位
{
LCD_write_instruction(LCD_GO_HOME);
}
*/

void LCD_printc(unsigned char lcd_data) //输出一个字符到LCD
{
LCD_write_data(lcd_data);
}

void LCD_prints(unsigned char *lcd_string) //输出一个字符串到LCD
{
unsigned char i=0;
while(lcd_string[i]!=0x00)
{
LCD_write_data(lcd_string[i]);
i++;
}
}

void LCD_initial(void) //初始化LCD
{
LCD_write_instruction(LCD_AC_AUTO_INCREMENT|LCD_MOVE_DISENABLE);
LCD_write_instruction(LCD_DISPLAY_ON|LCD_CURSOR_OFF);
LCD_write_instruction(LCD_DISPLAY_DOUBLE_LINE);
LCD_cls();
}
Peasant_Lee 2010-05-26
  • 打赏
  • 举报
回复
仿真下,假如是全速都可以的话,那么下载到mcu跑,也应该可以的。而且假如是仿真的问题,不会这样现象,会完全不显示,或者显示乱,你现在显示缺了高bit。我还是怀疑你开启了1602的4bit总线方式。将高位切掉了。
假如你不管时钟模块,就输出一个固定的数到1602,它能显示正确吗?这样可以排除是否是时钟模块引起的问题。
kangyonghui 2010-05-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 peasant_lee 的回复:]
楼主,问题可以完全锁定在1602上面了,我看了下,知道问题出现在哪了。你将Lcdinit(void)下的LcdWriteCommand(0x80)去掉即可,因为你使用了P4 所有8bit作为数据口,而0x80的命令代表的是,4bit总线方式,你应该选择8bit总线方式。而你的0x38命令就是8bit总线两行显示方式。但是你后来用个80给覆盖了。所有造成你现在高bit数据不见了,因为你4bit总线,……
[/Quote]


试了不行 会不是 仿真的原因呢?
kangyonghui 2010-05-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wslxs2008 的回复:]
楼主没用到忙检测函数void WaitForEna××e(void)啊;建议在写数据和写命令子程序中先调用此程序,至于你的LcdWriteCommand(0x80)是什么意思,按照datasheet来看,应该是禁止写的意思
[/Quote]
LcdWriteCommand(0x80):是从液晶的第一行开始写的。我在想不是仿真的问题呢?我用的PROTEUS仿真的。
空影 2010-05-25
  • 打赏
  • 举报
回复
楼主没用到忙检测函数void WaitForEna××e(void)啊;建议在写数据和写命令子程序中先调用此程序,至于你的LcdWriteCommand(0x80)是什么意思,按照datasheet来看,应该是禁止写的意思
Peasant_Lee 2010-05-25
  • 打赏
  • 举报
回复
楼主,问题可以完全锁定在1602上面了,我看了下,知道问题出现在哪了。你将Lcdinit(void)下的LcdWriteCommand(0x80)去掉即可,因为你使用了P4 所有8bit作为数据口,而0x80的命令代表的是,4bit总线方式,你应该选择8bit总线方式。而你的0x38命令就是8bit总线两行显示方式。但是你后来用个80给覆盖了。所有造成你现在高bit数据不见了,因为你4bit总线,呵呵,改过来,估计可以了。

27,382

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧