实验五 基于DS18b20的温度传感器设计

实验五 基于DS18b20的温度传感器设计

一、实验目的

1、掌握单片机串口通信的不同工作方式及应用;

2、掌握串口通信的编程方法

3、理解 DS18B20 的工作原理

4、掌握 DS18B20 编程

二、实验软硬件

1、Keil uVision4或者Keil uVision5;

2、仿真软件Proteus8,烧录软件stc-isp;

3、普中51开发板。

三、学习内容

1、单片机与 PC 机串口通信

2、DS18B20 的工作原理与控制方法

四、实验任务

任务一:

完成单片机与PC机串口通信,要求:

1、PC机发送字符数据到单片机上,通过数码管或LCD1602显示;

2、单片机发送数据到计算机上,可在串口助手显示;

(波特率设置为4800,数据位8位,无奇偶校验位;不做仿真,只做硬件验证。)

任务二:

编写程序,使用温度传感器DS18B20模块及串口,实现以下功能:

1、通过温度传感器获取到当前温度,并通过串口发送PC机。

2、通过PC机上的串口助手设置高温阈值,并通过LCD1602显示阈值,当温度超过时,能用蜂鸣器报警。(波特率设置为4800,数据位8位,无奇偶校验位)

任务一

完成单片机与PC机串口通信,要求:

1、PC机发送字符数据到单片机上,通过数码管或LCD1602显示;

2、单片机发送数据到计算机上,可在串口助手显示;

(波特率设置为4800,数据位8位,无奇偶校验位;不做仿真,只做硬件验证。)

在这里插入图片描述

先小试牛刀

实现串口数据收发

#include <reg51.h>
typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;
void uart_init(u8 baud)
{
	TMOD|=0X20;	//设置计数器工作方式2
	SCON=0X50;	//设置为工作方式1
	PCON=0X80;	//波特率加倍
  TH1 = baud;
  TL1 = baud;
	ES=1;		//打开接收中断
	EA=1;		//打开总中断
	TR1=1;		//打开计数器		
}

void main()
{	
	uart_init(0XF3);//波特率为4800
	while(1)
	{			
							
	}		
}

void uart() interrupt 4 //串口通信中断函数
{
	u8 rec_data;

	RI = 0;			//清除接收中断标志位
	rec_data=SBUF;	//存储接收到的数据
	SBUF=rec_data;	//将接收到的数据放入到发送寄存器
	while(!TI);		//等待发送数据完成
	TI=0;			//清除发送完成标志位				
}

加上lcd1602显示字符数据

主函数
#include "public.h"
#include "lcd1602.h"
u8 str;
void uart_init(u8 baud)
{
	TMOD|=0X20;	//设置计数器工作方式2
	SCON=0X50;	//设置为工作方式1
	PCON=0X80;	//波特率加倍
  TH1 = baud;
  TL1 = baud;
	ES=1;		//打开接收中断
	EA=1;		//打开总中断
	TR1=1;		//打开计数器		
}

void main()
{	
	uart_init(0XF3);//波特率为4800
	lcd1602_init();
	while(1)
	{		
			lcd1602_write_cmd(0x80);
			lcd1602_write_data(str);				
	}		
}

void uart() interrupt 4 //串口通信中断函数
{
	u8 rec_data;

	RI = 0;			//清除接收中断标志位
	rec_data=SBUF;	//存储接收到的数据
	SBUF=rec_data;	//将接收到的数据放入到发送寄存器
	while(!TI);		//等待发送数据完成
	TI=0;			//清除发送完成标志位
	str = rec_data;
}
lcd1602.h
#ifndef _lcd1602_H
#define _lcd1602_H

#include "public.h"
//LCD1602数据口4位和8位定义,若为1,则为LCD1602四位数据口驱动,反之为8位
#define LCD1602_4OR8_DATA_INTERFACE	0	//默认使用8位数据口LCD1602

//管脚定义
sbit LCD1602_RS=P2^6;//数据命令选择
sbit LCD1602_RW=P2^5;//读写选择
sbit LCD1602_E=P2^7; //使能信号
#define LCD1602_DATAPORT P0	//宏定义LCD1602数据端口


//函数声明
void lcd1602_init(void);
void lcd1602_clear(void);
void lcd1602_show_string(u8 x,u8 y,u8 *str);
void lcd1602_write_data(u8 dat);
void lcd1602_write_cmd(u8 cmd);

#endif
lcd1602.c
#include "lcd1602.h"


