温度测量与控制

来源:互联网 发布:淘宝网男士红色衬衣 编辑:程序博客网 时间:2024/05/01 13:54

实验七  温度测量与控制

三、实验内容

掌握使用传感器测量与控制温度的原理与方法,使用C51语言编写实现温度控制的功能,使用超声波/温度实验板测量温度,将温度测量的结果(单位为摄氏度)显示到液晶屏上。

编程实现测量当前教室的温度,显示在LCM液晶显示屏上。

通过S1设定一个稳定的目标温度值。

编程实现温度的控制,将当前温度值控制到目标温度值并稳定的显示。

四、实验步骤

1.预习,参考附录三,预习DS18B20的编程结构,编程时注意DS18B20的时间要求,必须准确满足。根据实验原理附录中的流程图进行编程。

2. 将编译后的程序下载到51单片机,观察温度的测量结果。

3. 程序调试

五、实验原理

本实验使用的DS18B20是单总线数字温度计,测量范围从—55℃到+125℃,增量值为0.5 ℃。

用于贮存测得的温度值的两个8位存贮器RAM 编号为0号和1号。

1号存贮器存放温度值的符号,如果温度为负(℃),则1号存贮器8位全为1,否则全为0。

0号存贮器用于存放温度值的补码LSB(最低位)的1表示0.5℃ 。

将存贮器中的二进制数求补再转换成十进制数并除以2,就得到被测温度值。

温度检测与控制系统由加热灯泡,温度二极管,温度检测电路,控制电路和继电器组成。温度二极管和加热灯泡封闭在一个塑料保温盒内,温度二极管监测保温盒内的温度,用温控实验板内部的A/D转换器ADC7109检测二极管两端的电压,通过电压和温度的关系,计算出盒内空气的实际温度。

相关背景知识参见DS18B20中文资料。

实验原理见附录三。

本实验使用STC89C516RD+单片机实验板。单片机的P1.4与DS18B20的DQ引脚相连,进行数据和命令的传输。

单片机的P1.1连接热电阻。当P1.1为高电平时,加热热电阻。

温度控制的方法建议采用PID控制

本实验设备的原理框图




