謝謝各位大神的指點,是程序有問題,現在修改好了 代碼:
- /********************************************************************************************
- 程序名: 1602智能液晶屏時鐘
- 硬件支持: LCD1602液晶屏 STC12C5608+外部12MHZ晶振 DS1302+32.768KHZ晶振
- 說明備注: 使用2402液晶屏程序,與1602液晶屏程序完全兼容
- /********************************************************************************************/
- #include <STC12C5630AD.h> // 包含頭文件 //
- #include <intrins.h>
- /********************************************************************************************/
- typedef unsigned char uint8; // 無符號8位整型變量 //
- typedef unsigned char uchar; // 無符號8位整型變量 //
- /********************************************************************************************
- // 引腳定義 // (使用者根據實際更改)
- /********************************************************************************************/
- #define LCM2402_DB0_DB7 P2 // 定義LCM2402的數據總線
- sbit LCM2402_RS = P1 ^ 5; // 定義LCM2402的RS控制線
- sbit LCM2402_RW = P1 ^ 6; // 定義LCM2402的RW控制線
- sbit LCM2402_E = P1 ^ 7; // 定義LCM2402的E控制線
- sbit LCM2402_Busy = P2 ^ 7; // 定義LCM2402的測忙線(與LCM2402_DB0_DB7關聯)
- sbit DQ = P1 ^ 3; // 定義18B20的數據端
- sbit SCLK = P1 ^ 0; //定義ds1302_clk(1302時鐘線)
- sbit DSIO = P1 ^ 1; //定義ds1302_dat(1302數據線)
- sbit RST = P1 ^ 2; //定義ds1302_Rst(1302復位線)
- data unsigned char TIME_WW;//設置星期存放區
- /********************************************************************************************
- // 定義LCM2402指令集 // (詳細請見技術手冊)
- /********************************************************************************************/
- #define CMD_clear 0x01 // 清除屏幕
- #define CMD_back 0x02 // DDRAM回零位
- #define CMD_dec1 0x04 // 讀入后AC(指針)減1,向左寫
- #define CMD_add1 0x06 // 讀入后AC(指針)加1,向右寫
- #define CMD_dis_gb1 0x0f // 開顯示_開光標_開光標閃爍
- #define CMD_dis_gb2 0x0e // 開顯示_開光標_關光標閃爍
- #define CMD_dis_gb3 0x0c // 開顯示_關光標_關光標閃爍
- #define CMD_OFF_dis 0x08 // 關顯示_關光標_關光標閃爍
- #define CMD_set82 0x38 // 8位總線_2行顯示
- #define CMD_set81 0x30 // 8位總線_1行顯示(上邊行)
- #define CMD_set42 0x28 // 4位總線_2行顯示
- #define CMD_set41 0x20 // 4位總線_1行顯示(上邊行)
- #define lin_1 0x80 // 4位總線_1行顯示(上邊行)
- #define lin_2 0xc0 // 4位總線_1行顯示(上邊行)
- /********************************************************************************************
- // 讀LCM忙程序 [底層協議] // (所有底層協議都無需關注)
- // LCM2402測忙,若LCM2402處于忙狀態,本函數將等待至非忙狀態 //
- /********************************************************************************************/
- void LCM2402_TestBusy(void){
- LCM2402_DB0_DB7 = 0xff; //設備讀狀態
- LCM2402_RS = 0;
- LCM2402_RW = 1;
- LCM2402_E = 1;
- while(LCM2402_Busy); //等待LCM不忙
- LCM2402_E = 0; //
- }
- /********************************************************************************************
- // 寫指令程序 //
- // 向LCM2402寫命令 本函數需要1個指令集的入口參數 //
- /********************************************************************************************/
- void LCM2402_WriteCMD(uint8 LCM2402_command) {
- LCM2402_TestBusy();
- LCM2402_RS = 0;
- LCM2402_RW = 0;
- LCM2402_DB0_DB7 = (LCM2402_command/16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- LCM2402_DB0_DB7 = (LCM2402_command%16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- }
- /********************************************************************************************
- // 寫數據程序 //
- // 向LCM2402寫數據 //
- /********************************************************************************************/
- void LCM2402_WriteData(uint8 LCM2402_data){
- LCM2402_TestBusy();
- LCM2402_RS = 1;
- LCM2402_RW = 0;
- LCM2402_DB0_DB7 = (LCM2402_data/16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- LCM2402_DB0_DB7 = (LCM2402_data%16)*16;
- LCM2402_E = 1;
- LCM2402_E = 0;
- }
- /********************************************************************************************
- // 打印字符串程序 // (本函數調用指針函數)
- // 向LCM發送一個字符串,長度48字符之內
- // 第一行位置 0x00~0x17 第二行位置 0x40~0x57
- // 應用舉例:print(0x80,"abc"); //在第一行第一位處從左向右打印abc字符串
- /********************************************************************************************/
- void print(uint8 a,uint8 *str){
- LCM2402_WriteCMD(a | 0x80);
- while(*str != '\0'){
- LCM2402_WriteData(*str++);
- }
- *str = 0;
- }
- /********************************************************************************************
- // 打印單字符程序 //
- // 第一行位置 0x00~0x17 第二行位置 0x40~0x57
- // 向LCM發送一個字符,以十六進制(0x00)表示
- // 應用舉例:print(0xc0,0x30); //在第二行第一位處打印字符“0”
- /********************************************************************************************/
- void print2(uint8 a,uint8 t){
- LCM2402_WriteCMD(a | 0x80);
- LCM2402_WriteData(t);
- }
- /********************************************************************************************
- // 定義小漢字 //
- // 可寫入8個自字義字符,寫入后可用其CGRAM代碼直接提取顯示。
- // 字符定義方法請參考技術手冊
- /********************************************************************************************/
- uint8 code Xword[]={
- 0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //℃,代碼 0x00
- 0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00, //一,代碼 0x01
- 0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00, //二,代碼 0x02
- 0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00, //三,代碼 0x03
- 0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00, //四,代碼 0x04
- 0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00, //五,代碼 0x05
- 0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00, //六,代碼 0x06
- 0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00, //日,代碼 0x07
- };
- void CgramWrite(void) { // 裝入CGRAM //
- uint8 i;
- LCM2402_WriteCMD(0x06); // CGRAM地址自動加1
- LCM2402_WriteCMD(0x40); // CGRAM地址設為00處
- for(i=0;i<64;i++) {
- LCM2402_WriteData(Xword[i]);// 按數組寫入數據
- }
- }
- /********************************************************************************************
- // LCM2402初始化 //(使用者可自定義,加 * 號程序行必須保留但可修改)
- /********************************************************************************************/
- void LCM2402_Init(void){
- LCM2402_WriteCMD(CMD_set42); //* 顯示模式設置:顯示2行,每個字符為5*7個像素
- LCM2402_WriteCMD(CMD_set42); //* 顯示模式設置:顯示2行,每個字符為5*7個像素
- LCM2402_WriteCMD(CMD_clear); // 顯示清屏
- LCM2402_WriteCMD(CMD_back); //* 數據指針指向第1行第1個字符位置
- LCM2402_WriteCMD(CMD_add1); // 顯示光標移動設置:文字不動,光標右移
- LCM2402_WriteCMD(CMD_dis_gb3); // 顯示開及光標設置:顯示開,光標開,閃爍開
- CgramWrite(); // 向CGRAM寫入自定義字符
- }
- /******************************************************************************/
- // 以上是LCM2402驅動程序 //
- /*****************************************************************************/
- //---DS1302寫入和讀取時分秒的地址命令---//
- //---秒分時日月周年 最低位讀寫位;-------//
- uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
- uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
- //---DS1302時鐘初始化2016年5月7日星期六12點00分00秒。---//
- //---存儲順序是秒分時日月周年,存儲格式是用BCD碼---//
- uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};
- /*******************************************************************************
- * 函 數 名 : Ds1302Write
- * 函數功能 : 向DS1302命令(地址+數據)
- * 輸 入 : addr,dat
- * 輸 出 : 無
- *******************************************************************************/
- void Ds1302Write(uchar addr, uchar dat)
- {
- uchar n;
- RST = 0;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//先將SCLK置低電平。
- _nop_();_nop_();_nop_();_nop_();
- RST = 1; //然后將RST(CE)置高電平。
- _nop_();_nop_();_nop_();_nop_();
- for (n=0; n<8; n++)//開始傳送八位地址命令
- {
- DSIO = addr & 0x01;//數據從低位開始傳送
- addr >>= 1;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;
- _nop_();_nop_();_nop_();_nop_();
- }
- for (n=0; n<8; n++)//寫入8位數據
- {
- DSIO = dat & 0x01;
- dat >>= 1;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;
- _nop_();_nop_();_nop_();_nop_();
- }
-
- RST = 0;//傳送數據結束
- _nop_();_nop_();_nop_();_nop_();
- }
- /*******************************************************************************
- * 函 數 名 : Ds1302Read
- * 函數功能 : 讀取一個地址的數據
- * 輸 入 : addr
- * 輸 出 : dat
- *******************************************************************************/
- uchar Ds1302Read(uchar addr)
- {
- uchar n,dat,dat1;
- RST = 0;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//先將SCLK置低電平。
- _nop_();_nop_();_nop_();_nop_();
- RST = 1;//然后將RST(CE)置高電平。
- _nop_();_nop_();_nop_();_nop_();
- for(n=0; n<8; n++)//開始傳送八位地址命令
- {
- DSIO = addr & 0x01;//數據從低位開始傳送
- addr >>= 1;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//DS1302下降沿時,放置數據
- _nop_();_nop_();_nop_();_nop_();
- }
- _nop_();_nop_();_nop_();_nop_();
- for(n=0; n<8; n++)//讀取8位數據
- {
- dat1 = DSIO;//從最低位開始接收
- dat = (dat>>1) | (dat1<<7);
- SCLK = 1;
- _nop_();_nop_();_nop_();_nop_();
- SCLK = 0;//DS1302下降沿時,放置數據
- _nop_();_nop_();_nop_();_nop_();
- }
- RST = 0;
- _nop_();_nop_();_nop_();_nop_(); //以下為DS1302復位的穩定時間,必須的。
- SCLK = 1;
- _nop_();_nop_();_nop_();_nop_();
- DSIO = 0;
- _nop_();_nop_();_nop_();_nop_();
- DSIO = 1;
- _nop_();_nop_();_nop_();_nop_();
- return dat;
- }
- /*******************************************************************************
- * 函 數 名 : Ds1302Init
- * 函數功能 : 初始化DS1302.
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void Ds1302Init()
- {
- uchar n;
- Ds1302Write(0x8E,0X00); //禁止寫保護,就是關閉寫保護功能
- for (n=0; n<7; n++)//寫入7個字節的時鐘信號:分秒時日月周年
- {
- Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
- _nop_();_nop_();
- }
- Ds1302Write(0x8E,0x80); //打開寫保護功能
- }
- /*******************************************************************************
- * 函 數 名 : Ds1302ReadTime
- * 函數功能 : 讀取時鐘信息
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void Ds1302ReadTime()
- {
- uchar n;
- for (n=0; n<7; n++)//讀取7個字節的時鐘信號:分秒時日月周年
- {
- TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
- _nop_();_nop_();
- }
-
- }
- /******************************************************************************/
- //DS18B20溫度傳感器驅動(顯示0至60度)
- /******************************************************************************/
- void Delay(int num){//延時函數
- while(num--) ;
- }
- /******************************************************************************/
- void Init_DS18B20(void){//初始化ds1820
- unsigned char x=0;
- DQ = 1; //DQ復位
- Delay(35); //稍做延時
- DQ = 0; //單片機將DQ拉低
- Delay(480); //精確延時 大于 480us
- DQ = 1; //拉高總線
- Delay(70);
- x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
- Delay(90);
- }
- /******************************************************************************/
- unsigned char ReadOneChar(void){//讀一個字節
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--){
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;
- Delay(30);
- }
- return(dat);
- }
- /******************************************************************************/
- void WriteOneChar(unsigned char dat){//寫一個字節
- unsigned char i=0;
- for (i=8; i>0; i--){
- DQ = 0;
- DQ = dat&0x01;
- Delay(30);
- DQ = 1;
- dat>>=1;
- }
- }
- /******************************************************************************/
- unsigned int ReadTemperature(void){//讀取溫度
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- float tt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳過讀序號列號的操作
- WriteOneChar(0x44); // 啟動溫度轉換
- Init_DS18B20();
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器
- a=ReadOneChar(); //讀低8位
- b=ReadOneChar(); //讀高8位
- t=b;
- t<<=8;
- t=t|a;
- tt=t*0.0625;
- t= tt*10+0.5; //放大10倍輸出并四舍五入
- return(t);
- }
- /*****************************************************************************/
- //顯示項目 時間部分 在第一行全行顯示時間
- /*********************************************************************************************/
- // 測試用函數 //
- void main (void){
- LCM2402_Init();//LCD初始化
- Ds1302Init();//DS1302初始化
- while(1){ //主線程//
- unsigned int i=0,o=0,o2=0;
- unsigned char a=0,b=0,c=0;
- i=ReadTemperature();
- a=i/100;
- print2(0x40,a+0x30);
- b=i/10-a*10;
- print2(0x41,b+0x30);
- print(0x42,".");
- c=i-a*100-b*10;
- print2(0x43,c+0x30); //顯示溫度
- print2(0x44,0x00); //顯示℃
- //
- Ds1302ReadTime();
- print(0x00,"20");
- print2(0x02,TIME[6]/16+0x30);
- print2(0x03,(TIME[6]&0x0f)+0x30); //個位要打括號(先算)
- print(0x04,"/"); // 顯示年
- //
- print2(0x05,TIME[4]/16+0x30);
- print2(0x06,(TIME[4]&0x0f)+0x30);
- print(0x07,"/"); // 顯示月
- //
- print2(0x08,TIME[3]/16+0x30);
- print2(0x09,(TIME[3]&0x0f)+0x30);
- print2(0x0b,TIME[2]/16+0x30);
- print2(0x0c,(TIME[2]&0x0f)+0x30);
- print(0x0d,":");
- ////小時
- print2(0x0e,TIME[1]/16+0x30);
- print2(0x0f,(TIME[1]&0x0f)+0x30);
- print(0x10,":");
- ////分鐘
- print2(0x11,TIME[0]/16+0x30);
- print2(0x12,(TIME[0]&0x0f)+0x30);
- ////秒
- TIME_WW=TIME[5]&0x0f;
- print(0x46,"[");
- switch (TIME_WW){
- case 1:print(0x47,"Mon");break;
- case 2:print(0x47,"Tues");break;
- case 3:print(0x47,"Wed");break;
- case 4:print(0x47,"Thur");break;
- case 5:print(0x47,"Fri");break;
- case 6:print(0x47,"Sat");break;
- case 7:print(0x47,"Sun");break;
- default: print(0x47,"Error");break;
- } //顯示星期
- if(TIME_WW==2||TIME_WW==4)
- print(0x4b,"]");
- else print(0x4a,"]");
-
- }
- }
- /*********************************************************************************************/
復制代碼
|