求助!~本人是阿蔡~據以下程序做了一個電子鐘,但最后有點小問題,1602顯示不正確~秒走起來時每隔一個就顯示一個問號~其余年月日,時間等也是如此~請問有誰遇到類似問題?怎樣解決啊~?原理圖及PCB見附件
pcb.jpg (95.38 KB, 下載次數: 122)
下載附件
2009-12-10 15:41 上傳
#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);//顯示星期
}
}
sch.jpg (132.07 KB, 下載次數: 134)
下載附件
2009-12-10 15:41 上傳
|