#include<reg52.h> #include<intrins.h> #include<stdlib.h> #define uchar unsigned char #define uint unsigned int #define Lcd_Bus P0 //------------定义接口-------------// sbit PSB = P1^0; sbit RS = P1^1 ; sbit RW = P1^2 ; sbit EN = P1^3 ; sbit sig_18b20 = P2^7; sbit hot_door = P2^6; //加热 sbit cold_door_1 = P2^5; sbit cold_door_2 = P2^4; sbit key1 = P2^3; sbit key2 = P2^2; sbit key3 = P2^1; sbit key4 = P2^0; uchar stop=100 ; uchar high,high1,high2 ; //pwm uchar run1,run2; uchar get_time; uchar temp_sig; uchar miao,fen,time,fen1,miao1; uchar flag_1,flag_2; //设置稳态标志位 uchar set1,set2,set3; uchar key4_num = 0; uchar key2_num = 0; uint delay_time = 6000; //采样间隔时间 uint set_temp ; uint get_temp ; //全局变量, uint now_temp; int uk; uint k; //分段控制 uchar dis1[7]; uchar dis2[7]; uchar dis3[5]; uchar dis4[5]; uchar code pag0_1[] = {"初始化..."}; uchar code pag0_2[] = {"Waiting..."}; uchar code pag1_1[] = {"水温控制系统"}; uchar code pag1_2[] = {"2010.8"}; uchar code home_page_line1[] = {" 当前:"}; //为什么要垫4个字节?? uchar code home_page_line2[] = {"目标:"}; uchar code home_page_line3[] = {"时间:"}; uchar code home_page_line4[] = {"PWM :"}; uchar code cursor_on[] = {">"}; //显示光标 uchar code cursor_off[] = {" "}; //清除光标 /******************** pid设置 ************************/ uint PP = 54; uint II = 3; uint DD = 12; uint PP2 = 50; /******************** 延时函数 *************************/ void delay(unsigned int t) // { unsigned int i,j ; for(i=0;i<t;i++) for(j=0;j<10;j++); } void delay_us(uint time_us) { while(time_us --); //延时(time_us * 6 +14)us } void delay_ms(uint time_ms) //1ms延时 { uint m,n; for(m=time_ms;m>0;m--) for(n=110;n>0;n--); } /******************** 18b20区 ***********************************/ /* 初始化 */ void init_18b20() { sig_18b20 = 1; delay_us(5); sig_18b20 = 0; delay_us(100); // 400 - 900 us sig_18b20 = 1; //释放总线,进入接收状态 delay_us(10); temp_sig = sig_18b20; // delay_us(10); } /* 读 */ read_18b20(void) { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { sig_18b20 = 0; // 给脉冲信号 dat>>=1; sig_18b20 = 1; // 给脉冲信号 if(sig_18b20) // sig拉高 dat|=0x80; delay_us(4); } return(dat); } /* 写 */ void write_18b20(uchar dat) //写一个字节 { uchar i=0; for (i=8; i>0; i--) { sig_18b20 = 0; sig_18b20 = dat&0x01; //写0或1 delay_us(5); sig_18b20 = 1; dat>>=1; //移位 } delay_us(4); } /* 取温度 */ temperature_18b20(void) { uchar h8 = 0; //存放高8位 uchar l8 = 0; uint temp = 0; //临时 float temp2 =0 ; //总16位温度数据 TR0 = 0; //关中断,防干扰 init_18b20(); if(!temp_sig) { write_18b20(0xCC); // 跳过读序号列号的操作 write_18b20(0x44); // 启动温度转换 init_18b20(); if(!temp_sig) // 接收状态 { write_18b20(0xCC); //跳过读序号列号的操作 write_18b20(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 l8 = read_18b20();//读低8位 h8 = read_18b20();//读高8位 temp = h8; temp <<= 8; //移8位 temp = temp | l8; //求和 temp2 = temp*0.0625;//转换为实际温度值 temp = temp2*10+0.5;//四舍5入为整数 TR0 = 1; // temp = temp - 10; //校对1度误差 return(temp); } } } /***************************************************/ /* 液晶区 */ void chk_busy() //查忙 { RS=0 ; RW=1 ; EN=1 ; Lcd_Bus=0xff ; while((Lcd_Bus&0x80)==0x80); EN=0 ; } void write_com(unsigned char cmdcode) //写命令 { chk_busy(); RS=0 ; RW=0 ; EN=1 ; Lcd_Bus=cmdcode ; delay(5); //------------------在数据写入的时候加入适当的延时 EN=0 ; delay(5); } void write_data(unsigned char Dispdata) //写数据 { chk_busy(); RS=1 ; RW=0 ; EN=1 ; Lcd_Bus=Dispdata ; delay(5); //------------------在数据写入的时候加入适当的延时 EN=0 ; delay(5); } void lcd_pos(uchar X,uchar Y) //位置 { uchar pos; if(X==0) {X=0x80;} else if(X==1) {X=0x90;} else if(X==2) {X=0x88;} else if(X==3) {X=0x98;} pos = X+Y; write_com(pos); //显示地址 } void lcd_init() //初始化液 { PSB = 1; RW = 0; delay(2000); write_com(0x30); delay(10); //选择基本指令集 write_com(0x30); //选择8bit数据流 delay(5); write_com(0x0c); //开显示(无游标、不反白) delay(10); write_com(0x01); //清除显示,并且设定地址指针为00H delay(500); write_com(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位 delay(0); } void clear_lcdram() //清除ram { unsigned char x,y ; for(y=0;y<64;y++) for(x=0;x<16;x++) { write_com(0x34); write_com(y+0x80); //行地址 write_com(x+0x80); //列地址 write_com(0x30); write_data(0x00); write_data(0x00); } } uchar ReadByte(void) //读数据 { unsigned char byReturnValue ; chk_busy(); Lcd_Bus=0xff ; RS=1 ; RW=1 ; EN=0 ; EN=1 ; byReturnValue=Lcd_Bus ; EN=0 ; return byReturnValue ; } /* 画点子函数 */ void draw_point(unsigned char X,unsigned char Y,unsigned char Color) { unsigned char Row,Tier,Tier_bit ; unsigned char ReadOldH,ReadOldL ; write_com(0x34); write_com(0x36); Tier=X>>4 ; Tier_bit=X&0x0f ; if(Y<32) { Row=Y ; } else { Row=Y-32 ; Tier+=8 ; } write_com(Row+0x80); write_com(Tier+0x80); ReadByte(); ReadOldH=ReadByte(); ReadOldL=ReadByte(); write_com(Row+0x80); write_com(Tier+0x80); if(Tier_bit<8) { switch(Color) { case 0 : ReadOldH&=(~(0x01<<(7-Tier_bit))); break ; case 1 : ReadOldH|=(0x01<<(7-Tier_bit)); break ; case 2 : ReadOldH^=(0x01<<(7-Tier_bit)); break ; default : break ; } write_data(ReadOldH); write_data(ReadOldL); } else { switch(Color) { case 0 : ReadOldL&=(~(0x01<<(15-Tier_bit))); break ; case 1 : ReadOldL|=(0x01<<(15-Tier_bit)); break ; case 2 : ReadOldL^=(0x01<<(15-Tier_bit)); break ; default : break ; } write_data(ReadOldH); write_data(ReadOldL); } write_com(0x30); } /* 按键扫描 */ uint keyscan_temp(void) { /* */ if(key2 == 0) { delay_ms(1); if(key2 == 0) { key2_num++; while(!key2); } } if(key2_num == 1) { draw_point(68,29,1); draw_point(76,29,0); draw_point(92,29,0); if(key3 == 0) delay_ms(1); if(key3 == 0) { set1++; while(!key3); if(set1 == 10) set1 = 0; set_temp = set1*100 + set2*10 +set3; } } if(key2_num == 2) { draw_point(68,29,0); draw_point(76,29,1); draw_point(92,29,0); if(key3 == 0) delay_ms(2); if(key3 == 0) { set2++; while(!key3); if(set2 == 10) set2 = 0; set_temp = set1*100 + set2*10 +set3; } } if(key2_num == 3) { draw_point(68,29,0); draw_point(76,29,0); draw_point(92,29,1); if(key3 == 0) delay_ms(2); if(key3 == 0) { set3++; while(!key3); if(set3 == 10) set3 = 0; set_temp = set1*100 + set2*10 +set3; } } if(key2_num == 4) { draw_point(68,29,0); draw_point(76,29,0); draw_point(92,29,0); set_temp = set1*100 + set2*10 +set3; key2_num = 0; //key3_num = 0 ,不接受key4加减 } return set_temp; } /******* 控温子函数 *********/ void pid_control() { int duk,uk1,uk3; get_temp = temperature_18b20(); uk = set_temp - get_temp; /******************** 加热区 *******************************/ if(uk > 0) //未到设置温度 { /* 关制冷 开加热 */ cold_door_1 = 1; cold_door_2 = 1; hot_door = 0; TR0 = 1; high2 = 0; /* 判断温度范围 */ if(uk >= 130) //13度以外 high1 = 90; //99占空比加热 else { high1 =0; /* 开始pid调节 */ uk1 = uk; duk = PP * uk + DD*(uk1-uk);//+II*(uk1+uk); high1 = duk/100; } high = high1; } /********************* 降温区 **********************/ if(uk < 0) //超温 { /* 关热,开制冷 */ hot_door = 1; TR0 = 0; high1 =0; uk3 = -uk; //uk值转正 if(uk3 > 4) //超温0.5度,开制冷 { cold_door_1 = 0; cold_door_2 = 0; high2 = 100; } if(uk3 < 4) //0.5度以内,关制冷 { cold_door_1 = 1; cold_door_2 = 1; high2 = 0; } /* if(uk3 > 20) //2度以外,开2个制冷片 { cold_door_1 = 0; cold_door_2 = 0; high2 = 100; //制冷片1全速 } if((uk3 > 5)&&(uk3 <= 20)) // 0.5-2度,只开一个制冷器) { cold_door_2 = 1; cold_door_1 = 0; } if(uk3 < 5) // 0-1度,一个制冷器pid调节 { cold_door_1 = 0; TR0 = 1; uk4 = uk3; high2 = (PP2*uk4)/10; } */ high = high2; } } /* void check_error() //检查是否达到稳态 { get_temp = temprature_18b20(); if(get_temp < set_temp +50)&&(get_temp > get_temp-50) //0.5度以内判断是否稳态 check_time1 = get_temp; } */ void init() { TMOD = 0x11; T2CON = 0x00; //设置T2CON寄存器 TH0 = (65536-10000)/256; // TL0 = (65536-10000)%256; TH1 = (65536-100)/256; //10ms TL1 = (65536-100)%256; TH2 = (65536-50000)/256; ; //50ms定时常数 TL2 = (65536-50000)%256; EA = 1; TR0 = 1; //加热,制冷占空比 ET0 = 1; /* TR1 = 0; //串口 ET1 = 1; */ ET2 = 1; //时间 TR2 = 0; //启动定时器2 hot_door = 1; //初始化,关加热 cold_door_1 = 1; //初始化,关制冷 cold_door_2 = 1; run1 = 0; run2 = 0; high = 0; high1 = 0; high2 = 0; lcd_init(); } /****************************************************************** 液晶界面 ****************************************************************** /* 目标温度设置子函数 */ void wait1() { uchar i = 0; lcd_pos(1,2); while(pag0_1[i]!='/0') { write_data(pag0_1[i]); i++; } } void wait2() { uchar i = 0; lcd_pos(1,2); while(pag0_2[i]!='/0') { write_data(pag0_2[i]); i++; } } /* 首页 */ void headpage() { uchar i; lcd_pos(1,1); i = 0; while(pag1_1[i]!='/0') { write_data(pag1_1[i]); i++; } lcd_pos(3,5); i = 0; while(pag1_2[i]!='/0') { write_data(pag1_2[i]); i++; } } /* 主页 */ void homepage() { uchar i = 0; /* 显示温度,PWM,和时间 */ dis1[0] = get_temp/100+0x30; //定义温度数组 dis1[1] = get_temp%100/10+0x30; dis1[2] = '.'; dis1[3] = get_temp%100%10+0x30; dis1[4] = ' '; dis1[5] = '`'; dis1[6] = 'C'; lcd_pos(0,4); //写温度数组 for(i=0;i<7;i++) { write_data(dis1[i]); } i = 0; dis2[0] = set_temp/100+0x30; //定义温度数组 dis2[1] = set_temp%100/10+0x30; dis2[2] = '.'; dis2[3] = set_temp%100%10+0x30; dis2[4] = ' '; dis2[5] = '`'; dis2[6] = 'C'; lcd_pos(1,4); //写温度数组 for(i=0;i<7;i++) { write_data(dis2[i]); } i = 0; dis4[0] = high/100+0x30; //定义温度数组 dis4[1] = high%100/10+0x30; dis4[2] = high%100%10+0x30; dis4[3] = ' '; dis4[4] = '%'; lcd_pos(2,4); //写温度数组 for(i=0;i<5;i++) { write_data(dis4[i]); } i = 0; dis3[0] = fen/10+0x30; //定义温度数组 dis3[1] = fen%10+0x30; dis3[2] = ':'; dis3[3] = miao/10+0x30; dis3[4] = miao%10+0x30; lcd_pos(3,4); //写温度数组 for(i=0;i<5;i++) { write_data(dis3[i]); } /* 显示菜单 */ lcd_pos(0,1); //写“当前” while(home_page_line1[i]!='/0') { write_data(home_page_line1[i]); //显示字符 i++; } i = 0; lcd_pos(1,1); //写“目标” while(home_page_line2[i]!='/0') { write_data(home_page_line2[i]); //显示字符 i++; } lcd_pos(3,1); i = 0; //写“时间” while(home_page_line3[i]!='/0') { write_data(home_page_line3[i]); //显示字符 i++; } lcd_pos(2,1); //写“波形” i = 0; while(home_page_line4[i]!='/0') { write_data(home_page_line4[i]); //显示字符 i++; } /* 光标 */ /* 光标 */ if(key4 == 0) { delay_ms(2); if(key4 == 0) { key4_num++; while(!key4); } if(key4_num == 2){key4_num = 0;} // if(key4_num == 1) { /* lcd_pos(2,0); //先清除 i = 0; // while(cursor_off[i]!='/0') { write_data(cursor_off[i]); // i++; } */ TR2 = 1; //开始计时!!!! lcd_pos(1,0); i = 0; //显示光标 “>目标” while(cursor_on[i]!='/0') { write_data(cursor_on[i]); //显示字符 i++; } //进入温度设置 } /* if(key4_num == 0) { lcd_pos(1,0); //先清除 i = 0; // while(cursor_off[i]!='/0') { write_data(cursor_off[i]); // i++; } i = 0; lcd_pos(2,0); //显示光标 while(cursor_on[i]!='/0') { write_data(cursor_on[i]); //显示字符 i++; } } */ } } /* 温度曲线页 */ //坐标线 void coor_line() { uchar i ; /* 画纵坐标 */ for(i=0;i<64;i++) draw_point(0,i,1); /* 画横坐标 */ for(i=0;i<128;i++) draw_point(i,63,1); /* 画坐标角 */ // draw_point(1,1,1); // draw_point(2,2,1); draw_point(126,62,1); draw_point(125,61,1); /* 画纵坐标刻度 */ draw_point(1,53,1); draw_point(1,43,1); draw_point(1,33,1); draw_point(1,23,1); draw_point(1,13,1); draw_point(1,3,1); /* 画横坐标刻度 */ draw_point(10,62,1); draw_point(20,62,1); draw_point(30,62,1); draw_point(40,62,1); draw_point(50,62,1); draw_point(60,62,1); draw_point(70,62,1); draw_point(80,62,1); draw_point(90,62,1); draw_point(100,62,1); draw_point(110,62,1); draw_point(120,62,1); } //温度设置曲线 void set_line() { uchar i,j; now_temp = temperature_18b20(); //基准温度 /* 升温 */ if(now_temp < set_temp) //0点X轴为当前温度 { j = 63-(set_temp - now_temp)/4; //目标线 for(i=0;i<128;i+=2) draw_point(i,j,1); } /* 制冷 */ else if(now_temp > set_temp) { for(i=0;i<127;i++) draw_point(i,3,1); //制冷起始温度线 j = 3+(now_temp-set_temp)/4; //温度 for(i=0;i<128;i+=2) draw_point(i,j,1); //目标线 } } //温度曲线 void get_line() { uchar i,j; if(now_temp < set_temp) //升温 { for(i=0;i<125;i++) { get_temp = temperature_18b20();// pid_control(); //控制温度 j = 63-(get_temp-now_temp)/4; //纵坐标实时位置 draw_point(i,j,1); //3格一度 delay_ms(delay_time); //采样时间 } } write_com(0x01); if(now_temp > set_temp) //降温 { for(i=0;i<125;i++) { get_temp = temperature_18b20(); pid_control(); j = 3+(now_temp-get_temp)/4; draw_point(i,j,1); delay_ms(delay_time); //采样时间 } } write_com(0x01); } /* 画图总函数 */ void drawpage() { delay_ms(2); coor_line(); //画坐标 set_line(); //画设置线 get_line(); //画温度曲线 } /*************** 按键扫描 ***************/ void main() { init(); wait1(); clear_lcdram(); write_com(0x01); while(1) { headpage(); if(key1 == 0) { while(!key1); break; } } write_com(0x01);//清屏 while(1) { get_temp = temperature_18b20(); //获取温度 homepage(); keyscan_temp(); pid_control(); //控温 if(key1 == 0) { while(!key1); break; } } write_com(0x01);//清屏 wait2(); clear_lcdram(); write_com(0x01); drawpage(); while(1); } /*********************************************************** 中断子函数 ************************************************************/ void timer_0() interrupt 1 { TH0 = (65536-10000)/256; //10ms TL0 = (65536-10000)%256; run1 ++; run2++; if(high1 == 0) { hot_door = 1; } else { if(run1 < high1) //有效电平部分 { hot_door = 0; } if(run1 > high1) //无效电平部分 { if(run1 < stop) { hot_door = 1; } if(run1 == stop) //run1到100清0 { run1 = 0; hot_door = 0; } } } /* if(high2 == 0) { cold_door_1 = 1; } else { if(run2 < high2) { cold_door_1 = 0; } if(run2 >high2) { if(run2 < stop) //无效电平部分 { cold_door_1 = 1; } if(run2 == stop) { run2 = 0; // run2到100 清零,周期结束 cold_door_1 = 0; } } } */ } /* 时间 */ void timer_2() interrupt 5 { TF2 = 0; //软件清中断标志 TH2 = (65536-50000)/256; //50ms TL2 = (65536-50000)%256; time++; if(time == 20) { time = 0; miao++; if(miao == 60) { miao = 0; fen++; if(fen == 60) { fen = 0; } } } } 程序部分,不是模块化的,soory