配色: 字号:
基于PIC单片机的实时温度控制系统
2012-05-04 | 阅:  转:  |  分享 
  
基于PIC单片机的实时温度控制系统//实现的功能:数码管显示实时温度,支持负温度//芯片PIC16F877//XT:4MHZ//#include??????//包含单片机内部资源预定义#defineLVP0x3f39

//晶振:XT;代码:没有代码保护;上电延时定时器关闭;//低电压复位禁止;看门狗关闭;低电压编程禁止__CONFIG(XT&UNPROTECT&PWRTDIS&BORDIS&WDTDIS&LVP);

#defineuchunsignedchar????????????????????//给unsignedchar起别名uch#defineDQRA2???????????????????????????????//定义18B20数据端口#defineDQ_DIRTRISA2????????????????????????//定义18B20D口方向寄存器#defineDQ_HIGH()DQ_DIR=1??????????????????//设置数据口为输入#defineDQ_LOW()DQ_DIR=0;DQ=0???????????//设置数据口为输出

constunsignedcharledcode[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};//不带小数点的共阴极数码管0123456789段码,正负符号位constunsignedcharledcode1[12]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40};??//带小数点的共阴极数码管0123456789段码,正负符号位

voidinit_port(void);voiddelay(charx,chary);voiddelay_1ms(void);voiddelay_ms(unsignedinttime);voidinterruptdealtime();voidtmint(void);voidtimetoseg(uchfh_temp,uchbai_temp,uchshi_temp,uchge_temp,uchsf_temp,uchbf_temp,uchqf_temp,uchwf_temp);voidbinary_temp(uchTL,signedcharTH);voidreset(void);voidwrite_byte(uchval);uchread_byte(void);voidget_temp(void);

unsignedchardisplay_data[8];unsignedcharintcount=0;uchTLV=0;???????????????????????//采集到的温度高8位uchTHV=0;????????????????????????//采集到的温度低8位

uniontemp????????????????????????//定义一个联合体{intT;uchTV[2];}temp;

signedcharTZ=0;????????????????????//转换后的温度值整数部分,有符号位uchTX=0;???????????????????????????//转换后的温度值小数部分

unsignedintwd;?????????????????????????????//转换后的温度值BCD码形式

unsignedcharfh;??????????????????????????????//符号位unsignedcharbai;????????????????????????????//整数百位unsignedcharshi;????????????????????????????//整数十位unsignedcharge;?????????????????????????????//整数个位unsignedcharshifen;?????????????????????????//十分位unsignedcharbaifen;?????????????????????????//百分位unsignedcharqianfen;????????????????????????//千分位unsignedcharwanfen;?????????????????????????//万分位

////???主程序//voidmain(void){init_port();tmint();while(1){??????????get_temp();??timetoseg(fh,bai,shi,ge,shifen,baifen,qianfen,wanfen);????????}}////端口初始化//PORTD作为数码管段驱动(高有效)//PORTE作为数码管位选择驱动(低有效)//voidinit_port(void){RBPU=0;//PORTB=0xFF;TRISB=0xFF;PORTD=0x00;??????????//TRISC=0x00;??????????//C口控制LED指示灯,设置成输出TRISD=0;??????????//D口当作数码管段,设置成输出ADCON1=0x07;????????//使A口,E口全为数字I/O口TRISE=0x00;??//E口当作数码管位选择控制脚,设置成输出??PORTE=0x00;}////??延时程序//voiddelay(charx,chary){charz;do{?????z=y;?????do{;}while(--z);????}while(--x);}//其指令时间为:7+(3(Y-1)+7)(X-1)如果再加上函数调用的call指令、页面设定、传递参数花掉的7个指令。//则是:14+(3(Y-1)+7)(X-1)。////??延迟程序//voiddelay_1ms(void){unsignedintn;for(n=0;n<50;n++)??{???NOP();??}}//voiddelay_ms(unsignedinttime){for(;time>0;time--)??{???delay_1ms();??}}

//-----------------------------------------------//复位DS18B20函数voidreset(void){uchpresence=1;while(presence){???DQ_LOW();???????????????????????????????//主机拉至低电平???delay(2,90);?????????????????????????????//延时>480503us???DQ_HIGH();???????????????????????????????//释放总线等电阻拉高总线,并保持15~60us???delay(2,8);??????????????????????????????//延时>60us???if(DQ==1)presence=1;????????????????????//没有接收到应答信号,继续复位???elsepresence=0;?????????????????????????//接收到应答信号???delay(2,70);?????????????????????????????//延时>240us??}}

//-----------------------------------------------//写18b20写字节函数voidwrite_byte(uchval){uchi;uchtemp;for(i=8;i>0;i--){??temp=val&0x01;???????????????????????????//最低位移出??DQ_LOW();??NOP();??NOP();??NOP();??NOP();??NOP();???????????????????????????????????//从高拉至低电平,产生写时间隙??if(temp==1)DQ_HIGH();??????????????????//如果写1,拉高电平??delay(2,7);??????????????????????????????//延时63us??DQ_HIGH();??NOP();??NOP();??val=val>>1;??????????????????????????????//右移一位}}

//------------------------------------------------//18b20读字节函数uchread_byte(void){uchi;uchvalue=0;???????????????????????????????//读出温度staticbitj;for(i=8;i>0;i--){??value>>=1;??DQ_LOW();?????????//每次读时隙由主机发起,拉低总线至少1μs。??NOP();??NOP();??NOP();??NOP();??NOP();??NOP();??????????????????????????????????//6us??DQ_HIGH();?????????//读时隙开始后的15μs内释放总线,拉至高电平,准备采样总线。??NOP();??NOP();??NOP();??NOP();??NOP();?????????????????????????????????//5us??j=DQ;??????????????//采样总线??if(j)value|=0x80;//把采样到的数据放入value??delay(2,7);??????????????//所有读时隙至少60μs,这里大约63us}return(value);}

