TB來的二手溫控器,加裝液晶屏之旅。
制作出來的實物圖如下:
說明:
單片機源程序如下:
- #include <reg52.h>
- #include <INTRINS.H>
- #include <stdio.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /* ***************************************************** */
- // 起別名定義
- /* ***************************************************** */
- typedef unsigned char uChar8;
- typedef unsigned int uInt16;
- typedef enum{FALSE,TRUE} BOOL;
- /* ***************************************************** */
- // 宏定義
- /* ***************************************************** */
- #define LM75ADevIDAddr 0x90
- #define IIC_WRITE 0x00
- #define IIC_READ 0x01
- /* ***************************************************** */
- // 位定義
- /* ***************************************************** */
- sbit SCL = P2^1;//
- sbit SDA = P2^0;
- long int LM75WD;
- /* ***************************************************** */
- // 全局變量定義
- /* ***************************************************** */
- bit p_bH0L_Flag; // 溫度"0"上、下標志位
- float p_fLM75ATemp; // 溫度值
-
- /* ***************************************************** */
- // 函數名稱:Delay5US()
- // 函數功能:微秒延時
- // 入口參數:延時微秒數(ValUS)
- // 出口參數:無
- /* ***************************************************** */
- void Delay5US(void)
- {
- _nop_();_nop_();_nop_();_nop_();
- }
- /* ***************************************************** */
- // 函數名稱:DelayMS()
- // 函數功能:毫秒延時
- // 入口參數:延時毫秒數(ValMS)
- // 出口參數:無
- /* ***************************************************** */
- void DelayMS(uInt16 ValMS)
- {
- uInt16 uiVal,ujVal;
- for(uiVal = 0; uiVal < ValMS; uiVal++)
- for(ujVal = 0; ujVal < 120; ujVal++);
- }
-
- /* ***************************************************** */
- // 函數名稱:IIC_Start()
- // 函數功能:IIC起動
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void IIC_Start(void)
- {
- SDA = 1;
- Delay5US();
- SCL = 1;
- Delay5US();
- SDA = 0;
- Delay5US();
- }
- /* ***************************************************** */
- // 函數名稱:IIC_Stop()
- // 函數功能:IIC停止
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void IIC_Stop(void)
- {
- SDA = 0;
- Delay5US();
- SCL = 1;
- Delay5US();
- SDA =1;
- }
- /* ***************************************************** */
- // 函數名稱:IIC_Ack()
- // 函數功能:IIC應答
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void IIC_Ack(void)
- {
- SCL = 0; // 為產生脈沖準備
- SDA = 0; // 產生應答信號
- Delay5US(); // 延時你懂得
- SCL = 1;Delay5US();
- SCL = 0;Delay5US(); // 產生高脈沖
- SDA = 1; // 釋放總線
- }
- /* ***************************************************** */
- // 函數名稱:IIC_RdAck()
- // 函數功能:讀IIC應答
- // 入口參數:無
- // 出口參數:是否應答真值
- /* ***************************************************** */
- BOOL IIC_RdAck(void)
- {
- BOOL AckFlag;
- uChar8 uiVal = 0;
- SCL = 0;Delay5US();
- SDA = 1;
- SCL = 1;Delay5US();
- while((1 == SDA) && (uiVal < 255))
- {
- uiVal ++;
- AckFlag = SDA;
- }
- SCL = 0;
- return AckFlag; // 應答返回:0;不應答返回:1
- }
- /* ***************************************************** */
- // 函數名稱:IIC_Nack()
- // 函數功能:IIC不應答
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void IIC_Nack(void)
- {
- SDA = 1;
- SCL = 0;Delay5US();
- SCL = 1;Delay5US();
- SCL = 0;
- }
- /* ***************************************************** */
- // 函數名稱:OutputOneByte()
- // 函數功能:從IIC器件中讀出一個字節
- // 入口參數:無
- // 出口參數:讀出的一個字節(uByteVal)
- /* ***************************************************** */
- uChar8 OutputOneByte(void)
- {
- uChar8 uByteVal = 0;
- uChar8 iCount;
- SDA = 1;
- for (iCount = 0;iCount < 8;iCount++)
- {
- SCL = 0;
- Delay5US();
- SCL = 1;
- Delay5US();
- uByteVal <<= 1;
- if(SDA)
- uByteVal |= 0x01;
- }
- SCL = 0;
- return(uByteVal);
- }
- /* ***************************************************** */
- // 函數名稱:InputOneByte()
- // 函數功能:向IIC器件寫入一個字節
- // 入口參數:待寫入的一個字節(uByteVal)
- // 出口參數:無
- /* ***************************************************** */
- void InputOneByte(uChar8 uByteVal)
- {
- uChar8 iCount;
- for(iCount = 0;iCount < 8;iCount++)
- {
- SCL = 0;
- Delay5US();
- SDA = (uByteVal & 0x80) >> 7;
- Delay5US();
- SCL = 1;
- Delay5US();
- uByteVal <<= 1;
- }
- SCL = 0;
- }
- /* ***************************************************** */
- // 函數名稱:IIC_WrDevAddAndDatAdd()
- // 函數功能:向IIC器件寫入器件和數據地址
- // 入口參數:器件地址(uDevAdd),數據地址(uDatAdd)
- // 出口參數:寫入是否成功真值
- /* ***************************************************** */
- BOOL IIC_WrDevAddAndDatAdd(uChar8 uDevAdd,uChar8 uDatAdd)
- {
- IIC_Start(); // 發送開始信號
- InputOneByte(uDevAdd); // 輸入器件地址
- IIC_RdAck(); // 讀應答信號
- InputOneByte(uDatAdd); // 輸入數據地址
- IIC_RdAck(); // 讀應答信號
- return TRUE;
- }
- /* ***************************************************** */
- // 函數名稱:IIC_RdDatFromAdd()
- // 函數功能:向IIC器件讀數據
- // 入口參數:器件ID(uDevID)、數據存儲地址(uStaAddVal)
- // 待存數據(*p)、連續存儲數據的個數(uiLenVal)
- // 出口參數:無
- /* ***************************************************** */
- void IIC_RdDatFromAdd(uChar8 uDevID, uChar8 uStaAddVal, uChar8 *p, uChar8 uiLenVal)
- {
- uChar8 iCount;
- IIC_WrDevAddAndDatAdd(uDevID | IIC_WRITE,uStaAddVal);
- IIC_Start();
- InputOneByte(uDevID | IIC_READ);
- // IIC_READ 為寫命令后綴符
- IIC_RdAck();
- for(iCount = 0;iCount < uiLenVal;iCount++)
- {
- *p++ = OutputOneByte();
- if(iCount != (uiLenVal - 1))
- IIC_Ack();
- }
- IIC_Nack();
- IIC_Stop();
- }
- /* ***************************************************** */
- // 函數名稱:LM75A_ReadReg()
- // 函數功能:讀LM75A任意寄存器值
- // 入口參數:寄存器地址(addr),uLenVal,讀出字節的長度
- // 出口參數:寄存器內容(*val)
- /* ***************************************************** */
- void LM75A_ReadReg(uChar8 addr, uChar8 *val, uChar8 uLenVal)
- {
- IIC_RdDatFromAdd(LM75ADevIDAddr, addr, val, uLenVal);
- }
- /* ***************************************************** */
- // 函數名稱:LM75A_TempConv()
- // 函數功能:溫度轉換
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void LM75A_TempConv(void)
- {
- uChar8 TempML[2]={0}; // 臨時數值,用于存放Temp的高低字節
- uInt16 uiTemp; // 用于存放Temp的11位字節數據
- LM75A_ReadReg(0x00,TempML,2); // 讀出溫度,并存于數組TempHL中
- uiTemp = (uInt16)TempML[0]; // 將高字節存入變量uiTemp中
- uiTemp = (uiTemp << 8 | TempML[1]) >> 5; // 接著并入后3位,最后右移5位就是11位補碼數(8+3共11位)
- /* ***** 首先判斷溫度是“0上”還是是“0下” ***** */
- if(!(TempML[0] & 0x80)) // 最高位為“0”則為“0上”
- {
- p_bH0L_Flag = 0;
- p_fLM75ATemp = uiTemp * 0.125;
- }
- else // 這時為“0下”(p_fLM75ATemp)℃
- {
- p_bH0L_Flag = 1;
- p_fLM75ATemp = (0x800 - uiTemp) * 0.125;// 由于計算機中負數是以補碼形式存的,所以有這樣的算法。
- }
- }
- /* ***************************************************** */
- // 函數名稱:UART_Init()
- // 函數功能:串口初始化
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void UART_Init(void)
- {
- TMOD &= 0x0f; // 清空定時器1
- TMOD |= 0x20; // 定時器1工作于方式2
- TH1 = 0xfd; // 為定時器1賦初值
- TL1 = 0xfd; // 等價于將波特率設置為9600
- ET1 = 0; // 防止中斷產生不必要的干擾
- TR1 = 1; // 啟動定時器1
- SCON |= 0x40; // 串口工作于方式1,不允許接收
- }
- /***************************功能定義***************************/
- #define LCD12864_W_COM 0xF8 //寫指令
- #define LCD12864_R_COM 0xFC //讀指令
- #define LCD12864_W_DAT 0xFA //寫數據
- #define LCD12864_R_DAT 0xFE //讀數據
- #ifndef __LCD12864_H__
- #define __LCD12864_H__
- #define LCD12864_COM 0 //輸入指令
- #define LCD12864_DAT 1 //輸入數據
- #define LCD12864_CLEAR 0x01 //清除顯示
- #define LCD12864_CURSOR 0x02 //位址歸位,游標回原點
- #define LCD12864_CURSOR_RLF 0x04 //光標左移,整體顯示不移動
- #define LCD12864_CURSOR_RRF 0x06 //光標右移,整體顯示不移動
- #define LCD12864_CURSOR_RLN 0x05 //光標左移,整體顯示移動
- #define LCD12864_CURSOR_RRN 0x07 //光標右移,整體顯示移動
- #define LCD12864_DIS_OFF 0x08 //顯示狀態全關
- #define LCD12864_DIS_ON 0x0E //顯示狀態開
- #define LCD12864_DIS_CUR_ON 0x0E //游標顯示開
- #define LCD12864_DIS_CURS_ON 0x0F //游標位置顯示開
- #define LCD12864_CURSOR_RL 0x10 //游標左移
- #define LCD12864_CURSOR_RR 0x14 //游標右移
- #define LCD12864_CURDIS_RL 0x18 //整體顯示左移,光標跟隨
- #define LCD12864_CURDIS_RR 0x1C //整體顯示又移,光標跟隨
- #define LCD12864_COM_BASIC 0x30 //基本指令集動作
- #define LCD12864_COM_PLOT_ON 0x36 //擴展指令集動作,繪圖顯示ON
- #define LCD12864_COM_PLOT_OFF 0x34 //擴展指令集動作,繪圖顯示OFF
- #define LCD12864_STAND_TO 0x31 //進入待命模式
- #define LCD12864_PLACE_ROLL 0x03 //允許輸入卷動位址
- #define LCD12864_PLACE_IRAM 0x02 //允許輸入IRAM位址
- #define LCD12864_REVERES_13 0x04 //選擇一、三行同時作反白顯示
- #define LCD12864_REVERES_24 0x05 //選擇二、四行同時作反白顯示
- #define LCD12864_REST_ON 0x08 //進入睡眠模式
- #define LCD12864_REST_OFF 0x0C //脫離睡眠模式
- #define LCD12864_W_COM 0xF8 //寫指令
- #define LCD12864_R_COM 0xFC //讀指令
- #define LCD12864_W_DAT 0xFA //寫數據
- #define LCD12864_R_DAT 0xFE //讀數據
- //======串口模式=======
- sbit LCD12864_CS = P2^7; //片選信號輸入
- sbit LCD12864_STD = P2^6; //串行數據輸入
- sbit LCD12864_SCLK = P2^5; //串行移位脈沖輸入
- sbit LCD12864_PSB = P2^4; //串并模式選擇 0:串口,1:并口
- sbit LCDRST = P2^3;
- unsigned char code tabe[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//查表法//0-9數字
- /*****************************向12864寫入8位數據*************************************/
- void LCD12864_Wbyte(uchar byte)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- LCD12864_SCLK = 0;
- byte <<= 1; //左移待寫入數據,使最高位移至CY
- LCD12864_STD = CY; //寫入一位數據
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- }
- }
- /***************************從12864讀出8位數據***返回:sdat************************************/
- uchar LCD12864_Rbyte(void)
- {
- uchar i,sdat,temp1,temp2;
- temp1 = 0;
- temp2 = 0;
- //==========12864的串行數據輸出形式是D7-D6-D5-D4-0-0-0-0-D3-D2-D1-D0-0-0-0-0,故要度兩個八位整合==============
- for(i=0;i<8;i++)
- {
- temp1=temp1 << 1;
- LCD12864_SCLK = 0;
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- if( LCD12864_STD ) temp1|=0x01; //tempe1:D7-D6-D5-D4-0-0-0-0
- }
- for(i=0;i<8;i++)
- {
- temp2=temp2 << 1;
- LCD12864_SCLK = 0;
- LCD12864_SCLK = 1;
- LCD12864_SCLK = 0;
- if( LCD12864_STD ) temp2|=0x01; //tempe2:D3-D2-D1-D0-0-0-0-0
- }
- sdat = ((temp1 & 0xf0)|(temp2 >> 4)); //取出D7\D6\D5\D4\D3\D2\D1\D0
- return sdat; //返回一個值(sdat)
- }
- /****************************讀忙狀態**************************************/
- void LCD12864_busy( void )
- {
- do LCD12864_Wbyte( LCD12864_R_COM ); //LCD12864_RW=11111,RW(1),RS(0),0
- while( LCD12864_Rbyte() & 0x80 ); //讀BF,直到BF == 0
- }
- /*************************dat_com=0寫指令,dat_com=1寫數據*****************************************/
- void LCD12864_W (bit dat_com,uchar byte)
- {
- uchar temp;
- if(dat_com == 0) //為零,寫入指令
- temp = LCD12864_W_COM; //11111,RS(0),RW(0),0
- else //否則,寫入數據
- temp = LCD12864_W_DAT; //11111,RS(1),RW(0),0
- LCD12864_CS = 1; //片選使能
- LCD12864_busy(); //LCD忙檢測
- LCD12864_Wbyte(temp); //寫入模式選擇,指令還是數據
- LCD12864_Wbyte(byte&0xf0); //寫入字節
- LCD12864_Wbyte((byte<<4)&0xf0); //寫入字節
- LCD12864_CS = 0; //片選關閉
- }
- /****************************LCD12864初始化**************************************/
- void LCD12864_Init(void)
- {
- LCDRST=1;
- LCD12864_PSB = 0; //選擇串口模式
- LCD12864_W(LCD12864_COM,0x30); //基本指令功能.
- LCD12864_W(LCD12864_COM,0x03); //允許輸入卷動位址
- LCD12864_W(LCD12864_COM,0x0c); //脫離隨眠狀態,顯示打開,關光標,反白關.
- LCD12864_W(LCD12864_COM,0x01); //清屏指令.
- LCD12864_W(LCD12864_COM,0x06); //AC自動加一,光標右移,整體顯示不移動
- }
- /**************************LCD12864字符位置自定義顯示****************************************/
- void LCD12864_WPoss(uchar x,uchar y,uchar *buff)
- {
- uchar addr,i=0;
- switch (x)
- {
- case 0:addr=0x80;break;
- case 1:addr=0x90;break;
- case 2:addr=0x88;break;
- case 3:addr=0x98;break;
- }
- addr=addr+y;
- LCD12864_W(LCD12864_COM,LCD12864_COM_BASIC); //8BitMCU,基本指令集合
- LCD12864_W(LCD12864_COM,addr); //顯示在自定義位置
- while(buff[i]!='\0')
- {
- LCD12864_W(LCD12864_DAT,buff[i++]);
- if(++y==16)
- {
- y=0;
- if(++x==4) x=0;
- switch (x)
- {
- case 0:addr=0x80;break;
- case 1:addr=0x90;break;
- case 2:addr=0x88;break;
- case 3:addr=0x98;break;
- }
- addr=addr+y;
- LCD12864_W(LCD12864_COM,addr);
- }
-
- }
- }
- void Disp_img(unsigned char *img) //圖形方式12864顯示字模221 橫向取膜
- {
- unsigned char i,j;
- unsigned int k = 0;
- LCD12864_W(0,0x36); //圖形方式
- for(i=0;i<32;i++)
- {
- LCD12864_W(0,0x80+i);
- LCD12864_W(0,0x80);
- for(j=0;j<16;j++)
- {
- LCD12864_W(1,img[k++]);
- }
- }
- for(i=0;i<32;i++)
- {
- LCD12864_W(0,0x80+i);
- LCD12864_W(0,0x88);
- for(j=0;j<16;j++)
- {
- LCD12864_W(1,img[k++]);
- }
- }
- }
- /************************顯示11************************************/
- void display1(long temp)
- {
- uchar dt1,dt2,dt3,dt4,dt5,dt6,dt7,dt8;
- //temp=12345678;
- dt1 = temp%10;//1位
- dt2 = temp%100/10;//2位
- dt3 = temp%1000/100;//3位
- dt4 = temp%10000/1000;//4位
- dt5 = temp%100000/10000;//5位
- dt6 = temp%1000000/100000;//6位
- dt7 = temp%10000000/1000000;//7位
- dt8 = temp/10000000;//8位 最高位
- LCD12864_WPoss(3,0,"溫度:");//第1行顯示表1
- // LCD12864_W(0,0x80+3);//LCD12864_W ((0或1),****) 0寫指令 1寫數據
- //LCD12864_W(1,tabe[dt8]);//6位
- //LCD12864_W(1,tabe[dt7]);//5位
- //LCD12864_W(1,tabe[dt6]);//4位
- LCD12864_W(1,tabe[dt5]);//3位
- LCD12864_W(1,tabe[dt4]);//4位
- LCD12864_W(1,0x2e);
- LCD12864_W(1,tabe[dt3]);//3位
- //LCD12864_W(1,tabe[dt2]);//4位
- //LCD12864_W(1,tabe[dt1]);//3位
- LCD12864_WPoss(3,5,"C");//第1行顯示表1
- LCD12864_WPoss(0,0," LM75A 溫度計");//第1行顯示表1
- LCD12864_WPoss(1,0,"IIC 地址:0X90 ");//第1行顯示表1
- LCD12864_WPoss(2,0," 傳感器:LM75A");//第1行顯示表1
- }
- /* ***************************************************** */
- // 函數名稱:main()
- // 函數功能:讀取LN75A溫度值,數碼管顯示并串口打印
- // 入口參數:無
- // 出口參數:無
- /* ***************************************************** */
- void main()
- {
-
- uChar8 i;
- UART_Init();
- LCD12864_Init();
- while(1)
- {
-
-
- LM75A_TempConv();//讀取溫度LM75A
- DelayMS(200);
-
- LM75WD = p_fLM75ATemp * 1000;// 將溫度全部轉換成整數,以便數碼管顯示
- display1(LM75WD);//顯示溫度 //Ok
-
-
- }
- }
復制代碼
所有資料51hei提供下載:
128顯STC89C LM75A溫度OK.zip
(55.38 KB, 下載次數: 50)
2018-11-23 02:20 上傳
點擊文件名下載附件
|