上午花了一上午時(shí)間,用12864液晶寫了一個(gè)電子時(shí)鐘加溫度傳感器程序,先說一下程序的功能,可以實(shí)現(xiàn)顯示年月日時(shí)間和溫度,
年月日和時(shí)間是可通過按鍵調(diào)節(jié)的,調(diào)節(jié)相應(yīng)的選項(xiàng)時(shí),該選項(xiàng)會(huì)閃爍,并停止走時(shí),當(dāng)調(diào)節(jié)完畢后時(shí)鐘恢復(fù)走時(shí)。現(xiàn)在將程序和思路寫下來,以便日后查看和與大家探討改進(jìn),歡迎高手提出寶貴意見。
我使用的是HJ12864M-1帶字庫液晶,所以在顯示上稍微方便一點(diǎn)。下面先來說一下我的編程思路。時(shí)間更新用的是單片機(jī)自帶的定時(shí)器,液晶要顯示數(shù)字必需將它轉(zhuǎn)換成ASCii碼的形式,數(shù)字0-9的ASCii碼與數(shù)字之間有一個(gè)定量的關(guān)系,當(dāng)數(shù)字加上0x30之后便得到該數(shù)字的ASCii碼,這樣以來液晶更新數(shù)據(jù)就變得簡單了。調(diào)節(jié)時(shí)間時(shí)對(duì)應(yīng)選項(xiàng)閃爍,是通過不斷的交替寫入數(shù)據(jù)和空格實(shí)現(xiàn)的。溫度顯示用的是DS18B20,,將測(cè)得的當(dāng)前溫度不斷更新顯示在液晶上。調(diào)節(jié)時(shí)間用的是三個(gè)獨(dú)立按鍵。由于這個(gè)程序我使用模塊化來寫的,就只能將每個(gè)模塊分別給出來,大家只要組裝一下便可以使用。如果需要完整程序的可以給我留言我發(fā)給你們。
下面是12864液晶的初始化,讀寫命令,及讀忙操作
#include "lcd12864.h" #include <reg52.h> sbit RS=P2^5; //控制端口位定義 sbit RW=P2^6; sbit EN=P2^7; void init_12864() { delay(40); write_com(0x30);//8位數(shù)據(jù)格式,基本指令顯示 delay(10); //延時(shí)時(shí)間 write_com(0x30);//8位數(shù)據(jù)格式,基本指令顯示 delay(37); write_com(0x0C);//開顯示、關(guān)閉光標(biāo) delay(10); write_com(0x01);//清屏指令 delay(10); //延時(shí) write_com(0x06);//設(shè)置顯示點(diǎn):指針自加1 } void delay(uint t) { uint i,j; for(i=120;i>0;i--); for(j=t;j>0;j--); } /********************************************************** void delay_us(uchar t) //延時(shí)計(jì)算公式:5+2*t { while(--t); } ***********************************************************/ void read_busy() { EN=0; RW=1; RS=0; EN=1; while(P0&0x80); EN=0; } void write_com(uchar com) //寫命令 { read_busy(); EN=1; RS=0; RW=0; P0=com; delay(1); EN=0; } void write_dat(uchar dat) //寫數(shù)據(jù) { read_busy(); EN=1; RS=1; RW=0; P0=dat; delay(1); EN=0; } 控制閃爍的函數(shù)如下: void shan(void) { uchar i; write_com(0x94); //將數(shù)據(jù)寫在0x94地址上 if(f==1) //按鍵按一下年開份始閃爍 { { tab2[8]=' '; //向要閃爍的位置寫空格 tab2[9]=' '; } for (i=8;i<=15;i++) { write_dat(tab2[i]); //寫數(shù)據(jù) } goto return1; } if(f==2) //按鍵按兩下月份開始閃爍 { { tab2[11]=' '; tab3[12]=' '; } for (i=8;i<=15;i++) { write_dat(tab2[i]); } goto return1; } if(f==3) //按鍵按三下,日期開始閃爍 { { tab2[14]=' '; tab2[15]=' '; } for (i=8;i<=15;i++) { write_dat(tab2[i]); } goto return1; } write_com(0x8b); if(f==4) //按鍵按四下,小時(shí)開始閃爍 { { tab3[6]=' '; tab3[7]=' '; } for (i=6;i<=13;i++) { write_dat(tab3[i]); } goto return1; } if(f==5) //按鍵按五下,分鐘開始閃爍 { { tab3[9]=' '; tab3[10]=' '; } for (i=6;i<=13;i++) { write_dat(tab3[i]); } goto return1; } if(f==6) //按鍵按六下,秒開始閃爍 { { tab3[12]=' '; tab3[13]=' '; } for (i=6;i<=13;i++) { write_dat(tab3[i]); } goto return1; } if(f==7) //按鍵按七下,調(diào)時(shí)完畢,停止閃爍,開始走時(shí) { { for (i=6;i<=13;i++) { write_dat(tab3[i]); TR0=1; //時(shí)間設(shè)定完畢,打開定時(shí)器 } } } return1:_nop_(); } 顯示數(shù)組: uchar code tab1[]="時(shí)鐘 +溫度顯示 "; uchar tab2[16]="日期:20"; uchar tab3[14]="時(shí)間:"; uchar tab4[12]="當(dāng)前溫度:" ; 定時(shí)器初始化,ASCii碼轉(zhuǎn)換 /********************************************************** 程序功能:12864液晶顯示電子時(shí)鐘(包括年月日時(shí)分秒),具有閃爍,移位,調(diào)時(shí)功能 并顯示當(dāng)前溫度 程序編譯環(huán)境:keil4 程序運(yùn)行環(huán)境:HJ12864M-1 整理人:張家越 QQ:435835181 整理時(shí)間:2011-04-17 *********************************************************/ #include <reg52.h> #include"lcd12864.h" #include <intrins.h> #include "flash.h" #include"scan.h" #include "18B20.h" uchar tempreture[2]; #define uchar unsigned char #define uint unsigned int uchar utime; //定時(shí)20ms,每20ms,utime++ void shan(); //控制閃爍函數(shù) void tkey(void); //按鍵處理函數(shù) void init_clock() //定時(shí)器初始化函數(shù) { TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; ET0=1 ; EA=1; TR0=1; } void iscii_change() //將需要顯示的時(shí)間轉(zhuǎn)換成ISCii碼 { tab3[6]=clock[3]/10+0x30; tab3[7]=clock[3]%10+0x30; tab3[8]=0x3a; tab3[9]=clock[4]/10+0x30; tab3[10]=clock[4]%10+0x30; tab3[11]=0x3a; tab3[12]=clock[5]/10+0x30; tab3[13]=clock[5]%10+0x30; tab2[8]=clock[0]/10+0x30; tab2[9]=clock[0]%10+0x30; tab2[10]=0x2d; tab2[11]=clock[1]/10+0x30; tab2[12]=clock[1]%10+0x30; tab2[13]=0x2d; tab2[14]=clock[2]/10+0x30; tab2[15]=clock[2]%10+0x30; tab4[10]=temp/10+0x30; tab4[11]=temp%10+0x30; } void display() //顯示函數(shù) { uchar i; write_com(0x80); for(i=0;i<16;i++) { write_dat(tab1[i]); } write_com(0x90); for(i=0;i<16;i++) { write_dat(tab2[i]); } write_com(0x88); for(i=0;i<14;i++) { write_dat(tab3[i]); delay(1); } write_com(0x98); for(i=0;i<12;i++) { write_dat(tab4[i]); } } void main() { init_clock(); init_12864(); while(1) { Read_temp(); iscii_change(); display(); tkey(); shan(); } } void clk()interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; utime++; if(utime ==20) //一秒鐘時(shí)間到,秒加一 { utime=0; clock[5]++; } else if(clock[5]==60) //秒鐘加到60分鐘加一 { clock[5]=0; clock[4]++; } else if(clock[4]==60) { clock[4]=0; clock[3]++ ; } else if(clock[3]==24) { clock[3]=0; clock[2]++; } else if(clock[2]==31) { clock[2]=0; clock[1]++; } else if(clock[1]==13) { clock[1]=0; clock[0]++; } else if(clock[0]==100) { clock[0]=0; } } 按鍵掃描函數(shù) uchar clock[6]={11,3,22,12,22,34}; //用來存放年的后兩位,月,日,時(shí),分,秒 sbit key1=P3^2; //位定義三個(gè)按鍵(用來調(diào)時(shí)) sbit key2=P3^3; sbit key3=P3^4; void tkey(void) { /*******移位鍵*********/ if (key1==0) { //delay(10); f++; TR0=0; //調(diào)整時(shí)間時(shí)關(guān)閉定時(shí)器 } if (f==8) f=1; /**********加一鍵*********/ if(key2==0) { // delay(10); clock[f-1]++; } if (f==1) { if (clock[f-1]==100){ clock[f-1]=0;} } else if(f==2) { if(clock[f-1]==13) clock[f-1]=0; } else if(f==3) { if(clock[f-1]==31) clock[f-1]=0; } else if(f==4) { if(clock[f-1]==24) clock[f-1]=0; } else{ if (clock[f-1]==60) clock[f-1]=0; } /******減一鍵***********/ if(key3==0) { // delay(10); clock[f-1]--; } else if (f==1) { if (clock[f-1]==0xff){ clock[f-1]=99;} } else if (f==2) { if (clock[f-1]==0xff){ clock[f-1]=12;} } else if (f==3) { if (clock[f-1]==0xff){ clock[f-1]=30;} } else if (f==1) { if (clock[f-1]==0xff){ clock[f-1]=23;} } else { if (clock[f-1]==0xff) clock[f-1]=59; } } 18B20溫度傳感器控制函數(shù): #include<reg52.h> #include<intrins.h> #include "lcd12864.h" #define uchar unsigned char #define uint unsigned int uchar temp=80,temp_L,temp_H; sbit DQ=P2^3; void delay_us(uchar i) //延時(shí)函數(shù),計(jì)算公式:延時(shí)時(shí)間T=5+2*i; { while(--i); } bit Reset_DS18B20(void) //DS18B20復(fù)位函數(shù) { bit DS18B20_exist; DQ=1; DQ=0; delay_us(250); //將DQ拉低480 ~ 960us,產(chǎn)生復(fù)位信號(hào) DQ=1; //將總線釋放,進(jìn)入接收狀態(tài) delay_us(30); //等待15-60us,DS18b20發(fā)出存在信號(hào),將總線拉低60-240us DS18B20_exist=DQ; delay_us(200); //存在信號(hào)持續(xù)60 ~ 240us if(DS18B20_exist) return 1; //返回1,DS18B20復(fù)位失敗,總線上無DS18B20 else return 0; //返回0,DS18B20復(fù)位成功,總線上存在DS18b20 } //寫數(shù)據(jù)--線低后高 void write_DS18B20(unsigned char value) { unsigned char i; for(i=0;i<8;i++) { DQ=1; DQ=0; //將總線拉低,數(shù)據(jù)送入總線 _nop_(); DQ=value&0x01; delay_us(20); //DS18b20在之后的15-60us的時(shí)間對(duì)總線數(shù)據(jù)采樣 DQ=1; //連續(xù)寫入將須將總線釋放至少1us value=value>>1; } } //讀數(shù)據(jù)--先低后高 unsigned char Read_DS18B20(void) { unsigned char value,i; for(i=0;i<8;i++) { DQ=1; DQ=0; delay_us(1); //主機(jī)將總線拉低7us,!!!!時(shí)間不能過長 DQ=1; //之后釋放總線,告訴DS18B20“讀”數(shù)據(jù) _nop_(); _nop_(); value=value>>1; if(DQ) value|=0x80; //數(shù)據(jù)讀取 delay_us(20); } return value; } void Read_temp() { Reset_DS18B20(); write_DS18B20(0xCC); write_DS18B20(0x44); Reset_DS18B20(); write_DS18B20(0xcc); write_DS18B20(0xBE); temp_L=Read_DS18B20(); temp_H=Read_DS18B20(); temp=(temp_H*256+temp_L)/16; } ------------------------------------- #include "lcd12864.h" #include <reg52.h> sbit RS=P2^5; //控制端口位定義 sbit RW=P2^6; sbit EN=P2^7; void init_12864() { delay(40); write_com(0x30);//8位數(shù)據(jù)格式,基本指令顯示 delay(10); //延時(shí)時(shí)間 write_com(0x30);//8位數(shù)據(jù)格式,基本指令顯示 delay(37); write_com(0x0C);//開顯示、關(guān)閉光標(biāo) delay(10); write_com(0x01);//清屏指令 delay(10); //延時(shí) write_com(0x06);//設(shè)置顯示點(diǎn):指針自加1 } void delay(uint t) { uint i,j; for(i=120;i>0;i--); for(j=t;j>0;j--); } /********************************************************** void delay_us(uchar t) //延時(shí)計(jì)算公式:5+2*t { while(--t); } ***********************************************************/ void read_busy() { EN=0; RW=1; RS=0; EN=1; while(P0&0x80); EN=0; } void write_com(uchar com) //寫命令 { read_busy(); EN=1; RS=0; RW=0; P0=com; delay(1); EN=0; } void write_dat(uchar dat) //寫數(shù)據(jù) { read_busy(); EN=1; RS=1; RW=0; P0=dat; delay(1); EN=0; }
完整代碼下載:點(diǎn)這里