/*******************************************************************************
* 函 数 名       : lcd1602_write_cmd
* 函数功能		 : LCD1602写命令
* 输    入       : cmd:指令
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS=0;//选择命令
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=cmd;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入	
}
#else	//4位LCD
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS=0;//选择命令
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=cmd;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入
	
	LCD1602_DATAPORT=cmd<<4;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入	
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_write_data
* 函数功能		 : LCD1602写数据
* 输    入       : dat:数据
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_write_data(u8 dat) 
{
	LCD1602_RS=1;//选择数据
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=dat;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入		
}
#else
void lcd1602_write_data(u8 dat) 
{
	LCD1602_RS=1;//选择数据
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=dat;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入
	
	LCD1602_DATAPORT=dat<<4;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入		
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_init
* 函数功能		 : LCD1602初始化
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x38);//数据总线8位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01);//清屏	
}
#else
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x28);//数据总线4位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01);//清屏	
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_clear
* 函数功能		 : LCD1602清屏
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void lcd1602_clear(void)
{
	lcd1602_write_cmd(0x01);	
}

/*******************************************************************************
* 函 数 名       : lcd1602_show_string
* 函数功能		 : LCD1602显示字符
* 输    入       : x,y:显示坐标,x=0~15,y=0~1;
				   str:显示字符串
* 输    出    	 : 无
*******************************************************************************/
void lcd1602_show_string(u8 x,u8 y,u8 *str)
{
	u8 i=0;

	if(y>1||x>15)return;//行列参数不对则强制退出

	if(y<1)	//第1行显示
	{	
		while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示
		{
			if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示
			{
				lcd1602_write_cmd(0x80+i+x);//第一行显示地址设置	
			}
			else
			{
				lcd1602_write_cmd(0x40+0x80+i+x-16);//第二行显示地址设置	
			}
			lcd1602_write_data(*str);//显示内容
			str++;//指针递增
			i++;	
		}	
	}
	else	//第2行显示
	{
		while(*str!='\0')
		{
			if(i<16-x) //如果字符长度超过第二行显示范围,则在第一行继续显示
			{
				lcd1602_write_cmd(0x80+0x40+i+x);	
			}
			else
			{
				lcd1602_write_cmd(0x80+i+x-16);	
			}
			lcd1602_write_data(*str);
			str++;
			i++;	
		}	
	}				
}

public.h
#ifndef _public_H
#define _public_H

#include "reg52.h"

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;


void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

#endif

public.c
#include "public.h"

/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ms:ms延时时间
* 输    出    	 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
	u16 i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
}

单片机发送数据到计算机

在这里插入图片描述

加入stdio.h,用printf函数打印字符数据

#include "public.h"
#include "lcd1602.h"
#include <stdio.h>
u8 str;
void uart_init(u8 baud)
{
	TMOD|=0X20;	//设置计数器工作方式2
	SCON=0X50;	//设置为工作方式1
	PCON=0X80;	//波特率加倍
  TH1 = baud;
  TL1 = baud;
	ES=1;		//打开接收中断
	EA=1;		//打开总中断
	TR1=1;		//打开计数器		
}

void main()
{	
	uart_init(0XF3);//波特率为4800
	lcd1602_init();
	while(1)
	{		
			lcd1602_write_cmd(0x80);
			lcd1602_write_data(str);				
	}		
}

void uart() interrupt 4 //串口通信中断函数
{
	u8 rec_data;

	RI = 0;			//清除接收中断标志位
	rec_data=SBUF;	//存储接收到的数据
	SBUF=rec_data;	//将接收到的数据放入到发送寄存器
	while(!TI);		//等待发送数据完成
	printf("Hello World!\n");
	TI=0;			//清除发送完成标志位
	str = rec_data;	
}

任务二

编写程序,使用温度传感器DS18B20模块及串口,实现以下功能:

1、通过温度传感器获取到当前温度,并通过串口发送PC机。

2、通过PC机上的串口助手设置高温阈值,并通过LCD1602显示阈值,当温度超过时,能用蜂鸣器报警。(波特率设置为4800,数据位8位,无奇偶校验位)

用定时器0给蜂鸣器提供脉冲,但效果不理想。超过设定温度后蜂鸣器不能明显鸣叫

主函数

在这里插入图片描述

通过PC发送hex进制数据,再将单片机接受到的数据转化成预先设定对应的十进制数。

可自行设定switch函数中对应转化的值

#include <stdio.h>
#include "public.h"
#include "ds18b20.h"
#include "lcd1602.h"
#include "beep.h"

