- #include<reg51.h> //51单片机的头文件
- #define uchar unsigned char //宏定义,用uchar来代替unsigned char(无符号字符型变量,也即是无符号的8位变量),
- //宏定义的原因就是书写方便,宏定义后,uchar可直接用来定义变量
- #define uint unsigned int //原因同上,不过要注意,unsigned int为无符号的整型变量
- uint present; // 实际温度(扩大了10倍)
- uint setting=30; //设定值
- sbit led=P3^5; //sbit是用来管脚的。此处定义LED灯由P3.5口控制
- sbit buzzer=P3^6; //蜂鸣器由P3.6口控制
- sbit DS=P3^7; //读取温度引脚
- sbit NixieTube0_DIG1=P1^2; // 实际温度显示十位数字的数码管位选端
- sbit NixieTube0_DIG2=P1^3; //// 实际温度显示个位数字的数码管位选端
- sbit NixieTube1_DIG1=P1^4; //// 设定温度显示十位数字的数码管位选端
- sbit NixieTube1_DIG2=P1^5; //// 设定温度显示个位数字的数码管位选端
-
- sbit add=P1^0; //按键加
- sbit sub=P1^1; //按键减
- unsigned char code table[]={0x82,0xF3,0x4A,0x62,0x33,0x26,0x06,0xE3,0x02,0x22}; //数码管端码表,相当于显示缓冲区,依次是0——9.
- void delay(uint count) //延时函数,用来进行延时,应该是毫秒级延时
- {
- uint i;
- while(count) // count为函数的形参,当count为0时,跳出此处while循环
- {
- i=200;
- while(i>0) //
- i--; //此i--和while(i>0)可以看成是一个整体,当i=0时,就会跳出,执行count--。
- count--; //count自减一次,i就会由200减到0
- }
- }
- /***********************************************************
- void initialize(void)//初始化函数
- 温度传感器采用的是DS18b20,此传感器采用的
- 是“单总线”来传输数据。
- 在使用DS18b20时,要对其进行初始化操作,其初始化的要求是(根据DS18b20的时序图得):
- (1)先将数据线置1,但是置1的时间要尽可能短(可以直接忽略此操作,因为51单片机引脚上电默认就是高电平。)。
- (2)将数据线(DS)拉低
- (3)延时750us左右
- (4)再将数据线(DS)拉高
- (5)进行短暂延时
- *****************************************************************/
- void initialize(void) //初始化
- {
-
- uint i;
- DS=0; //将DS(P3.7)引脚拉低。请注意,这里的DS不是变量,而是单片机的引脚!!!
- i=103;
- while(i>0)i--; //延时
- DS=1; //将DS拉高
- i=4;
- while(i>0)i--; //短暂延时
- }
- /*************************************************************************************
- 说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。
- 函数作用:bit tmpreadbit(void) //温度读取函数,此处读取的是温度的1个bit,带返回值
- 函数使用举例:A=tmpreadbit(); // 变量A保存的只是温度的一个bit
- DS18B20温度读取时序用单片机来实现的步骤如下:
- (1) 数据线DS拉低
- (2) 延时6us左右
- (3)将数据线DS拉高
- (4)延时4us左右
- (5) 此时DS便会得到一个状态位,即1个Bit的数据
- (6)延时30us左右
- **************************************************************************************/
- bit tmpreadbit(void) //温度读取函数,此处读取的是温度的1个bit.带返回值
- {
- uint i;
- bit dat;
- DS=0;i++; //将数据线拉低并延时
- DS=1;i++;i++; //将数据线拉高并延时
- dat=DS; //读取1个bit数据,此处注意,DS变成了输入引脚,DS18b20的数据会保存到局部变量dat中
- i=8;while(i>0)i--; //延时
- return (dat); //将读取的数据返回
- }
- /***********************************************************************************************
- 说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。温度一共8个bit,此函数共读了8次
- 函数作用:uchar tmpread(void) //温度读取函数,此处读取的是温度数据的原始数据,带返回值
- 函数使用举例:A=tmpread(); // 变量A保存的是温度的原始数据
- *************************************************************************************************/
- uchar tmpread(void)
- {
- uchar i,j,dat;
- dat=0;
- for(i=1;i<=8;i++) //采用for 循环,读取原始温度数据
- {
- j=tmpreadbit(); //读取一个位
- dat=(j<<7)|(dat>>1);//读取的温度最低位在前,这样刚好一个字节的温度在dat中
- }
- return(dat); //将温度数据返回
- }
-
- void tmpwritebyte(uchar dat) // 写指令函数, dat为形参。
- {
- uint i;
- uchar j;
- bit testb;
- for(j=1;j<=8;j++) //for循环,8次,刚好写一个字节
- {
- testb=dat&0x01; //将形参的最低位与1相与,1&1=1,0&1=0;
- dat=dat>>1; //执行完testb=dat&0x01;把传入的形参右移一位,方便判断下一位数据是0还是1,共移位8次,保证写入一个字节
- if(testb) //write 1
- {
- DS=0;
- i++;i++;
- DS=1; //DS=1的延时比较长,写入的就是1
- i=8;while(i>0)i--;
- }
- else
- {
- DS=0; //write 0
- i=8;while(i>0)i--; //DS=0的延时比较长,写入的就是0
- DS=1;
- i++;i++;
- }
- }
- }
- void tmpchange(void) //温度转换函数,
- {
- initialize(); //初始
- delay(1);
- tmpwritebyte(0xcc); //跳过读ROM指令
- tmpwritebyte(0x44); //告诉DS18b20转换温度
- }
- uint tmp() //转换函数,将原始数据转化成实际的温度数据
- {
- float tt;
- uchar a,b;
- initialize(); //初始化
- delay(1); //延时
- tmpwritebyte(0xcc);//跳过读ROM指令
- tmpwritebyte(0xbe); //读温度指令
- a=tmpread(); // 低8位数据,即温度的小数部分
- b=tmpread(); //高8位,即温度的整数部分
- present=b;
- present<<=8; //将整数部分右移8位
- present=present|a; //将两个字节组合成一个字
- tt=present*0.0625; //分辨率是0.0625,即原始数据*分辨率=实际温度
- present=tt*10+0.5; //乘10表示小数点后面只取一位,+0.5是表示四舍五入
- return present; //返回实际温度
- }
- //用的是共阳极数码管,显示原理采用的是动态显示
- void display0(uint temp) //温度显示函数 ,temp 为形参
- {
- uchar A1,A2,A2t;
- ////此处注意!因温度读取函数中 present=tt*10+0.5;即将温度扩大了10倍,所以原始温度的十位变成了百位,
- //各位变成了十位,十分位变成了个位,因此我们只需取百位上的数字和十位上的数字即可。注意,是数字,不是数!
- A1=temp/100; //取模,将百位数字取下,存到变量A1中,
- A2t=temp%100; //取余,比如传进来的temp=325,则325%100=25;
- A2=A2t/10; //将余数对10取模,比如 25/10=2;
-
- NixieTube0_DIG1=1; //打开数码管位选端
- if(A1<=9|A1>=0) //判断A1是否位一位数字,实际温度的十位上的数字
- P2=table[A1]; //送入显示
- delay(1); //延时,待显示稳定
- NixieTube0_DIG1=0; // 关断数码管
- NixieTube0_DIG2=1; //打开数码管位选端
- if(A2<=9|A2>=0) //判断A2是否位一位数字,实际温度的个位上的数字
- P2=table[A2]; //送入显示
- delay(1); //延时,待显示稳定
- NixieTube0_DIG2=0; // 关断数码管
-
- }
- void display1(uint spare) //设定温度显示
- {
- uchar B1,B2;
- B1=spare/10; //将设定温度对10取模,获取十位上的数字
- B2=spare%10; //将设定温度对10取余,获取个位上的数字
- NixieTube1_DIG1=1; ////打开数码管位选端
- P2=table[B1]; //送入十位上的数字
- delay(1); ////延时,待显示稳定
- NixieTube1_DIG1=0; //关断显示
-
- NixieTube1_DIG2=1; //打开显示
- P2=table[B2]; //送入个位上的数字
- delay(1); //延时,待显示稳定
- NixieTube1_DIG2=0; //关断显示
- }
- void main() //主函数
- {
-
- uchar a;
- uchar b;
- uchar c;
- P2=0xf7; //对P2口初始化,开机先不让数码管显示
- NixieTube0_DIG1=1; //初始化,数码管位选端拉高
- NixieTube0_DIG2=1; //同上
- NixieTube1_DIG1=1; //同上
- NixieTube1_DIG2=1; //同上
- buzzer=0; //蜂鸣器引脚拉低,上电,蜂鸣器响一秒
- delay(1000); //延时1S左右
- while(1)
- {
- tmpchange();//向温度传感器写入温度转换指令
- if(add==1) //如果 按键加 没有按下
- b=1; //b=1;b的作用相当于松手检测
- if(add==0&b==1) //如果按键按下
- {
- if(setting==99)
- {}
- else
- {
- setting++;//设定值自加一次
- b=0; //只有按下松手后,再按 按键加 才能再次使设定值自加一次
- }
- };
- if(sub==1) //按键减未被按下
- c=1; //作用与b相同
- if(sub==0&c==1) //如果按键减 被按下
- {
- if(setting==0)
- {}
- else
- {
- setting--;//设定值自减一次
- c=0; //作用同上面的b
- }
- };
- if(present<=setting*10) //如果实际温度小于设定温度
- {
- buzzer=0; //蜂鸣器不响
- led=0; //灯亮
- }
- else
- {
- buzzer=0; //否则 蜂鸣器响
- led=1; //灯不亮
- }
- for(a=10;a>0;a--)
- {
- display0(tmp()); //显示实际温度
- display1(setting); //显示设定温度
- }
- }
- }
复制代码
|