实验五 基于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
上述代码只能实现蜂鸣器滴答滴答地响
也许是定时器与串口中断发生冲突,可通过调整定时器的优先级等方法实现长鸣报警。待解决。