|
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- //**********宏定義所需指令
- #define BASIC_SET 0x30
- #define EXTEND_SET 0x34
- #define DRAW_ON 0x36
- #define DRAW_OFF 0x34
- //*************端口定義
- sbit LCD_RS = P3^5;
- sbit LCD_RW = P3^6;
- sbit LCD_EN = P3^4;
- sbit DQ=P2^2;
- //sbit k1=P1^0;
- //定義溫度DS18B20接口
- //************變量定義
- uchar code t0[]="溫度 . ℃";
- uchar code t1[]="0123456789"; //利用一個溫度表解決溫度顯示亂碼
- uchar i,k,a,b;
- unsigned int temperature;
- unsigned char temp_x; //溫度小數部分
- unsigned int temp_disp;
- //****************短延時
- void delay(uint k)
- {
- uint i;
- uchar j;
- for(i = 0; i < k ;i ++)
- for(j = 120; j>0 ;j--);
- }
- //***********12864寫指令函數
- void write_com(uchar cmd)
- {
- LCD_RS = 0;
- LCD_RW = 0;
-
- delay(5);
- LCD_EN = 1; P0 = cmd;
- delay(10);
- LCD_EN = 0;
- }
- //********12864寫數據函數
- void write_dat(uchar dat)
- {
- LCD_RS = 1;
- LCD_RW = 0;
- delay(5);
- LCD_EN = 1; P0 = dat;
- delay(10);
- LCD_EN = 0;
- }
- //
- uchar read_dat(void)
- {
- uchar temp;
- P0 = 0XFF;
- //釋放數據線
- LCD_RS = 1;
- //數據
- LCD_RW = 1;
- // 讀模式
- LCD_EN = 1;
- //E為高電平進行讀數據或指令
- delay(1);
- temp = P0;
- LCD_EN = 0;
- return temp;
- }
- //設置光標(地址)函數
- //參數說明:x---為行號,y為列號
- void set_cursor(unsigned char x, unsigned char y)
- {
- unsigned char i;
- switch(x)
- //確定行號
- {
- case 0x00: i=0x80; break; //第一行
- case 0x01: i=0x90; break; //第二行
- case 0x02: i=0x88; break; //第三行
- case 0x03: i=0x98; break; //第四行
- default : break;
- }
- i = y+i; //確定列號
- write_com(i);
- }
- //********************************************************
- //顯示字符函數
- //********************************************************
- void display_char(unsigned char Alphabet)
- {
- write_dat(Alphabet);
- //寫入需要顯示字符的顯示碼
- }
- //********************************************************
- //指定位置顯示字符串函數
- //參數說明:x為行號,y為列號
- //********************************************************
- void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet)
- {
- unsigned char i=0;
- set_cursor(x,y); //設置顯示的起始地址
- while(Alphabet[i]!='\0')
- {
- write_dat(Alphabet[i]); //寫入需要顯示字符的顯示碼
- i++;
- }
- }
- //以下為GDRAM繪圖部分
- //繪圖顯示的清屏函數(因清屏指令在畫圖時不能用)
- void gui_clear()
- {
- uchar i , j , k;
- write_com(EXTEND_SET);//擴展指令集,8位數據傳輸
- write_com(DRAW_OFF);//繪圖顯示關閉
- for(i = 0; i < 2; i ++)//分上下兩屏寫
- {
- for(j = 0; j < 32; j ++)
- {
- write_com(0x80 + j);//寫y坐標
- delay(1);
- if(i == 0) //寫x坐標
- {
- write_com(0x80);
- delay(1);
- }
- else //寫下半屏
- {
- write_com(0x88);
- delay(1);
- }
- for(k = 0; k < 16; k ++)//寫一整行數據
- {
- write_dat(0x00);//寫高字節
- write_dat(0x00);//寫低字節
- delay(1);
- }
-
- }
- }
- write_com(DRAW_ON);//打開繪圖顯示
- write_com(BASIC_SET);//打開基本指令集
- }
- //(給定坐標并打點的)任意位置打點函數
- void lcd_set_dot(uchar x,uchar y)
- {
- uchar x_byte,x_bit; //確定在坐標的那一字節哪一位
- uchar y_ping , y_bit; //確定在坐標的哪一屏哪一行
- uchar tmph , tmpl; //定義兩個臨時變量,用于存放讀出來的數據
- write_com(EXTEND_SET); //擴展指令集
- write_com(DRAW_OFF); //繪圖顯示關閉
- x_byte = x / 16; //算出在哪一字節,注意一個地址是16位的
- x_bit = x % 16; //& 0x0f;//算出在哪一位
- y_ping = y / 32; //確定在上半屏還是下半屏,0代表上半屏,1代表下半屏
- y_bit = y % 32; //& 0x1f;//確定在第幾行
- write_com(0X80 + y_bit);//先寫垂直地址(最高位必須)
- write_com(0x80 + x_byte + 8 * y_ping);//水平坐標,下半屏坐標起始地址為0x88,(+8*y_ping)就是用來確定上半屏還是下半屏
- read_dat();//預讀取數據
- tmph = read_dat();//讀取當前顯示高8位數據
- tmpl = read_dat();//讀取當前顯示低8位數據
- delay(1);
- write_com(0x80 + y_bit);//讀操作會改變AC,所以重新設置一下
- write_com(0x80 + x_byte + 8 * y_ping);
- delay(1);
- if(x_bit < 8)
- {
- write_dat(tmph | (0x01 << (7 - x_bit)));//寫高字節,因為坐標是從左向右的,GDRAM高位在昨,低位在右
- write_dat(tmpl);//原低位數據送回
- }
- else
- {
- write_dat(tmph);//原高位數據送回
- write_dat(tmpl | (0x01 << (15 - x_bit)));
- }
- write_com(DRAW_ON); //打開繪圖顯示
- write_com(BASIC_SET);//回到基本指令集
- }
- //畫水平線函數
- //x0、x1為起始點和終點的水平坐標,y為垂直坐標
- //**********************************************************
- void gui_hline(uchar x0, uchar x1, uchar y)
- {
- uchar bak;//用于對兩個數互換的中間變量,使x1為大值
- if(x0 > x1)
- {
- bak = x1;
- x1 = x0;
- x0 = bak;
- }
- do
- {
- lcd_set_dot(x0 , y);//從左到右逐點顯示
- x0 ++;
- }
- while(x1 >= x0);
- }
- //***********畫豎直線函數***********************************//
- //x為起始點和終點的水平坐標,y0、y1為垂直坐標***************//
- //**********************************************************//
- void gui_rline(uchar x, uchar y0, uchar y1)
- {
- uchar bak;//用于對兩個數互換的中間變量,使y1為大值
- if(y0 > y1)
- {
- bak = y1;
- y1 = y0;
- y0 = bak;
- }
- do
- {
- lcd_set_dot(x , y0);//從上到下逐點顯示
- y0++;
-
- }
- while(y1 >= y0);
- }
- //*********任意兩點間畫直線*********************************//
- //x0、y0為起始點坐標,x1、y1為終點坐標**********************//
- //**********************************************************//
- void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1)
- {
- char dx; //直線x軸差值
- char dy; //直線y軸差值
- char dx_sym; //x軸增長方向,為-1時減值方向,為1時增值方向
- char dy_sym; //y軸增長方向,為-1時減值方向,為1時增值方向
- char dx_x2; //dx*2值變量,用于加快運算速度
- char dy_x2; //dy*2值變量,用于加快運算速度
- char di; //決策變量
- if(x0 == x1)//判斷是否為垂直線
- {
- gui_rline(x0 , y0 , y1);//畫垂直線
- return;
- }
- if(y0 == y1)//判斷是否為水平線
- {
- gui_hline(x0 , x1 , y0);//畫水平線
- return;
- }
- dx = x1 - x0;//求取兩點之間的差值
- dy = y1 - y0;//****判斷增長方向,或是否為水平線、垂直線、點*//
- if(dx > 0)//判斷x軸方向
- dx_sym = 1;
- else
- {
- if(dx < 0)
- dx_sym = -1;
- else
- {
- gui_rline(x0 , y0 , y1);
- return;
- }
- }
- if(dy > 0)//判斷y軸方向
- dy_sym = 1;
- else
- {
- if(dy < 0)
- dy_sym = -1;
- else
- {
- gui_hline(x0 , x1 , y0);
- return;
- }
- }
- /*將dx、dy取絕對值***********/
- dx = dx_sym * dx;
- dy = dy_sym * dy;
- /****計算2倍的dx、dy值*******/
- dx_x2 = dx * 1;//我改為了一倍,這樣才跟真實的兩點對應
- dy_x2 = dy * 1; /***使用bresenham法進行畫直線***/
- if(dx >= dy)//對于dx>=dy,使用x軸為基準
- {
- di = dy_x2 - dx;
- while(x0 != x1)
- {
- lcd_set_dot(x0,y0);
- x0 +=dx_sym;
- if(di < 0)
- di += dy_x2;//計算出下一步的決策值
- else
- {
- di += dy_x2 - dx_x2;
- y0 += dy_sym;
- }
- }
- lcd_set_dot(x0, y0);//顯示最后一點
- }
- else //對于dx<dy使用y軸為基準
- {
- di = dx_x2 - dy;
- while(y0 != y1)
- {
- lcd_set_dot(x0, y0);
- y0 += dy_sym;
- if(di < 0)
- di += dx_x2;
- else
- {
- di += dx_x2 - dy_x2;
- x0 += dx_sym;
- }
- }
- lcd_set_dot(x0, y0);//顯示最后一點
- }
- }
- //以上為自定義字庫部分
- //****************12864初始化函數
- void lcd_init()
- {
- write_com(0x30);//基本指令操作,8位并口
- delay(1);
- write_com(0x0c);//設置為游標右移,DDRAM地址加一,畫面不動
- delay(1);
- write_com(0x01);//顯示開,關光標
- delay(1);
- write_com(0x06);//清除lcd顯示內容
- delay(1);
- } //5ms延時
- void Delay5Ms(void)
- {
- unsigned int TempCyc = 5552;
- while(TempCyc--);
- }
- //400ms延時
- void Delay400Ms(void)
- {
- unsigned char TempCycA = 5;
- unsigned int TempCycB;
- while(TempCycA--)
- {
- TempCycB=7269;
- while(TempCycB--);
- };
- }
- /*************DS18B20溫度讀取模塊*************/
- void delay_nus(unsigned char n)
- {
- while(n--)
- {
- _nop_();
- _nop_();
- }
- }
- bit ds18b20_reset(void)
- {
- CY = 1;
- while(CY)
- {
- DQ = 0; //送低電平復位信號
- delay_nus(240); //至少延時480us
- delay_nus(240);
- DQ = 1; //釋放數據線
- delay_nus(60); //等待60us
- CY = DQ; //檢測存在脈沖
- delay_nus(240); //等待設備釋放數據線
- delay_nus(180);
- }
- return 1;
- }
- unsigned char ds18b20_readbyte(void)
- {
- unsigned char i;
- unsigned char dat = 0;
- for(i=0;i<8;i++)
- {
- dat >>= 1;
- DQ = 0; //開始時間片
- delay_nus(1); //延時等待
- DQ = 1; //準備接收
- delay_nus(1); //延時
- if(DQ) dat |= 0x80; //讀取數據
- delay_nus(60); //等待時間片結束
- }
- return dat;
- }
- void ds18b20_writebyte(unsigned char dat)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- DQ = 0;
- delay_nus(1);
- dat >>= 1;
- DQ = CY;
- delay_nus(60);
- DQ = 1;
- delay_nus(1);
- }
- }
- void read_temp(void)
- {
- if(ds18b20_reset())
- {
- ds18b20_writebyte(0xcc);
- ds18b20_writebyte(0x44);
- if(ds18b20_reset())
- {
- ds18b20_writebyte(0xcc);
- ds18b20_writebyte(0xbe);
- temperature = ds18b20_readbyte(); //讀溫度整數值
- temperature = (ds18b20_readbyte() << 8) + temperature;
- temp_x = (unsigned char)(temperature & 0x000f); //讀溫度小數值
- temp_x = (unsigned char)(((unsigned int)temp_x * 625) / 1000);
- temperature >>= 4;
- temp_disp = temperature * 10 + temp_x;
- }
- }
- }
- //*****************************顯示函數
- void display()
- {
- uint num;
- uint shi,ge,xiaoshu;
- num=temp_disp;
- shi=num/100;
- ge=num/10%10;
- xiaoshu=num%10;
- if(k==100)
- {
- ++i;
- k=0;
- if(i>127)
- {
- i=0;
- a=0;
- b=0;
- gui_clear();//畫圖時清屏函數
- gui_line(0,15,0,63);
- gui_line(0,63,127,63);
- }
- gui_line(a,63-b,i,63-shi*10-ge);
- b=shi*10+ge;
- a=i;
- }
- write_com(0x82);
- write_dat(t1[shi]);
- write_dat(t1[ge]);
- write_com(0x84);
- write_dat(t1[xiaoshu]);
- }
- void init_time0()
- {
- TMOD |= 0x10;
- TH1=(65536-50000)/256; //50毫秒
- TL1=(65536-50000)%256;
- EA=1;
- ET1=1;
- TR1=1;
- }
-
-
- void main()
- {
- init_time0(); //中斷
- lcd_init();//12864初始化函數
- gui_clear();//畫圖時清屏函數
- delay(10);
- display_string(0,0,t0);
- gui_line(0,15,0,63);
- gui_line(0,63,127,63);
-
- while(1)
- {
- display();read_temp();
- }
- }
- void time0() interrupt 3
- {
- TH1=(65536-50000)/256; //,50毫秒
- TL1=(65536-50000)%256;
- k++;
- }
復制代碼 |
-
-
12864溫度有線.rar
2019-6-28 17:06 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
109.3 KB, 下載次數: 46, 下載積分: 黑幣 -5
51單片機溫度顯示曲線
|