收藏 评论 分享到 微博 QQ 微信 LinkedIn #include #include #include #include struct PID { unsigned int SetPoint; // 设定目标 Desired Value unsigned int Proportion; // 比例常数 Proportional Const unsigned int Integral; // 积分常数 Integral Const unsigned int Derivative; // 微分常数 Derivative Const unsigned int LastError; // Error[-1] unsigned int PrevError; // Error[-2] unsigned int SumError; // Sums of Errors }; struct PID spid; // PID Control Structure unsigned int rout; // PID Response (Output) unsigned int rin; // PID Feedback (Input) sbit data1=P1^0; sbit clk=P1^1; sbit plus=P2^0; sbit subs=P2^1; sbit stop=P2^2; sbit output=P3^4; sbit DQ=P3^3; unsigned char flag,flag_1=0; unsigned char high_time,low_time,count=0;//占空比调节参数 unsigned char set_temper=35; unsigned char temper; unsigned char i; unsigned char j=0; unsigned int s; /*********************************************************** 延时子程序,延时时间以12M晶振为准,延时时间为30us×time ***********************************************************/ void delay(unsigned char time) { unsigned char m,n; for(n=0;n for(m=0;m<2;m++){} } /*********************************************************** 写一位数据子程序 ***********************************************************/ void write_bit(unsigned char bitval) { EA=0; DQ=0; /*拉低DQ以开始一个写时序*/ if(bitval==1) { _nop_(); DQ=1; /*如要写1,则将总线置高*/ } delay(5); /*延时90us供DS18B20采样*/ DQ=1; /*释放DQ总线*/ _nop_(); _nop_(); EA=1; } /*********************************************************** 写一字节数据子程序 ***********************************************************/ void write_byte(unsigned char val) { unsigned char i; unsigned char temp; EA=0; TR0=0; for(i=0;i<8;i++) /*写一字节数据,一次写一位*/ { temp=val>>i; /*移位操作,将本次要写的位移到最低位*/ temp=temp&1; write_bit(temp); /*向总线写该位*/ } delay(7); /*延时120us后*/ // TR0=1; EA=1; } /*********************************************************** 读一位数据子程序 ***********************************************************/ unsigned char read_bit() { unsigned char i,value_bit; EA=0; DQ=0; /*拉低DQ,开始读时序*/ _nop_(); _nop_(); DQ=1; /*释放总线*/ for(i=0;i<2;i++){} value_bit=DQ; EA=1; return(value_bit); } /*********************************************************** 读一字节数据子程序 ***********************************************************/ unsigned char read_byte() { unsigned char i,value=0; EA=0; for(i=0;i<8;i++) { if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01< delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/ } EA=1; return(value); } /*********************************************************** 复位子程序 ***********************************************************/ unsigned char reset() { unsigned char presence; EA=0; DQ=0; /*拉低DQ总线开始复位*/ delay(30); /*保持低电平480us*/ DQ=1; /*释放总线*/ delay(3); presence=DQ; /*获取应答信号*/ delay(28); /*延时以完成整个时序*/ EA=1; return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/ } /*********************************************************** 获取温度子程序 ***********************************************************/ void get_temper() { unsigned char i,j; do { i=reset(); /*复位*/ }while(i!=0); /*1为无反馈信号*/ i=0xcc; /*发送设备定位命令*/ write_byte(i); i=0x44; /*发送开始转换命令*/ write_byte(i); delay(180); /*延时*/ do { i=reset(); /*复位*/ }while(i!=0); i=0xcc; /*设备定位*/ write_byte(i); i=0xbe; /*读出缓冲区内容*/ write_byte(i); j=read_byte(); i=read_byte(); i=(i<<4)&0x7f; s=(unsigned int)(j&0x0f); s=(s*100)/16; j=j>>4; temper=i|j; /*获取的温度放在temper中 */ } /*========================================================================= =========================== Initialize PID Structure =========================================================================== ==========================*/ void PIDInit (struct PID *pp) { memset ( pp,0,sizeof(struct PID)); } /*========================================================================= =========================== PID计算部分 =========================================================================== ==========================*/ unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) { unsigned int dError,Error; Error = pp->SetPoint - NextPoint; // 偏差 pp->SumError += Error; // 积分 dError = pp->LastError - pp->PrevError; // 当前微分 pp->PrevError = pp->LastError; pp->LastError = Error; return (pp->Proportion * Error // 比例项 + pp->Integral * pp->SumEror // 积分项 + pp->Derivative * dError); // 微分项 } /*********************************************************** 温度比较处理子程序 ***********************************************************/ compare_temper() { unsigned char i; if(set_temper>temper) { if(set_temper-temper>1) { high_time=100; low_time=0; } else { for(i=0;i<10;i++) { get_temper(); rin = s; // Read Input rout = PIDCalc ( &spid,rin ); // Perform PID Interation } if (high_time<=100) high_time=(unsigned char)(rout/800); else high_time=100; low_time= (100-high_time); } } else if(set_temper<=temper) { if(temper-set_temper>0) { high_time=0; low_time=100; } else { for(i=0;i<10;i++) { get_temper(); rin = s; // Read Input rout = PIDCalc ( &spid,rin ); // Perform PID Interation } if (high_time<100) high_time=(unsigned char)(rout/10000); else high_time=0; low_time= (100-high_time); } } // else // {} } /***************************************************** T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期 ******************************************************/ void serve_T0() interrupt 1 using 1 { if(++count<=(high_time)) output=1; else if(count<=100) { output=0; } else count=0; TH0=0x2f; TL0=0xe0; } /***************************************************** 串行口中断服务程序,用于上位机通讯 ******************************************************/ void serve_sio() interrupt 4 using 2 { /* EA=0; RI=0; i=SBUF; if(i==2) { while(RI==0){} RI=0; set_temper=SBUF; SBUF=0x02; while(TI==0){} TI=0; } else if(i==3) { TI=0; SBUF=temper; while(TI==0){} TI=0; } EA=1; */ } void disp_1(unsigned char disp_num1[6]) { unsigned char n,a,m; for(n=0;n<6;n++) { // k=disp_num1[n]; for(a=0;a<8;a++) { clk=0; m=(disp_num1[n]&1); disp_num1[n]=disp_num1[n]>>1; if(m==1) data1=1; else data1=0; _nop_(); clk=1; _nop_(); } } } /***************************************************** 显示子程序 功能:将占空比温度转化为单个字符,显示占空比和测得到的温度 ******************************************************/ void display() { unsigned char code number[]= {0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6]; unsigned int k,k1; k=high_time; k=k%1000; k1=k/100; if(k1==0) disp_num[0]=0; else disp_num[0]=0x60; k=k%100; disp_num[1]=number[k/10]; disp_num[2]=number[k%10]; k=temper; k=k%100; disp_num[3]=number[k/10]; disp_num[4]=number[k%10]+1; disp_num[5]=number[s/10]; disp_1(disp_num); } /*********************************************************** 主程序 ***********************************************************/ main() { unsigned char z; unsigned char a,b,flag_2=1,count1=0; unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};; TMOD=0x21; TH0=0x2f; TL0=0x40; SCON=0x50; PCON=0x00; TH1=0xfd; TL1=0xfd; PS=1; EA=1; EX1=0; ET0=1; ES=1; TR0=1; TR1=1; high_time=50; low_time=50; PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8; spid.Derivative =6; spid.SetPoint = 100; // Set PID Setpoint while(1) { if(plus==0) { EA=0; for(a=0;a<5;a++) for(b=0;b<102;b++){} if(plus==0) { set_temper++; flag=0; } } else if(subs==0) { for(a=0;a<5;a++) for(b=0;a<102;b++){} if(subs==0) { set_temper--; flag=0; } } else if(stop==0) { for(a=0;a<5;a++) for(b=0;b<102;b++){} if(stop==0) { flag=0; break; } EA=1; } get_temper(); b=temper; if(flag_2==1) a=b; if((abs(a-b))>5) temper=a; else temper=b; a=temper; flag_2=0; if(++count1>30) { display(); count1=0; } compare_temper(); } TR0=0; z=1; while(1) { EA=0; if(stop==0) { for(a=0;a<5;a++) for(b=0;b<102;b++){} if(stop==0) disp_1(phil); // break; } EA=1; } } 关键字:51单片机 温度控制 PID算法 DS18B20 引用地址:51单片机-温度控制-PID算法-DS18B20-C语言 上一篇:用C51编写单片机延时函数 下一篇:单片机控制的LED数码管动态驱动电路 推荐阅读最新更新时间:2024-03-16 15:08 51单片机学习——4--数码管显示 数码管静态显示原理 显示器及其接口 单片机系统中常用的显示器有: 发光二极管LED(Light Emitting Diode)显示器、液晶LCD(Liquid Crystal Display)显示器、TFT液晶显示器等。LED显示器有两种显示结构:段显示(7段、米字型等)和点阵显示(5×8、8×8点阵等)。 LED数码管根据LED的不同接法可以分为2类:共阴和共阳。 使用LED显示器时,要注意区分这两种不同的接法。为了显示数字或字符,必须对数字或字符进行编码。七段数码管加上一个小数点,共计8段。因此为LED显示器提供的编码正好是一个字节。我们实验板用共阴LED显示器,根据电路连接图显示16进制数的编码已列在下表。 0x [单片机] 浅析51单片机P0口上拉电阻的选择应用 P0口作为I/O口输出的时候时,输出低电平为0 输出高电平为高组态(并非5V,相当于悬空状态,也就是说P0 口不能真正的输出高电平)。给所接的负载提供电流,因此必须接上拉电阻(一电阻连接到VCC),由电源通过这个上拉电阻给负载提供电流。 P0作输入时不需要上拉电阻,但要先置1。因为P0口作一般I/O口时上拉场效应管一直截止,所以如果不置1,下拉场效应管会导通,永远只能读到0。因此在输入前置1,使下拉场效应管截止,端口会处于高阻浮空状态,才可以正确读入数据。 由于P0口内部没有上拉电阻,是开漏的,不管它的驱动能力多大,相当于它是没有电源的,需要外部的电路提供,绝大多数情况下P0口是必需加上拉电阻的。 1.一般51 [单片机] 51单片机使用槽型光耦测速模块 【测速模块】 模块资料 我使用的是窄体的槽型光耦测速模块,如下图所示: 接线 1、VCC接电源正极3.3V-5V 2、GND接电源负极 3、D0(TTL开关信号输出)接单片机外部中断 4、A0无效 使用说明 1、模块槽中无遮挡时,接收管导通,模块DO输出低电平,遮挡时,DO输出高电平; 2、DO输出接口可以与单片机10口直接相连,检测传感器是否有遮档,如用电机码盘则可检测电机的转速。 3、模块DO可与继电器相连,组成限位开关等功能,也可以与有源蜂鸣器模块相连,组成报警器。 【单片机程序】 我使用的是传统的89C51单片机,外部晶振为11.0592M。以下程序仅提供思路,省去无关的定义内容等等 [单片机] 51单片机避坑指南 内存的使用 和stm32不同,51往往内存资源非常紧张,所以建立工程之时要列出资源使用统计表。 规则: 要给所有使用到的内存变量都指定好存放位置。 51单片机的存储器资源使用情况如下图所示: 各区域使用场合如下: 1、data区空间小,所以只有频繁用到或对运算速度要求很高的变量才放到data区内,比如for循环中的计数值。 2、data区内最好放局部变量。因为局部变量的空间是可以覆盖的(某个函数的局部变量空间在退出该函数是就释放,由别的函数的局部变量覆盖),可以提高内存利用率。当然静态局部变量除外,其内存使用方式与全局变量相同; 4、程序中遇到的逻辑标志变量可以定义到bdata中,可以大大降低内存占用空间 [单片机] 51单片机教程(八):图型带字库液晶128×64 简介:上期我向大家介绍了字符型液晶1602的基本功能,并用51单片机的驱动显示,你可以用它表达你的幸运日期或者你喜欢的数字。虽然说1602液晶使用方便,但如果你想用它表达更多的语言,就难以满足要求了。 一、原理简介 我手里的这款128×64液晶内部是以ST7920芯片作为控制器,是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192个16×16点汉字,和128个16×8点ASCII字符集。可以显示8×4行16×16点阵的汉字。因此利用该液晶模块可以灵活的构成全中文人机交互图形界面,也可完成图形显示。低电压低功耗也是其一显着特点。 [单片机] 51单片机寄存器寻址方式与指令举例 寄存器寻址的寻址范围是: 1、4个工作寄存器组共有32个通用寄存器,但在 指令 中只能使用当前寄存器组(工作寄存器组的选择在前面专用寄存器的学习中,我们已知道,是由程序状态字PSW中的RS1和RS0来确定的),因此在使用前常需要通过对PSW中的RS1、RS0位的状态设置,来进行对当前工作寄存器组的选择。 2、部份专用寄存器。例如,累加器A、通用寄存器B、地址寄存器DPTR和进位位CY。 寄存器寻址方式是指操作数在寄存器中,因此指定了寄存器名称就能得到操作数。 例如:MOV A,R0 这条指令的意思是把寄存器R0的内容传送到累加器A中,操作数就在R0中。 INC R3 这条指令的意思是把寄存器R3中的内容加1 从前面的学习中我产 [单片机] 基于51单片机太阳能风能风光互补路灯控制器设计 一.硬件方案 本设计由STC89C52单片机电路+太阳能电池板电路+风机发电电路+锂电池充电保护电路+升压电路+稳压电路+光敏电阻电路+4位高亮LED灯电路+2档拨动开关电路+电源电路设计而成。 二.设计功能 (1)采用风机和太阳能电池板给锂电池充电,具有充电保护电路和稳压电路。 (2)锂电池升压到5V给单片机和附属电路供电。 (3)路灯用4个高亮LED灯模拟。 (4)用光敏传感器测光线亮度,低于设置值时自动开启灯光。 (5)路灯控制分为手动模式和自动模式,手动模式下可以自由的开灯或者关灯,自动模式下通过光敏电阻根据光照强度自动控制灯的开和关。 三.设计原理图 (1)原理图主要采用AD软件进行设计,如图: (2)PCB [单片机] 智能温度传感器DS18B20的原理与应用 DS18B20是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。与传统的热敏电阻相比,他能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。可以分别在93.75 ms和750 ms内完成9位和12位的数字量,并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根口线(单线接口)读写,温度变换功率来源于数据总线,总线本身也可以向所挂接的DS18B20供电,而无需额外电源。因而使用DS18B20可使系统结构更趋简单,可靠性更高。他在测温精度、转换时间、传输距离、分辨率等方面较DS1820有了很大的改进,给用户带来了更方便的使用和更令人满意的效果。 1DS18 [应用] 热门资源推荐 热门放大器推荐 更多 控制系统设计指南 (埃利斯) 数据采集系统源代码 电子电路实用原理图300例 自动驾驶系统设计及应用 (余贵珍) LM741CE EL5423CL-T7 ALD1701DAMXXXX ICL7641BMJD/883C 5962-9209403MPX BA4560F-T1 SA5532N LT1394CS8#PBF 小广播 添点儿料... 无论热点新闻、行业分析、技术干货…… 发布文章 热门活动换一批更多 设计资源 培训 开发板 精华推荐 【下载】LAT1439 关于STM32H745的MC SDK电机控制工程问题的解决办法 【下载】LAT1444 ADC采样中的阻抗匹配计算方法 【下载】LAT1446 TrustZone应用中串口通信的DMA传输失败问题 【下载】LAT1450 不断电情况下修改RDP选项并生效的解决方案 【下载】LAT1455 分辨OEMiROT的Bash与BAT脚本 【下载】LAT1457 Keil工程使用NEAI库的异常问题 【直播】实时数据革命:在STM32设备中融合现代ITTIA实时数据库技术 【课程】《STM32MPU安全启动》课程上线 【课程】《ST MC SDK 6.3软件工具概览》课程上线! 【视频】在STM32MP2上运行Android系统 【直播】解析高性价比STM32WB0,让蓝牙低功耗应用触手可及 【视频】STM32C071新系列,升级128K Flash 【新品】STM32U0新一代超低功耗入门级MCU,助力终端产品省电,安全,BOM成本低 【新品】STM32H7R/S 基于Cortex-M7,运行频率高达600 MHz,板载闪存型MCU 拥有高速的外部存储 【新品】STM32WBA54/55 支持BLE5.4、IEEE 802.15.4通信协议、Zigbee®、Thread和Matter协议 【新品】STM32MP2 最高配备双核Arm® Cortex®-A35和Cortex®-M33的STM32MP2系列微处理器 【新品】STM32H5-Arm® Cortex®-M33 内核,主频高达250MHz,提升性能与信息安全性 【新品】STM32C0,你的下一代8位应用神器 【生态】体验电机开发软件ST MCSDK 6.3的新功能 【产品】STM32WB0系列,让高性价比蓝牙应用触手可及 【视频】STM32新增安卓支持 — OpenSTDROID,开启MPU应用新格局 【课程】推荐 |《STM32MPU安全启动》全新上线 【线下】STM32巡回研讨会资料下载与视频回放 【生态】全新STM32 VS Code扩展V2.1.0发布 最新单片机文章 纳芯微联合芯弦推出NS800RT系列实时控制MCU11月20日,纳芯微宣布联合芯弦半导体(ChipSine),推出NS800RT系列实时控制MCU。该系列MCU凭借更加高效、功能更强大的实时控制能力和丰富 ... 如何学习基于ARM平台的嵌入式系统一、嵌入式系统的概念着重理解"嵌入"的概念主要从三个方面上来理解 1、从硬件上,将基于CPU的处围器件,整合到CPU芯片内部,比如早期基于X86体 ... 有关 jffs2_scan_eraseblock 问题小结总结前面遇到的问题:1 有关类似:mtd->read(0x44 bytes from 0x68cf44) returned ECC errorjffs2_get_inode_nodes(): CRC failed ... SPCOMM控件在Delphi7.0串口通信中的应用摘要:利用Delphi开发工业控制系统软件成为越来越多的开发人员的选择,而串口通信是这个过程中必须解决的问题之一。本文在对几种常用串口通 ... Delphi环境下利用TComm组件实现串行通信摘要:利用Delphi开发工业控制系统软件成为越来越多的开发人员的选择,而串口通信是这个过程中必须解决的问题之一。本文在对几种常用串口通 ... 嵌入式开发实践的柱状图代码 嵌入式开发学习(10)<汇编写启动代码之设置栈、调用c语言、开关看门狗和开关iCache> 嵌入式开发学习(8)<一步一步点亮LED灯> 嵌入式开发学习(6) 何立民专栏 单片机及嵌入式宝典 北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。 《单片机与嵌入式系统应用》历年文章目录 物联网时代的嵌入式系统机遇 从嵌入式系统视角看物联网 更多精选电路图 换一换 更多 相关热搜器件 更多热门文章 LCD驱动芯片——BL55072A驱动程序 功率放大器基于声振响应法的香梨硬度无损检测 带有MIPI接口的新型高端传感器 英伟达收购Arm概率降低 但短期内无人能敌 moto edge X30关闭预售:声称已卖光库存 三星CES 2022主题演讲于1月4日 Galaxy S21 FE或亮相 恩智浦携手台积电推出行业首创汽车级16纳米FinFET嵌入式MRAM 更多每日新闻 更多往期活动 是德科技电子书,下载有礼进行时! 悦读 TI DEYISUPPORT 中国工程师精彩博文,答题赢好礼喽! 是德科技有奖问答活动之一,A4WP无线充电测试的示波器方案,答题闯关赢好礼! 新书推荐《ARM Cortex-M0从这里开始 》 艾睿电子线上研讨会:英特尔FPGA深度学习加速技术 7月30日上午10:00-11:30 期待您的莅临! 如何利用WEBENCH快速设计? 阅读并了解 TE Connectivity 无创想,不奇迹 精彩专题,答题有礼! 安全在任何时候都是第一要素,你的嵌入式设计也是!诚邀参加英飞凌 OPTIGA™ Trust M 安全防御大揭秘! 厂商技术中心 最能打国产芯 TI 培训 Qorvo 电源技术站 Vicor技术站 随便看看