求助!~本人是阿蔡~据以下程序做了一个电子钟,但最后有点小问题,1602显示不正确~秒走起来时每隔一个就显示一个问号~其余年月日,时间等也是如此~请问有谁遇到类似问题?怎样解决啊~?原理图及PCB见附件
#include "regx51.h"
#include "string.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
typedef unsigned char byte;
typedef unsigned int word;
//*********** 1602引脚定义引脚
#define LCM_RS P2_0 // 数据/命令选择信号
#define LCM_RW P2_1 // 读/写选择信号
#define LCM_E P2_2 // 使能信号
//*********** DS1302 时间显示定义部分
sbit T_CLK=P1^0; //串行时钟输入
sbit T_IO =P1^1; //串行数据端口
sbit T_RST=P1^2; //复位端口
//*********** 18B20温度显示定义部分
sbit DQ=P3^3; //18B20 接P33口
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
#define LCM_Data P0 //显示数据端口
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
uchar id,timecount; //全局变量
bit flag,sflag; //flag是时钟冒号闪烁标志,sflag是温度负号显示标志
bit sec,min,hour,year,mon,day,weekk; //闪烁标志位
//*********************函数申明
void Disp_line1(void); // 显示屏幕第一行
void Disp_line2(void); // 显示屏幕第二行
void id_case1_key(); // id为1时的下一级选择
void Set(uchar,uchar); // 根据选择调整相应项目
void RTInputByte(uchar); /* 输入 1Byte */
uchar RTOutputByte(void); /* 输出 1Byte */
void W1302(uchar, uchar); // 向DS1302写入一个字节
uchar R1302(uchar); // 从DS1302读出一个字节
void Set1302(uchar * ); // 设置时间
//******* 1602LCD驱动 **********************************************************
void WriteDataLCM(uchar WDLCM); //写数据
void WriteCommandLCM(uchar WCLCM,BuysC); //写指令
uchar ReadStatusLCM(void); //读状态
void LCMInit(void); //LCM初始化
void DisplayOneChar(uchar X, uchar Y, uchar DData); //按指定位置显示一个字符
void DisplayListChar(uchar X, uchar Y, uchar code *DData); //按指定位置显示一串字符
void Delay5Ms(void); //5ms延时
void Delay400Ms(void); //400ms延时
Read_Temperature(char,char);//温度显示
void mychar(void); //显示自定义字符
void adjust_res(char res); //res 分别等于 0x1f, 0x3f, 0x5f 温度读数分辨率分别对应
// 0.5, 0.25, 0.125
//初始化后设置为:07年07月04日 星期3 12点00分00秒
// 12:00:00 XX. C
// 07/07/04 Week.3
unsigned char inittime[7]={0x00,0x00,0x12,0x04,0x07,0x03,0x07};
// 秒 分钟 小时 日 月 星期 年
uchar code week[]={"Week."};//星期显示
//主函数
void main(void)
{
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)
mychar(); //显示自定义字符
TMOD=0x01; //选择定时模式
TH0=(65535-50000)/256;//取定时初值
TL0=(65535-50000)%256;
EA=1; //开中断
TR0=1;
ET0=1;
W1302(0x90,0xa5); //打开充电二级管 一个二级管串联一个2K电阻
W1302(0x8e,0x80); //写保护,禁止写操作
adjust_res(0x5f); //调整18B20的分辨率 0x1f:0.5; 0x3f:0.25; 0x5f:0.125
while(1)
{
if ((P1_4|P1_5)==0) // 初始化 同时按下P1_4、P1_5
{
Delay5Ms(); // 适当延时,消除抖动
if ((P1_4|P1_5)==0) Set1302(inittime); // 显示初始值
}
if (P1_6==0) // 设置和选择项目键
{
Delay5Ms(); // 适当延时,消除抖动
if(P1_6==0){id++;if(id>7) id=0;} // 7个可调节项目循环调节
while(P1_6==0);
}
switch(id) // 跳转到对应的项目进行设置
{
case 0:
sec=0;
Disp_line1(); Disp_line2();
break;
case 1: //调节年
year=1;//设置年闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 2: //调节月
year=0;mon=1;//设置月闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 3: //调节日
mon=0;day=1;//设置日闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 4: //调节星期
day=0;weekk=1;//设置星期闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 5: //调节小时
weekk=0;hour=1;//设置小时闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 6: //调节分钟
hour=0;min=1;//设置分钟闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
case 7: //调节秒
min=0;sec=1;//设置秒钟闪烁标志位
Disp_line1(); Disp_line2();
id_case1_key();
break;
}
}
}
//================================== 定时中断
/*****************************************************
// 函 数 名:void t0()
// 功 能:时间工作时,冒号闪烁
//T0中断入口,方式1
void t0(void) interrupt 1 using 0
{
TH0=(65535-50000)/256; //取50ms定时初值
TL0=(65535-50000)%256;
timecount++;
if(timecount>9)
{
timecount=0; //计时到,从先开始
flag=~flag; //标志位取反
}
}
//==================================== 项目设置
/*****************************************************
函 数 名:void id_case1_key()
功 能:项目设置加减控制
说 明:P1.5和P1.4 <==> +和-
*****************************************************/
//id为1时的下一级选择
void id_case1_key()
{
if (P1_5==0) //P1_5有按下,则数值增加(+)
{
Delay5Ms(); //适当延时,消除抖动
if(P1_5==0) Set(id,0); //根据选择调整相应项目
if(id!=7) while(P1_5==0);
}
if (P1_4==0) //P1_4有按下,则数值减少(-)
{
Delay5Ms(); //适当延时,消除抖动
if(P1_4==0) Set(id,1); //根据选择调整相应项目
if(id!=7) while(P1_4==0);
}
}
/*****************************************************
函 数 名:void Set()
功 能:项目设置
说 明:sel_1=0时,数值加;sel_1=1时,数值减
入口参数:sel和sel_1
*****************************************************/
//根据选择调整相应项目并写入DS1302
void Set(uchar sel,uchar sel_1)
{
signed char address,item;
signed char max,mini;
//偶数指令是写,奇数指令是读
//最大值与最小值限定
if(sel==7) {address=0x80; max=00;mini=0;} //秒
if(sel==6) {address=0x82; max=59;mini=0;} //分钟
if(sel==5) {address=0x84; max=23;mini=0;} //小时
if(sel==3) {address=0x86; max=31;mini=1;} //日
if(sel==2) {address=0x88; max=12;mini=1;} //月
if(sel==1) {address=0x8c; max=99;mini=0;} //年
if(sel==4) {address=0x8a; max=07;mini=1;} //星期
//先从1302中读出数据,把数据转换成十进制进行加减设置;后从先转换回来写入1302中
item=R1302(address+1)/16*10+R1302(address+1)%16;//从1302中读出1字节,再转换成十进制
if (sel_1==0) item++; else item--; //sel_1=0则加,sel_1=1则减
if(item>max) item=mini; //大于最大值,则赋最小值(循环)
if(item<mini) item=max; //小于最小值,则赋最大值(循环)
W1302(0x8e,0x00); //允许写操作
W1302(address,item/10*16+item%10);//把调节好的十进制数据转换成十六进制后写入1302中
W1302(0x8e,0x80); //写保护,禁止写操作
}
//=======================================================================================
/*****************************************************
函 数 名:void Disp_line1()
功 能:显示时间和温度 (XX:XX:XX XX.X C)
说 明:第一行显示数据处理
入口参数:无
返 回 值:无
*****************************************************/
//屏幕显示第一行: 时间和温度显示
void Disp_line1(void)
{
Read_Temperature(10,0); //温度显示
//冒号闪烁
if(flag==0)
{DisplayOneChar(3,0,0x3a); DisplayOneChar(6,0,0x3a);}
else
{DisplayOneChar(3,0,0x20); DisplayOneChar(6,0,0x20);}
if(sec==1) //秒闪烁标志位
{
if(flag==1)
{
DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位
DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位
}
else
{
DisplayOneChar(7,0,0x20); //显示秒十位
DisplayOneChar(8,0,0x20); //显示秒个位
}
}
else
{
DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位
DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位
}
if(min==1) //分钟闪烁标志位
{
if(flag==1)
{
DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位
DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位
}
else
{
DisplayOneChar(4,0,0x20); //显示分钟十位
DisplayOneChar(5,0,0x20); //显示分钟个位
}
}
else
{
DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位
DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位
}
if(hour==1) //小时闪烁标志位
{
if(flag==1)
{
DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位
DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位
}
else
{
DisplayOneChar(1,0,0x20); //显示小时十位
DisplayOneChar(2,0,0x20); //显示小时个位
}
}
else
{
DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位
DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位
}
}
/*****************************************************
函 数 名:void Disp_line2()
功 能:显示日期和星期 (XX/XX/XX Week.X)
说 明:第二行显示数据处理
*****************************************************/
// 屏幕显示第二行 日期和星期
void Disp_line2(void)
{
DisplayOneChar(3,1,0x2f); //显示固定字符
DisplayOneChar(6,1,0x2f);
DisplayListChar(10,1,week);
if(year==1) //年闪烁标志位
{
if(flag==1)
{
DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位
DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位
}
else
{
DisplayOneChar(1,1,0x20); //显示年十位
DisplayOneChar(2,1,0x20); //显示年个位
}
}
else
{
DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位
DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位
}
if(mon==1) //月闪烁标志位
{
if(flag==1)
{
DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位
DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位
}
else
{
DisplayOneChar(4,1,0x20); //显示月十位
DisplayOneChar(5,1,0x20); //显示月个位
}
}
else
{
DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位
DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位
}
if(day==1) //日闪烁标志位
{
if(flag==1)
{
DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位
DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位
}
else
{
DisplayOneChar(7,1,0x20); //显示日十位
DisplayOneChar(8,1,0x20); //显示日个位
}
}
else
{
DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位
DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位
}
if(weekk==1) //星期闪烁标志位
{
if(flag==1)
{
DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期
}
else
{
DisplayOneChar(15,1,0x20); //显示星期
}
}
else
{
DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期
}
}
|