求助论坛大神,为什么我学习改写别人的PID温控源码代码,其中PWM 和temp_PID.SetPoint 总是不对,用串口调试的结果总是不对。
输出结果: PWM:100 PWM:12288 PWM_P: 设置温度:30 实?饰露?2619 temp_s:3000 temp_PID.SetPoint:
按理说我用了这样的 PWM应该在0到100之间temp_PID.SetPoint:应该是3000才对可是输出为什么不是,实在查不出原因,请大神指正。
引脚分配 lcd lcddata: P0
lcd_e: P2^7
lcd_rs: P2^6
lcd_rw: P2^5
设置按键 limit_choise: P //温度上下限选择按键
increase_temperature P //增加温度限值按键
reduce_temperature P //减少温度限值按键
蜂鸣器报警 warning P
温度传感器 temperature_sensor P
制热 heatting P
制冷 refrigerating P
LED显示 normal P //正常温度指示灯
high_temperature P //高温指示灯
low_temperature P //低温指示灯
单片机源程序如下:
- /*******************************************************************************
- * 包含头文件
- *******************************************************************************/
- #include <main.h>
- /*******************************************************************************
- * 变量声明
- *******************************************************************************/
- uint PWM=0;
- uint PWM_P;//PWM_P 功率占比显示
- uchar time_value=0;
- uchar time_heatting=0;
- uint temp_m=0; //实际温度
- uint up_limit_temp=30;
- uint temp_s; //设置温度*100
- PID temp_PID;
- uchar massage[]=0;
- /*******************************************************************************
- * 函数名 : void main()
- * 函数功能 : 主函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void main()//主函数
- {
- init();//初始化函数
-
- temp_PID.Proportion =150; // 设置 PID 系数
- temp_PID.Integral =5;
- temp_PID.Derivative =2;
- while(1)
- {
- temp_s = up_limit_temp*100;
- temp_PID.SetPoint = temp_s;
- if(time_value==10) //读取温度
- {
- temp_m=get_temp(Ds18b20ReadTemp());
- }
- if(time_value==50)
- {
- if(temp_s-temp_m>=100)
- {
- PWM=100;
- }
- else
- {
- PWM = pid_calc(&temp_PID,temp_m);
- if( PWM>=100 ) PWM=100;
- else if(PWM<=1) PWM=1;
- }
- }
- if(time_value==60) //显示温度
- {
- display_real_temp(temp_m);
- }
- if(time_value==70)
- {
- send_string(" PWM:");
- DtoA(PWM,massage);
- send_string(massage);
- /*
- PWM_P = PWM;
-
- LcdWriteCom(0x80+0X40+0x0C);
- LcdWriteData('0'+PWM_P/100);
- LcdWriteCom(0x80+0X40+0x0D);
- LcdWriteData('0'+PWM_P%100/10);
- LcdWriteCom(0x80+0X40+0x0E);
- LcdWriteData('0'+PWM_P%10);
-
- */
- send_string(" PWM:");
- DtoA(PWM,massage);
- send_string(massage);
-
- send_string(" PWM_P:");
- DtoA(PWM_P,massage);
- send_string(massage);
-
- send_string(" 设置温度:");
- DtoA(up_limit_temp,massage);
- send_string(massage);
-
- send_string(" 实际温度:");
- DtoA(temp_m,massage);
- send_string(massage);
- send_string(" temp_s:");
- DtoA(temp_s,massage);
- send_string(massage);
-
- send_string(" temp_PID.SetPoint:");
- DtoA(temp_PID.SetPoint,massage);
- send_string(massage);
- send_string("\n");
- }
- if(time_value>=100) //指令执行时间,一个单位时间是10ms
- {
- time_value=0;
- }
- if(time_heatting >= 500) time_heatting = 0;
- if(time_heatting <= PWM*5)
- {
- heatting=1;
- }
- else
- {
- heatting=0;
- }
- }
- }
- /*******************************************************************************
- * 函数名 : void init()
- * 函数功能 : 初始化函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void init()//初始化函数
- {
- uint i,j;
- Ds18b20Init();//Ds18b20初始化
- //heatting=0;//不制热
-
- IT0Init();
- IT1Init();
- InitUart0();
- InitTimer0();//定时器初始化
- pid_init (&temp_PID);//PID初始化
-
- LcdInit();//LCD初始化函数
-
- LcdWriteCom(0x80);//第一行显示
- j=strlen(num1);
- for(i=0; i<j; i++)
- {
- LcdWriteData(num1[i]);
- delay_ms(1);
- }
- LcdWriteCom(0x80+0x40);//第二行显示
- j=strlen(num2);
- for(i=0; i<j; i++)
- {
- LcdWriteData(num2[i]);
- delay_ms(1);
- }
- LcdWriteCom(0x04); //关闭写一个指针加1
- }
- /*******************************************************************************
- * 函数名 : uint get_temp(uint temp)
- * 函数功能 : 计算温度函数
- * 输入 : 温度
- * 输出 : 温度
- *******************************************************************************/
- uint get_temp(uint temp)//计算温度函数
- {
- float tp;
-
- tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
- //如果温度是正的那么,那么正数的原码就是补码它本身
- temp=tp*0.0625*100+0.5;
- //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
- //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
- //算加上0.5,还是在小数点后面。
- return temp;
- }
- /*******************************************************************************
- * 函数名 : void display_real_temp(uint temp)
- * 函数功能 : 实时温度显示函数
- * 输入 : 温度
- * 输出 : 无
- *******************************************************************************/
- void display_real_temp(uint temp)//实时温度显示函数
- {
- uchar datas[] = {0, 0, 0, 0}; //定义数组
- datas[0] = temp % 10000 / 1000;
- datas[1] = temp % 1000 / 100;
- datas[2] = temp % 100 / 10;
- datas[3] = temp % 10;
-
- LcdWriteCom(0x80+0x0a); //写地址 80表示初始地址
- LcdWriteData('0'+datas[0]); //十位
- LcdWriteCom(0x80+0x0b); //写地址 80表示初始地址
- LcdWriteData('0'+datas[1]); //个位
- LcdWriteCom(0x80+0x0d); //写地址 80表示初始地址
- LcdWriteData('0'+datas[2]); //显示小数点
- LcdWriteCom(0x80+0x0e); //写地址 80表示初始地址
- LcdWriteData('0'+datas[3]); //显示小数点
- }
- /*******************************************************************************
- * 函数名 : void InitTimer0(void)
- * 函数功能 : 定时器初始化函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void InitTimer0(void)
- {
- TMOD &= 0xF0;
- TMOD |= 0x01;//设置定时模式1
- TH0 = 0xD8;
- TL0 = 0xF0;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- /*******************************************************************************
- * 函数名 : void Timer0Interrupt(void) interrupt 1
- * 函数功能 : 定时器中断函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void Timer0Interrupt(void) interrupt 1
- {
- TH0 = 0xD8;
- TL0 = 0xF0;
-
- time_value++; //功能计数值+1
- time_heatting++; //加热计数值+1
- }
- /*******************************************************************************
- * 函数名 : void INIT0(void) interrupt 0
- * 函数功能 : 外部中断0执行函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void INIT0(void) interrupt 0
- {
-
- delay_ms(5);
- if (increase_temperature == 0)
- {
- while(increase_temperature == 0);
- if(up_limit_temp<=110)
- {
- up_limit_temp=up_limit_temp+5;
- LcdWriteCom(0x80+0X40+0x03);
- LcdWriteData('0'+up_limit_temp%1000/100);
- LcdWriteCom(0x80+0X40+0x04);
- LcdWriteData('0'+up_limit_temp%100/10);
- LcdWriteCom(0x80+0X40+0x05);
- LcdWriteData('0'+up_limit_temp%10);
- }
- }
- }
- /*******************************************************************************
- * 函数名 : void INIT1(void) interrupt 2
- * 函数功能 : 外部中断1执行函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void INIT1(void) interrupt 2
- {
-
- delay_ms(5);
- if (reduce_temperature == 0)
- {
- while(reduce_temperature == 0);
- if(up_limit_temp>=20)
- {
- up_limit_temp=up_limit_temp-5;
- LcdWriteCom(0x80+0X40+0x03);
- LcdWriteData('0'+up_limit_temp%1000/100);
- LcdWriteCom(0x80+0X40+0x04);
- LcdWriteData('0'+up_limit_temp%100/10);
- LcdWriteCom(0x80+0X40+0x05);
- LcdWriteData('0'+up_limit_temp%10);
- }
- }
-
- }
- /*******************************************************************************
- * 函数名 : void IT0Init(void)
- * 函数功能 : 外部中断0初始化
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void IT0Init(void)
- {
- IT0 = 0;//0为电平,1为下降沿
- EX0 = 1;//外部中断1
- }
- /*******************************************************************************
- * 函数名 : void IT1Init(void)
- * 函数功能 : 外部中断1初始化
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void IT1Init(void)
- {
- IT1 = 0;//0为电平,1为下降沿
- EX1 = 1;//外部中断0
- }
- /*******************************************************************************
- * 函数名 : void InitUart0(void)
- * 函数功能 : 串口中断初始化
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void InitUart0(void)
- {//设计波特率:4800bps;实际波特率:4464bps
- TMOD&=0x0F;
- TMOD|=0x20;
- SCON=0x50;
- PCON|=0x80;
- TH1 = 0xF3;
- TL1 = 0xF3;
- ES = 1; //使能串口中断 ,无论是TI/RI出现,只要中断打开,单片机就进入中断函数。
- TR1 = 1;
- //ET1 = 0;//禁止T1中断
- }
- /*******************************************************************************
- * 函数名 : void IT1Init(void)
- * 函数功能 : 串口中断函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void Usart() interrupt 4
- {
- //uchar receiveData;
- //receiveData=SBUF;//出去接收到的数据
- RI = 0;//清除接收中断标志位
-
- //SBUF=receiveData;//将接收到的数据放入到发送寄存器
- //while(!TI); //等待发送数据完成
- //TI=0; //清除发送完成标志
- //massage[0]=0;
-
- }
- /*******************************************************************************
- * 函数名 : void send_byte(uchar by)
- * 函数功能 : 串口发送字节函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void send_byte(uchar by)
- {
- SBUF = by;
- while(!TI);//当写下这句的时候,就不要在中断函数里面在写TI = 0;这句了,不然进入中断函数将TI清零之后,程序就会一直卡在这里
- TI = 0; //在这里将TI清零
- }
- /*发送一个字符串*/
- /*******************************************************************************
- * 函数名 : void send_string(uchar *p)
- * 函数功能 : 串口发送字符串函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void send_string(uchar *p)
- {
- while(*p!= '\0')
- {
-
- send_byte(*p);
- p++;
- }
- }
- /*******************************************************************************
- * 函数名 : void DtoA(unsigned long dat, unsigned char* buffer)
- * 函数功能 : 串口发送字符串函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
-
- void DtoA(uint dat, unsigned char* buffer)
- {
- uint tmp = 0;
- char length = 0;
- tmp = dat;
- while(tmp != 0)//求出数字的实际长度
- {
- tmp = tmp/10;
- length++;
- }
- buffer[length] = '\0';//长度数为字符串截止位
- length--;
- while(length >= 0)//数字的低位放入数组的高位
- {
- tmp = dat%10;
- buffer[length--] = 0x30|tmp;
- dat = dat/10;
- }
- }
复制代码 全部资料51hei下载地址:
PID恒温控制器.zip
(113.68 KB, 下载次数: 20)
|