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) ;
- }
复制代码
|