温湿度LCD显示并上传服务器

项目需求

通过温湿度传感器将值传到LCD1602,并实时通过蓝牙透传到手机。

硬件介绍

温湿度传感器 DHT11温湿度传感器 DHT11_温湿度传感器数据格式-CSDN博客

LCD1602LCD1602-CSDN博客

HC-01

继电器模块

硬件接线

LCD1602
  • D0~D7 --> A0~A7
  • VDD, A --> 5v
  • VSS, VO, K --> GND
  • RS --> B1
  • RW --> B2
  • E --> B10
DHT11
  • VCC --> 5v
  • GND --> GND
  • DATA --> B7
HC-01(也可不接,和电脑串口显示一样的,透传模式)
  • VCC --> 5v
  • GND --> GND
  • RXD --> TX1
  • TXD --> RX1

 各个硬件在先前学习了,就不再一一讲述,此项目仅做代码的移植

 CubeMX

1.常规配置

SYS->Debug->Serial Wire

RCC->High Speed Clock(HSE)->Crystal/Ceramic Resonator

时钟树HSE、PLLCLK打开,HCLK设置成72MHz

打开GPIO口

打开uart1

框内的是在CubeMx重定义的引脚名称,会在mian.h中显示

其中,DHT11的DATA线既作为输入也作为输出,因此不能在CubeMX中进行配置!

为了方便阅读与编写,可在main.h文件重定义引脚

2.时钟

由于hal_delay()只是ms级别的延时,而DHT11中需要us的延时,则需要重新写延时函数,这里我们可以使用软件延时或者硬件延时

软件延时 
void delay_us(uint16_t cnt)
{uint8_t i;while(cnt){for (i = 0; i < 10; i++){}cnt--;}
}
硬件延时:打开定时器

计数一次经过的时间是 (PSC + 1) / Tclk , 因此如果我想要计数1微秒,即0.000001s, 已知Tclk = 72 000 000, 那么PSC就应该设置为 71。然后在main.c中就可以定义出一个实现微秒级延时的函数: 

STM32的HAL库开发各函数意义、笔记_hal_tim_set_counter-CSDN博客

void TIM1_Delay_us(uint16_t n_us) //使用TIM1来做us级延时函数  一个基于STM32 HAL库的TIM1(定时器1)进行微秒级延时的功能。
{
/* 使能定时器1计数 */__HAL_TIM_ENABLE(&htim1);__HAL_TIM_SetCounter(&htim1, 0);while(__HAL_TIM_GetCounter(&htim1) < ((1 * n_us)-1) );
/* 关闭定时器1计数 */__HAL_TIM_DISABLE(&htim1);
}

 3.生成代码

keil

1. 打开MICRO-LIB

2. 编写代码:

 关于上面提到的DHT的DATA引脚,由于有时需要作为输入,有时需要输出,所以不能在Cube中进行定义,而是在Keil中自己写代码定义,可以直接参考main函数中main.c的MX_GPIO_Init()函数,经过跳转可以看到详细信息:

如图,需要:

  • 定义一个结构体
  • 使能时钟
  • 赋初值(这步可省略)
  • 对于结构体的成员变量进行赋值,分别是GPIO_InitStruct.Pin; GPIO_InitStruct.Mode; 
  • GPIO_InitStruct.Speed,其中GPIO_InitStruct.Mode就是需要根据情况修改的
  • 调用HAL_GPIO_Init 函数
    void DHT11_Init(uint32_t Mode)
    {GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = Mode;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}

    然后,

    就可以在需要往DATA写数据的时候写:DHT_GPIO_Init(GPIO_MODE_OUTPUT_PP);

    在需要从DATA读数据的时候写:DHT_GPIO_Init(GPIO_MODE_INPUT);

并且,由于89C52和STM32的硬件差别,使用STM32来驱动LCD1602时,是不需要检测BUSY信号的!!!

但是32驱动LCD的时候,在写命令或内容时,需要用到us级的延时,故要重新编写延时函数

 分文件编写,要将相应的.c.h文件分别添加到incsrc文件中,在新添加的文件在CubeMx重新更改的配置重新生成的文件并不会消失。

main.h

