找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 397|回复: 0
打印 上一主题 下一主题
收起左侧

PID温度控制出现问题

[复制链接]
跳转到指定楼层
楼主
ID:1125252 发表于 2024-10-14 09:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PID恒温控制出现可以加热,但是不能关闭加热,大佬们帮忙看下是啥问题?是数据符号类型不一致吗?**********************************************************************************************************************//*********************************************************************************************************************/#define INT_TIME                        1000        //定时时间,单位为us#define        TH_VAL                                (unsigned char)((0x10000 - (INT_TIME*(FOSC/1000))/12000)>>8)#define        TL_VAL                                (unsigned char)((0x10000 - (INT_TIME*(FOSC/1000))/12000))void TIMER0_ISR (void) interrupt 1         //每1ms产生中断{        TH0 = TH_VAL;        TL0 = TL_VAL;        count++;        if(count>=10)                                //10ms        {                cnt++;                                //计数                count=0;        }        //        P03 = ~P03;}void Timer0_Init(void){        TMOD = (TMOD&0xFC)|0x01;                 //模式选择: 定时器0,模式1。        TH0 = TH_VAL;                                    //高8位装初值        TL0 = TL_VAL;                                    //低8位装初值                TR0 = 1;                                               //定时器0使能          ET0 = 1;                                               //定时器0中断使能                EA = 1;//        PT0 = 1;                                               //设置定时器0中断优先级为高优先级        }/***********************************************************************************函数名称: ADC_Init                                                                                         功能描述: 初始化ADC寄存器(设置ADC时钟、设置采样时间、选择ADC参考电压)输入参数: 无返 回 值: 无***********************************************************************************/void ADC_Init(void){//         ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(1) | VSEL(ADC_REF_INNER);        //设置ADC参考电压为内部1.5V        ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(0) | VSEL(ADC_REF_VDD);                //设置ADC参考电压为VDD         ADCFGL = ACKD(7);        P06F = P06_ADC8_SETTING;                                                                                                //设置P0.6为ADC引脚功能}/***********************************************************************************函数名称: Get_AdcValue                                                                                         功能描述: 获取ADC转换数值输入参数: channel ADC通道号返 回 值: ADC值***********************************************************************************/unsigned int Get_AdcValue(unsigned char channel){        unsigned int AD_Value;                ADCFGL = (ADCFGL&0xE0) | ADCHS(channel);                //选择ADC通道        ADCON |= AST(1);                                                                //启动ADC转换        while(!(ADCON & ADIF));                                                        //等待ADC转换完成        ADCON |= ADIF;                                                                        //清除ADC中断标志        AD_Value = ADCDH*256 + ADCDL;                                        //读取AD值        AD_Value >>= 4;                               return AD_Value;}/*********************************************************************************************************************/struct _pid{        float Set_WD;                        //设定值        float Actual_WD;                //实际值                float err;                                //偏差        float err_last;                        //上一次偏差        float err_next;        float Kp,Ki,Kd;                       float voltage;                        //电压值        float integral;                        //积分值}pid;void PID_INIT(){        pid.Set_WD=0.0;        pid.Actual_WD=0.0;        pid.err=0.0;        pid.err_last=0.0;        pid.err_next=0.0;        pid.voltage=0.0;        pid.integral=0.0;        pid.Kp=0.4;        pid.Ki=0.5;        pid.Kd=0.4;}unsigned int temp=40;                             //设置温度值void PID_Realize(){                                   //PID控制        unsigned int index;        if(temp==40){temp_adc=1419;}        //100K热敏电阻40度温度值时对应的ADC值                pid.Set_WD=temp_adc;                       pid.err=pid.Set_WD-AD_Value;           if(pid.err>200 || pid.err<-200)              {                index=0;        }        else if(pid.err<100 || pid.err>-100)        {                index=1;                pid.integral+=pid.err;        }        else        {                if(pid.err>0)                {                        index=(200-pid.err)/100;                        pid.integral+=pid.err;                }                else                {                        index=(200+pid.err)/100;                        pid.integral+=pid.err;                }                       }        pid.voltage=pid.Kp*pid.err + pid.Ki*pid.integral + pid.Kd*(pid.err-pid.err_last);                pid.err_last=pid.err;                        PWM_OUT=pid.voltage*1.0;      //赋值给PWM_OUT        if(PWM_OUT>100){PWM_OUT=100;}   }void hot(unsigned int PWM)          //加热函数{        if(cnt<PWM){P07=1;}     //加热,        if(cnt>PWM){P07=0;}    //关闭加热        if(cnt>100){cnt=0;}}/*********************************************************************************************************************/void System_Init(void){        LVDCON = 0xE0;                                        //开启LVD,设置为低电压复位模式,检测电压为2.7V                           #ifdef SYSCLK_8MHZ                                               CKDIV = 0;                                                //系统时钟上电默认为IRCH的二分频(4MHz),运行8MHz,则CKDIV设置为0#endif        #ifdef UART1_EN        Uart1_Initial(UART1_BAUTRATE);#endif        }void main(void){                P06F = INPUT | PU_EN;                //ADC脚        P07F = OUTPUT | PU_EN;                //加热脚        P06=1;        P07=0;                                               System_Init();        EA = 1;                                //开全局中断        Timer0_Init();                    //定时器初始化        ADC_Init();                        //初始化ADC        PID_INIT();                      //PID初始化        while(1)        {                        AD_Value = Get_AdcValue(ADC_CH8);        //获取温度值                PID_Realize();   //PID运算                hot(PWM_OUT);//控制加热        }}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表