STC15实现温控闭环控制,数码管显示温度,按键调节温度,PID控制

1.控温系统的PWM控制方案
① 加热元件和驱动电路设计
② 控温的工作原理及加热元件的数学模型,特别是模型参数的确定
③ PCA、PWM波形产生方法
ⅰ) 寄存器配置及编程
ⅱ) 8位PWM与16位PWM产生方法
2.温度采样原理与实现方法
① 温度传感器工作原理与输出关系
② 放大电路设计
③ A/D转换程序设计
3.温度控制闭环系统结构图与数学模型建立,以及与MCU的关系(参考下图设计出本系统结构)

① PID数字控制与编程方法
② PID参数整定
4.温度设定与显示
① LED数码管显示的电路设计及相关计算
② 数码管控制方案与温度显示的编程方法
③ 键盘设置的电路设计与编程方法

#include "STC15.H"
#include "intrins.h"#define display P2
typedef unsigned char uchar;
typedef unsigned int uint;sbit Led_CS1 = P0^0;     //位定义
sbit Led_CS2 = P0^1;
sbit Led_CS3 = P0^2;
sbit Led_CS4 = P0^3;
sbit Key_Tup = P0^4;
sbit Key_Tdown = P0^5;
sbit Key_Confirm = P0^6;//数码管数值码表  共阳极接法
uchar code TABLE[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80, 0x90};
char SetT = 40;            //设定温度初始化为 40 摄氏度
float RealT = 25;              //实际温度初始化为 25 摄氏度
float Error = 0;           //当前误差
float ErrorInt = 0;            //累积误差          设定温度太大可能溢出
float Kp = 25,Ki = 0.5e-3;    //PID参数
float u;                    //控制量
float pwmduty;              //PWM波占空比
//uint ADCRESValue;         //ADC10位采样值     调试实际温度数码管闪烁时用void IO_Init();                //IO端口初始化
void AD_Init();             //AD模块初始化
void PWM_Init();            //PWM模块初始化void SetTemperature();        //设定温度
void KeyScan();             //按键扫描
void SetTdisp();            //设定温度显示
void RealTdisp();           //实际温度显示
void getRealT();            //测温
void PIDControl();          //PID调节
void PWMOutput();           //PWM/DA输出
//void ADCRESshow();        //AD采样后,寄存器值显示   调试实际温度数码管闪烁时用
void delay1ms();
void delay5ms();void main()
{                           IO_Init();              //与数码管段选、片选以及按键有关的Io端口初始化AD_Init();             //AD模块初始化PWM_Init();                //PWM模块初始化while(1){SetTemperature();    //设定温度getRealT();           //测温PIDControl();       //PID调节PWMOutput();     //PWM/DA输出SetTdisp();           //设定温度显示RealTdisp();        //实际温度显示//      ADCRESshow();       //AD采样后,寄存器值显示   调试实际温度数码管闪烁时用}return;
}void IO_Init()         //与数码管段选、片选以及按键有关的Io端口初始化
{P0M1 = 0xF0;      // P0.0~P0.3 初始化为输出;P0.4~P0.7初始化为输入P0M0 = 0x0F;P2M1 = 0x00;        // P2口初始化为输出P2M0 = 0xFF;   return;
}void AD_Init()         //AD模块初始化
{P1ASF = 0x01;     //设定 P1.0 作为AD使用ADC_CONTR = 0x60;  //关闭ADC电源;90个时钟周期转换1次//结束标志位、启动控制位清零;输入通道选择 P1.0CLK_DIV &= 0xDF; //ADRJ:ADC转换结果存放位置调整EA = 1;             //CPU开放中断;禁止AD转换中断EADC = 0;PADC = 1;           //AD转换中断为最高优先级return;
}void PWM_Init()            //PWM模块初始化
{P1M1 &= 0xFD;     //P1.1设为输出P1M0 |= 0x02;    CMOD = 0x80;       //空闲模式下计数器停止计数;时钟源输入选择 SYSCLK/12//禁止计数器溢出中断CCON = 0x00;     //溢出标志位CF清零;运动控制位清零;//PCA模块0、1、2中断标志清零CCAPM0 = 0x42;     //PCA模块0工作于PWM模式;禁止CCF0中断PCA_PWM0 = 0x00;   //8位PWM功能;EPC0H = EPC0L = 0P_SW1 &= 0xCF;     //CCP切换为P1CH = 0x00;           //PCA装载值清零CL = 0x00;CCAP0H = 0xFF;        //捕获寄存器值,初始化占空比为 1/256CCAP0L = 0xFF;       CCON |= 0x40;      //启动PWM输出return;
}void SetTemperature()                  //设定温度
{if( !(Key_Tup & Key_Tdown) )       //检测 升温/降温 按键是否按下{                                  //进入设定温度过程uchar i,j;do{KeyScan();                   //按键扫描getRealT();                   //测温for(i=0;i<2;i++)          //设定温度闪烁显示,用来指示设定温度过程{                           //实际温度常量if( i==0 )                //设定温度显示for(j=0;j<20;j++){SetTdisp();RealTdisp();}if( i==1 )                //设定温度不显示for(j=0;j<20;j++){delay5ms();delay5ms();RealTdisp();}}}while(Key_Confirm);           //直到确认键按下,退出设定温度过程}return;
}void KeyScan()                         //按键扫描
{static uchar flag = 0;                //设置标志位if( !(Key_Tup & Key_Tdown) )     //检测 升温/降温 按键是否按下{if(!flag)                     //标志位为0时才进行 升温/降温,产生延时效果{                                //防止按键按下过程中 升温/降温 多次,同时不占用CPUif(!Key_Tup)                //升温{SetT++;if(SetT > 99)SetT = 0;}if(!Key_Tdown)             //降温{SetT--;if(SetT < 0)SetT = 0;}}flag++;                            //标志位加一if(flag == 15);                    //标志位加到15清零flag = 0;}           else                               //无按键按下,标志位清零flag = 0;return;
}void SetTdisp()                            //设定温度显示
{Led_CS1 = 0;Led_CS2 = 1;Led_CS3 = 1;Led_CS4 = 1;display = TABLE[SetT/10];delay5ms();Led_CS1 = 1;Led_CS2 = 0;Led_CS3 = 1;Led_CS4 = 1;display = TABLE[SetT%10];delay5ms();Led_CS1 = 1;Led_CS2 = 1;Led_CS3 = 1;Led_CS4 = 1;return;
}void RealTdisp()                       //实际温度显示
{uchar T = (uchar) RealT;Led_CS1 = 1;Led_CS2 = 1;Led_CS3 = 0;Led_CS4 = 1;display = TABLE[T/10];delay5ms();Led_CS1 = 1;Led_CS2 = 1;Led_CS3 = 1;Led_CS4 = 0;display = TABLE[T%10];delay5ms();Led_CS1 = 1;Led_CS2 = 1;Led_CS3 = 1;Led_CS4 = 1;return;
}void getRealT()                            //测温
{/*uint AD_Data = 0;uchar Temp = 0;ADC_CONTR |= 0x80;delay1ms();ADC_CONTR |= 0x08;while( !(ADC_CONTR & 0x10) );ADC_CONTR &= 0x67;//    AD_Data = ADC_RES;                 //(1)无滤波
//  AD_Data <<= 2;
//  Temp = ADC_RESL;
//  Temp &= 0x03;
//  AD_Data |= Temp;ADC_RESL &= 0x03;                 //(2)无滤波RealT = (uchar)((ADC_RES*4+ADC_RESL)/1023.0*100); //出现bug,以后注意!!!*/uint temp = 0;                        //(3)均值滤波   效果最好uchar i;ADC_CONTR |= 0x80;                 //开电源delay1ms();                            //延时1msfor(i = 0;i < 20;i++)              //采样20次{ADC_CONTR |= 0x08;             //开始采样while( !(ADC_CONTR & 0x10) ); //查询转换是否完成ADC_CONTR &= 0xE7;               //停止转换,清标志位ADC_RESL &= 0x03;                //计算10位采样值temp += ADC_RES*4+ADC_RESL;    }ADC_CONTR &= 0x7F;                    //关电源// ADCRESValue = temp/20;             //计算20次10位采样值的平均值//调试实际温度数码管闪烁时用RealT = temp/20.0/1023.0*100;      //计算20次平均温度/*uint SampleValue[31] = {0},temp;  //(4)中值滤波   不太稳定    uchar i,j,k;ADC_CONTR |= 0x80;                 //开电源delay1ms();                            //延时1msADC_CONTR |= 0x08;                  //采第一个值while( !(ADC_CONTR & 0x10) );ADC_CONTR &= 0xE7;ADC_RESL &= 0x03;SampleValue[0] = ADC_RES*4+ADC_RESL;for(i = 1;i < 31;i++)              //再采20个(共21个)   同时将21个值排序{ADC_CONTR |= 0x08;while( !(ADC_CONTR & 0x10) );ADC_CONTR &= 0xE7;ADC_RESL &= 0x03;temp = ADC_RES*4+ADC_RESL;for(j = 0;j < i;j++){if(temp < SampleValue[j]){for(k = i;k > j;k--)SampleValue[k] = SampleValue[k-1];SampleValue[j] = temp;break; }}if(j == i){SampleValue[j] = temp;}}ADC_CONTR &= 0x7F;                 //关电源// ADCRESValue = SampleValue[15];     //取中值   调试实际温度数码管闪烁时用RealT = (uchar)( SampleValue[15]/1023.0*100 );    //计算实际温度*/return;
}void PIDControl()                          //PID调节
{Error = (float)SetT - RealT;          //注意数据类型!!!ErrorInt += Error;u = Kp*Error + Ki*ErrorInt;return;
}void PWMOutput()                           //PWM/DA输出
{pwmduty = u/255;                      //计算占空比if(pwmduty >0.9)                      //占空比限幅pwmduty = 0.9;if(pwmduty < 0.1)pwmduty = 0.1;CCAP0H = (uchar)(256*(1-pwmduty));        //占空比调节return;
}void delay1ms()
{unsigned char a,b;for(b=4;b>0;b--)for(a=248;a>0;a--);_nop_();  //if Keil,require use intrins.h
}void delay5ms()
{unsigned char a,b;for(b=19;b>0;b--)for(a=130;a>0;a--);
}//void ADCRESshow()                        //AD采样后,寄存器值显示
//{                                     //调试实际温度数码管闪烁时用
//
    ADCRESValue = ADC_RES*4+ADC_RESL; //不使用滤波算法时使用
    ADCRESValue = (uint)ErrorInt;      //可以观测误差变化
    ADCRESValue = (uint)ErrorInt;      //可以观测误差累积的变化