#define RS_GPIO_Pin GPIO_PIN_1
#define RS_GPIO_GPIO_Port GPIOB
#define RW_GPIO_Pin GPIO_PIN_2
#define RW_GPIO_GPIO_Port GPIOB
#define EN_GPIO_Pin GPIO_PIN_10
#define EN_GPIO_GPIO_Port GPIOB/* USER CODE BEGIN Private defines */
#define DHT_11_GPIO GPIOB
#define DHT_11_PIN GPIO_PIN_7#define DHT_11_LOW  HAL_GPIO_WritePin(DHT_11_GPIO,DHT_11_PIN,GPIO_PIN_RESET)
#define DHT_11_HIGH HAL_GPIO_WritePin(DHT_11_GPIO,DHT_11_PIN,GPIO_PIN_SET)
#define DHT_11_VALUE HAL_GPIO_ReadPin(DHT_11_GPIO,DHT_11_PIN)#define RS_HIGH HAL_GPIO_WritePin(RS_GPIO_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_SET)
#define RS_LOW  HAL_GPIO_WritePin(RS_GPIO_GPIO_Port,RS_GPIO_Pin,GPIO_PIN_RESET)
#define RW_HIGH HAL_GPIO_WritePin(RW_GPIO_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_SET)
#define RW_LOW  HAL_GPIO_WritePin(RW_GPIO_GPIO_Port,RW_GPIO_Pin,GPIO_PIN_RESET)
#define EN_HIGH HAL_GPIO_WritePin(EN_GPIO_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_SET)
#define EN_LOW  HAL_GPIO_WritePin(EN_GPIO_GPIO_Port,EN_GPIO_Pin,GPIO_PIN_RESET)

main.c

#include "stdio.h"
#include "lcd1602.h"
#include "dht11.h"extern char datas[5];
char temperature[9];
char humidity[9];void Build_datas()
{humidity[0] = 'H';humidity[1] = ':';humidity[2] = datas[0]/10 + 0x30;humidity[3] = datas[0]%10 + 0x30;humidity[4] = '.';humidity[5] = datas[1]/10 + 0x30;humidity[6] = datas[1]%10 + 0x30;humidity[7] = '%';humidity[8] = '\0';temperature[0] = 'T';temperature[1] = ':';temperature[2] = datas[2]/10 + 0x30;temperature[3] = datas[2]%10 + 0x30;temperature[4] = '.';temperature[5] = datas[3]/10 + 0x30;temperature[6] = datas[3]%10 + 0x30;temperature[7] = 'C';temperature[8] = '\0';
}int fputc(int a, FILE *f) //一个字符一个字符发送
{unsigned char temp[1] = {a};HAL_UART_Transmit(&huart1, temp, 1, 0xffff);return a;
}printf("code hhh\r\n");LCD1602_Init();LCD1602_ShowLine(1,5,"shion");LCD1602_ShowLine(2,5,"114514");HAL_Delay(2000);while (1){Read_data_From_DHT();printf("Temp ; %d,%d\t",datas[2],datas[3]);printf("Humi ; %d,%d\r\n",datas[0],datas[1]);Build_datas();printf("%s\t",humidity);printf("%s",temperature);LCD1602_ShowLine(1,2,humidity);LCD1602_ShowLine(2,2,temperature);HAL_Delay(1000);}}

 LCD1602.h

#ifndef __LCD1602_H
#define __LCD1602_Hvoid Write_cmd_Func(char cmd);//写入指令的函数void Write_data_Func(char dataShow);//写入数据的函数void LCD1602_Init(void);void LCD1602_ShowLine(char row,char col,char *string);#endif

LCD1602.c

#include "lcd1602.h"
#include "gpio.h"
#include "main.h"void Write_cmd_Func(char cmd)//写入指令的函数
{RS_LOW;//写指令RW_LOW;EN_LOW;HAL_Delay(5);GPIOA->ODR = cmd;EN_HIGH;HAL_Delay(5);EN_LOW;
}void Write_data_Func(char dataShow)//写入数据的函数
{RS_HIGH;//写内容RW_LOW;EN_LOW;HAL_Delay(5);GPIOA->ODR = dataShow;EN_HIGH;HAL_Delay(5);EN_LOW;
}void LCD1602_Init(void)
{//(1)延时 15msHAL_Delay(15);//(2)写指令 38H(不检测忙信号)Write_cmd_Func(0x38);//(3)延时 5msHAL_Delay(5);//(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;	}/*char pos;if(hang == 0){//如果第一行pos = 0x80 + 0x00 + lie; }else if(hang == 1){//如果第二行pos = 0x80 + 0x40 + lie;}Check_Busy();Write_data_Func(*string);while(*string != '\0'){Check_Busy();Write_data_Func(*string);string++;}*/
}

 DHT11.h

#ifndef __DHT11_H
#define __DHT11_Hvoid Read_data_From_DHT();#endif

 dht11.c

