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