基于AT89C52设计的温度调节控制直流电机,可以通过4*4按键设定经过MAX6675驱动的K型热电偶转化的温度上限与下限,高于上限电机正转,低于下限电机反转,处于正常温度电机停止转动。文件包含具体论文说明,理论与原理描述。
带proteus仿真工程文件,附件里面可以下载.
整个温度控制直流电机正反转系统的仿真原理图:
51单片机源程序:
- #include <reg51.h>
- #include <Intrins.h>
- #include <LCD1602.H>
- #include <math.H>
- #define C02_write 0xa0 //c02写地址
- #define C02_read 0xa1 //c02读地址
- #define uchar unsigned char
- #define uint unsigned int
- sbit MAX6675_CS=P1^2; //MAX6675冷端温度补偿,将K型热电偶信号转为数字信号
- sbit MAX6675_SCK=P1^1;
- sbit MAX6675_SO=P1^0;
- sbit normal=P2^3; //LED灯表示温度正常,过高,过低
- sbit upper=P2^4;
- sbit lower=P2^5;
- sbit direction=P2^6;
- sbit stop=P2^7;
- sbit SCL=P1^3; //EEPROM,256byte
- sbit SDA=P1^4;
- sbit beep=P1^7; //蜂鸣器
- bit ack,flag=0,flag1=0;
- uint tz;
- int sth=0,stl=0,t_zhi=0;
- uchar data temp1[]={'+','1','2','0','0',0},temp2[]={'-' ,'1','0','0','0',0};
- uchar data temp[7];
- char code keytab[]={0xEE,0xDE,0xBE,0x7E,0xED,0xDD,0xBD,0x7D,0xEB,0xDB,0xBB,0x7B,0xE7,0xD7,0xB7,0x77};
- unsigned char code str1[]={"STH STL"}; //system temperature high,low
- unsigned char code str2[]={"PARAMTER STEUP"};
- unsigned char code str3[]={" "};
- unsigned int testD2;
- unsigned char data disdata[5];
- void delay0(uchar x) // 延时函数
- {
- uchar i;
- while(x--)
- {
- for (i=0; i<13; i++);
- }
- }
- void delayms(uchar i)
- {
- uchar j;
- for(; i>0; i--)
- for(j=124; j>0; j--);
- }
- void longdelay(uchar i)
- {
- uint j;
- for(;i>0;i--)
- for(j=10000;j>0;j--);
- }
- void keysound() //按键声音函数
- {
- uchar i;
- for (i=0;i<180;i++)
- {
- delay0(5);
- beep=!beep; //BEEP取反
- }
- }
- void I2C_start(void) //I2C开始信号
- {
- SDA=1; SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SDA=0;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SCL=0; _nop_(); _nop_();
- }
- void I2C_stop(void) //I2C结束
- {
- SDA=0; SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SDA=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SCL=0;
- _nop_(); _nop_();
- }
- void I2C_no_ackownledge(void) //发送noack信号
- {
- SDA=1;
- _nop_(); _nop_();
- SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SCL=0;
- _nop_(); _nop_(); _nop_();
- }
- void I2C_sendB(uchar byte)//发送一字节数据
- {
- uchar counter;
- for(counter=0;counter<8;counter++)
- {
- if(byte&0x80) SDA=1;
- else SDA=0;
- _nop_();
- SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
- SCL=0;
- _nop_(); _nop_();
- byte<<=1;
- }
- _nop_(); _nop_();
- SDA=1;
- _nop_(); _nop_(); _nop_();
- SCL=1;
- _nop_(); _nop_(); _nop_();
- if(SDA==0) ack=1;
- else ack=0;
- SCL=0;
- _nop_(); _nop_();
- }
-
- uchar I2C_receiveB(void) //接收一字节数据
- {
- uchar temp;
- uchar counter;
- temp=0;
- SDA=1;
- _nop_(); _nop_();
- for(counter=0;counter<8;counter++)
- {
- _nop_(); _nop_(); _nop_();
- _nop_(); _nop_();
- SCL=1;
- _nop_();
- _nop_();
- if(SDA==1) temp=(temp<<1)|0x01;
- else temp=temp<<1;
- _nop_(); _nop_();
- SCL=0;
- _nop_(); _nop_(); _nop_();
- }
- _nop_(); _nop_();
- return(temp);
- }
- bit I2C_send_string(uchar *string,uchar no,uchar address) //发送8位温度
- {
- uchar counter;
- for(counter=0;counter<no;counter++)
- {
- I2C_start();
- I2C_sendB(C02_write);
- if(ack==0) return(0);
- I2C_sendB(address+counter);
- if(ack==0) return(0);
- I2C_sendB(string[counter]);
- I2C_stop();
- delayms(20);
- }
- return(1);
- }
- bit I2C_receive_string(uchar *string,uchar no,uchar address) //接收8位温度
- {
- uchar counter;
- for(counter=0;counter<no;counter++)
- {
- I2C_start();
- I2C_sendB(C02_write);
- if(ack==0) return(0);
- I2C_sendB(address+counter);
- if(ack==0) return(0);
- I2C_start();
- I2C_sendB(C02_read);
- if(ack==0) return(0);
- *(string+counter)=I2C_receiveB();
- I2C_no_ackownledge();
- I2C_stop();
- }
- }
- //温度值读取程序
- unsigned int ReadMAX6675() //从MAX6675读取温度
- {
- unsigned char count;
- unsigned int Value;
- MAX6675_CS=0; //置低,使能MAX6675
- MAX6675_SCK=0;
- Value=0;
- _nop_() ;_nop_();_nop_();_nop_();
- for(count=0;count<16;count++) //获取16位MSB
- {
- Value=Value<<1; //左移
- MAX6675_SCK=1; //sck置高
- _nop_() ;_nop_();_nop_();_nop_();
- if(MAX6675_SO==1) //取当前值
- Value|=0x01;
- MAX6675_SCK=0;
- }
- MAX6675_CS=1; //关闭MAX6675
- return Value;
- }
- unsigned int GetCurrentTemp(unsigned int CurrentValue) //获取当前温度
- {
- unsigned int TempValue;
- TempValue=CurrentValue;
- if(TempValue&0x8000) //D15=1;标识位错
- return 0;
- if(TempValue&0x0004) //D2=1;热电偶开路
- return 1;
- }
- void tempdisp() //温度值显示
- { unsigned char i;
- unsigned int TempValue;
- unsigned int testD2;
- int xiaoshu;
- TempValue=ReadMAX6675();
- testD2=GetCurrentTemp(TempValue);
- TempValue=ReadMAX6675();
- TempValue&=0x7ff8; //取D14位到D3的值
- TempValue>>=3; //转换温度值
- xiaoshu= (TempValue*1023.75/4095)*10-327;
- t_zhi=xiaoshu/10;
- disdata[0]=xiaoshu/10000+0x30; //千位数
- xiaoshu=xiaoshu%10000;
- disdata[1]=xiaoshu/1000+0x30; //百位数
- xiaoshu=xiaoshu%1000;
- disdata[2]=xiaoshu/100+0x30; //十位数
- xiaoshu=xiaoshu%100;
- disdata[3]=xiaoshu/10+0x30; //个位数
- xiaoshu=xiaoshu%10;
- disdata[4]=xiaoshu/1+0x30; //十分位
- LCD_set_position(68);
- for(i=0;i<4;i++)
- LCD_write_data(disdata[i]); //显示千百十个位
- LCD_write_data('.'); //显示小数点
- LCD_write_data(disdata[4]); //显示十分位
- LCD_write_data(0xDF); //显示dot
- LCD_write_data(0x43); //显示C
- if(t_zhi>sth){ normal=0; upper=1;lower=0;stop=1;direction=1;} //高于上限
- else if(t_zhi<stl){ normal=0; upper=0;lower=1;stop=1;direction=0;} //低于下限
- else { normal=1; upper=0;lower=0;stop=0;direction=0;} //正常
- }
- //返回-1表示没有检测到按键按下
- char getkey(void)
- { unsigned char scancode,tmpcode, key_zhi=0;
- P3 = 0xf0; // 发全0行扫描码
- if ((P3&0xf0)!=0xf0) // 若有键按下
- { delayms(5); // 延时去抖动
- if ((P3&0xf0)!=0xf0) // 延时后再判断一次,去除抖动影响
- { scancode = 0xfe;
- while((scancode&0x10)!=0) // 逐行扫描
- { P3 = scancode; // 输出行扫描码
- if ((P3&0xf0)!=0xf0) // 本行有键按下
- { tmpcode = P3; // 返回特征字节码
- while((P3&0xf0)!=0xf0);
- key_zhi=0;
- while(tmpcode!=keytab[key_zhi])
- key_zhi++;
- return( key_zhi++);
- }
- else scancode = (scancode<<1)|0x01;// 行扫描码左移一位
- }
- }
- }
- return(-1); // 无键按下,返回值为0
- }
- void timer0() interrupt 1 using 0
- {
- TR0=0;
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- TR0=1;
- tz++;
- }
- void main()
- {
- uchar kcode,count1=3,count2=12,i;
- normal=0;
- upper=0;
- lower=0;
- TMOD=0X01;
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- ET0=1;
- TR0=0;
- LCD_initial();
- LCD_cls();
- LCD_set_position(0);
- LCD_prints(str1);
- LCD_set_position(3);
-
- I2C_receive_string(temp1,5,0x00);
- I2C_receive_string(temp2,4,0x10);
- //change_data();
- LCD_prints(temp1); //显示上限
- LCD_set_position(12);
- LCD_prints(temp2); //显示上限
- sth=0;stl=0;
- for(i=1;i<5;i++)
- sth=sth*10+temp1[i]-'0';
- for(i=1;i<4;i++)
- stl=stl*10+temp2[i]-'0';
-
- MAX6675_CS=1; //复位MAX6675
- while(1)
- {
- if(flag==0)
- {
- tempdisp();
- }
- kcode=getkey();
- if(kcode==12&&flag==0)
- {
- flag=1;sth=0;stl=0;
- keysound();
- LCD_set_position(0x41);
- LCD_prints(str2);
- LCD_set_position(count1);
- LCD_write_instruction(0x0f); //光标闪烁
- }
- if(flag)
- {
- if(kcode>=0&&kcode<=9)
- {
- if(flag1==0&&count1!=3) //设置上限温度
- {
- LCD_set_position(count1);
- sth=sth*10+kcode;
- LCD_write_data(kcode+0x30);
- keysound();
- temp1[count1-3]=kcode+0x30;
- count1++;
- if(count1==8)
- {
- flag1=1;count1=12,count2=12;
- }
- LCD_set_position(count1);
- }
- if(flag1==1&&count2!=12) //设置下限温度
- {
- LCD_set_position(count2);
-
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
下载:
7-温度控制直流电机.zip
(845.7 KB, 下载次数: 230)
|