#include "dht11.h"
#include "gpio.h"
#include "main.h"uint8_t datas[5];void delay_us(uint16_t cnt)
{uint8_t i;while(cnt){for (i = 0; i < 10; i++){}cnt--;}
}void DHT11_Init(uint32_t Mode)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = Mode;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}void DHT_Start()
{DHT11_Init(GPIO_MODE_OUTPUT_PP);//设置为输出模式!!DHT_11_HIGH;DHT_11_LOW;HAL_Delay(30);DHT_11_HIGH;DHT11_Init(GPIO_MODE_INPUT);//设置为输入模式!!while(DHT_11_VALUE == 1);//不断读取直到DHT再次变低,跳出循环,说明模块响应while(DHT_11_VALUE == 0);//不断读取直到DHT再次拉高,80us之后,再经过50us后DHT变成低电平,就代表要开始变高并开始传输数据了while(DHT_11_VALUE == 1);//等待数据传输,不断读取直到DHT再次变低,如退出循环说明数据传输前的50us低电平开始了}void Read_data_From_DHT()
{int i;//轮int j;//每一轮读多少次char temp;char flag;DHT_Start();for(i = 0;i < 5;  i++){//5组数据for(j =0;j<8;j++){//每组数据8位while(!DHT_11_VALUE);//等待上拉  dht = 1 退出循环delay_us(40);//高电平持续26-28us是‘0’,高电平持续70us是'1',所以delay40us之后观察还是否是高电平if(DHT_11_VALUE == 1){flag = 1;while(DHT_11_VALUE);//不断读取下拉的一瞬间,因为在开始传输数据之前要延迟80us,如果提前结束,下一次开始传输数据就会出错,因为“开始传输数据”是从判断上拉开始的}else{flag = 0;}temp =  temp << 1;//temp左移一位,例如temp= 10101011  左移之后变成-》01010110(第一个数移出去,最后一位补零)temp |= flag;//假如flag=1,temp=01010111}datas[i] = temp;}}

 效果显示

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/1318.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32H750外设ADC之双重 ADC 模式

目录 概述 1 双重 ADC 模式介绍 1.1 双重 ADC模式 1.2 双重 ADC 模式的类型 2 双重 ADC 模式寄存器的配置 3 模式功能实现 3.1 注入同步模式 3.2 支持独立注入的常规同步模式 3.2.1 中断的方式 3.2.2 DMA 读取常规数据 3.3 支持独立注入的交替模式 3.3.1 中断触发…

色彩的魔力:渐变色在设计中的无限可能性

夕阳&#xff0c;天空&#xff0c;湖面&#xff0c;夕阳...随着距离和光影的变化&#xff0c;颜色的渐变色&#xff0c;近大远小、近实远虚的透视&#xff0c;为大自然营造了浪漫的氛围。延伸到UI/UX设计领域&#xff0c;这种现实、惊艳、独特的渐变色也深受众多设计师的喜爱。…

setmapAVL树红黑树

目录 关联式容器树形结构的关联式容器setset的模板参数列表set的构造函数set的迭代器set的容量操作set其他操作 multisetmap键值对map的模板参数列表map的迭代器map中元素的修改map的容量与元素访问 multimap底层结构avl树avl树概念AVL树结点的定义AVL树的插入AVL树的旋转AVL树…

python-flask结合bootstrap实现网页小工具实例-半小时速通版

参考&#xff1a; Python之flask结合Bootstrap框架快速搭建Web应用_支持bootstrap的python软件-CSDN博客 https://blog.csdn.net/lovedingd/article/details/106696832 Bootstrap 警告框 | 菜鸟教程 https://www.runoob.com/bootstrap/bootstrap-alert-plugin.html flask框架…

数据结构——7.3 树形查找

7.3 树形查找 概念 二叉排序树&#xff08;BST&#xff09; 二叉排序树&#xff08;Binary Sort Tree&#xff0c;BST&#xff09;&#xff0c;又称为二叉查找&#xff08;搜索&#xff09;树&#xff08;Binary Search Tree&#xff09;&#xff0c;是一种特殊的二叉树&am…

FreeLearning C/C++ 译文集翻译完成

C 高级编程C 高级编程秘籍Qt Creator 应用开发C 游戏编程入门指南C 编程入门指南Boost.Asio C 网络编程Boost C 应用开发秘籍第二版C 数据结构与算法设计原理C Qt5 GUI 编程C 高性能编程C 反应式编程C 系统编程秘籍C 研讨会C 现代嵌入式编程秘籍C 专家编程&#xff1a;成为熟练…

Android,判断是否快速点击

问题背景 在Android控件中,如果快速点击容易造成一些不同的bug,尤其是那种在click事件中方有耗时操作的代码,容易引起anr,并且有些性能低的机器,在用户点击多次控件的时候很容易出现问题,在车机中也会导致回弹的一系列问题(这里面包括get到的信号导致回弹),针对于这种…

力扣---从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示…

Rust常用特型之Borrow和BorrowMut特型

在Rust标准库中&#xff0c;存在很多常用的工具类特型&#xff0c;它们能帮助我们写出更具有Rust风格的代码。 std::borrow::Borrow和AsRef有点相似&#xff0c;如果一个类型实现了Borrow<T>&#xff0c;那么你可以从它的borrow函数里高效的借出一个&T。但是Borrow施…

synchronized和ReentrantLock傻傻分不清楚

synchronized和ReentrantLock都是用于线程间同步的机制&#xff0c;都是可重入锁&#xff08;同一个线程可以多次获取同一个锁&#xff09;&#xff0c;它们的异同点如下&#xff1a; 一、应用场景 1.synchronized可应用于实例方法、静态方法和代码块。 2.ReentrantLock 是 jav…

使用Docker搭建Redis主从集群

文章目录 ☃️前言☃️搭建❄️❄️架构❄️❄️实例说明❄️❄️搭建第一个服务器上的两个实例❄️❄️搭建第二个服务器上的一个实例 ☃️开启主从❄️❄️改配置❄️❄️重启从节点 ☃️验证 ☃️前言 单节点 Redis 的并发能力是有上限的&#xff0c;要进一步提高Redis的并…

了解监控易(33):工单管理

在复杂的IT运维环境中&#xff0c;高效、规范地处理各种事务请求至关重要。监控易的工单管理功能&#xff0c;作为一款轻量化的运维协同工具&#xff0c;为团队提供了一个集中化、标准化的平台&#xff0c;以创建、接单、转交、挂起和重启工单&#xff0c;从而确保客户设备故障…

搜维尔科技:SenseGlove 的 Nova 被用于组装卫星接收器的虚拟现实培训项目中

SenseGlove 的 Nova 被用于组装卫星接收器的虚拟现实培训项目中 搜维尔科技&#xff1a;SenseGlove 的 Nova 被用于组装卫星接收器的虚拟现实培训项目中 得益于 SenseGlove 的力反馈专利&#xff0c;学员可以感受到他们正在组装的零件的形状、尺寸和密度。学员可以通过运动跟踪…

[大模型]TransNormerLLM-7B FastApi 部署调用

TransNormerLLM-7B FastApi 部署调用 1. TransNormer 介绍 TransNormerLLM 是一个基于线性注意力的 LLM&#xff0c;在准确性和效率方面均优于传统的基于 softmax 注意力的模型。它是在包含多达1.4 万亿个令牌的高质量语料库上进行训练的&#xff0c;TransNormerLLM 从之前的…

K-means和DBSCAN

目录 一、K-means和DBSCAN之间的主要区别 二、DBSCAN聚类算法 2.1DBSCAN聚类算法实现点集数据的聚类 2.2DBSCAN聚类算法实现鸢尾花数据集的聚类 三、K-means聚类算法 3.1K-means聚类算法实现随机数据的聚类 3.2K-means聚类算法实现鸢尾花数据集的聚类 一、K-means和DBSC…

014Node.js时间格式包silly-datetime安装与使用

下载&#xff1a; https://www.npmjs.com/网站上下载silly-datetime 安装 npm i silly-datetime --save var sd require(silly-datetime);console.log(new Date()); //2024-04-18T04:40:38.505Zvar dsd.format(new Date(), YYYY-MM-DD HH:mm);console.log(d); //2024…

未加权的相位解包裹算法DCT-0基础入门(含matlab代码和详细教程解析)

后面会更新c++ 的代码 ! phi = phase_unwrap(psi, weight) % get the wrapped differences of the wrapped valuesdx = [zeros([size(psi,1),1]), wrapToPi(diff(psi, 1, 2)), zeros([size(psi,1),1])];dy = [zeros([1,size(psi,2)]); wrapToPi(diff(psi, 1, 1)); zeros([1,s…

idea在controller或者service使用ctrl+alt+b进入方法后,如何返回到 进入前的那一层

idea在controller或者service使用ctrlaltb进入方法后&#xff0c;如何返回到进入方法的最外层 解决方案使用 ctrlalt ← /→← /→ 键盘上的左右键盘

jQuery 选择器有几种,分别是什么

jQuery选择器是用于“选择”&#xff08;或查找&#xff09;HTML元素的强大工具。jQuery选择器基于元素的名称、ID、类、类型、属性等进行选择。以下是jQuery选择器的几种主要类型&#xff0c;以及它们的详细代码示例&#xff1a; 基本选择器&#xff1a; 元素选择器&#xff1…

2024.4.20力扣每日一题——组合总和

2024.4.20 题目来源我的题解方法一 回溯 题目来源 力扣每日一题&#xff1b;题序&#xff1a;39 我的题解 方法一 回溯 以每一个位置开始深搜&#xff0c;直到target等于0或者小于0或者遍历完结束。 关键在于&#xff1a;注意去重 巧妙方法&#xff1a;传入一个index&#x…