在LCD屏&手机上显示温湿度(通过蓝牙)

在LCD屏&手机上显示温湿度(通过蓝牙)

1.1 功能描述

  • 通过温湿度传感器,在LCD屏上显示温湿度;
  • 通过蓝牙模块,在手机上也可以显示温湿度;

1.2 所需模块

  • HC01蓝牙模块
  • LCD1602模块
  • DHT11温湿度传感器模块

2.0 模块介绍

2.1 蓝牙模块

我用的是HC01
请添加图片描述
在这里插入图片描述

大家在某宝买一个有差不多引脚的就ok;

  • 引脚连接
    • 我们只要接4根线就行,VCC & GND 就不讲了;
    • 注意!注意!蓝牙模块的RXD引脚 要接对应芯片原理图对应的TXD口、蓝牙模块的TDX要对应芯片的RXD口

在这里插入图片描述

TXD发送,RXD接收,进而进行通讯;

  • 怎么在手机上显示呢?

    根据模块上的网站,www.hc01.com下载HC蓝牙助手

根据模块的名字,找到对应的蓝牙模块;(显示的效果,后面会讲)

2.2 LCD模块

我用的是LCD1602模块

在这里插入图片描述
在这里插入图片描述

看不懂也没关系,copy好 LCD的初始化配置后,LCD模块无非是最后改一下显示字符而已

  • 接线

    //电源
    VSS -- GND
    VDD -- 5V
    //对比度
    V0 -- GND
    //控制线
    RS -- P1.0
    RW -- P1.1
    E -- P1.4
    //背光灯
    A -- 5V
    K -- GDN
    //数据
    D0到D7 -- P0.到P0.7
    

    认真接线;

    注意!: V0 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度 过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整对比度;

在这里插入图片描述

电位器就是一个滑动变阻器,在VO口接一个电阻就ok

LCD只能显示两行,初始化的逻辑也蛮麻烦的,这边直接给整理好的代码,cv就ok

  • LCD模块代码,注释很丰富,有兴趣大家可以看看,

LCD1602.c

#include "reg52.h"
#include "intrins.h"
#include "delay.h"

#define databuffer  P0 //定义八位数据线,P0端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;

void check_busy()
{
    char tmp = 0x80;//忙线,判断
    databuffer = 0x80;
    
    while(tmp & 0x80) // 1000 0000
    {
        RS = 0;
        RW = 1;
        EN = 0;
        _nop_();
        EN = 1;
        _nop_();
        _nop_();
        tmp = databuffer;
        EN = 0;
        _nop_();
    }
   
}
void Write_Data_Func(char dataShow)
{
    check_busy();
    RS = 1;
    RW = 0;
    
    EN = 0;
    _nop_();
    databuffer = dataShow; 
    _nop_();
    EN = 1;
    _nop_();
    _nop_();
    EN = 0;
    _nop_();
}

void Write_Cmd_Func(char cmd)
{
    check_busy();
    RS = 0; //写操作
    RW = 0;
    
    EN = 0;
    _nop_();
    databuffer = cmd; 
    _nop_();
    EN = 1;
    _nop_();
    _nop_();
    EN = 0;
    _nop_();
}
void LCD1602_INIT()
{
    //(1)延时 15ms
    Delay15ms();
    //(2)写指令 38H(不检测忙信号)
    Write_Cmd_Func(0x38);
    //(3)延时 5ms
    Delay5ms();
    //(4)以后每次写指令,读/写数据操作均需要检测忙信号
    //(5)写指令 38H:显示模式设置
    Write_Cmd_Func(0x38);
    //(6)写指令 08H:显示关闭
    Write_Cmd_Func(0x08);
    //(7)写指令 01H:显示清屏
    Write_Cmd_Func(0x01);
    //(8)写指令 06H:显示光标移动设置
    Write_Cmd_Func(0x06);
    //(9)写指令 0CH:显示开及光标设置}
    Write_Cmd_Func(0x0c);
}

void LCD1602_showLine(char row,char col,char *string)
{
    switch(row)
    {
        case 1:
            Write_Cmd_Func(0x80+col);
            while(*string)
            {   
                Write_Data_Func(*string);
                string++;
            }                
            break;
        case 2:
            Write_Cmd_Func(0x80+0x40+col);
            while(*string)
            {   
                Write_Data_Func(*string);
                string++;
            }   
            break; 
    }
}

