STM32F1基于标准库ST7735 1.8‘‘LCD显示DHT11数据

news/2024/11/21 1:46:56/

STM32基于标准库ST7735 1.8‘’LCD显示DHT11数据


  • 📍HAL库驱动可以参考:《STM32基于HAL工程读取DHT11数据》
  • 🌼显示效果:
    在这里插入图片描述
    在这里插入图片描述

🌻ST7735 128x160 1.8’'LCD屏幕

  • 📌屏幕资料和相关驱动可以参考《1.8寸TFT LCD128X160 ST7735S SPI串口屏驱动示例》
  • 🚩如果驱动显示边框出现雪花,那可以调整函数setCursor()中的参数加以修正。

📓DHT11驱动代码

  • 🌿bsp_DHT11.h
/*************************************************************************************************************************************【文件名称】  bsp_DHT11.c**【文件功能】**【适用平台】  STM32F103 + 标准库v3.5 + keil5************************************************************************************************************************************/
#include "bsp_DHT11.h"xDHT11_TypeDef       xDHT11;             // 声明全局结构体, 用于记录信息static GPIO_TypeDef *DHT11_GPIOx = 0;    // 引脚端口
static uint32_t      DHT11_PINx  = 0;    // 引脚编号#define  DHT11_BUS_HIGH     (DHT11_GPIOx->BSRR = (uint32_t)DHT11_PINx)           // DAT引脚 置高电平
#define  DHT11_BUS_LOW      (DHT11_GPIOx->BSRR = ((uint32_t)DHT11_PINx) << 16)   // DAT引脚 置低电平
#define  DHT11_BUS_READ     ((DHT11_GPIOx->IDR & DHT11_PINx) ? 1: 0)             // 读取引脚的电平#if DELAY_MODE_TIM2
#include "stm32f10x_tim.h"
#include "misc.h"
// 定时器初始化配置
// 不使用中断
void Tim2_Init(uint16_t psc, uint16_t arr, FunctionalState NewState)
{TIM_TimeBaseInitTypeDef tim;                         // 结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 开启TIM时钟TIM_DeInit(TIM2);tim.TIM_ClockDivision = TIM_CKD_DIV1;                // 采样分频tim.TIM_CounterMode   = TIM_CounterMode_Up;          // 向上计数tim.TIM_Period        = arr;                         // 自动重装载寄存器的值tim.TIM_Prescaler     = psc - 1;                     // 时钟预分频TIM_TimeBaseInit(TIM2, &tim);                        // 初始化结构体TIM2->SR = (uint16_t)~((uint16_t)0x01);              // 清除更新标志 TIM2->CNT = 0;                                       // 清0计数器TIM_Cmd(TIM2, NewState);                             // 是否开始工作
}static void delay_us(uint32_t us)
{Tim2_Init(72, us, ENABLE);while ((TIM2->SR & 1) == 0);TIM_Cmd(TIM2, DISABLE);
}static void delay_ms(uint32_t ms)
{for (uint16_t i = 0; i < ms; i++){Tim2_Init(72, 990, ENABLE);while ((TIM2->SR & 1) == 0);TIM_Cmd(TIM2, DISABLE);}
}
#else// 本地US粗略延时函数,减少移植时对外部文件依赖;
static void delay_us(uint32_t us)
{uint16_t i = 0;while (us--){i = 7;while (i--);}
}// 本地MS粗略延时函数,减少移植时对外部文件依赖;
static void delay_ms(uint32_t ms)
{uint32_t i = 0;while (ms--){i = 12000;while (i--);}
}
#endif // 结束延时static void DHT11_Mode_IPU(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DHT11_PINx ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DHT11_GPIOx, &GPIO_InitStructure);
}static void DHT11_Mode_Out_PP(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DHT11_PINx ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DHT11_GPIOx, &GPIO_InitStructure);
}static void DHT11_Init(GPIO_TypeDef *GPIOx, uint32_t PINx)
{DHT11_GPIOx = GPIOx;DHT11_PINx = PINx;// 时钟使能:引脚端口;用判断端口的方式使能时钟线, 减少移植时的工作if (GPIOx == GPIOA)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);if (GPIOx == GPIOB)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);if (GPIOx == GPIOC)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);if (GPIOx == GPIOD)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);if (GPIOx == GPIOE)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);if (GPIOx == GPIOF)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);if (GPIOx == GPIOG)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);DHT11_Mode_Out_PP();DHT11_BUS_HIGH;
}// 从DHT11读取一个字节,MSB先行
// 1:每bit以50us低电平标置开始,
// 2:以26~28us的高电平表示“0”
// 3:以70us高电平表示“1”
// 4: 通过检测从高电平开后 x us后的电平即可区别这两个状态
static uint8_t readByte(void)
{uint8_t  temp = 0;for (uint8_t i = 0; i < 8; i++){while (DHT11_BUS_READ == 0);             // 每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束delay_us(40);                             // 延时x us 这个延时需要大于数据0持续的时间即可temp <<= 1;if (DHT11_BUS_READ == 1)                 // x us后仍为高电平表示数据“1”{while (DHT11_BUS_READ == Bit_SET);  // 等待数据1的高电平结束temp |= 1;                           // 位置“1“}}return temp;
}/******************************************************************************* 函  数: DHT11_GetData* 功  能: 从DHT11中读取数据* 参  数: 1:* 说  明: 调用后,获取到的数据,保存到结构体xDHT11中*          温度值:xDHT11.Temperature (有效范围:0~50℃)*          湿度值: xDHT11.Humidity    (有效范围:20%~90%)* 返回值: 0-失败; 1-正常******************************************************************************/
uint8_t DHT11_GetData(GPIO_TypeDef *GPIOx, uint32_t PINx)
{static uint8_t humiInt = 0;        // 湿度的整数部分static uint8_t humiDec = 0;        // 湿度的小数部分static uint8_t TempInt = 0;        // 温度的整数部分static uint8_t TempDec = 0;        // 温度的小数部分static uint8_t sum = 0;            // 校验和DHT11_Init(GPIOx, PINx);// 1:主机产生开始信号DHT11_Mode_Out_PP();               // 输出模式DHT11_BUS_LOW;                     // 主机拉低电平delay_ms(25);                      // 延时18~30ms// 2:主机拉高等待DHT11_BUS_HIGH;                    // 总线拉高delay_us(50);                      // 延时20~40us,这里设置50,是因为要直接进入下一个时序(电平状态),以方便检测// 3: 从机产生响应和准备信号DHT11_Mode_IPU();                  // 主机设为输入 判断从机响应信号if (DHT11_BUS_READ == 0)           // 判断从机是否产生响应信号_低电平, 如不响应则跳出{while (DHT11_BUS_READ == 0);   // 等待响应信号结束:低电平持续约80uswhile (DHT11_BUS_READ == 1);   // 等待标置信号结束:高电平持续约80us// 4: 从机连续输出5字节数据humiInt = readByte();          // 湿度的整数部分// 开始接收数据humiDec = readByte();          // 湿度的小数部分TempInt = readByte();          // 温度的整数部分TempDec = readByte();          // 温度的小数部分sum     = readByte();          // 校验和DHT11_Mode_Out_PP();           // 读取结束,引脚改为输出模式DHT11_BUS_HIGH;                // 主机拉高// 5: 检查读取的数据是否正确if (sum == (humiInt + humiDec + TempInt + TempDec)){xDHT11.Humidity = humiInt + humiDec;xDHT11.Temperature = (float)TempInt  + (float)TempDec / 10;return SUCCESS;            // 校检正确, 返回:SUCCESS=1}return ERROR;                  // 校检错误,返回:ERROR=0}return ERROR;                      // 通信错误,返回:ERROR=0
}/******************************************************************************* 函  数: DHT11_GetTemperature* 功  能: 从DHT11中读取温度值* 参  数: GPIO_TypeDef *GPIOx: GPIO端口号,取值范围:GPIOA ~ GPIOG*          uint32_t     PINx  : 引脚编号,  取值范围:GPIO_Pin_0 ~ GPIO_Pin_15* 说  明: 温度值有效范围:0~50℃; 精度±2°C; 小数部份无效* 返回值: 0-失败,非0值-湿度值******************************************************************************/
float DHT11_GetTemperature(GPIO_TypeDef *GPIOx, uint32_t PINx)
{ DHT11_GetData(GPIOx, PINx);return xDHT11.Temperature;
}/******************************************************************************* 函  数: DHT11_GetHumidity* 功  能: 从DHT11中读取湿度值* 参  数: GPIO_TypeDef *GPIOx: GPIO端口号,取值范围:GPIOA ~ GPIOG*          uint32_t     PINx  : 引脚编号,  取值范围:GPIO_Pin_0 ~ GPIO_Pin_15* 说  明: 湿度值有效范围:20%~90%; 精度±5%; 小数部分无效* 返回值: 0-失败,非0值-湿度值******************************************************************************/
float DHT11_GetHumidity(GPIO_TypeDef *GPIOx, uint32_t PINx)
{  DHT11_GetData(GPIOx, PINx);return xDHT11.Humidity;
}
  • 🌿bsp_DHT11.h
#ifndef __BSP_DHT11_H
#define __BSP_DHT11_H
/*************************************************************************************************************************************【文件名称】  bsp_DHT11.h**【功能测试】  DHT11-温湿度获取**【文件名称】  bsp_DHT11.h**【功能描述】  定义引脚、定义全局结构体、声明全局函数****【适用平台】  STM32F103 + 标准库v3.5 + keil5****【实验操作】  1-模块接线,VCC  接 3.3V 或 5V**                          DATA 接 PC3**                          GND  接 GND****【划 重 点】  1-电压范围:3.3V~5.0V,工作电流:0.2~1mA; 待机电流:150uA**              2-DHT11反应有点慢:上电后1S后进入稳定状态; **              3-采样周期,不同店家的DHT11,参数不同,一般是1次/秒, 有部分可以数百毫秒间隔采集一次; 当小于采样周期进行重复采集数据,会发生错误;**              5-DHT11时序要求较高,us级别,当使用delay粗略延时,同一份代码同一个模块,在不同keil里跑也可能发生错误(代码优化设置对while延时的影响)。建议使用TIM的精准延时;**              4-注意判断使用的DHT11器件,是单独的DHT11元件,还是完整的DHT11模块**                单独的DHT11元件:蓝色塑料主体、三个引脚,不带上拉电阻;适合低成本工程方案使用,建议测试时引脚使用推挽输出模式;**                完整的DTH11模块:蓝色塑料主体、三个引脚、PCB底板、上拉电阻、电源指示LED,适合方案搭建;**              6-精度误差:DHT11分旧版和新版**                          旧版数据稳定,但只有整数部分,新版有小数部分,但数据跳动稍大;**                          温度0-50°C; 精度±2°C; 小数部份无效**                          湿度20-80%; 精度±5%; 小数部分无效******【文件移植】  步骤1-复制文件:可复制bsp_DHT11.c和bsp_DHT11h两个文件,或复制DHT11文件夹,保存到所需工程目录文件夹下;**              步骤2-添加文件:在keil工各程左侧文件管理器中,双击某文件夹,以添加bsp_DHT11.c文件;**              步骤3-添加路径:点击魔术棒工具按钮,在“c/c++"选项页中,点击”Include Path"后面的按键,以添加文件存放所在路径(是文件夹,不是文件);**         步骤4-添加引脚:在所需DHT11功能的代码文件头部,添加:#include "bsp_DHT11.h";******【函数使用】  函数2-DHT11_GetData(GPIOx, GPIO_Pin_x);           // 获取数据, 获取的数据存放于结构体xDHT11中,具体使用方法,可参考示例代码**
***********************************************************************************************************************************/
#include <stm32f10x.h>
#include <stdio.h>#define   DELAY_MODE_TIM2   1     // 通信时序中的延时方式:0_使用while方式的粗略延时; 1_使用TIM2进行计时; 注意计时器是否和其它设备有冲突// 0_使用粗略延时:注意本代码是在勾选下列参数状态下调试的:Options / C++ /One ELF Section per Function ;// 1_使用TIM2计时:首选推荐; 注意同一工程中是否有其它功能使用TIM2,以免发生冲突;/******************************************************************************* 声明 全局变量
****************************************************************************/
typedef struct
{float          Temperature;   // 温度值:在调用DHT11_GetTemp()函数后,获取到的温度值;float          Humidity;      // 湿度值:在调用DHT11_GetTemp()函数后,获取到的温度值;
} xDHT11_TypeDef;
extern xDHT11_TypeDef  xDHT11;    // 声明全局结构体, 用于存放读取的结果值/******************************************************************************* 声明  全局函数
****************************************************************************/
uint8_t DHT11_GetData(GPIO_TypeDef *GPIOx, uint32_t PINx);
float DHT11_GetTemperature(GPIO_TypeDef *GPIOx, uint32_t PINx);
float DHT11_GetHumidity(GPIO_TypeDef *GPIOx, uint32_t PINx);#endif 
  • 📝main.c
#include <stm32f10x.h>            // 头文件引用(标准库); 内核、芯片外设....;(stm32f10x.conf.h, 对标准库头文件进行调用)     
#include "stm32f10x_conf.h"       // 头文件引用(标准库); 内核、芯片外设....;(stm32f10x.conf.h, 对标准库头文件进行调用) 
#include "bsp_led.h"              // LED指示灯
#include "bsp_usart.h"            // USART1、2、3,UART4、5
#include "bsp_lcd_ST7735.h"       // 1.8寸显示屏驱动 
//#include "bsp_w25Qxx.h"           // 外部FLASH,用于中文支持
#include "bsp_DHT11.h"            // DHT11float temperature = 0.0;          // 用于存储温度值; DHT11的精度,小数部分无效
float humidity = 0.0;             // 用于存储湿度值; DHT11的精度,小数部分无效
char   strTem[12];               // 用于临时存储字符串// ms延时函数,减少移植时对外部文件依赖;
static void delay_ms(u32 ms)
{ms = ms * 6500;for (u32 i = 0; i < ms; i++); // 72MHz系统时钟下,多少个空循环约耗时1ms
}// 主函数
int main(void)
{USART1_Init(115200);                                        // 串口初始化:USART1(115200-N-8-1), 且工程已把printf重定向至USART1输出Led_Init();                                                 // LED 初始化LED_RED_ON;                                                 // 点亮红灯//    W25qx_Init();                                               // 初始化外部Flash, 已烧录有中文字库LCD_Init();                                                 // 初始化显示屏-驱动芯片ST7735LCD_String(25, 3, "DHT11 DATA", 16, WHITE, BLACK);      // 预先显示固定的屏显内容,不用重复刷新占用芯片资源LCD_Line(0, 25, 127, 25, WHITE);LCD_String(5, 35, "Temp Value:", 12, WHITE, BLACK);LCD_String(5, 55, "Humi Value:", 12, WHITE, BLACK);LCD_Chinese16ForFile(101, 35, 6, GREEN, BLACK);while (1)                                                   // while函数死循环,不能让main函数运行结束,否则会产生硬件错误{delay_ms(500);                                          // 延时500msLED_RED_TOGGLE;                                         // 红色LED,间隔亮灭,以判断系统正常工作printf("DHT11  ");temperature = DHT11_GetTemperature(GPIOC, GPIO_Pin_3);  // 获取DHT11温度值, 注意,DHT11的精度,小数部分无效printf("温度:%4.1f℃   ", temperature);                  // 把数据输出到电脑串口软件,方便观察sprintf(strTem, "%4.1f", temperature);              // 格式化,把float值存储为字符数组LCD_String(75, 35, strTem, 12, GREEN, BLACK);           // 温度值显示在显示屏上humidity =  DHT11_GetHumidity(GPIOC, GPIO_Pin_3);       // 获取DHT11湿度值, 注意,DHT11的精度,小数部分无效printf("湿度:%4.1fRH%%\r\n", humidity);                 // 把数据输出到电脑串口软件,方便观察sprintf(strTem, "%4.1f%%  ", humidity);                 // 格式化,把float值存储为字符数组LCD_String(75, 55, strTem, 12, GREEN, BLACK);           // 温度值显示在显示屏上}
}

📚工程源码

链接:https://pan.baidu.com/s/1k6iZADRF0rSesPrTYK7rxA 
提取码:82cz

http://www.ppmy.cn/news/999860.html

相关文章

ELK 企业级日志分析系统(ElasticSearch、Logstash 和 Kiabana 详解)

目录 一.ELK简介 1.1ELK的概述 1.2ELK的组成 1.2.1 ElasticSearch 1.2.2 Logstash 1.2.3 Kibana 1.2.4 小总结 1.3可以添加其他组件 1.4filebeat 结合 logstash 带来好处 1.5日志处理的步骤 二.Elasticsearch 2.1Elasticsearch概述 2.2Elasticsearch核心概念 2.2.1接近…

使用Python动画粒子的薛定谔波函数(ψ)(完整代码)

使用Python动画粒子的薛定谔波函数&#xff08;ψ&#xff09;&#xff08;完整代码&#xff09; 使用曲柄-尼科尔森方法求解盒子中的粒子 Kowshik chilamkurthy 以后 发表于 书技术 4 分钟阅读 2月 2021&#xff0c; <> 1.4K 5 左图&#xff1a;来源&#xff0c;右图…

JSON格式Python,Java,PHP等封装根据商品ID获取快手商品详情数据方法

快手商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取拼多多商品详情数据&#xff0c;您可以通过开放平台的接口或者直接访问快手商城的网页来获取商品详情信息。以下是两种常用方法的介绍&#xff1a; 1.…

第七章 图论

第七章 图论 一、数据结构定义 图的邻接矩阵存储法#define MaxVertexNum 100 // 节点数目的最大值// 无边权&#xff0c;只用0或1表示边是否存在 bool graph[MaxVertexNum][MaxVertexNum];// 有边权 int graph[MaxVertexNum][MaxVertexNum];图的邻接表存储法 把所有节点存储为…

量化交易——MACD策略

目标&#xff1a;通过macd指标判断股票买入卖出时机 一、金叉死叉定义 金叉定义&#xff1a; 当MACD指标中的DIFF线从下而上与DEA线交叉时&#xff0c;这个交叉为金叉&#xff0c;金叉一般情况下是买入的信号。 死叉定义&#xff1a; 当MACD指标中的DIFF线从上而下与DEA线交…

掌握 TypeScript 语法的绝佳速览指南

1.环境搭建 1.1 安装 安装 typescript yarn add typescript -g安装 ts-node ts-node 是一个在内存中运行的 TypeScript 运行时&#xff0c;它可以直接运行 ts 文件&#xff0c;而不需要将 ts 文件编译成 js 文件 yarn add ts-node -g安装 types/node types/node 是 node.js …

python的decimal或者叫Decimal,BigDecimal

前言 在python中进行小数计算时&#xff0c;很容易发生精度错误问题&#xff01;&#xff01;&#xff01;&#xff01;一定要注意&#xff01;&#xff01;&#xff01;或者说&#xff0c;只要进行小数的运算都要用decimal。如&#xff1a;银企对账&#xff1b;工程计算等等在…

Java项目-苍穹外卖-Day01

文章目录 博客介绍软件开发流程项目介绍产品原型技术选型 博客介绍 从头开始做黑马的苍穹外卖项目 每天记录一下新学的知识点以及对应的开发进度 然后一些在项目中遇到的问题会重点标注 本篇主要是后端的&#xff0c;前端会一笔带过 软件开发流程 流程介绍需求分析需求规格说…