基于C51单片机+DS18B20温度传感器+LCD1602显示器的智能水温控制系统(PID)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

DS = 1;           //拉高
delay\_18B20(40); 

}

uchar ds1820rd(void)//读数据
{
unsigned char i=0;
unsigned char dat = 0;
TR0=0;
for (i=8;i>0;i–)
{
DS = 0; //给脉冲信号
dat>>=1;
DS = 1; //给脉冲信号
if(DS)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}

void ds1820wr(uchar wdata)//写数据
{
unsigned char i=0;
TR0=0;
for (i=8; i>0; i–)
{
DS = 0;
DS = wdata&0x01;
delay_18B20(10);
DS = 1;
wdata>>=1;
}
}

uint get_temper()//获取温度
{

uchar a,b;

ds1820rst();    
ds1820wr(0xcc);//跳过读序列号
ds1820wr(0x44);//启动温度转换
ds1820rst();    
ds1820wr(0xcc);//跳过读序列号 
ds1820wr(0xbe);//读取温度 
a=ds1820rd();
b=ds1820rd();

tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
TR0=1;
if(tvalue<0x0fff)   tflag=0;
else {tvalue=~tvalue+1;tflag=1;}
  tvalue=tvalue\*(0.625);//温度值扩大10倍,精确到1位小数
  temp=tvalue;
return temp;

}

void dis_temp(int t)//显示温度
{
uchar d0,d1,d2,d3;
if(tflag0)
{
d0=t/1000+0x30;//百位
d1=t%1000/100+0x30;//十位
d2=t%100/10+0x30;//个位
d3=t%10+0x30;//小数位
if(d0
0x30)
{
wr_com(0x80+10);
wr_data(d1);
wr_com(0x80+11);
wr_data(d2);
wr_com(0x80+12);
wr_data(0x2e);
wr_com(0x80+13);
wr_data(d3);
}
else
{
wr_com(0x80+10);
wr_data(d0);
wr_com(0x80+11);
wr_data(d1);
wr_com(0x80+12);
wr_data(d2);
wr_com(0x80+13);
wr_data(’ ');
}

}
else
{
	wr\_com(0x80+10);
	wr\_data('-');
	wr\_com(0x80+11);
	wr\_data(d1);
	wr\_com(0x80+12);
	wr\_data(d2);
	wr\_com(0x80+13);
	wr\_data(' ');
}
wr\_com(0x80+14); //摄氏度符号
wr\_data(0xdf);
temper=t/10;

}


## 二、LCD1602显示温度


#### 接口信号说明



> 
> 1、`VSS`接电源地  
>  2、`VDD`接+5V  
>  3、`VO`是液晶显示的偏压信号,可接10K的3296精密电位器。或同样阻值的RM065、RM063蓝白可调电阻。如下图所示:  
>  ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1b78238c12e14e4eaef98a72f8dfa053.png#pic_center)  
>  4、`RS`是命令/数据选择引脚,接单片机的一个`I/O`,当`RS`为低电平时,选择命令;当`RS`为高电平时,选择数据。  
>  5、`RW`是读/写选择引脚,接单片机的一个`I/O`,当`RW`为低电平时,向`LCD1602`写入命令或数据;当`RW`为高电平时,从`LCD1602`读取状态或数据。如果不需要进行读取操作,可以直接将其接`VSS`。  
>  6、`E`,执行命令的使能引脚,接单片机的一个`I/O`。  
>  7、`D0--D7`,并行数据输入/输出引脚,可接单片机的`P0--P3`任意的`8个I/O`口。如果接`P0`口,`P0`口应该接`4.7K--10K`的上拉电阻。如果是`4线并行驱动,只须接4个I/O口`。  
>  8、`A`背光正极,可接一个`10--47`欧的限流电阻到`VDD`。  
>  9、`K`背光负极,接`VSS`。
> 
> 
> 


#### 基本操作步骤与时序



> 
> 1、读状态:输入`RS=0`,`RW=1`,`E=高脉冲`。输出:`D0--D7`为状态字;  
>  2、读数据:输入`RS=1`,`RW=1`,`E=高脉冲`。输出:`D0--D7`为数据;  
>  3、写命令:输入`RS=0`,`RW=0`,`E=高脉冲`。输出:无;  
>  4、写数据:输入`RS=1`,`RW=0`,`E=高脉冲`。输出:无。
> 
> 
> 


#### LCD1602接线图


![在这里插入图片描述](https://img-blog.csdnimg.cn/d3dfc1c3a0b0487797a551b6d68b3a3d.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAWmVhbC5aaGFuZw==,size_20,color_FFFFFF,t_20,g_se,x_16#pic_center)


#### 初始化过程



> 
> 延时15ms  
>  写指令38H(不检测忙信号)  
>  延时5ms  
>  写指令38H(不检测忙信号)  
>  延时5ms  
>  写指令38H(不检测忙信号)  
>  (以后每次写指令,读/写数据操作之前均需检测忙信号) 写指令38H:显示模式设置  
>  写指令08H:显示关闭  
>  写指令01H:显示清屏  
>  写指令06H:显示光标移动设置  
>  写指令0CH:显示开及光标设置
> 
> 
> 


#### LCD1602程序代码



/********************************************
******************LCD1602********************
*********************************************/
void delay(i)//延时函数
{
uint j;
for(i;i>0;i–)
for(j=110;j>0;j–);
}

void wr_com(uchar ml)//LCD液晶写命令
{
lcdrs=0; //寄存器低电平选择指令寄存器
P0=ml;
delay(5);
lcden=1;
delay(5);
lcden=0;

}

void wr_data(uchar shuju)//LCD液晶写数据
{
lcdrs=1;
P0=shuju;
delay(5);
lcden=1;
delay(5);
lcden=0;

}

void init() //按照时序操作的初始化
{
lcdrw=0; //低电平为写操作
wr_com(0x38);//显示模式设置,设置为16*2显示,5*7点阵,八位数据口
wr_com(0x0c);//开显示,但不开光标,光标不闪
wr_com(0x06);//显示光标移动设置
wr_com(0x01);// 清屏
wr_com(0x80);// 数据指针初始化
for(num=0;num<16;num++)
{
wr_data(str1[num]);//实际温度
}
wr_com(0x80+0x40); //地址初始化
for(num=0;num<16;num++)
{
wr_data(str2[num]);//设置温度
}
}


## 三、其他模块


其他模块包括`独立按键模块`、`单片机核心模块`和`继电器模块`。通过独立按键设置目标温度,然后通过温度传感器将数字温度信号传递给单片机,单片机通过高低电平转换,控制继电器的通断,进而实现加热设备对水温进行控制。


#### 独立按键模块


独立按键式直接用I/O口线构成的单个按键电路,其特点式每个按键单独占用一根I/O口线,每个按键的工作不会影响其他I/O口线的状态。独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一个I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。


![在这里插入图片描述](https://img-blog.csdnimg.cn/197417e644924d4c86c71e788b82dadb.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAWmVhbC5aaGFuZw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


独立按键的软件常采用查询式结构。先逐位查询没跟I/O口线的输入状态,如某一根I/O口线输入为低电平,则可确认该I/O口线所对应的按键已按下,然后,再转向该键的功能处理程序。


独立键盘理想的波形是按下去时保持低电平,实际上在上升沿和下降沿的过程中(即按键和离键时的一段微小时间)会出现抖动。消抖的方法有两种,一种是通过硬件:在电路上连个电容;另一种是软件消抖,根据经验增加10ms的延时。**这样即能起到消抖的作用。**



sbit key = P1 ^ 1;

while(!key); //有按键抬起
delay_ms(10);
while(!key); //确实有按键抬起


#### 单片机核心模块


![在这里插入图片描述](https://img-blog.csdnimg.cn/cf036d5c3d0e41b89ee522971eb5a68b.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAWmVhbC5aaGFuZw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


#### 继电器模块


![在这里插入图片描述](https://img-blog.csdnimg.cn/4dd1b803e2d94b9c93568807cd0c164a.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAWmVhbC5aaGFuZw==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


当输入高电平时,晶体管T1饱和导通,继电器线圈通电,触点吸合。  
 当输入低电平时,晶体管T1截止,继电器线圈断电,触点断开。


## 四、温控系统PID


采用位置式PID控制水温



void PIDInit (struct PID *p)
{
memset ( p,0,sizeof(struct PID)); //用参数0初始化p
}

/**********************************************
根据位置式离散PID公式
PID = Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
e(k)代表本次偏差
e(k-1)代表上一次的偏差
∑e(k)代表e(k)以及之前的偏差的累积和;其中k为1,2,k;
PID代表输出
***********************************************/
unsigned int PIDCalc( struct PID *p, unsigned int NextPoint )
{
unsigned int dError,Error;
Error = p->SetPoint - NextPoint; // 偏差
p->SumError += Error; // 积分
dError = p->LastError - p->PrevError; // 当前微分
p->PrevError = p->LastError;
p->LastError = Error;
return (p->Proportion * Error//比例
+ p->Integral * p->SumError //积分项
+ p->Derivative * dError); // 微分项
}




**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/a26e582866eedb829da50e6ee3df12a7.png)
![img](https://img-blog.csdnimg.cn/img_convert/f6acadcc2affbfa32fa488ba4d12d39b.png)

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**


} 

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-KbyXtSuW-1715714002605)]
[外链图片转存中…(img-nCHlEpmB-1715714002606)]

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #define uchar unsigned char #define uint unsigned int sbit led=P2^5; sbit wei=P2^7; sbit duan=P2^6; sbit DQ=P2^2; uchar mazhi_duan[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,0x00}; uchar mazhi_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xff}; void delayl(uint n) { uint i,j; for(i=n;i>0;i--) for(j=114;j>0;j--); } void delays(uchar i) { while(i--); } bit init_DS18B20() //DS8B20初始化 { bit x; DQ=1; //DQ复位 delays(8); DQ=0; //单片机将DQ拉低 delays(75); DQ=1; //拉高总线 delays(15); x=DQ; //延时过后 若x=0则初始化成功 若x=1则初始化失败 delays(5); return x; } void write_data(uchar dat) { uchar i,temp; temp=dat; DQ=1; for(i=0;i>=1; } } uchar read_data() { uchar i,dat; DQ=1; for(i=0;i>=1; DQ=1;//配置为输入 if(DQ) dat|=0x80; delays(4); } return dat; } uint readtemp() { uchar temph,templ; uint temp; float wendu; init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0x44);//启动温度转换 //delayl(100); init_DS18B20(); write_data(0xcc);//跳过ROM write_data(0xBE);//读温度 //以下读温度,低八位在前 //高8位在后 templ=read_data(); temph=read_data(); temp = (temph<<8)|templ; wendu = temp*0.625+0.5;//温度扩大10倍,四舍五入 temp = wendu;//10倍温度 return temp; } void STC_init() { P1=0x00;//关闭led led=0; //锁存 wei=0; duan=0; } void display(uchar weil,uchar duanl,bit dp) { wei=1; P0=mazhi_wei[weil-1]; wei=0; duan=1; if(dp==1) P0=(mazhi_duan[duanl]|0x80); else P0=mazhi_duan[duanl]; duan=0; } void main() { uchar i; uint wendu; STC_init(); wendu=readtemp(); delayl(500); wendu=readtemp(); delayl(500); while(1) { wendu=readtemp(); for(i=0;i<80;i++) { display(1,wendu/100,0); delayl(3); display(2,wendu0/10,1); delayl(3); display(3,wendu,0); delayl(3); } } }
### 回答1: 以下是基于51单片机+DS18B20温度传感器+LCD1602显示器的程序: ```c #include <reg52.h> #include <intrins.h> #define LCD1602_DATAPORT P0 // LCD1602数据口定义 sbit LCD1602_RS = P2^0; // LCD1602 RS引脚定义 sbit LCD1602_RW = P2^1; // LCD1602 RW引脚定义 sbit LCD1602_EN = P2^2; // LCD1602 EN引脚定义 #define DS18B20_DQ P3_7 // DS18B20数据线定义 unsigned char str[16]; // 存储温度字符串 void delay(unsigned int t) // 延时函数 { unsigned int i,j; for(i=0;i<t;i++) { for(j=0;j<125;j++); } } void LCD1602_WriteCmd(unsigned char cmd) // 写命令函数 { LCD1602_RS = 0; // RS置低 LCD1602_RW = 0; // RW置低 LCD1602_DATAPORT = cmd; // 将命令写入数据口 LCD1602_EN = 1; // EN置高 _nop_(); // 空操作 _nop_(); _nop_(); LCD1602_EN = 0; // EN置低 } void LCD1602_WriteData(unsigned char dat) // 写数据函数 { LCD1602_RS = 1; // RS置高 LCD1602_RW = 0; // RW置低 LCD1602_DATAPORT = dat; // 将数据写入数据口 LCD1602_EN = 1; // EN置高 _nop_(); // 空操作 _nop_(); _nop_(); LCD1602_EN = 0; // EN置低 } void LCD1602_Init() // LCD1602初始化函数 { LCD1602_WriteCmd(0x38); // 8位数据总线,2行显示,5*7点阵字符 delay(5); LCD1602_WriteCmd(0x0c); // 关闭光标显示 delay(5); LCD1602_WriteCmd(0x06); // 右移光标 delay(5); LCD1602_WriteCmd(0x01); // 清屏 delay(5); } unsigned char DS18B20_Init() // DS18B20初始化函数 { unsigned char flag = 0; DS18B20_DQ = 1; // DQ置高 delay(10); DS18B20_DQ = 0; // DQ置低 delay(80); DS18B20_DQ = 1; // DQ置高 delay(10); flag = DS18B20_DQ; // 读取DS18B20应答信号 delay(10); return flag; } void DS18B20_WriteByte(unsigned char dat) // DS18B20写字节函数 { unsigned char i; for(i=0;i<8;i++) { DS18B20_DQ = 0; // DQ置低 _nop_(); // 空操作 _nop_(); DS18B20_DQ = dat&0x01; // 写入数据,从低位开始写 delay(10); DS18B20_DQ = 1; // DQ置高 dat >>= 1; // 右移一位 } } unsigned char DS18B20_ReadByte() // DS18B20读字节函数 { unsigned char i,dat = 0; for(i=0;i<8;i++) { dat >>= 1; // 右移一位 DS18B20_DQ = 0; // DQ置低 _nop_(); // 空操作 _nop_(); DS18B20_DQ = 1; // DQ置高 delay(2); if(DS18B20_DQ) // 判断数据位 { dat |= 0x80; // 写入数据,从高位开始写 } else { dat &= 0x7f; } delay(10); } return dat; } void DS18B20_GetTemp() // DS18B20读取温度函数 { unsigned char TL,TH; float temp; DS18B20_Init(); // DS18B20初始化 DS18B20_WriteByte(0xcc); // 跳过ROM操作 DS18B20_WriteByte(0x44); // 启动温度转换 delay(750); // 等待转换完成 DS18B20_Init(); // DS18B20初始化 DS18B20_WriteByte(0xcc); // 跳过ROM操作 DS18B20_WriteByte(0xbe); // 读取温度寄存器数据 TL = DS18B20_ReadByte(); // 读取低温度字节 TH = DS18B20_ReadByte(); // 读取高温度字节 temp = TH; temp *= 256; temp += TL; temp *= 0.0625; // 计算温度值 sprintf(str,"Temp:%.2fC ",temp); // 将温度值转换为字符串 } void main() { LCD1602_Init(); // LCD1602初始化 while(1) { DS18B20_GetTemp(); // 获取温度LCD1602_WriteCmd(0x80); // 设置光标位置为第一行第一列 for(unsigned char i=0;i<16;i++) // 写入温度字符串 { LCD1602_WriteData(str[i]); } delay(1000); // 延时1秒 } } ``` 以上程序实现了基于51单片机+DS18B20温度传感器+LCD1602显示器温度监测功能。具体实现过程为:初始化LCD1602DS18B20,循环读取DS18B20温度值,将温度值转换为字符串并在LCD1602显示,然后延时1秒后继续循环读取温度值。 ### 回答2: 这是一个基于51单片机DS18B20温度传感器LCD1602显示器的程序,用于测量环境温度并在LCD显示器显示。 首先,我们需要连接硬件设备。将DS18B20温度传感器的VCC引脚连接到51单片机的5V电源引脚,将GND引脚连接到GND引脚,将DQ引脚连接到P0口(可以根据需要更改引脚)。然后,将LCD1602显示器的VCC引脚连接到5V电源引脚,将GND引脚连接到GND引脚,将SCL引脚连接到51单片机的P2口,将SDA引脚连接到P3口。 接下来,打开编程软件,创建一个新的项目。首先,我们需要引入51单片机的头文件和宏定义。然后,我们需要定义DS18B20传感器的一些常量和变量,包括温度传感器的ROM码和温度值。接着,我们需要写一些函数用于初始化DS18B20传感器和LCD1602显示器,并读取温度值。 在主函数中,我们首先需要调用初始化函数来初始化DS18B20传感器和LCD1602显示器。然后,我们可以通过调用读取温度值的函数来获取当前环境温度,并将其存储到温度变量中。最后,我们可以通过调用LCD显示函数来在LCD显示器显示温度值。 程序的基本逻辑是,当主函数运行时,首先初始化DS18B20传感器和LCD1602显示器。然后,通过读取温度传感器的值并将其转换为实际温度值,将实际温度值存储在温度变量中。最后,通过将温度值转换为字符串,并调用LCD显示函数将其显示LCD1602显示器上。 以上是一个简单的基于51单片机DS18B20温度传感器LCD1602显示器的程序。程序的功能是测量环境温度并在LCD显示器显示。 ### 回答3: 基于51单片机DS18B20温度传感器LCD1602显示器的程序如下: 首先,我们需要包含头文件 #include <reg51.h> #include <lcd.h> #include <ds18b20.h> 然后,定义所需的变量 sbit LCD_RS = P2^0; // 设置LCD_RS引脚 sbit LCD_RW = P2^1; // 设置LCD_RW引脚 sbit LCD_EN = P2^2; // 设置LCD_EN引脚 定义主函数 void main() { float temperature; // 存储温度值 char display[16]; // 存储显示在LCD上的字符串 LCD_Init(); // 初始化LCD1602显示器 DS18B20_Init(); // 初始化DS18B20传感器 while (1) // 无限循环 { temperature = DS18B20_GetTemp(); // 获取温度值 sprintf(display, "Temperature: %.2fC", temperature); // 格式化温度值字符串 LCD_Clear(); // 清除LCD屏幕 LCD_Write_String(display); // 显示温度值 Delay(500); // 延迟500毫秒 } } 程序的逻辑是:首先,我们初始化LCD和DS18B20传感器。然后,在无限循环中,我们不断获取温度值,并将其格式化为字符串。然后,我们清除LCD屏幕并在LCD上显示温度值。最后,我们延迟500毫秒,以便能够看到温度在LCD上的显示。该程序可以实时显示DS18B20传感器测量到的温度值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值