作为一个51单片机的初学者,自己完成一个实物制作是感到很有成就感的事,在这里与大家分享,也希望可以和这里的大佬们进行交流和学习。本人算是入门新手,有错误或者不足的地方希望大佬可以指正和交流,在这里先提前请教。有想要做关于热敏电阻测温的也可以拿去参考希望我的这个拙作能给你带来一些启发。
首先我来谈一谈热敏电阻测温装置制作中遇到的困难,这个东西大概花费了一周的时间,最难完成的部分就是测温不准确的问题,首先我写程序的时候,关于采集的电压值转化为ADC值,最后又转化为温度的这个过程,最初是使用了公式进行转换的,但是,进入调试环节后发现,显示的不准确,因为每一个不同的NTC热敏电阻不会和它自身B值所计算的电阻值那么吻合,实际的使用中有着许多不确定的因素,所以我最后就确定使用EXCEL 表格去计算出对应的电压值,最后在得出我需要的ADC值,然后放在数组中,直接使用。
硬件部分的Proteus仿真图如下:
我使用的AD是adc0832 8位并行的芯片,测温范围为0-200度,所以精度不高,误差有1度左右,还是挺大的,如果追求高精度的可以选择12位或者更高位的AD转化芯片。温度采集使用的分压式,分压电阻是2K欧姆,热敏电阻是10K电阻B值为3940.
制作出来的实物图如下::
/*单片机程序如下*/
- #include <reg51.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit CS =P1^0;
- sbit CLK=P1^1;
- sbit DIO =P1^2;
- sbit K_H=P1^3;
- sbit K_L=P1^4;
- sbit LED_U=P1^5;
- sbit LED_D=P1^6;
- sbit SOUNDER=P1^7;
- sbit K_T =P3^1;
- sbit K_U =P3^2;
- sbit K_D =P3^3;
- uint i,j,m,n,H,L,T,num,date,a=0,b=0;
- void Delay10ms(unsigned int c) //延迟为10ms的延迟函数,用于按键的延迟去抖
- {
- unsigned char a, b;
- for (;c>0;c--)
- {
- for (b=38;b>0;b--)
- {
- for (a=130;a>0;a--);
- }
- }
- }
- uchar code table[]={//共阴数码管段码"0~f"
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80};
- uchar data dis_buf[4];
- uchar code Temp[201]={//温度:0-200 对应的ADC值
- 255.9,255.8, 255.7, 255.6, 255.5, 255.4, 255.3, 255.2, 255.1, 254.1, 253.1, 252.1, 251.0, 249.9, 248.7, 247.6, 246.4, 245.1,
- 243.8, 242.5, 241.1, 239.8, 238.3, 236.9, 235.4, 233.8, 232.2, 230.6, 229.0, 227.3, 225.6, 223.8, 222.0, 220.2, 218.4, 216.5,
- 214.6, 212.6, 210.6, 208.6, 206.6, 204.5, 202.5, 200.4, 198.2, 196.1, 193.9, 191.7, 189.5, 187.3, 185.1, 182.8, 180.6, 178.3,
- 176.0, 173.8, 171.5, 169.2, 166.9, 164.6, 162.3, 160.1, 157.8, 155.5, 153.2, 151.0, 148.7, 146.5, 144.3, 142.1, 139.9, 137.7,
- 135.6, 133.4, 131.3, 129.2, 127.1, 125.1, 123.0, 121.0, 119.1, 117.1, 115.2, 113.2, 111.4, 109.5, 107.7, 105.9, 104.1, 102.4,
- 100.6, 98.9 ,97.3 ,95.7 ,94.0 ,92.5 ,90.9 ,89.4 ,87.9 ,86.4 ,85.0 ,83.6 ,82.2 ,80.9 ,79.5 ,78.2 ,77.0 ,75.7 ,74.5 ,72.7 ,72.1 ,71.0 ,69.9 ,
- 68.8 ,67.7 ,66.6 ,65.6 ,64.6 ,63.6 ,62.7 ,61.7 ,60.8 ,59.9 ,59.0 ,58.2 ,57.4 ,56.5 ,55.7 ,55.0 ,54.2 ,53.5 ,52.7 ,52.0 ,51.3 ,50.7 ,50.0 ,
- 49.4 ,48.7 ,48.1 ,47.5 ,46.9 ,46.4 ,45.8 ,45.3 ,44.7 ,44.2 ,43.7 ,43.2 ,42.7 ,42.3 ,41.8 ,41.3 ,40.9 ,40.5 ,40.1 ,39.6 ,39.2 ,38.9 ,38.5 ,38.1 ,
- 37.7 ,37.4 ,37.0 ,36.7 ,36.4 ,36.0 ,35.7 ,35.4 ,35.1 ,34.8 ,34.5 ,34.3 ,34.0 ,33.7 ,33.5 ,33.2 ,33.0 ,32.7 ,32.5 ,32.3 ,32.0 ,31.8 ,31.6 ,
- 31.4 ,31.2 ,31.0 ,30.8 ,30.6 ,30.4 ,30.2 ,30.0 ,29.9 ,29.7 ,29.9 ,29.7 ,29.5 ,29.0 ,28.9 ,28.7 ,28.6 ,28.4 ,
- };
- uchar ADC0832() //ADC0832 8位串行的AD转换芯片
- {
- uchar aaa,temp;
- CS=1; //一个转换周期开始
- CLK=0; //为第一个脉冲作准备
- CS=0; //CS置0,片选有效
- DIO=1; //DIO置1,规定的起始信号
- CLK=1; //第一个脉冲
- CLK=0; //第一个脉冲的下降沿,此前DIO必须是高电平
- DIO=1; //DIO置1, 通道选择信号
- CLK=1; //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0
- CLK=0; //第二个脉冲下降沿
- DIO=0; //DI置0,选择通道0
- CLK=1; //第三个脉冲
- CLK=0; //第三个脉冲下降沿
- DIO=1; //第三个脉冲下沉之后,输入端DIO失去作用,应置1
- CLK=1; //第四个脉冲
- for(aaa=0;aaa<8;aaa++) //高位在前
- {
- CLK=1; //第四个脉冲
- CLK=0;
- temp<<=1; //将下面储存的低位数据向右移
- temp|=(uchar)DIO; //将输出数据DIO通过或运算储存在dat最低位
- }
- CS=1; //片选无效
- return temp; //将读的数据返回
- }
- void delay(uint n)
- {
- uint i,j;
- for(i=n;i>0;i--)
- for(j=30;j>0;j--);
- }
- void LED_SOUND() //LED和蜂鸣器的报警显示
- {
- LED_U=0;
- LED_D=0;
- SOUNDER=0;
- if(T>=H) //温度高于上限红色LED灯亮,同时蜂鸣器报警
- {
- LED_U=1;
- SOUNDER=1;
- }
- if(T<=L) //温度低于下限黄灯点亮,同时蜂鸣器报警
- {
- LED_D=1;
- SOUNDER=1;
- }
- }
- void xianshi() //用于数码管显示的函数
- {
- static uchar i=0;
- P0=0x00;
- P2=~(0x01<<i);
- delay(1);
- P0=dis_buf[ i];[ i]
- i++;
- i%=4;
- }
- void main()
- {
- LED_U=0;
- EX0=1;
- IT0=1;
- EX1=1;
- IT1=1;
- EA=1;
- while(1)
- {
- for(j=0;j<5;j++) //多次采集求平均值,用于防止显示时值的不稳定
- {
- num+=ADC0832();
- date=num/5;
- }
- j=0;
- num=0;
-
- for(i=0;i<201;i++) //用于判断ADC值在那个值的范围内,然后输出数组值,也就是对应的温度值
- {
- if(date<=Temp[ i]&&date>Temp[i+1])[ i]
- {
- T=i;
- break;
- }
- }
- dis_buf[0]=table[T/100]; //个位显示
- dis_buf[1]=table[T/10%10]; //十位显示
- dis_buf[2]=table[T%10]; //百位显示
- dis_buf[3]=0x39; //显示“C”
- xianshi();
- delay(1);
- if(K_H==0) //按键是否按下
- {
- Delay10ms(1); //按键的延迟去抖
- if(K_H==0)
- {
- while(1) //用于显示上限的报警数值
- {
- H=20+a;
- dis_buf[0]=0x76;
- dis_buf[1]=table[H/100];
- dis_buf[2]=table[H/10%10];
- dis_buf[3]=table[H%10];
- xianshi();
- if(K_H==0) //再次按下按键,跳出调节上限的显示界面,继续显示温度
- {
- Delay10ms(1);
- if(K_H==0)
- break;
- }
- }
- }
- }
- if(K_L==0) //按键是否按下
- {
- Delay10ms(1); //按键的延迟去抖
- if(K_L==0)
- {
- while(1) //用于显示下限的报警数值
- {
- L=10+b;
- dis_buf[0]=0x38;
- dis_buf[1]=table[L/100];
- dis_buf[2]=table[L/10%10];
- dis_buf[3]=table[L%10];
- xianshi();
- if(K_L==0) //再次按下按键,跳出调节下限的显示界面,继续显示温度
- {
- Delay10ms(1);
- if(K_L==0)
- break;
- }
- }
- }
- }
- LED_SOUND(); //报警函数
- }
- }
- void u_init() interrupt 0 //用于按键“加一”的中断函数
- {
- if(K_U==0)
- {
- Delay10ms(1);
- if(K_U==0)
- {
- if(dis_buf[0]==0X76) //用于判断数码管是否处于调节上限显示的界面
- {
- a++;
- }
- if(dis_buf[0]==0X38) //用于判断数码管是否处于调节下限显示的界面
- {
- b++;
- }
- }
- }
- }
- void d_init() interrupt 2 //用于按键“减一”的中断函数
- {
- if(K_D==0)
- {
- Delay10ms(1);
- if(K_D==0)
- {
- if(dis_buf[0]==0X76) //用于判断数码管是否处于调节上限显示的界面
- {
- a--;
- }
- if(dis_buf[0]==0X38) //用于判断数码管是否处于调节下限显示的界面
- {
- b--;
- }
- }
- }
- }
复制代码
最后我有将程序,仿真,还有ADC处理等放在附件内,有需要的可以下载,希望可以得到大家的指正和交流 。
全部资料51hei下载地址:
热敏电阻测温装置.7z
(79.56 KB, 下载次数: 148)
|