18B20測溫恐怕是高手玩膩了的玩意,對我這個剛學單片機的中年人來說,卻是個很大的挑戰。
起因是想做一個在屋內就能測出室外溫度的想法,走走停停弄了好幾個月,有一天兒子說學校要交科技作品,難為我了,一個小學生要什么科技作品?沒辦法把這個測溫的東西交上去應付一下過關。用了兩周的時間。不多說上圖:
實測一下
液晶屏是拆機件
實測一下
液晶屏用的是拆機件
右面是成品
右面是用茶葉盒做出來的成品
單片機程序:
- /************************************************
- 程序名稱:溫度測量裝置20160107調試成功
- 程序功能:用串行方式訪問12232液晶顯示器
- DS18B20溫度測量,帶斷線報警
- ************************************************/
- #include<reg52.h>
- #include < intrins.h >
- #define uint unsigned int
- #define uchar unsigned char
- sbit CS=P1^2;
- sbit SID=P1^1;
- sbit SCLK=P1^0; //定義12232液晶端口線
- sbit DQ = P2^7 ; //定義DS18B20端口DQ
- sbit BEEP=P2^1 ; //蜂鳴器驅動線
- bit presence ;
- uchar code disps[]={" 溫 度 "};
- uchar code dispx[]={"."};
- uchar code dispy[]={"℃"};
- uchar code cdis3[]={"傳感器錯誤!"} ;
- uchar code cdis4[]={"請檢查線路!"} ;
- unsigned char data temp_data[2] = {0x00,0x00} ;
- unsigned char data display[5] = {0x00,0x00,0x00,0x00,0x00} ;
- unsigned char code ditab[16] = {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
- 0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09} ;
- void beep() ;
- unsigned char code mytab[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00} ;
- #define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
- /*******************************************************************/
- /*us級延時函數 18B20使用 */
- /*******************************************************************/
- void Delay(unsigned int num)
- {
- while( --num ) ;
- }
- /*******************************************************************/
- /*初始化ds1820 */
- /*******************************************************************/
- Init_DS18B20(void)
- {
- DQ = 1 ; //DQ復位
- Delay(8) ; //稍做延時
- DQ = 0 ; //單片機將DQ拉低
- Delay(90) ; //精確延時 大于 480us
- DQ = 1 ; //拉高總線
- Delay(8) ;
- presence = DQ ; //如果=0則初始化成功 =1則初始化失敗
- Delay(100) ;
- DQ = 1 ;
- return(presence) ; //返回信號,0=presence,1= no presence
- }
- /*******************************************************************/
- /* 讀一個字節 ds1820 */
- /*******************************************************************/
- ReadOneChar(void)
- {
- unsigned char i = 0 ;
- unsigned char dat = 0 ;
- for (i = 8 ; i > 0 ; i--)
- {
- DQ = 0 ; // 給脈沖信號
- dat >>= 1 ;
- DQ = 1 ; // 給脈沖信號
- if(DQ)
- dat |= 0x80 ;
- Delay(4) ;
- }
- return (dat) ;
- }
- /*******************************************************************/
- /* 寫一個字節 ds1820 */
- /*******************************************************************/
- WriteOneChar(unsigned char dat)
- {
- unsigned char i = 0 ;
- for (i = 8 ; i > 0 ; i--)
- {
- DQ = 0 ;
- DQ = dat&0x01 ;
- Delay(5) ;
- DQ = 1 ;
- dat>>=1 ;
- }
- }
- /*******************************************************************/
- /* 蜂鳴器響一聲 */
- /*******************************************************************/
- void beep()
- {
- unsigned char y ;
- for (y=0 ;y<100 ;y++)
- {
- Delay(60) ;
- BEEP=!BEEP ; //BEEP取反
- }
- BEEP=1 ; //關閉蜂鳴器
- Delay(40000) ;
- }
- /*******************************************************************/
- /* 讀取溫度 18B20 */
- /*******************************************************************/
- Read_Temperature(void)
- {
- Init_DS18B20() ;
- WriteOneChar(0xCC) ; // 跳過讀序號列號的操作
- WriteOneChar(0x44) ; // 啟動溫度轉換
- Init_DS18B20() ;
- WriteOneChar(0xCC) ; //跳過讀序號列號的操作
- WriteOneChar(0xBE) ; //讀取溫度寄存器
- temp_data[0] = ReadOneChar() ; //溫度低8位
- temp_data[1] = ReadOneChar() ; //溫度高8位
- }
- /************************************************
- 函數名稱:void delay_1ms(uint x)
- 函數功能:延時xms
- ************************************************/
- void delay_1ms(uint x)
- {
- uint i,j;
- for(j=0;j<x;j++)
- for(i=0;i<110;i++);
- }
- /***********************************************
- 函數名稱:void send_command(uchar command_data)
- 函數功能:寫指令,分兩次寫,先寫高4 位,后寫低 4 位。
- ************************************************/
- void send_command(uchar command_data)
- {
- uchar i,i_data;
- i_data=0xf8;//寫指令控制字
- CS=1;
- SCLK=0;
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0x80);//高位在前,低位在后
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- i_data=command_data;
- i_data&=0xf0;//指令高4 位,低 4 位置0
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0x80); //高位在前,低位在后
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- i_data=command_data;
- i_data<<=4;
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0X80);
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- CS=0;
- delay_1ms(10);
- }
- /*********************************************************
- 函數名稱:void send_data(uchar command_data)
- 函數功能:寫數據,分兩次寫,先寫高4 位,后寫低 4 位。
- *********************************************************/
- void send_data(uchar command_data)
- {
- uchar i,i_data;
- i_data=0xfa;//寫數據控制字
- CS=1;
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0x80);//高位在前,低位在后
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- i_data=command_data;
- i_data&=0xf0;//數據高4 位,低 4 位置0
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0x80);
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- i_data=command_data;
- i_data<<=4;//數據低4 位,其余置 0
- for(i=0;i<8;i++)
- {
- SID=(bit)(i_data&0x80);
- SCLK=0;
- SCLK=1;
- i_data=i_data<<1;
- }
- CS=0;
- delay_1ms(10);
- }
- /*******************************************************
- 函數名稱:void lcd_init()
- 函數功能:初始化12232LCD 顯示器
- *******************************************************/
- void lcd_init()
- {
- delay_1ms(100);
- send_command(0x30);//設置 8 位數據接口,基本指令模式
- send_command(0x02);//清DDRAM
- send_command(0x06);//游標及顯示右移一位
- send_command(0x0c);//整體顯示開,游標關,反白關
- send_command(0x01);//寫入空格清屏幕
- send_command(0x80);//設定首次顯示位置
- }
- /*******************************************************
- 函數名稱:void display_s()
- 函數功能:在LCD第一行寫入數據
- *******************************************************/
- void display_s()
- {
- uchar a;
- send_command(0x80);//第一行的首地址寫入數據
- for(a=0;a<15;a++)
- {
- send_data(disps[a]);
- }
- }
- /*******************************************************
- 函數名稱:void display_e()
- 函數功能:在LCD第一行寫入數據
- *******************************************************/
- void display_e()
- {
- uchar a,b;
- send_command(0x80);//第一行的首地址寫入數據
- for(a=0;a<11;a++)
- {
- send_data(cdis3[a]);
- }
- send_command(0x90);//第一行的首地址寫入數據
- for(b=0;b<11;b++)
- {
- send_data(cdis4[b]);
- }
- }
- /*******************************************************************/
- /* DS18B20 ERROR 顯示菜單 */
- /*******************************************************************/
- void Error_Menu ()
- {
- lcd_init();
- display_e() ;
-
- }
- /*******************************************************************/
- /* 數據轉換與溫度顯示 */
- /*******************************************************************/
- Disp_Temperature()
- {
- uchar a;
- display[4]=temp_data[0]&0x0f ;
- display[0]=ditab[display[4]]+0x30 ; //查表得小數位的值
- display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4) ;
- display[3]=display[4]/100+0x30 ;
- display[1]=display[4]%100 ;
- display[2]=display[1]/10+0x30 ;
- display[1]=display[1]%10+0x30 ;
- if(display[3]==0x30) //高位為0,不顯示
- {
- display[3]=0x20 ;
- if(display[2]==0x30) //次高位為0,不顯示
- display[2]=0x20 ;
- }
-
- send_command(0x91);//顯示百位
- send_data(display[3]);
- send_command(0x92);//顯示十位
- send_data(display[2]);
-
- send_command(0x93);//顯示各位
- send_data(display[1]);
-
- send_command(0x94);//顯示小數點
- send_data(dispx[0]);
-
- send_command(0x95);//顯示小數點后一位
- send_data(display[0]);
-
- send_command(0x96);//顯示溫度符號
- for(a=0;a<2;a++)
- {
- send_data(dispy[a]);
- }
-
-
- }
- /******************************************************
- 函數名稱:void main()
- 函數功能:主函數,實現題目要求
- ******************************************************/
- void main()
- {
- lcd_init();
- display_s();
- do
- {
- Read_Temperature() ;
- Disp_Temperature() ;
- }
- while(!presence) ;
- Error_Menu () ;
- do
- {
- Init_DS18B20() ;
- beep() ;
- }
- while(presence) ;
- }
復制代碼
|