//-------------------------------------------------//启动温度转换函数voidget_temp(){inti;DQ_HIGH();reset();????????????????????????????????//复位等待从机应答write_byte(0XCC);???????????????????????//忽略ROM匹配write_byte(0X44);???????????????????????//发送温度转化命令for(i=10;i>0;i--)???{??????????delay(201,132);?????????????????????????}???

reset();????????????????????????????????//再次复位,等待从机应答write_byte(0XCC);???????????????????????//忽略ROM匹配write_byte(0XBE);???????????????????????//发送读温度命令

TLV=read_byte();?????????????????//读出温度低8位THV=read_byte();?????????????????//读出温度高8位

DQ_HIGH();??????????????????????????????//释放总线

?????????????????????????????????????????TZ=(TLV>>4)|(THV<<4);??????????//温度整数部分TX=TLV<<4;?????????????????????//温度小数部分,注意TX的后四位无效码binary_temp(TX,TZ);??//将相应的温度二进制值转换成十进制数}

//将相应的温度温度整数部分和小数部分的二进制值转换成十进制数

voidbinary_temp(charTL,signedcharTH){if(TH>=0)?????????????????????????//如果是正温度{???fh=0x0A;????????????????????????????????//正数符号位???bai=TH/100;??????????????????????????????//整数部分百位???shi=(TH%100)/10;//十位??????????????????//整数十位???ge=(TH%100)%10;//个位?????????????????????????//整数部分个位

???wd=0;???if(TL&0x80)wd=wd+5000;???if(TL&0x40)wd=wd+2500;???if(TL&0x20)wd=wd+1250;???if(TL&0x10)wd=wd+625;???????????????//以上4条指令把小数部分转换为BCD码形式????????????

???shifen=wd/1000;?????????????????????????//十分位??????????????????????baifen=(wd%1000)/100;???????????????????//百分位???qianfen=(wd%100)/10;????????????????????//千分位???wanfen=wd%10;???????????????????????????//万分位???NOP();??}else??????????????????????????????????????//否则,是负温度,要求补码{temp.TV[0]=TL;temp.TV[1]=TH;temp.T=(~temp.T)+0x0010;?????????????//补码形式,起反加1??????TL=temp.TV[0];TH=temp.TV[1];

???fh=0x0B;???????????????????????????????//负数符号位???bai=TH/100;??????????????????????????????//整数部分百位???shi=(TH%100)/10;//十位??????????????????//整数十位???ge=(TH%100)%10;//个位?????????????????????????//整数部分个位

???wd=0;???if(TL&0x80)wd=wd+5000;???if(TL&0x40)wd=wd+2500;???if(TL&0x20)wd=wd+1250;???if(TL&0x10)wd=wd+625;???????????????//以上4条指令把小数部分转换为BCD码形式????????????

???shifen=wd/1000;?????????????????????????//十分位??????????????????????baifen=(wd%1000)/100;???????????????????//百分位???qianfen=(wd%100)/10;????????????????????//千分位???wanfen=wd%10;???????????????????????????//万分位???NOP();}??}

//?????????温度值各位转换成段码//voidtimetoseg(uchfh_temp,uchbai_temp,uchshi_temp,uchge_temp,uchsf_temp,uchbf_temp,uchqf_temp,uchwf_temp){??display_data[0]=ledcode[wf_temp];??display_data[1]=ledcode[qf_temp];??display_data[2]=ledcode[bf_temp];??display_data[3]=ledcode[sf_temp];??display_data[4]=ledcode1[ge_temp];??display_data[5]=ledcode[shi_temp];??display_data[6]=ledcode[bai_temp];??display_data[7]=ledcode[fh_temp];}

////???定时中断初始化(OPTION_REG)//voidtmint(void){T0CS=0;?????//时钟源为内部指令周期???????????PSA=0;??????????//分频器分配给TMR0//PS2=0;?????????//TMR0的分频比为1:16?????????PS1=1;PS0=1;//GIE=1;?????????//允许总中断T0IE=1;????????//允许定时器0溢出中断T0IF=0;????????//清楚定时器0中断标志TMR0=0X06;?????//预置初值T=(256-6)x16=4000uS}//voidinterruptdealtime()??//中断入口,该中断完成数码管的动态扫描{?????????????????????????//每中断一次的时间为4毫秒???T0IF=0;???TMR0=0X06;

???PORTD=0x00;???????????//先关闭显示??if(intcount==0)????{?????PORTD=display_data[0];?????PORTE=0x00;?????intcount+=1;????}??elseif(intcount==1)????{?????PORTD=display_data[1];?????PORTE=0x01;?????intcount+=1;????}??elseif(intcount==2)????{?????PORTD=display_data[2];?????PORTE=0x02;?????intcount+=1;????}??elseif(intcount==3)????{?????PORTD=display_data[3];?????PORTE=0x03;?????intcount+=1;????}??elseif(intcount==4)????{?????PORTD=display_data[4];?????PORTE=0x04;?????intcount+=1;????}??elseif(intcount==5)????{?????PORTD=display_data[5];?????PORTE=0x05;?????intcount+=1;????}??elseif(intcount==6)????{?????PORTD=display_data[6];?????PORTE=0x06;?????intcount+=1;????}?????elseif(intcount==7)????{?????PORTD=display_data[7];?????PORTE=0x07;?????intcount=0;????}??}

仿真图:

































































献花(0)
+1
(本文系朽木轩首藏)