//
//  Led_CS1 = 0;
//  Led_CS2 = 1;
//  Led_CS3 = 1;
//  Led_CS4 = 1;
//  display = TABLE[ADCRESValue/1000];
//  ADCRESValue -= (ADCRESValue/1000)*1000;
//  delay5ms();
//
//  Led_CS1 = 1;
//  Led_CS2 = 0;
//  Led_CS3 = 1;
//  Led_CS4 = 1;
//  display = TABLE[ADCRESValue/100];
//  ADCRESValue -= (ADCRESValue/100)*100;
//  delay5ms();
//
//
//  Led_CS1 = 1;
//  Led_CS2 = 1;
//  Led_CS3 = 0;
//  Led_CS4 = 1;
//  display = TABLE[ADCRESValue/10];
//  delay5ms();
//
//  Led_CS1 = 1;
//  Led_CS2 = 1;
//  Led_CS3 = 1;
//  Led_CS4 = 0;
//  display = TABLE[ADCRESValue%10];
//  delay5ms();
//
//  Led_CS1 = 1;
//  Led_CS2 = 1;
//  Led_CS3 = 1;
//  Led_CS4 = 1;
//
//  return;
//}

STC15实现温控闭环控制,数码管显示温度,按键调节温度,PID控制相关推荐

  1. 单片机原理及其应用——单片机外部中断实验(八段数码管通过按键依次显示0~9数字)

    目录 一.实验要求 二.知识要点 (一)数码管 (二)八段数码管的字形编码 (三)C51变量定义的四要素 (四)中断源 (五)相关的特殊功能寄存器 1.定时器/计数器控制寄存器TCON 2.中断允许控 ...

  2. 矩阵键盘数 码管显示多位数 c语言,4×4矩阵键盘数码管显示按键值程序

    4×4矩阵键盘数码管显示按键值程序本文引用地址:http://www.eepw.com.cn/article/201607/294422.htm //电路说明如下. //单片机:使用51系列兼容的即可 ...

  3. 基于51单片机定时器计数+2片74HC595联级+8位数码管时钟+按键修改时间

    基于51单片机定时器计数+2片74HC595联级+8位数码管时钟+按键修改时间 Proteus仿真 实例代码 #include "at89x52.h" /**74hc595引脚定义 ...

  4. Proteus VSM Studio汇编 + 8位数码管时钟按键可调

    Proteus VSM Studio汇编 + 8位数码管时钟按键可调 Proteus基于VSM Studio编译仿真演示 VSM Studio代码(.asm) 基于Keil编译器 S_SET BIT ...

  5. 20141115 【 Arduino - LM35 - 4位八段数码管 】 数码管显示温度

    4位八段数码管型号:SMA420564 引脚图如下: 通过公式,转换成温度值(摄氏度,精确到小数点后一位). 不过 LM35 之前被我正负极反接, 结果温度升的奇高(手测超过80°C), 不知道有没有 ...

  6. 51单片机DS18B20温度传感器及数码管显示温度

    51单片机DS18B20温度传感器及数码管显示温度 大家好,今天给大家带来的代码及原理解释是,在51单片机在接收DS18B20温度传感器数据,并且在数码管上实时显示温度 DS18B20及数码管显示温度 ...

  7. 国信长天单片机之led、数码管与按键

    目录 一.LED模块 二.数码管模块 三.按键模块 四.相关代码 config.h文件 config.c文件 main.c文件 在蓝桥杯单片机比赛中,LED灯.数码管.按键这三个模块的重要性我就不明说 ...

  8. 4*4矩阵键盘扫描c语言,用扫描法读出4×4矩阵键盘,在数码管显示按键值

    原标题:用扫描法读出4×4矩阵键盘,在数码管显示按键值 //电路说明如下. //:使用51系列兼容的即可: //4×4:接在P1口: //两位数码显示器: P0口输出七段码,P2口输出位选码. //= ...

  9. PID温控实验平台搭建(四)——PID温控系统实验代码讲解

    PID温控实验平台搭建 (一)PID基础知识介绍 (二)PID进阶知识介绍及源码分享 (三)从零开始搭建STM32温控实验平台 (四)PID温控系统代码讲解 (五)最终实验现象与总结 文章目录 前言 ...