float temp_value = 0;//传感器测量温度
int set_temp = 30;//串口设定温度,默认30℃

void uart_init(u8 baud)
{
	TMOD=0x21; //定时器0工作在方式1,定时器1工作在方式2
	SCON=0X50;	//设置为工作方式1
	PCON=0X80;	//波特率加倍
  TH1 = baud;
  TL1 = baud;
	ES=1;		//打开接收中断
	EA=1;		//打开总中断
	TR1=1;		//打开计数器	
	IP = 0x06;	
}

void main()
{	
	uart_init(0XF3);//波特率为4800
	ds18b20_init();
	lcd1602_init();
	T0_init();//蜂鸣器定时器初始化
	while(1)
	{	
		lcd1602_Show2Num(7,0,set_temp);//显示设定温度
		
		temp_value=ds18b20_read_temperture();
		if(temp_value<0)//温度值为负值
		{
			temp_value = -temp_value;
		}
		else;
		
		if(temp_value>set_temp)//判断当前温度是否超过设定温度
		{
			TR0=1;
		}		
		else
		{
			TR0=0;
		}				
	}		
}

void uart() interrupt 4 //串口通信中断函数
{
	u8 rec_data;
	EA = 0;
	RI = 0;			//清除接收中断标志位
	rec_data=SBUF;	//存储接收到的数据
	SBUF=rec_data;
	while(!TI);//等待发送数据完成
	printf("temperature:%2f\n",temp_value);
	TI = 0;			//清除发送完成标志位
	switch(rec_data)
	{
		case 0x10:set_temp=10;break;
		case 0x20:set_temp=20;break;
		case 0x30:set_temp=30;break;
		default:set_temp=40;
	}
	EA = 1;
}
ds18b20.c
#include "ds18b20.h"
#include "intrins.h"

/*******************************************************************************
* 函 数 名         : ds18b20_reset
* 函数功能		   : 复位DS18B20  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_reset(void)
{
	DS18B20_PORT=0;	//拉低DQ
	delay_10us(75);	//拉低750us
	DS18B20_PORT=1;	//DQ=1
	delay_10us(2);	//20US
}

/*******************************************************************************
* 函 数 名         : ds18b20_check
* 函数功能		   : 检测DS18B20是否存在
* 输    入         : 无
* 输    出         : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 ds18b20_check(void)
{
	u8 time_temp=0;

	while(DS18B20_PORT&&time_temp<20)	//等待DQ为低电平
	{
		time_temp++;
		delay_10us(1);	
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	else time_temp=0;
	while((!DS18B20_PORT)&&time_temp<20)	//等待DQ为高电平
	{
		time_temp++;
		delay_10us(1);
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	return 0;
}

/*******************************************************************************
* 函 数 名         : ds18b20_read_bit
* 函数功能		   : 从DS18B20读取一个位
* 输    入         : 无
* 输    出         : 1/0
*******************************************************************************/
u8 ds18b20_read_bit(void)
{
	u8 dat=0;
	
	DS18B20_PORT=0;
	_nop_();_nop_();
	DS18B20_PORT=1;	
	_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
	if(DS18B20_PORT)dat=1;	//如果总线上为1则数据dat为1,否则为0
	else dat=0;
	delay_10us(5);
	return dat;
} 

/*******************************************************************************
* 函 数 名         : ds18b20_read_byte
* 函数功能		   : 从DS18B20读取一个字节
* 输    入         : 无
* 输    出         : 一个字节数据
*******************************************************************************/
u8 ds18b20_read_byte(void)
{
	u8 i=0;
	u8 dat=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
	{
		temp=ds18b20_read_bit();
		dat=(temp<<7)|(dat>>1);
	}
	return dat;	
}

/*******************************************************************************
* 函 数 名         : ds18b20_write_byte
* 函数功能		   : 写一个字节到DS18B20
* 输    入         : dat:要写入的字节
* 输    出         : 无
*******************************************************************************/
void ds18b20_write_byte(u8 dat)
{
	u8 i=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
	{
		temp=dat&0x01;//选择低位准备写入
		dat>>=1;//将次高位移到低位
		if(temp)
		{
			DS18B20_PORT=0;
			_nop_();_nop_();
			DS18B20_PORT=1;	
			delay_10us(6);
		}
		else
		{
			DS18B20_PORT=0;
			delay_10us(6);
			DS18B20_PORT=1;
			_nop_();_nop_();	
		}	
	}	
}

