STC15实现温控闭环控制,数码管显示温度,按键调节温度,PID控制
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控制相关推荐
- 单片机原理及其应用——单片机外部中断实验(八段数码管通过按键依次显示0~9数字)
目录 一.实验要求 二.知识要点 (一)数码管 (二)八段数码管的字形编码 (三)C51变量定义的四要素 (四)中断源 (五)相关的特殊功能寄存器 1.定时器/计数器控制寄存器TCON 2.中断允许控 ...
- 矩阵键盘数 码管显示多位数 c语言,4×4矩阵键盘数码管显示按键值程序
4×4矩阵键盘数码管显示按键值程序本文引用地址:http://www.eepw.com.cn/article/201607/294422.htm //电路说明如下. //单片机:使用51系列兼容的即可 ...
- 基于51单片机定时器计数+2片74HC595联级+8位数码管时钟+按键修改时间
基于51单片机定时器计数+2片74HC595联级+8位数码管时钟+按键修改时间 Proteus仿真 实例代码 #include "at89x52.h" /**74hc595引脚定义 ...
- Proteus VSM Studio汇编 + 8位数码管时钟按键可调
Proteus VSM Studio汇编 + 8位数码管时钟按键可调 Proteus基于VSM Studio编译仿真演示 VSM Studio代码(.asm) 基于Keil编译器 S_SET BIT ...
- 20141115 【 Arduino - LM35 - 4位八段数码管 】 数码管显示温度
4位八段数码管型号:SMA420564 引脚图如下: 通过公式,转换成温度值(摄氏度,精确到小数点后一位). 不过 LM35 之前被我正负极反接, 结果温度升的奇高(手测超过80°C), 不知道有没有 ...
- 51单片机DS18B20温度传感器及数码管显示温度
51单片机DS18B20温度传感器及数码管显示温度 大家好,今天给大家带来的代码及原理解释是,在51单片机在接收DS18B20温度传感器数据,并且在数码管上实时显示温度 DS18B20及数码管显示温度 ...
- 国信长天单片机之led、数码管与按键
目录 一.LED模块 二.数码管模块 三.按键模块 四.相关代码 config.h文件 config.c文件 main.c文件 在蓝桥杯单片机比赛中,LED灯.数码管.按键这三个模块的重要性我就不明说 ...
- 4*4矩阵键盘扫描c语言,用扫描法读出4×4矩阵键盘,在数码管显示按键值
原标题:用扫描法读出4×4矩阵键盘,在数码管显示按键值 //电路说明如下. //:使用51系列兼容的即可: //4×4:接在P1口: //两位数码显示器: P0口输出七段码,P2口输出位选码. //= ...
- PID温控实验平台搭建(四)——PID温控系统实验代码讲解
PID温控实验平台搭建 (一)PID基础知识介绍 (二)PID进阶知识介绍及源码分享 (三)从零开始搭建STM32温控实验平台 (四)PID温控系统代码讲解 (五)最终实验现象与总结 文章目录 前言 ...
最新文章
- java为什么序列化不一致_java – 为什么Jackson多态序列化在列表中不起作用?
- html表格上下移动,Vue实现table上下移动功能示例
- GitHub开源项目!一款功能强大的特征选择工具
- mysql 数据库异常大_Mysql连接数据库异常汇总【必收藏】
- RabbitMQ中的消息确认ACK机制
- QT的foreach用法
- find linux 目录深度_浪里淘沙,详解Linux系统中Find命令的实用技巧
- linux mysql安装_LINUX 安装 MYSQL
- 【科普篇】推荐系统之矩阵分解模型
- 18岁参加工作,工龄30年
- [bbk4965] 第102集 -第13章 - 表空间管理 00
- HTML 基础和实例
- 视频编辑软件(Nero Video2021中文版) v23.0.1.12pjb
- eyb:Java代码通过FastDFS实现文件上传
- 安卓车载中控竖屏分三屏
- java 双三次线性插值_双三次插值算法实现
- SQLServer简繁互换
- 报错 Missing number, treated as zero. \begin{subfigure}{0.24\linewidth}?怎么解决
- 2019 ICPC南昌网络赛 E题 Magic Master 【双向队列】
- PADS打开PCB文件时出现提示:发生严重的运行时错误。