最新文章

  1. java为什么序列化不一致_java – 为什么Jackson多态序列化在列表中不起作用?
  2. html表格上下移动,Vue实现table上下移动功能示例
  3. GitHub开源项目!一款功能强大的特征选择工具
  4. mysql 数据库异常大_Mysql连接数据库异常汇总【必收藏】
  5. RabbitMQ中的消息确认ACK机制
  6. QT的foreach用法
  7. find linux 目录深度_浪里淘沙,详解Linux系统中Find命令的实用技巧
  8. linux mysql安装_LINUX 安装 MYSQL
  9. 【科普篇】推荐系统之矩阵分解模型
  10. 18岁参加工作,工龄30年
  11. [bbk4965] 第102集 -第13章 - 表空间管理 00
  12. HTML 基础和实例
  13. 视频编辑软件(Nero Video2021中文版) v23.0.1.12pjb
  14. eyb:Java代码通过FastDFS实现文件上传
  15. 安卓车载中控竖屏分三屏
  16. java 双三次线性插值_双三次插值算法实现
  17. SQLServer简繁互换
  18. 报错 Missing number, treated as zero. \begin{subfigure}{0.24\linewidth}?怎么解决
  19. 2019 ICPC南昌网络赛 E题 Magic Master 【双向队列】
  20. PADS打开PCB文件时出现提示:发生严重的运行时错误。

热门文章

  1. 鼠标交互的使用与优化
  2. showmore网页录屏操作指南
  3. 文华财经指标公式博易大师软件指标公式期货多空买卖指标图,文华加密破解二次加密
  4. 动态网站的制作与设计_北京网站设计的新秀——“动态网页”
  5. 攻防世界 -- very_easy_sql
  6. Android实战项目: 视频资讯APP,源码在文章里免费分享
  7. 每日一练--IT冷知识C/C++--第八天
  8. 直流变频电机驱动的技术原理及特点
  9. 惠买车利剑出鞘 易车平台化战略再布一子
  10. 安全运维 | Linux系统基线检查