/*******************************************************************************
* 函 数 名         : ds18b20_start
* 函数功能		   : 开始温度转换
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_start(void)
{
	ds18b20_reset();//复位
	ds18b20_check();//检查DS18B20
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0x44);//转换命令	
}

/*******************************************************************************
* 函 数 名         : ds18b20_init
* 函数功能		   : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输    入         : 无
* 输    出         : 1:不存在,0:存在
*******************************************************************************/ 
u8 ds18b20_init(void)
{
	ds18b20_reset();
	return ds18b20_check();	
}

/*******************************************************************************
* 函 数 名         : ds18b20_read_temperture
* 函数功能		   : 从ds18b20得到温度值
* 输    入         : 无
* 输    出         : 温度数据
*******************************************************************************/
float ds18b20_read_temperture(void)
{
	float temp;
	u8 dath=0;
	u8 datl=0;
	u16 value=0;

	ds18b20_start();//开始转换
	ds18b20_reset();//复位
	ds18b20_check();
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0xbe);//读存储器

	datl=ds18b20_read_byte();//低字节
	dath=ds18b20_read_byte();//高字节
	value=(dath<<8)+datl;//合并为16位数据

	if((value&0xf800)==0xf800)//判断符号位,负温度
	{
		value=(~value)+1; //数据取反再加1
		temp=value*(-0.0625);//乘以精度	
	}
	else //正温度
	{
		temp=value*0.0625;	
	}
	return temp;
}

ds18b20.h
#ifndef _ds18b20_H
#define _ds18b20_H

#include "public.h"

//管脚定义
sbit DS18B20_PORT=P3^7;	//DS18B20数据口定义


//函数声明
u8 ds18b20_init(void);
float ds18b20_read_temperture(void);

#endif
lcd1602.c

编写一个显示两位数的显示函数lcd1602_Show2Num

#include "lcd1602.h"


/*******************************************************************************
* 函 数 名       : lcd1602_write_cmd
* 函数功能		 : LCD1602写命令
* 输    入       : cmd:指令
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS=0;//选择命令
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=cmd;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入	
}
#else	//4位LCD
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS=0;//选择命令
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=cmd;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入
	
	LCD1602_DATAPORT=cmd<<4;//准备命令
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入	
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_write_data
* 函数功能		 : LCD1602写数据
* 输    入       : dat:数据
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_write_data(u8 dat) 
{
	LCD1602_RS=1;//选择数据
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=dat;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入		
}
#else
void lcd1602_write_data(u8 dat) 
{
	LCD1602_RS=1;//选择数据
	LCD1602_RW=0;//选择写
	LCD1602_E=0;
	LCD1602_DATAPORT=dat;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入
	
	LCD1602_DATAPORT=dat<<4;//准备数据
	delay_ms(1);
	LCD1602_E=1;//使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E=0;//使能脚E后负跳变完成写入		
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_init
* 函数功能		 : LCD1602初始化
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
#if (LCD1602_4OR8_DATA_INTERFACE==0)//8位LCD
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x38);//数据总线8位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01);//清屏	
}
#else
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x28);//数据总线4位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01);//清屏	
}
#endif

/*******************************************************************************
* 函 数 名       : lcd1602_clear
* 函数功能		 : LCD1602清屏
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void lcd1602_clear(void)
{
	lcd1602_write_cmd(0x01);	
}

/*******************************************************************************
* 函 数 名       : lcd1602_show_string
* 函数功能		 : LCD1602显示字符
* 输    入       : x,y:显示坐标,x=0~15,y=0~1;
				   str:显示字符串
* 输    出    	 : 无
*******************************************************************************/
void lcd1602_show_string(u8 x,u8 y,u8 *str)
{
	u8 i=0;

	if(y>1||x>15)return;//行列参数不对则强制退出

	if(y<1)	//第1行显示
	{	
		while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示
		{
			if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示
			{
				lcd1602_write_cmd(0x80+i+x);//第一行显示地址设置	
			}
			else
			{
				lcd1602_write_cmd(0x40+0x80+i+x-16);//第二行显示地址设置	
			}
			lcd1602_write_data(*str);//显示内容
			str++;//指针递增
			i++;	
		}	
	}
	else	//第2行显示
	{
		while(*str!='\0')
		{
			if(i<16-x) //如果字符长度超过第二行显示范围,则在第一行继续显示
			{
				lcd1602_write_cmd(0x80+0x40+i+x);	
			}
			else
			{
				lcd1602_write_cmd(0x80+i+x-16);	
			}
			lcd1602_write_data(*str);
			str++;
			i++;	
		}	
	}				
}
/*用户函数*/