LCD1602.h

#include "reg52.h"
#include "intrins.h"
#include "delay.h"

#define databuffer  P0 //定义八位数据线,P0端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;

void check_busy();
void Write_Data_Func(char dataShow);
void Write_Cmd_Func(char cmd);
void LCD1602_INIT();
void LCD1602_showLine(char row,char col,char *string);

2.3温湿度传感器模块

我用的是DHT11

在这里插入图片描述

  • 引脚介绍

    • VCC & GND 就不讲了;
    • DATA 引脚 我随便接在一个没被占用的口就行,我接在了P3.3口;
  • 内部逻辑

    • 数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和

    • 通讯过程时序图

在这里插入图片描述

我们需要检验模块是否存在,并提供延时等一些了逻辑关系来推理给出的信号是1/0;比较麻烦,这边直接给代码,大家可以通过代码和下列时序图理解;

在这里插入图片描述

  • 模块代码附上

DTH.c

#include "reg52.h"
#include "delay.h"
sbit dht = P3^3;//模块的data插在p3.3
char datas[5];

void DHT11_Start()
{
	dht = 1;
	dht = 0;
	//延时30ms
	Delay30ms();
	dht = 1;
	//卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht)
	while(dht);
	while(!dht);
	while(dht);
}

void Read_Data_From_DHT()
{
	int i;//轮
	int j;//每一轮读多少次
	char tmp;
	char flag;
	
	DHT11_Start();
	for(i= 0;i < 5;i++){
		//卡g点:while(!dht)       有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平
		for(j=0;j<8;j++){
			while(!dht);//等待卡g点
			Delay40us();
			if(dht == 1){
				flag = 1;
				while(dht);
			}else{
				flag = 0;
			} 
			tmp = tmp << 1;
			tmp |= flag;
		} 
		datas[i] = tmp;
	}
}

DTH.h

#include "reg52.h"
#include "delay.h"

void DHT11_Start();
void Read_Data_From_DHT();

3.0整合

把线都接好后,keil4里的程序也分模块放

main.c

#include "reg52.h"
#include "intrins.h"
#include "delay.h"
#include "uart.h"
#include "LCD1602.h"
#include "DTH.h"

char temp[8];
char huma[8];
extern char datas[5];
sbit ledOne = P3^7;


void Build_Datas()
{
    huma[0] = 'H';
    huma[1] = datas[0]/10 + 0x30;
    huma[2] = datas[0]%10 + 0x30;
    huma[3] = '.';
    huma[4] = datas[1]/10 + 0x30;
    huma[5] = datas[1]%10 + 0x30;
    huma[6] = '%';
    huma[7] = '\0';
    
    temp[0] = 'T';
    temp[1] = datas[2]/10 + 0x30;
    temp[2] = datas[2]%10 + 0x30;
    temp[3] = '.';
    temp[4] = datas[3]/10 + 0x30;
    temp[5] = datas[3]%10 + 0x30;
    temp[6] = '%';
    temp[7] = '\0';
}

void main() 
{
	
    Delay1000ms();  
    UartInit();
    LCD1602_INIT();   
	Delay1000ms();
	ledOne = 0;
	while(1){
		Delay1000ms();
		Read_Data_From_DHT();	
		Build_Datas();
        sendString(huma);
        sendString("\r\n");
        sendString(temp);
        sendString("\r\n");
        LCD1602_showLine(1,2,huma);
        LCD1602_showLine(2,2,temp);
	}
	
}

uart.c

#include "reg52.h"
sfr AUXR = 0x8E;

void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;
	SCON = 0x40; //配置串口工作方式1,REN不使能接收
	TMOD &= 0xF0;
	TMOD |= 0x20;//定时器1工作方式位8位自动重装
	
	TH1 = 0xFD;
	TL1 = 0xFD;//9600波特率的初值
	TR1 = 1;//启动定时器
}
void sendByte(char data_msg)
{
	SBUF = data_msg;
	while(!TI);
	TI = 0;
}

void sendString(char* str)
{
	while( *str != '\0'){
		sendByte(*str);
		str++;
	}
}

uart.h

#include "reg52.h"
sfr AUXR = 0x8E;

void UartInit(void);		//9600bps@11.0592MHz
void sendByte(char data_msg);
void sendString(char* str);

LCD1602.c

