專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

12864液晶電子時(shí)鐘+溫度顯示

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2012年03月09日   【字體:



        上午花了一上午時(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)這里

關(guān)閉窗口

相關(guān)文章