本帖最后由 岚翎 于 2016-5-28 12:50 编辑
小弟在做
单片机课程设计--智能
电子钟LCD显示,跟着书本例子打出来的代码,但是lcd液晶屏显示错误 ,求大神帮我看看是怎么回事,小弟感激不尽!!!!
程序代码如下:
#include<reg51.h>
#include<absacc.h> //定义绝对地址访问
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit T_CLK = P1^3; //DS1302时钟线引脚
sbit T_IO = P1^4; //DS1302数据线引脚
sbit T_RST = P1^2; //DS1302复位线引脚
sbit RS = P2^7; //定义LCD的控制线
sbit RW = P2^6;
sbit EN = P2^5;
sbit ACC7 = ACC^7;
sbit ACC0 = ACC^0;
uchar datechar[] = {"DATE:"};
uchar
timechar[] = {"TIME:"};
uchar datebuffer[10] = {0x32,0x30,0,0,0x2d,0,0,0x2d,0,0}; //定义日历显示缓冲区
uchar timebuffer[8] = {0,0,0x3a,0,0,0x3a,0,0}; //定义时间显示缓冲区
uchar weekbuffer = {0x30}; //定义星期显示缓冲区
/***********************************************************************************
*名称:WriteB
*功能:往DS1302写入1Byte数据
*输入:ucDa写入的数据
*返回值:无
************************************************************************************/
void WriteB(uchar ucDa)
{
uchar i;
ACC = ucDa;
for(i=8; i>0; i--)
{
T_IO = ACC0; //相当于汇编中的RRC
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/***********************************************************************************
*名称:ReadB
*功能:从DS1302读取1Byte数据
*输入:ucDa写入的数据
*返回值:ACC
************************************************************************************/
uchar ReadB(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >> 1;
ACC7 = T_IO; T_CLK = 1; T_CLK = 0; //相当于汇编中的RRC
}
return(ACC);
}
/***********************************************************************************
*名称:v_W1302
*功能:单字写,向DS1302某地址写入命令/数据,先写地址,后写命令/数据
*调用:WriteB()
*输入:ucAddr:DS1302地址,ucDa:要写的数据
*返回值:无
************************************************************************************/
void v_W1302(uchar ucAddr ,uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
_nop_();_nop_();
T_RST = 1;
_nop_();_nop_();
WriteB(ucAddr); //地址,命令
WriteB(ucDa); //写一字节数据
T_CLK = 1;
T_RST = 0;
}
/***********************************************************************************
*名称:uc_R1302
*功能:单字节读,向DS1302读取某地址数据,先写地址,后写命令/数据
*调用:WriteB(),ReadB()
*输入:ucAddr:DS1302地址
*返回值:ucDa读取的数据
************************************************************************************/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa = 0;
T_RST = 0;T_CLK = 0;
T_RST = 1;
WriteB(ucAddr); //写地址
ucDa = ReadB(); //读一字节命令/数据
T_CLK = 1; T_RST = 0;
return(ucDa);
}
/***************检查忙函数*******************/
void fbusy()
{ P0 = 1;
P0 = 0Xff; RS = 0; RW = 1;
EN = 1; EN = 0;
while ((P0&0x80)) { EN = 0; EN = 1;} //忙,等待
}
/*******************写命令函数*******************/
void wc51r(uchar j)
{
fbusy(); //读状态
EN = 0; RS = 0; RW = 0;
EN = 1;
P0 = 1;
P0 = j;
EN = 0;
}
/**************写数据函数***************/
void wc51ddr(uchar j)
{
fbusy(); //读状态
EN = 0; RS = 1; RW = 0;
EN = 1;
P0 = 1;
P0 = j;
EN = 0;
}
/*******************LCD1602初始化函数*******************/
void init()
{
wc51r(0x01); //清屏
wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型
wc51r(0x0c); //显示器开,光标关,字符不闪烁
wc51r(0x06); //字符不动,光标自动右移一格
}
/*******************延时函数*******************/
void delay(uint i)
{
uint y,j;
for (j=0;j<i;j++)
{
for(y=0;y<0xff;y++) {;}
}
}
void main(void)
{
uchar i;
uchar data temp;
delay(10);
init();
wc51r(0x80);
for(i=0;i<5;i++) wc51ddr(datechar
); //第一行显示DATA:
wc51r(0xc0);
for(i=0;i<5;i++) wc51ddr(timechar); //第二行显示TIME:
v_W1302(0x8e,0); //打开写保护
v_W1302(0x8c,0x13); //向DS1302写入日期13-12-21,时间16:25:30 星期六
v_W1302(0x8A,0x06);
v_W1302(0x88,0x12);
v_W1302(0x86,0x21);
v_W1302(0x84,0x16);
v_W1302(0x82,0x25);
v_W1302(0x80,0x30);
v_W1302(0x8e,0x80); //关闭写保护
while(1)
{
temp = uc_R1302(0x8d); //读年,分成十位和各位,转换成字符,放入日历显示缓冲区
datebuffer[2] = 0x30+temp/16; datebuffer[3] = 0x30+temp%16;
temp = uc_R1302(0x8B); //读星期,转换成字符,放入星期显示缓冲区
weekbuffer = 0x30 + temp;
temp = uc_R1302(0x89); //读月,分成十位和各位,转换成字符,放入日历显示缓冲区
datebuffer[5] = 0x30+temp/16; datebuffer[6] = 0x30+temp%16;
temp = uc_R1302(0x87); //读日,分成十位和各位,转换成字符,放入日历显示缓冲区
timebuffer[8] = 0x30+temp/16; datebuffer[9] = 0x30+temp%16;
temp = uc_R1302(0x85); //读小时,分成十位和各位,转换成字符,放入时间显示缓冲区
temp = temp&0x7f;
timebuffer[0] = 0x30+temp/16; datebuffer[1] = 0x30+temp%16;
temp = uc_R1302(0x83); //读分,分成十位和各位,转换成字符,放入时间显示缓冲区
timebuffer[3] = 0x30+temp/16; datebuffer[4] = 0x30+temp%16;
temp = uc_R1302(0x81); //读秒,分成十位和各位,转换成字符,放入时间显示缓冲区
temp = temp&0x7f;
timebuffer[6] = 0x30+temp/16; datebuffer[7] = 0x30+temp%16;
wc51r(0x86); //第一行后面显示日历
for(i=0;i<10;i++) wc51ddr(datebuffer);
wc51r(0xc6); //第二行后面显示时间
for(i=0;i<8;i++) wc51ddr(datebuffer);
wc51ddr(0x20);
wc51ddr(weekbuffer); //后面显示星期
}
}
#include<reg51.h>
#include<absacc.h> //定义绝对地址访问
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit T_CLK = P1^0; //DS1302时钟线引脚
sbit T_IO = P1^1; //DS1302数据线引脚
sbit T_RST = P1^2; //DS1302复位线引脚
sbit RS = P2^7; //定义LCD的控制线
sbit RW = P2^6;
sbit EN = P2^5;
sbit ACC7 = ACC^7;
sbit ACC0 = ACC^0;
uchar datechar[] = {"DATE:"};
uchar timechar[] = {"TIME:"};
uchar datebuffer[10] = {0x32,0x30,0,0,0x2d,0,0,0x2d,0,0}; //定义日历显示缓冲区
uchar timebuffer[8] = {0,0,0x3a,0,0,0x3a,0,0}; //定义时间显示缓冲区
uchar weekbuffer = {0x30}; //定义星期显示缓冲区
/***********************************************************************************
*名称:WriteB
*功能:往DS1302写入1Byte数据
*输入:ucDa写入的数据
*返回值:无
************************************************************************************/
void WriteB(uchar ucDa)
{
uchar i;
ACC = ucDa;
for(i=8; i>0; i--)
{
T_IO = ACC0; //相当于汇编中的RRC
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/***********************************************************************************
*名称:ReadB
*功能:从DS1302读取1Byte数据
*输入:ucDa写入的数据
*返回值:ACC
************************************************************************************/
uchar ReadB(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >> 1;
ACC7 = T_IO; T_CLK = 1; T_CLK = 0; //相当于汇编中的RRC
}
return(ACC);
}
/***********************************************************************************
*名称:v_W1302
*功能:单字写,向DS1302某地址写入命令/数据,先写地址,后写命令/数据
*调用:WriteB()
*输入:ucAddr:DS1302地址,ucDa:要写的数据
*返回值:无
************************************************************************************/
void v_W1302(uchar ucAddr ,uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
_nop_();_nop_();
T_RST = 1;
_nop_();_nop_();
WriteB(ucAddr); //地址,命令
WriteB(ucDa); //写一字节数据
T_CLK = 1;
T_RST = 0;
}
/***********************************************************************************
*名称:uc_R1302
*功能:单字节读,向DS1302读取某地址数据,先写地址,后写命令/数据
*调用:WriteB(),ReadB()
*输入:ucAddr:DS1302地址
*返回值:ucDa读取的数据
************************************************************************************/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa = 0;
T_RST = 0;T_CLK = 0;
T_RST = 1;
WriteB(ucAddr); //写地址
ucDa = ReadB(); //读一字节命令/数据
T_CLK = 1; T_RST = 0;
return(ucDa);
}
/***************检查忙函数*******************/
void fbusy()
{ P0 = 1;
P0 = 0Xff; RS = 0; RW = 1;
EN = 1; EN = 0;
while ((P0&0x80)) { EN = 0; EN = 1;} //忙,等待
}
/*******************写命令函数*******************/
void wc51r(uchar j)
{
fbusy(); //读状态
EN = 0; RS = 0; RW = 0;
EN = 1;
P0 = 1;
P0 = j;
EN = 0;
}
/**************写数据函数***************/
void wc51ddr(uchar j)
{
fbusy(); //读状态
EN = 0; RS = 1; RW = 0;
EN = 1;
P0 = 1;
P0 = j;
EN = 0;
}
/*******************LCD1602初始化函数*******************/
void init()
{
wc51r(0x01); //清屏
wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型
wc51r(0x0c); //显示器开,光标关,字符不闪烁
wc51r(0x06); //字符不动,光标自动右移一格
}
/*******************延时函数*******************/
void delay(uint i)
{
uint y,j;
for (j=0;j<i;j++)
{
for(y=0;y<0xff;y++) {;}
}
}
void main(void)
{
uchar i;
uchar data temp;
delay(10);
init();
wc51r(0x80);
for(i=0;i<5;i++) wc51ddr(datechar); //第一行显示DATA:
wc51r(0xc0);
for(i=0;i<5;i++) wc51ddr(timechar); //第二行显示TIME:
v_W1302(0x8e,0); //打开写保护
v_W1302(0x8c,0x13); //向DS1302写入日期13-12-21,时间16:25:30 星期六
v_W1302(0x8A,0x06);
v_W1302(0x88,0x12);
v_W1302(0x86,0x21);
v_W1302(0x84,0x16);
v_W1302(0x82,0x25);
v_W1302(0x80,0x30);
v_W1302(0x8e,0x80); //关闭写保护
while(1)
{
temp = uc_R1302(0x8d); //读年,分成十位和各位,转换成字符,放入日历显示缓冲区
datebuffer[2] = 0x30+temp/16; datebuffer[3] = 0x30+temp%16;
temp = uc_R1302(0x8B); //读星期,转换成字符,放入星期显示缓冲区
weekbuffer = 0x30 + temp;
temp = uc_R1302(0x89); //读月,分成十位和各位,转换成字符,放入日历显示缓冲区
datebuffer[5] = 0x30+temp/16; datebuffer[6] = 0x30+temp%16;
temp = uc_R1302(0x87); //读日,分成十位和各位,转换成字符,放入日历显示缓冲区
timebuffer[8] = 0x30+temp/16; datebuffer[9] = 0x30+temp%16;
temp = uc_R1302(0x85); //读小时,分成十位和各位,转换成字符,放入时间显示缓冲区
temp = temp&0x7f;
timebuffer[0] = 0x30+temp/16; datebuffer[1] = 0x30+temp%16;
temp = uc_R1302(0x83); //读分,分成十位和各位,转换成字符,放入时间显示缓冲区
timebuffer[3] = 0x30+temp/16; datebuffer[4] = 0x30+temp%16;
temp = uc_R1302(0x81); //读秒,分成十位和各位,转换成字符,放入时间显示缓冲区
temp = temp&0x7f;
timebuffer[6] = 0x30+temp/16; datebuffer[7] = 0x30+temp%16;
wc51r(0x86); //第一行后面显示日历
for(i=0;i<10;i++) wc51ddr(datebuffer);
wc51r(0xc6); //第二行后面显示时间
for(i=0;i<8;i++) wc51ddr(datebuffer);
wc51ddr(0x20);
wc51ddr(weekbuffer); //后面显示星期
}
}
-
恩恩,非常感谢。但是我还是不怎么懂ds1302和lcd1602的具体原理,因为之前老师没教过,现在都是自学的,所以有点模糊,希望多多指教
一周热门 更多>