#include <reg51.h>
#include <intrins.h>
#include<stdlib.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
#define pi 3.1415926
/************* 12864LCD引腳定義 *************/
#define LCD_data P0 //數據口
sbit LCD_RS = P1^0; //寄存器選擇輸入
sbit LCD_RW = P1^1; //液晶讀/寫控制
sbit LCD_EN = P1^2; //液晶使能控制
sbit LCD_PSB = P2^4; //串/并方式控制
sbit LCD_RST = P2^5; //液晶復位端口
sbit k1=P3^5; //按鍵
sbit k2=P3^2;
sbit k3=P3^3;
sbit k4=P3^4;
sbit DQ = P1^7; //數據口define interface
uchar a,b,c,count,num;
uint temp;
uchar tabbjsj[]="北京時間";
uchar tabsswd[]="實時溫度";
uchar tab[]="01:00:00";
uchar code table[]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0xF8,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0E,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x87,0x13,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x03,0xF7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x30,0x0E,0x30,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x78,0x1C,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x3C,0xFC,0x38,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xDE,0x71,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x79,0x9E,0x79,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x3B,0x9E,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0F,0xF7,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xEF,0x37,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x03,0xDE,0x7B,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xBC,0xFD,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x79,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x1E,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,
0x00,0x01,0x9C,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xC0,0x00,0x99,0x00,0x00,0x30,0x00,0x03,0x9A,0x00,0x0C,0x23,0x00,0x00,0x00,0x02,0xC6,
0x00,0x99,0x80,0x06,0xB4,0x00,0x02,0x21,0x00,0x06,0x33,0x00,0x10,0x80,0x07,0x26,0x00,0x98,0x00,0x12,0x88,0x00,0x02,0x24,0x80,0x06,0x3F,
0x00,0x1F,0xC0,0x05,0x26,0x00,0x15,0x00,0x1C,0x00,0x00,0x03,0x66,0x70,0x17,0x67,0x00,0x0F,0x00,0x01,0xBE,0x00,0x02,0x00,0x0E,0x70,0x00,
0x03,0x7E,0x00,0x17,0xE2,0x00,0x07,0x00,0x07,0x00,0x01,0xA0,0x40,0x18,0x00,0x00,0x06,0xCE,0x00,0x0E,0x62,0x00,0x07,0x00,0x03,0xA6,0x00,
0x9C,0x80,0x12,0x38,0x00,0x06,0x0F,0x80,0x06,0x62,0x00,0x06,0x00,0x03,0x08,0x00,0x84,0x00,0x10,0xF0,0x00,0x0C,0xFC,0x00,0x06,0x22,0x00,
0x1E,0x00,0x05,0x1C,0x00,0x1E,0x00,0x10,0x40,0x00,0x12,0x24,0x80,0x3E,0x42,0x00,0x1E,0x00,0x01,0x1C,0x00,0x04,0x00,0x10,0x80,0x00,0x02,
0x44,0xC0,0x3C,0x43,0x00,0x7F,0xF0,0x01,0x0E,0x00,0x04,0x00,0x11,0x10,0x80,0x02,0x64,0x80,0x00,0x03,0x00,0x20,0x00,0x00,0xFA,0x80,0x08,
0x00,0x13,0x08,0x80,0x02,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x18,0x00,0x00,0x07,0x00,0x02,0x0C,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00};
/*******************************************************************/
/* */
/* 延時函數 */
/* */
/*******************************************************************/
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<150;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/*******************************************************************/
/* */
/* 精確延時函數,延時1秒,軟件算得 */
/* */
/*******************************************************************/
void Delay_S(void) //延時1s誤差 0us
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
_nop_(); //if Keil,require use intrins.h
}
/*******************************************************************/
/* */
/*檢查LCD忙狀態 */
/*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數據。 */
/* */
/*******************************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*******************************************************************/
/* */
/*寫指令數據到LCD */
/*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */
/* */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
LCD_data = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*寫顯示數據到LCD */
/*RS=H,RW=L,E=高脈沖,D0-D7=數據。 */
/* */
/*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*從lcd讀取數據到data */
/*RS=H,RW=L,E=高脈沖,D0-D7=數據。 */
/* */
/*******************************************************************/
uchar lcd_rdat()
{
uchar dat;
while(lcd_busy());
LCD_data = 0XFF;
LCD_RS = 1;
LCD_RW = 1;
LCD_EN = 0;
LCD_EN = 1;
dat = LCD_data;
LCD_EN = 0;
return(dat);
}
/*******************************************************************/
/* */
/* LCD初始化設定 */
/* */
/*******************************************************************/
void lcd_init()
{
LCD_PSB = 1; //并口方式
LCD_RST = 0; //液晶復位
delay(3);
LCD_RST = 1;
delay(3);
lcd_wcmd(0x34); //擴充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //顯示開,關光標
delay(5);
lcd_wcmd(0x01); //清除LCD的顯示內容
delay(5);
}
/***********************************************************
函數名: DrawPoint
函數說明:畫點
傳入參數:打點位置(x0,y0);color=1,點亮;color=0,擦除
傳出參數:無
返回值: 無
**********************************************************/
void DrawPoint(unsigned char x,unsigned char y,unsigned char color)
{
unsigned char row,collum,cbite;
unsigned char tempH,tempL;
lcd_wcmd(0x34);//打開擴充指令集
lcd_wcmd(0x36);//打開圖形顯示
collum=x>>4;
cbite=x&0x0f;
if(y<32)
row=y;
else
{
row=y-32;
collum+=8;
}
lcd_wcmd(0x80+row);//先寫Y坐標
lcd_wcmd(0x80+collum);//再寫X坐標
lcd_rdat();
tempH = lcd_rdat();//先讀出高字節
tempL = lcd_rdat();//再讀出低字節
lcd_wcmd(0x80+row);//先寫Y坐標
lcd_wcmd(0x80+collum);//再寫X坐標
if (color)
{
if(cbite<8)
{
tempH|=(1<<(7-cbite));
}
else
{
tempL|=(1<<(15-cbite));
}
}
else
{
if(cbite<8)
{
tempH&=~(1<<(7-cbite));
}
else
{
tempL&=~(1<<(15-cbite));
}
}
lcd_wdat(tempH);
lcd_wdat(tempL);
lcd_wcmd(0x30);
}
/***********************************************************
函數名: line
函數說明:畫直線
傳入參數:直線起始位置(x0,y0);終點(x1,y1)
傳出參數:無
返回值: 無
**********************************************************/
void line(unsigned char x0,unsigned char y0, unsigned char x1,unsigned char y1,unsigned char color)
{
int dx; /* 直線x軸差值變量*/
int dy; /* 直線y軸差值變量 */
char dx_sym; /* x軸增長方向,為-1時減值方向,為1時增值方向 */
char dy_sym; /* y軸增長方向,為-1時減值方向,為1時增值方向 */
int dx_x2; /* dx*2值變量,用于加快運算速度*/
int dy_x2; /* dy*2值變量,用于加快運算速度*/
int di; /* 決策變量 */
if (x0 == x1) /* 畫垂直線 */
{
if (y0 > y1)
{
dx = y0;
y0 = y1;
y1 = dx;
}
for (dx = y0; dx < y1+1; dx++)
{
DrawPoint(x0, dx,color);
}
}
if (y0 == y1) /* 畫水平線 */
{
if(x0 > x1)
{
dy = x0;
x0 = x1;
x1 = dy;
}
for (dy = x0; dy < x1+1; dy++)
{
DrawPoint(dy, y0,color);
}
}
/****************************畫斜線******************************/
dx = x1-x0; /* 求取兩點之間的差值 */
dy = y1-y0;
if (dx > 0) /* 判斷x軸方向 */
{
dx_sym = 1; /* dx>0,設置dx_sym=1 */
}
else
{
if (dx < 0)
{
dx_sym = -1; /* dx<0,設置dx_sym=-1 */
}
}
if (dy > 0) /* 判斷y軸方向 */
{
dy_sym = 1; /* dy>0,設置dy_sym=1 */
}
else
{
if (dy < 0)
{
dy_sym = -1; /* dy<0,設置dy_sym=-1 */
}
}
dx = dx_sym * dx; /* 將dx、dy取絕對值 */
dy = dy_sym * dy;
dx_x2 = dx*2; /* 計算2倍的dx及dy值 */
dy_x2 = dy*2;
/* 使用Bresenham法進行畫直線 */
if (dx >= dy) /* 對于dx>=dy,則使用x軸為基準 */
{
di = dy_x2 - dx;
while(x0!=x1)
{
DrawPoint(x0, y0,color);
x0 += dx_sym;
if (di < 0)
{
di += dy_x2; /* 計算出下一步的決策值 */
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
DrawPoint(x0, y0,color); /* 顯示最后一點 */
}
else /* 對于dx<dy,則使用y軸為基準 */
{
di = dx_x2 - dy;
while(y0!=y1)
{
DrawPoint(x0, y0,color);
y0 += dy_sym;
if (di < 0)
{
di += dx_x2;
}
else
{
di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
DrawPoint(x0, y0,color); /* 顯示最后一點 */
}
}
/***********************************************************
函數名: circle
函數說明:畫圓
傳入參數:圓心坐標(x1,y1),半徑r
傳出參數:無
返回值: 無
**********************************************************/
void circle(int x1, int y1, unsigned int r)
{
int x, y, d;
x = 0;
y = r;
d = 1-r; /* 計算初始值 */
while (x <= y)
{
/* 繪制點(x,y)及其在八分圓中的另外7個對稱點 */
DrawPoint(x1+x, y1+y,1);
DrawPoint(x1+y, y1+x,1);
DrawPoint(x1-y, y1+x,1);
DrawPoint(x1-x, y1+y,1);
DrawPoint(x1-x, y1-y,1);
DrawPoint(x1-y, y1-x,1);
DrawPoint(x1+y, y1-x,1);
DrawPoint(x1+x, y1-y,1);
if (d < 0)
{
d += 2*x+3; /* 根據誤差項d的判斷,決定非最大位移方向上是走還是不走 */
}
else
{
d += 2*(x-y)+5;
y--;
}
x++;
}
}
/*******************************************
函數名稱:void DrawHand(char x0,char y0,char a,char b,char c,char color)
功 能:畫時鐘指針
參 數:(x0,y0)表盤圓心坐標,
R指針長度
Time指針所指刻度(秒、分60進制,時12進制)
step指針步長(秒、分為6,時為30)
color指針顏色
返回值 :無
********************************************/
void DrawHand(char x0,char y0,char R,char Time,char step,char color)
{
char x,y;
x=R*cos(Time*step*pi/180-pi/2)+x0;
y=R*sin(Time*step*pi/180-pi/2)+y0;
line(x0,y0,x,y,color);
}
/*******************************************
函數名稱:clr_screen(void)
功 能:清除液晶GDRAM內部的隨機數據
參 數:無
返回值 :無
********************************************/
void clr_screen(void)
{
uchar i,j;
for(j=0;j<64;j++)
{
for(i=0;i<128;i++)
{
DrawPoint(i,j,0);
}
}
}
/*******************************************************************************
* 描述: *
* 12864標準字庫液晶演示 數據p0,控制p2 *
********************************************************************************/
#define x0 31
#define y0 31 //表盤圓心坐標
/***********************************************************
函數名: DISP_BP
函數說明:畫表盤
傳出參數:無
返回值: 無
**********************************************************/
void DISP_BP(void)
{
circle(x0,y0,30);//畫圓
line(31,1,31,3,1);//12點
line(30,1,30,3,1);
line(32,1,32,3,1);
line(31,61,31,59,1);//6點
line(30,61,30,59,1);
line(32,61,32,59,1);
line(61,31,59,31,1);//3點
line(61,30,59,30,1);
line(61,32,59,32,1);
line(1,31,3,31,1);//9點
line(1,30,3,30,1);
line(1,32,3,32,1);
line(109,51,111,51,1);//℃符號
line(109,50,111,50,1);
line(109,49,111,49,1);
line(110,50,110,50,0);
circle(8,8,8); //耳朵左
line(16,7,16,11,0);
line(7,16,12,16,0);
line(15,12,11,15,0);
line(15,11,12,17,0);
line(12,15,12,15,0);
circle(54,8,8); //耳朵右
line(46,7,46,11,0);
line(55,16,50,16,0);
line(47,12,51,16,0);
line(47,11,47,11,0);
// line(48,14,48,14,1);
line(51,15,51,15,0);
}
/*****************顯示時分秒*****************/
void sfm(uchar add,uchar sfm)
{
uchar sfm1,sfm2;
sfm1=sfm/10;
sfm2=sfm%10;
lcd_wcmd(0x90+add);
lcd_wdat(0x30+sfm1);
lcd_wdat(0x30+sfm2);
}
void sfmfen()
{
uchar fen1,fen2;
fen1=b/10;
fen2=b%10;
lcd_wcmd(0x90+5);
lcd_wdat(0x3a);
lcd_wdat(0x30+fen1);
lcd_wdat(0x30+fen2);
}
//按鍵掃描函數
void keyscan()
{
// uchar i,j,k;
if(k1==0)
delay(5);
if(k1==0)
{
while(!k1);
DrawHand(x0,y0,25,a,6,0); // 消除秒針位置
DrawHand(x0,y0,20,b,6,1); //顯示新的分針位置
DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
a++;
if(a==60)
a=0;
sfm(7,a);
DrawHand(x0,y0,25,a,6,1); //顯示秒針位置
}
if(k2==0)
delay(5);
if(k2==0)
{
while(!k2);
DrawHand(x0,y0,20,b,6,0); //消除原來分針位置
DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
DrawHand(x0,y0,25,a,6,1); //顯示秒針位置
b++;
if(b==60)
b=0;
sfmfen();
DrawHand(x0,y0,20,b,6,1); //顯示新的分針位置
}
if(k3==0)
delay(5);
if(k3==0)
{
while(!k3);
DrawHand(x0,y0,15,c,6,0);//消除原來的時針位置
DrawHand(x0,y0,25,a,6,1); //顯示秒針位置
DrawHand(x0,y0,20,b,6,1); //顯示新的分針位置
c++;
if(c==60)
c=0;
sfm(4,c/5);
DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
}
}
/*******************畫開機畫面********************/
void GUI_CLEAR(const uchar *pic)
{
uchar i,j,k;
lcd_wcmd(0X34);
lcd_wcmd(0X34);
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
lcd_wcmd(0X80+j);
delay(2);
if(i==0)
{
lcd_wcmd(0X80);
delay(2);
}
else
{
lcd_wcmd(0X88);
delay(2);
}
for(k=0;k<16;k++)
{
lcd_wdat(*(pic++));
//LCD_WRITE_DATA(0X00);
delay(2);
}
}
}
lcd_wcmd(0X36);
lcd_wcmd(0X30);
}
/********************DS18B20***********************************/
void delay18b20(unsigned char i)
{
while(--i);
}
void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
{
DQ = 1; //DQ復位,不要也可行。
delay18b20(1); //稍做延時
DQ = 0; //單片機拉低總線
delay18b20(250); //精確延時,維持至少480us
DQ = 1; //釋放總線,即拉高了總線
delay18b20(100); //此處延時有足夠,確保能讓DS18B20發出存在脈沖。
}
uchar Read_One_Byte() //讀取一個字節的數據read a byte date
//讀數據時,數據以字節的最低有效位先從總線移出
{
uchar i = 0;
uchar dat = 0;
for(i=8;i>0;i--)
{
DQ = 0; //將總線拉低,要在1us之后釋放總線
//單片機要在此下降沿后的15us內讀數據才會有效。
_nop_(); //至少維持了1us,表示讀時序開始
dat >>= 1; //讓從總線上讀到的位數據,依次從高位移動到低位。
DQ = 1; //釋放總線,此后DS18B20會控制總線,把數據傳輸到總線上
delay18b20(1); //延時7us,此處參照推薦的讀時序圖,盡量把控制器采樣時間放到讀時序后的15us內的最后部分
if(DQ) //控制器進行采樣
{
dat |= 0x80; //若總線為1,即DQ為1,那就把dat的最高位置1;若為0,則不進行處理,保持為0
}
delay18b20(10); //此延時不能少,確保讀時序的長度60us。
}
return (dat);
}
void Write_One_Byte(uchar dat)
{
uchar i = 0;
for(i=8;i>0;i--)
{
DQ = 0; //拉低總線
_nop_(); //至少維持了1us,表示寫時序(包括寫0時序或寫1時序)開始
DQ = dat&0x01; //從字節的最低位開始傳輸
//指令dat的最低位賦予給總線,必須在拉低總線后的15us內,
//因為15us后DS18B20會對總線采樣。
delay18b20(10); //必須讓寫時序持續至少60us
DQ = 1; //寫完后,必須釋放總線,
dat >>= 1;
delay18b20(1);
}
}
uint Get_Tmp() //獲取溫度get the temperature
{
float tt;
uchar a,b;
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0x44); //溫度轉換指令
Init_Ds18b20(); //初始化
Write_One_Byte(0xcc); //忽略ROM指令
Write_One_Byte(0xbe); //讀暫存器指令
a = Read_One_Byte(); //讀取到的第一個字節為溫度LSB
b = Read_One_Byte(); //讀取到的第一個字節為溫度MSB
temp = b; //先把高八位有效數據賦于temp
temp <<= 8; //把以上8位數據從temp低八位移到高八位
temp = temp|a; //兩字節合成一個整型變量
tt = temp*0.0625; //得到真實十進制溫度值
//因為DS18B20可以精確到0.0625度
//所以讀回數據的最低位代表的是0.0625度
temp = tt*10+0.5; //放大十倍
//這樣做的目的將小數點后第一位也轉換為可顯示數字
//同時進行一個四舍五入操作。
return temp;
}
/****************動態顯示溫度函數**************/
void Display(uint temp) //顯示程序
{
uchar A1,A2,A3;
A1 = temp/100; //百位
A2 = temp%100/10; //十位
A3 = temp%10; //個位
lcd_wcmd(0x98+4);
lcd_wdat(' ');
lcd_wdat(0x30+A1);
lcd_wdat(0x30+A2);
lcd_wdat('.');
lcd_wdat(0x30+A3);
}
/*********************************************************
* *
* 主函數 *
* *
*********************************************************/
void main()
{
lcd_init();
GUI_CLEAR(table);
Delay_S(); Delay_S();Delay_S();
Delay_S(); Delay_S();Delay_S();
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;ET0=1;TR0=1;
a=0;b=0;c=45;
delay(100); //上電,等待穩定
lcd_init(); //初始化LCD
clr_screen(); //清屏
DISP_BP(); //畫表盤
//DrawHand(x0,y0,25,a,6,1); //顯示秒針
//DrawHand(x0,y0,20,b,6,1); //顯示分針
//DrawHand(x0,y0,15,c,6,1); //顯示時針
lcd_wcmd(0x90+4); //顯示初始時間
for(num=0;num<8;num++)
{
lcd_wdat(tab[num]);
}
lcd_wcmd(0x98+7); //顯示溫度符號C
lcd_wdat('C');
lcd_wcmd(0x80+4); //顯示”北京時間“
for(num=0;num<8;num++)
{
lcd_wdat(tabbjsj[num]);
}
lcd_wcmd(0x88+4); //顯示"實時溫度"
for(num=0;num<8;num++)
{
lcd_wdat(tabsswd[num]);
}
c=5;b=0;a=0;
DrawHand(x0,y0,25,a,6,1); //顯示秒針
DrawHand(x0,y0,20,b,6,1); //顯示分針
DrawHand(x0,y0,15,c,6,1); //顯示時針
while(1)
{
keyscan();
Display(Get_Tmp());//顯示溫度
if(count==20)
{
count=0;
DrawHand(x0,y0,25,a,6,0); // 消除秒針位置
DrawHand(x0,y0,20,b,6,1); //顯示新的分針位置
DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
a++;
if(a==60)
{
a=0;
DrawHand(x0,y0,20,b,6,0); //消除原來分針位置
DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
b++;
if(b==60 )
{
b=0;
DrawHand(x0,y0,15,c,6,0);//消除原來的時針位置
c++;
if(c==60)
{
c=0;
}
sfm(4,c/5); DrawHand(x0,y0,15,c,6,1);//顯示新的時針位置
}
sfmfen(); DrawHand(x0,y0,20,b,6,1); //顯示新的分針位置
}
sfm(7,a); DrawHand(x0,y0,25,a,6,1); //顯示新的秒針位置
}
}
}
void ser0()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
}
|