#include "reg52.h"
#include "intrins.h"
#include "delay.h"

#define databuffer  P0 //定义八位数据线,P0端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;

void check_busy()
{
    char tmp = 0x80;//忙线,判断
    databuffer = 0x80;
    
    while(tmp & 0x80) // 1000 0000
    {
        RS = 0;
        RW = 1;
        EN = 0;
        _nop_();
        EN = 1;
        _nop_();
        _nop_();
        tmp = databuffer;
        EN = 0;
        _nop_();
    }
   
}
void Write_Data_Func(char dataShow)
{
    check_busy();
    RS = 1;
    RW = 0;
    
    EN = 0;
    _nop_();
    databuffer = dataShow; 
    _nop_();
    EN = 1;
    _nop_();
    _nop_();
    EN = 0;
    _nop_();
}

void Write_Cmd_Func(char cmd)
{
    check_busy();
    RS = 0; //写操作
    RW = 0;
    
    EN = 0;
    _nop_();
    databuffer = cmd; 
    _nop_();
    EN = 1;
    _nop_();
    _nop_();
    EN = 0;
    _nop_();
}
void LCD1602_INIT()
{
    //(1)延时 15ms
    Delay15ms();
    //(2)写指令 38H(不检测忙信号)
    Write_Cmd_Func(0x38);
    //(3)延时 5ms
    Delay5ms();
    //(4)以后每次写指令,读/写数据操作均需要检测忙信号
    //(5)写指令 38H:显示模式设置
    Write_Cmd_Func(0x38);
    //(6)写指令 08H:显示关闭
    Write_Cmd_Func(0x08);
    //(7)写指令 01H:显示清屏
    Write_Cmd_Func(0x01);
    //(8)写指令 06H:显示光标移动设置
    Write_Cmd_Func(0x06);
    //(9)写指令 0CH:显示开及光标设置}
    Write_Cmd_Func(0x0c);
}

void LCD1602_showLine(char row,char col,char *string)
{
    switch(row)
    {
        case 1:
            Write_Cmd_Func(0x80+col);
            while(*string)
            {   
                Write_Data_Func(*string);
                string++;
            }                
            break;
        case 2:
            Write_Cmd_Func(0x80+0x40+col);
            while(*string)
            {   
                Write_Data_Func(*string);
                string++;
            }   
            break; 
    }
}

LCD1602.h

#include "reg52.h"
#include "intrins.h"
#include "delay.h"

#define databuffer  P0 //定义八位数据线,P0端口组
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;

void check_busy();
void Write_Data_Func(char dataShow);
void Write_Cmd_Func(char cmd);
void LCD1602_INIT();
void LCD1602_showLine(char row,char col,char *string);

delay.c

#include "intrins.h"
#include "delay.h"
void Delay40us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do{
		while (--j);
	} while (--i);
}


void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 9;
	j = 244;
	do{
		while (--j);
	} while (--i);
}

void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 27;
	j = 226;
	do{
		while (--j);
	} while (--i);
}

delay.h

#include "intrins.h"
void Delay40us();		//@11.0592MHz
void Delay1000ms();		//@11.0592MHz
void Delay30ms();		//@11.0592MHz
void Delay5ms();		//@11.0592MHz
void Delay15ms();		//@11.0592MHz

DHT.c

#include "reg52.h"
#include "delay.h"
sbit dht = P3^3;//模块的data插在p3.3
char datas[5];

void DHT11_Start()
{
	dht = 1;
	dht = 0;
	//延时30ms
	Delay30ms();
	dht = 1;
	//卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht)
	while(dht);
	while(!dht);
	while(dht);
}

void Read_Data_From_DHT()
{
	int i;//轮
	int j;//每一轮读多少次
	char tmp;
	char flag;
	
	DHT11_Start();
	for(i= 0;i < 5;i++){
		//卡g点:while(!dht)       有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平
		for(j=0;j<8;j++){
			while(!dht);//等待卡g点
			Delay40us();
			if(dht == 1){
				flag = 1;
				while(dht);
			}else{
				flag = 0;
			} 
			tmp = tmp << 1;
			tmp |= flag;
		} 
		datas[i] = tmp;
	}
}

DTH.h

#include "reg52.h"
#include "delay.h"

void DHT11_Start();
void Read_Data_From_DHT();

在这里插入图片描述

欢迎大家交流讨论

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值