void LcdSetCursor(u8 x, u8 y)//x为列,y为行
{
	u8 addr;
	if(y==0)
		addr=0x80+x;//第一行
	else
		addr=0xC0+x;//第二行
	lcd1602_write_cmd(addr);
}

void LcdSlide(u8 x, u8 y, u8 *str, u8 len)//滚动显示
{
	LcdSetCursor(x,y);
	while(len--)
	{
		lcd1602_write_data(*str++);
	}
}
void lcd1602_Show2Num(u8 x, u8 y, u8 num)
{
	u8 a,b;
	a=num/10;
	b=num%10;
	LcdSetCursor(x,y);
	lcd1602_write_data(a+'0');
	LcdSetCursor(x+1,y);
	lcd1602_write_data(b+'0');
	
}
lcd1602.h
#ifndef _lcd1602_H
#define _lcd1602_H

#include "public.h"
//LCD1602数据口4位和8位定义,若为1,则为LCD1602四位数据口驱动,反之为8位
#define LCD1602_4OR8_DATA_INTERFACE	0	//默认使用8位数据口LCD1602

//管脚定义
sbit LCD1602_RS=P2^6;//数据命令选择
sbit LCD1602_RW=P2^5;//读写选择
sbit LCD1602_E=P2^7; //使能信号
#define LCD1602_DATAPORT P0	//宏定义LCD1602数据端口


//函数声明
void lcd1602_init(void);
void lcd1602_clear(void);
void lcd1602_show_string(u8 x,u8 y,u8 *str);
void lcd1602_write_data(u8 dat);
void lcd1602_write_cmd(u8 cmd);
void LcdSetCursor(u8 x,u8 y);
void LcdSlide(u8 x, u8 y, u8 *str, u8 len);
void lcd1602_Show2Num(u8 x, u8 y, u8 num);
#endif
beep.c
#include <reg52.h>
#include "beep.h"
unsigned int flag = 0;
void T0_init(void)
{
		TMOD=0x21; //定时器0工作在方式1,定时器1工作在方式2
    TH0 = 0x0FF;//定时10us
    TL0 = 0x0F6;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void T0_isr(void) interrupt 1
{
	flag++;
    TH0 = 0x0FF;//定时10us
    TL0 = 0x0F6; 
	if(flag == 1000)//以1Khz频率发声
	{
		BEEP = ~BEEP;
		flag = 0;
	}
}
beep.h
#ifndef _BEEP_H
#define _BEEP_H
sbit BEEP = P1^5;
void T0_init(void);
#endif
public.c
#include "public.h"

/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ms:ms延时时间
* 输    出    	 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
	u16 i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
}
public.h
#ifndef _public_H
#define _public_H

#include "reg52.h"

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;


void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

#endif

上述代码只能实现蜂鸣器滴答滴答地响

也许是定时器与串口中断发生冲突,可通过调整定时器的优先级等方法实现长鸣报警。待解决。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基于51单片机DS18B20温度传感器设计的温控系统主要是用于测量和控制温度的系统。DS18B20温度传感器是一款数字温度传感器,基于单总线协议,可直接与51单片机进行通信。 首先,系统通过DS18B20温度传感器实时测量环境温度。该传感器使用3引脚结构(VCC、GND和DATA),其中DATA引脚与51单片机的IO口相连,通过总线控制器将数据发送给单片机。传感器输出的数字信号可以转换成温度值,使用51单片机的ADC模块进行模数转换,得到实际温度。 其次,系统根据测得的温度值进行控制。根据设定的温度范围,在单片机程序中设定一个目标温度值。当实际温度高于该目标温度值时,单片机可以通过控制继电器或开关来开启降温装置,如风扇或空调。当实际温度低于目标温度时,则关闭降温装置。以此实现对温度的控制。 此外,系统还可以加入一些功能以增强可调节性和稳定性。例如,可以设置上下限警报温度,当温度超过上限或低于下限时,系统可以通过蜂鸣器或显示屏发出警报,提醒操作人员。另外,还可以利用51单片机的定时功能,定时监测温度并记录,以便分析温度变化趋势。 综上所述,基于51单片机DS18B20温度传感器设计的温控系统,通过实时测量温度值,并根据设定的目标温度值进行温度控制,不仅可以稳定环境温度,还可以发出警报和记录温度变化。这样的系统在实验室、温室和家庭等环境中都有广泛应用前景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值