基于单片机的温湿度控制器设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#define _SCI_H
#include "main.h"
void init_uart();
void putchar (unsigned char i);
#endif
sci.c
#include "sci.h"
void init_uart()
{
PCON &= 0x7f; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
#endif
嵌入式系统应用
基于单片机的温湿度控制器
一、实验要求
设计一个温度测控系统(温度信号使用相应的传感器输入),利用键盘或上位机通信方式设置报警上下限值,利用数码LED或液晶模块或通过上位机进行当前值和报警值的显示。当前值超过上限值或下限值的时候,蜂鸣器发出不同的报警声音。
二、实验分析
实验主要分为硬件设计和程序设计两部分。
#include "main.h"
sbit DS=P1^1;
bit init_18b20();
void write_byte(unsigned char val);
int read_byte(void);
read_temp();
void delayms(unsigned int j);
#endif
ds18b20.c
{
ES = 0; //关串口中断
TI = 0; //清零串口发送完成中断请求标志
SBUF = i;
while(TI ==0); //等待发送完成
TI = 0; //清零串口发送完成中断请求标志
ES = 1; //允许串口中断
}
ds18b20.h
#ifndef _SCI_H
#define _SCI_H
BRT = 0xFD; //设定独立波特率发生器重装值
AUXR |= 0x04; //独立波特率发生器时钟为Fosc,即1T
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10; //启动独立波特率发生器
EA=1;
ES=1;
}
void putchar (unsigned char i)
#endif
main.c
#include "main.h"
unsigned char tmp_top=40;
unsigned char tmp_bot=15;
unsigned char tmp;
unsigned char tmp_flag=0;
unsigned char rec[4];
void main()
delay10us(10);
init_18b20();
write_byte(0xCC); // Skip ROM
write_byte(0xbe); //发转换命令
}
void delayms(unsigneபைடு நூலகம் int j)
{
int i=0;
while(j){
for(i=0;i<125;i++);
j--;
rec_flag=0;
}
}
if(TI)
TI=0;
}
void timer() interrupt 1
{
static unsigned char tt=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tt++;
if(tmp_flag)
{
if(tmp_flag==1)
rec[rec_count]=Temp;
rec_count++;
if(rec_count==3&&tmp_top>tmp_bot)
{
rec_count=1;
tmp_bot=rec[1];
tmp_top=rec[2];
rec_flag=0;
che_flag=0;
}
}
if(rec_flag==1)
{
che_flag=1;
附录1:单片机程序源码
main.h
#ifndef _MAIN_H
#define _MAIN_H
#include "stc12c5a60s2.h"
#include "intrins.h"
#include "sci.h"
#include "ds18b20.h"
#include "deal.h"
sbit BEEP=P2^7;
程序设计框图
软件设计过程中,遇到的最大问题就是手机与蓝牙的通信。由于担心干扰的发生会引起数据的错误,所以在发送端和接收端都进行了数据校验。开始选用的是加和校验法,发现很难收到正常的帧,导致无法进行数据传输。之后采用标志位校验法,虽然有时会出现数据错乱,但是大部分时间都是正常的。对于此系统来说,个别的错误数据对整体来说,影响不大,故没有再进一步优化。
三、实验过程
完成实验要求分析后,首先进行硬件设计。单片机选型方面,并未使用提供的IAP15F2K61S2型单片机。因为之前有过使用STC公司另一款增强型51单片机STC12C5A16S2进行开发设计的经验,而且设计了成型的PCB板图,并发厂制作。在征得老师同意后,选用此类型单片机,并以原先设计好的PCB板作为硬件平台。
unsigned char value=0;
for(i=0;i<8;i++)
{
DS=1;
_nop_();
_nop_();
value>>=1;
DS=0;
_nop_();
_nop_();
_nop_();
_nop_();
DS=1; //人为拉高,总线有拉低的功能没有拉低的功能,若是0则总线拉低
_nop_();
程序设计
程序方面,包括单片机下位机程序和手机上位机程序。单片机程序总体比较简单。在进行完单片机必要的相关程序配置之后,还要有针对性的对用到的代码块进行编程。对于温度传感器DS18B20,使用软件模拟one wire通信协议,进行数据通信(见源码ds18b20.h、ds18b20.c)。由于使用的是蓝牙串口模块,故需要对串行通信进行初始化和软件调用(见源码sci.h、sci.c)。各个模块调整完毕后,还需要对传感器采集到的值与设定的温度上限限进行比较并根据不同的异常反映到蜂鸣器上,而且需要对接收到的上位机的值进行处理等工作,还需要程序协调各项工作的时序关系(见源码deal.h、deal.c)。最后,也是最重要的部分,设置程序的入口,统筹整个工程的工作(见源码main.h、main.c)。手机上位机程序中,主要完成了对蓝牙的配对连接、数据接收、数据显示和数据修改功能。因为Android程序所包含的不仅仅是数据处理本身,还有很多对系统底层的配置和资源的调用部分,故代码无法全部给出,仅在附录中将数据通信、校验、处理和发送部分录入(见源码TMP.java)。
_nop_();
_nop_();
_nop_();
if(DS)
value|=0x80;
delay10us(6);
}
DS=1;
return(value);
}
read_temp()
{
init_18b20();
write_byte(0xCC); //发Skip ROM命令
write_byte(0x44); //发读命令
sbit LED=P1^2;
extern unsigned char tmp_top;
extern unsigned char tmp_bot;
extern unsigned char tmp;
extern unsigned char tmp_flag;
extern unsigned char rec[4];
电源部分,PCB板图已经计划并设计完成。使用9V碱性电池,经过LM7805及多个电容降压、稳压之后,给整个系统供电。这种供电方式的优点是,不需要使用外接的电源,器件少,稳定性好等。当然,也有不足。LM7805本身发热严重,而9V电池本身放电电流较小,无法支持较大功耗的器件。
主控单片机需要搭建最小系统。使用11.0592MHz的无缘晶振作为单片机外部晶振,并连接两个33pF的电容帮助起振。因为单片机本身有着上电复位功能,所以并未在外部给出复位电路。引出单片机的P3.0、P3.1引脚(即TXD、RXD),作程序烧写和蓝牙串口通信用。
}
}
deal.h
#ifndef _SCI_H
#define _SCI_H
#include "main.h"
#include "sci.h"
void check();
unsigned char tmp_read();
void send_delay();
void delay_s(unsigned int );
系统外围的外设很少,只有一个DS18B20温度传感器,一个蜂鸣器、一个LED灯,具体电路较为简单,不详细解释。
硬件部分设计制作完成并调试无误后,进行程序设计。
首先确认各个外设工作正常。然后,依次进行点亮LED灯、蜂鸣器鸣响、串口数据传输、DS18B20数据采集、定时器功能配置等工作。完成后,将各个部分时序协调完毕再进行手机上位机程序设计。因手机部分与课程相关性不大,不过多赘述。单片机程序时序分配见以下的程序设计框图。
#include "ds18b20.h"
void delay10us(unsigned int n)//10us @12.000MHz
{
unsigned char i;
while(n){
_nop_();
i = 25;
while (--i);
n--;
}
}
bit init_18b20()
{
bit flag;
硬件设计
为了实现功能,应使用合适款型的单片机,提供的单片机型号为STC公司的IAP15FCK61S2。传感器选用的是操作简单、精度较高的DS18B20温度传感器。蜂鸣器选型方面,有源或者无源对实验效果影响不大,但应该注意使用三极管驱动,否则无论使用I/O口灌电流或者拉电流都无法达到其电流大小的要求。温度显示方面,此处放弃了数码管或者液晶等较为常规的方式,而是使用蓝牙模块,与安卓手机通信,完成数据传递和数值控制的功能,连接方便,且功耗较低。电源方面,使用9V碱性电池,并使用LM7805降压至5V后,给单片机及其他部分供电。原理图在文档后附上。
{
if(tt>5)
{
LED=~LED;
BEEP=~BEEP;
tt=0;
}
}
if(tmp_flag==2)
{
if(tt>20)
{
LED=~LED;
BEEP=~BEEP;
tt=0;
}
}
}
if(tt>20)
{
tt=0;
}
if(!tmp_flag)
{
BEEP=1;
LED=0;
}
}
sci.h
#ifndef _SCI_H
putchar(tmp);
putchar(tmp_bot);
putchar(tmp_top);
send_delay();
check();
}
}
void UART_SER (void) interrupt 4
{
static unsigned char rec_flag=0;
static unsigned char che_flag=0;
static unsigned char rec_count=1;
static unsigned char Temp;
if(RI)
{
RI=0;
Temp=SBUF;
if(Temp==0X8A)
{
rec[0]=Temp;
rec_flag=1;
}
if(che_flag==1&&rec[0]==0x8A)
{
flag=DS;
//delay10us(60);
for(time=0;time<200;time++);
return (flag);
}
void write_byte(unsigned char val)//写一个命令函数
{
unsigned char i;//先写低位在写高位
for(i=0;i<8;i++)
int time;
DS=1;
//delay10us(1);
for(time=0;time<2;time++) ;
DS=0;
//delay10us(60);
for(time=0;time<200;time++);
DS=1;
//delay10us(3);
for(time=0;time<10;time++) ;
{
DS=1;
_nop_();
_nop_();
DS=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
DS=val&0x01;
delay10us(6);
val=val>>1;
}
DS=1;
delay10us(2);
}
int read_byte(void)
{
unsigned char i;
{
init_uart();
BEEP=1;
while(!init_18b20());
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{
tmp=tmp_read();
putchar(0X70);
#include "main.h"
void init_uart();
void putchar (unsigned char i);
#endif
sci.c
#include "sci.h"
void init_uart()
{
PCON &= 0x7f; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
#endif
嵌入式系统应用
基于单片机的温湿度控制器
一、实验要求
设计一个温度测控系统(温度信号使用相应的传感器输入),利用键盘或上位机通信方式设置报警上下限值,利用数码LED或液晶模块或通过上位机进行当前值和报警值的显示。当前值超过上限值或下限值的时候,蜂鸣器发出不同的报警声音。
二、实验分析
实验主要分为硬件设计和程序设计两部分。
#include "main.h"
sbit DS=P1^1;
bit init_18b20();
void write_byte(unsigned char val);
int read_byte(void);
read_temp();
void delayms(unsigned int j);
#endif
ds18b20.c
{
ES = 0; //关串口中断
TI = 0; //清零串口发送完成中断请求标志
SBUF = i;
while(TI ==0); //等待发送完成
TI = 0; //清零串口发送完成中断请求标志
ES = 1; //允许串口中断
}
ds18b20.h
#ifndef _SCI_H
#define _SCI_H
BRT = 0xFD; //设定独立波特率发生器重装值
AUXR |= 0x04; //独立波特率发生器时钟为Fosc,即1T
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10; //启动独立波特率发生器
EA=1;
ES=1;
}
void putchar (unsigned char i)
#endif
main.c
#include "main.h"
unsigned char tmp_top=40;
unsigned char tmp_bot=15;
unsigned char tmp;
unsigned char tmp_flag=0;
unsigned char rec[4];
void main()
delay10us(10);
init_18b20();
write_byte(0xCC); // Skip ROM
write_byte(0xbe); //发转换命令
}
void delayms(unsigneபைடு நூலகம் int j)
{
int i=0;
while(j){
for(i=0;i<125;i++);
j--;
rec_flag=0;
}
}
if(TI)
TI=0;
}
void timer() interrupt 1
{
static unsigned char tt=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tt++;
if(tmp_flag)
{
if(tmp_flag==1)
rec[rec_count]=Temp;
rec_count++;
if(rec_count==3&&tmp_top>tmp_bot)
{
rec_count=1;
tmp_bot=rec[1];
tmp_top=rec[2];
rec_flag=0;
che_flag=0;
}
}
if(rec_flag==1)
{
che_flag=1;
附录1:单片机程序源码
main.h
#ifndef _MAIN_H
#define _MAIN_H
#include "stc12c5a60s2.h"
#include "intrins.h"
#include "sci.h"
#include "ds18b20.h"
#include "deal.h"
sbit BEEP=P2^7;
程序设计框图
软件设计过程中,遇到的最大问题就是手机与蓝牙的通信。由于担心干扰的发生会引起数据的错误,所以在发送端和接收端都进行了数据校验。开始选用的是加和校验法,发现很难收到正常的帧,导致无法进行数据传输。之后采用标志位校验法,虽然有时会出现数据错乱,但是大部分时间都是正常的。对于此系统来说,个别的错误数据对整体来说,影响不大,故没有再进一步优化。
三、实验过程
完成实验要求分析后,首先进行硬件设计。单片机选型方面,并未使用提供的IAP15F2K61S2型单片机。因为之前有过使用STC公司另一款增强型51单片机STC12C5A16S2进行开发设计的经验,而且设计了成型的PCB板图,并发厂制作。在征得老师同意后,选用此类型单片机,并以原先设计好的PCB板作为硬件平台。
unsigned char value=0;
for(i=0;i<8;i++)
{
DS=1;
_nop_();
_nop_();
value>>=1;
DS=0;
_nop_();
_nop_();
_nop_();
_nop_();
DS=1; //人为拉高,总线有拉低的功能没有拉低的功能,若是0则总线拉低
_nop_();
程序设计
程序方面,包括单片机下位机程序和手机上位机程序。单片机程序总体比较简单。在进行完单片机必要的相关程序配置之后,还要有针对性的对用到的代码块进行编程。对于温度传感器DS18B20,使用软件模拟one wire通信协议,进行数据通信(见源码ds18b20.h、ds18b20.c)。由于使用的是蓝牙串口模块,故需要对串行通信进行初始化和软件调用(见源码sci.h、sci.c)。各个模块调整完毕后,还需要对传感器采集到的值与设定的温度上限限进行比较并根据不同的异常反映到蜂鸣器上,而且需要对接收到的上位机的值进行处理等工作,还需要程序协调各项工作的时序关系(见源码deal.h、deal.c)。最后,也是最重要的部分,设置程序的入口,统筹整个工程的工作(见源码main.h、main.c)。手机上位机程序中,主要完成了对蓝牙的配对连接、数据接收、数据显示和数据修改功能。因为Android程序所包含的不仅仅是数据处理本身,还有很多对系统底层的配置和资源的调用部分,故代码无法全部给出,仅在附录中将数据通信、校验、处理和发送部分录入(见源码TMP.java)。
_nop_();
_nop_();
_nop_();
if(DS)
value|=0x80;
delay10us(6);
}
DS=1;
return(value);
}
read_temp()
{
init_18b20();
write_byte(0xCC); //发Skip ROM命令
write_byte(0x44); //发读命令
sbit LED=P1^2;
extern unsigned char tmp_top;
extern unsigned char tmp_bot;
extern unsigned char tmp;
extern unsigned char tmp_flag;
extern unsigned char rec[4];
电源部分,PCB板图已经计划并设计完成。使用9V碱性电池,经过LM7805及多个电容降压、稳压之后,给整个系统供电。这种供电方式的优点是,不需要使用外接的电源,器件少,稳定性好等。当然,也有不足。LM7805本身发热严重,而9V电池本身放电电流较小,无法支持较大功耗的器件。
主控单片机需要搭建最小系统。使用11.0592MHz的无缘晶振作为单片机外部晶振,并连接两个33pF的电容帮助起振。因为单片机本身有着上电复位功能,所以并未在外部给出复位电路。引出单片机的P3.0、P3.1引脚(即TXD、RXD),作程序烧写和蓝牙串口通信用。
}
}
deal.h
#ifndef _SCI_H
#define _SCI_H
#include "main.h"
#include "sci.h"
void check();
unsigned char tmp_read();
void send_delay();
void delay_s(unsigned int );
系统外围的外设很少,只有一个DS18B20温度传感器,一个蜂鸣器、一个LED灯,具体电路较为简单,不详细解释。
硬件部分设计制作完成并调试无误后,进行程序设计。
首先确认各个外设工作正常。然后,依次进行点亮LED灯、蜂鸣器鸣响、串口数据传输、DS18B20数据采集、定时器功能配置等工作。完成后,将各个部分时序协调完毕再进行手机上位机程序设计。因手机部分与课程相关性不大,不过多赘述。单片机程序时序分配见以下的程序设计框图。
#include "ds18b20.h"
void delay10us(unsigned int n)//10us @12.000MHz
{
unsigned char i;
while(n){
_nop_();
i = 25;
while (--i);
n--;
}
}
bit init_18b20()
{
bit flag;
硬件设计
为了实现功能,应使用合适款型的单片机,提供的单片机型号为STC公司的IAP15FCK61S2。传感器选用的是操作简单、精度较高的DS18B20温度传感器。蜂鸣器选型方面,有源或者无源对实验效果影响不大,但应该注意使用三极管驱动,否则无论使用I/O口灌电流或者拉电流都无法达到其电流大小的要求。温度显示方面,此处放弃了数码管或者液晶等较为常规的方式,而是使用蓝牙模块,与安卓手机通信,完成数据传递和数值控制的功能,连接方便,且功耗较低。电源方面,使用9V碱性电池,并使用LM7805降压至5V后,给单片机及其他部分供电。原理图在文档后附上。
{
if(tt>5)
{
LED=~LED;
BEEP=~BEEP;
tt=0;
}
}
if(tmp_flag==2)
{
if(tt>20)
{
LED=~LED;
BEEP=~BEEP;
tt=0;
}
}
}
if(tt>20)
{
tt=0;
}
if(!tmp_flag)
{
BEEP=1;
LED=0;
}
}
sci.h
#ifndef _SCI_H
putchar(tmp);
putchar(tmp_bot);
putchar(tmp_top);
send_delay();
check();
}
}
void UART_SER (void) interrupt 4
{
static unsigned char rec_flag=0;
static unsigned char che_flag=0;
static unsigned char rec_count=1;
static unsigned char Temp;
if(RI)
{
RI=0;
Temp=SBUF;
if(Temp==0X8A)
{
rec[0]=Temp;
rec_flag=1;
}
if(che_flag==1&&rec[0]==0x8A)
{
flag=DS;
//delay10us(60);
for(time=0;time<200;time++);
return (flag);
}
void write_byte(unsigned char val)//写一个命令函数
{
unsigned char i;//先写低位在写高位
for(i=0;i<8;i++)
int time;
DS=1;
//delay10us(1);
for(time=0;time<2;time++) ;
DS=0;
//delay10us(60);
for(time=0;time<200;time++);
DS=1;
//delay10us(3);
for(time=0;time<10;time++) ;
{
DS=1;
_nop_();
_nop_();
DS=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
DS=val&0x01;
delay10us(6);
val=val>>1;
}
DS=1;
delay10us(2);
}
int read_byte(void)
{
unsigned char i;
{
init_uart();
BEEP=1;
while(!init_18b20());
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{
tmp=tmp_read();
putchar(0X70);