实验七//字模方式:列行式,逆向,16*16#include<reg52.h>#include<intrins.h> //声明本征函数库#include<math.h>typedef unsigned char uchar;typedef unsigned int uint;sbit s1 = P3^6;sbit s2 = P3^7;sbit RS=P3^5;//寄存器选择信号sbit RW=P3^4;//读/写操作选择信号,高电平读,低电平写sbit EN=P3^3;//使能信号sbit CS1=P1^7;//左半屏显示信号,低电平有效sbit CS2=P1^6;//右半屏显示信号,低电平有效sbit DQ=P1^4; sbit up=P1^1;uchar Ek,Ek1,Ek2;uchar Kp,Ki,Kd;uint res,Pmax;uint xx=0; //页面uint times=0;//延时计数 void delay_us(uchar n){ while (n--) { _nop_(); _nop_(); }} unsigned  char code shu[10][32]={(数字0123456789)void delay(uint i)//延时子程序,i最大256,超过256部分无效{while(--i);}void Read_busy()  //等待BUSY=0{      //busy p2^7P2=0xff;RS=0;//RS/RW=0/1,读取状态字指令RW=1;EN=1;//控制LCM开始读取while(P2&0x80);//判忙,循环等待P2.7=0.EN=0;//控制LCM读取结束}void write_command(uchar value)//设置地址或状态{   P2=0xff;   Read_busy();//等待LCM空闲RS=0;//RS/RW=00,设置LCM状态或选择地址指令RW=0;P2=value;//设置EN=1;//控制LCM开始读取delay(100);EN=0;//控制LCM读取结束}void write_data(uchar value)//写数据到显示存储器{   P2=0xff;   Read_busy();RS=1;// RS/RW=10,写数据指令RW=0;P2=value;//写数据EN=1;delay(100);EN=0;}void Set_column(uchar column)//选择列地址(Y){  column=column&0x3f;//高两位清0,保留后六位的列地址  column=0x40|column;//01000000|column,根据后六位选择列地址  write_command(column);}void Set_line(uchar startline)//显示起始行设置{  startline=0xC0|startline;// 11000000|startline, 根据startline后六位选择起始行  write_command(startline);}void Set_page(uchar page)//选择页面地址(X){  page=0xb8|page;//10111000|page,根据page后三位确定所选择的页  write_command(page);}void display(uchar ss,uchar page,uchar column,uchar *p){//ss选择屏幕,page选择页面,column选择列,P是要显示的数据数组的指针uchar i;switch(ss)  {   case 0: CS1=1;CS2=1;break; //全屏case 1: CS1=1;CS2=0;break; //左半屏case 2: CS1=0;CS2=1;break; //右半屏default: break;  }  page=0xb8|page;//10111000|page,根据page后三位确定所选择的页  write_command(page);  column=column&0x3f;//高两位清0,保留后六位的列地址  column=0x40|column;//01000000|column,根据后六位选择列地址  write_command(column);  for(i=0;i<16;i++)//列地址自动+1  {    write_data(p[i]);//写前16个长度数据  }  page++;  write_command(page);//  column--;  write_command(column);  for(i=0;i<16;i++)//列地址自动+1  {    write_data(p[i+16]);//写后16个长度数据  }}void SetOnOff(uchar onoff)//显示开关设置{  onoff=0x3e|onoff;//00111110|onoff,根据最后一位设置开/关触发器状态,从而控制显示屏的显示状态  write_command(onoff);}void ClearScreen()//清屏{  uchar i,j;  CS2=1;  CS1=1;  for(i=0;i<8;i++)  {    Set_page(i); //依次选择8个页面 Set_column(0);//选择第0列for(j=0;j<64;j++)//列地址具有自动加1的功能,依次对页面的64列写入0从而清屏{ write_data(0x00);}  }}void InitLCD()//初始化{   Read_busy();CS1=1;CS2=1;SetOnOff(0);   CS1=1;CS2=1;SetOnOff(1);//打开显示开关CS1=1;CS2=1;   ClearScreen();//清屏   Set_line(0);//设置显示起始行}bit DS_init(){bit flag;DQ = 0;delay_us(255);   //500us以上DQ = 1;          //释放delay_us(40);    //等待16~60usflag = DQ;delay_us(150);return flag;     //成功返回0}uchar read()   //byte{ uchar i; uchar val = 0;      for (i=0; i<8; i++)  { val >>= 1; DQ = 0; //拉低总线产生读信号 delay_us(1);  DQ = 1; //释放总线准备读信号 delay_us(1);  if (DQ) val |= 0x80;  delay_us(15);  } return val;} void write(char val)   //byte{ uchar i; for (i=0; i<8; i++)  { DQ = 0; //拉低总线,产生写信号 delay_us(8);  val >>= 1; DQ = CY; delay_us(35);  DQ = 1;  delay_us(10);  }}void PID(){uchar Px,Pp,Pi,Pd,a,b,c;uint count;Pp = Kp*(Ek-Ek1);Pi = Ki*Ek;Pd = Kd*(Ek-2*Ek1+Ek2);Px = Pp+Pi+Pd;res = Px;a=res/100;b=res%100/10;c=res%10;display(1,4,2*16,shu[a]);delay(255);    display(1,4,3*16,shu[b]);delay(255);display(2,4,0*16,shu[c]);delay(255);Ek2 = Ek1;Ek1 = Ek;count = 0;if(res>Pmax)res =Pmax ;while((count++)<=res){up = 1;delay_us(250);delay_us(250);}while((count++)<=Pmax){up = 0;delay_us(250);delay_us(250);}}void main(){uchar aim,low,high,b,c;uint result;InitLCD();  Set_line(0);  aim = 40;Kp = 4;Ki = 5;Kd = 2;  Pmax = 5;Ek1 = 0;Ek2 = 0;res = 0;    while(1){if(s1 == 0)aim++;if(s2 == 0)aim--;while(DS_init());write(0xcc);  //跳过ROM命令write(0x44);  //温度转换命令delay(600);while(DS_init());write(0xcc);      write(0xBE);    //读DS 温度暂存器命令low = read(); //采集温度high = read();delay(255);result = high;result <<= 8;result |= low;result >>= 4 ; //result /= 16;Ek = aim - result;b=result/10;c=result%10;display(1,0,0*16,shiji[0]);delay(255);display(1,0,1*16,shiji[1]);delay(255);    display(1,0,3*16,shu[b]);delay(255);display(2,0,0*16,shu[c]);delay(255);display(2,0,1*16,du);delay(100);b=aim/10;c=aim%10;display(1,2,0*16,mubiao[0]);delay(255);display(1,2,1*16,mubiao[1]);delay(255);    display(1,2,3*16,shu[b]);delay(255);display(2,2,0*16,shu[c]);delay(255);display(2,2,1*16,du);delay(100);if(aim>=result)PID();elseup = 0;}}




0 0