[STM32F103C8T6]基于LCD和DHT11、HC08的温湿度检测系统并上传服务器

news2024/11/26 20:49:22

项目实际图

本次项目需要整合LCD1602、DHT11、HC08、继电器

1.首先是LCD1602显示程序

封装管脚,这样的话写时序的时候不用随时都在哪儿HAL_GPIO_WritePin

#define RS_GPIO_Port GPIOB
#define RW_GPIO_Port GPIOB
#define EN_GPIO_Port GPIOB
#define RS_Pin GPIO_PIN_1
#define RW_Pin GPIO_PIN_2
#define EN_Pin GPIO_PIN_10
#define RS_HIGH HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_SET)
#define RS_LOW HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_RESET)
#define RW_HIGH HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_SET)
#define RW_LOW HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_RESET)
#define EN_HIGH HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET)
#define EN_LOW HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_RESET)

 STM32不同于51,STM32的管脚比如PA0-PA7不能以此向直接写入一个字节的数据,必须操作寄存器

GPIOA -> ODR = cmd ;

 根据时序图写操作(stm32可以不检查忙)

LCD.c

#define RS_GPIO_Port GPIOB
#define RW_GPIO_Port GPIOB
#define EN_GPIO_Port GPIOB
#define RS_Pin GPIO_PIN_1
#define RW_Pin GPIO_PIN_2
#define EN_Pin GPIO_PIN_10
#define RS_HIGH HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_SET)
#define RS_LOW HAL_GPIO_WritePin(RS_GPIO_Port, RS_Pin, GPIO_PIN_RESET)
#define RW_HIGH HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_SET)
#define RW_LOW HAL_GPIO_WritePin(RW_GPIO_Port, RW_Pin, GPIO_PIN_RESET)
#define EN_HIGH HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET)
#define EN_LOW HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_RESET)

void Write_Cmd_Func(uint8_t cmd)
{
    RS_LOW;
    RW_LOW;
    EN_LOW;
    GPIOA->ODR = cmd;
    EN_HIGH;
    HAL_Delay(5);
    EN_LOW;
    HAL_Delay(5);
}

void Write_Data_Func(uint8_t dataShow)
{
    RS_LOW;
    RW_LOW;
    EN_LOW;
    GPIOA->ODR = dataShow;
    EN_HIGH;
    HAL_Delay(5);
    EN_LOW;
    HAL_Delay(5);
}

void LCD1602_INIT(void)
{
//(1)延时 15ms
    HAL_Delay(15);
//(2)写指令 38H(不检测忙信号)
    Write_Cmd_Func(0x38);
//(3)延时 5ms
    HAL_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 0:
            Write_Cmd_Func(0x80+0x00+col);
            while(*string != '\0')
               {
                    Write_Data_Func(*string++);
                }
        break;


        case 1:
            Write_Cmd_Func(0x80+0x40+col);
            while(*string != '\0')
               {
                    Write_Data_Func(*string++);
                }
        break;   
    }
    
}

2.DHT11温湿度检测程序

具体关于DHT11的硬件结构以及说明可以查看51章节的文章

https://blog.csdn.net/weixin_63303786/article/details/128692300?spm=1001.2014.3001.5502https://blog.csdn.net/weixin_63303786/article/details/128692300?spm=1001.2014.3001.5502

 IO口的几种输入输出状态

 GPIO_MODE_INPUT 输入

 GPIO_MODE_OUTPUT_PP 推挽输出

 GPIO_MODE_OUTPUT_OD 开漏输出

 GPIO_Mode_AF_OD 复用开漏输出模式

 GPIO_Mode_AF_PP 复用推挽输出模式

 GPIO_MODE_AF_INPUT 模拟输入(AD用)

1. 四种输入模式

    GPIO_Mode_IN_FLOATING 浮空输入模式
    GPIO_Mode_IPU 上拉输入模式
    GPIO_Mode_IPD 下拉输入模式
    GPIO_Mode_AIN 模拟输入模式

2. 四种输出模式

    GPIO_Mode_Out_OD 开漏输出模式
    GPIO_Mode_Out_PP 推挽输出模式
    GPIO_Mode_AF_OD 复用开漏输出模式
    GPIO_Mode_AF_PP 复用推挽输出模式

根据时序图写出DHT11的读操作

DHT11.c

//首先检查DHT11是否存在,时序图黑色部分需要我们写程序实现,棕色部分则是读IO口实现
//所以DHT11所用IO口有两种状态:输入和输出,所以cubeMX中不配置IO口状态,用程序配置

/*封装引脚*/
#define DHT_HIGHT HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET)
#define DHT_LOW HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET)
#define DHT_VALUE HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)

unsigned char datas[5]={0};//接收温湿度数据的数组

//可以现在cubeMX中随意配置一个管脚如PA1,然后去工程里找到GPIO初始化程序,模仿写出DHT_GPIO_Init
void DHT_GPIO_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);
}

//根据时序图写出strat(检查DHT11是否存在),读温度
void delay_us(uint16_t cnt)
{
    uint8_t i;
    while(cnt)
    {
        for (i = 0; i < 10; i++)
    {
       }
    cnt--;
    }
 }

void DHT11_Start()
{
    DHT_GPIO_Init((GPIO_MODE_OUTPUT_PP);//推挽输出
    DHT_LOW;
    HAL_Delay(20);
    DHT_HIGHT;
    DHT_GPIO_Init(GPIO_MODE_INPUT);
    while(DHT_VALUE);//卡d点
    while(!DHT_VALUE);//卡e点
    while(DHT_VALUE);//卡f点
}

void Read_Data_From_DHT()
{
    unsigned char flag,temp,i=0,j=0;
    DHT11_Start();
    DHT_GPIO_Init(GPIO_MODE_INPUT);
    while(!DHT_VALUE);//卡g点,因为判断读0还是读1的时序图是IO口自己实现,不需要写程序拉低或者释放
    delay_us(40);
   for(i=0;i<5;i++)//总共接收5个数据,第0,第1是湿度的整数和小数,第2,第3是温度的整数和小数,第4是校验位
    {
     for(=0;j<8;j++)//一个数据八位,每次接收一位,接收八次
     {
        if(DHT_VALUE == 1)
               flag = 1;
        else if(DHT_VALUE == 0)
               flag = 0;
        temp <<= 1;
        temp |= flag;//如果读0,最低位则为0(因为出初始化temp = 0000 0000),如果读1,则最低位为1,8次左移过后原本的最低位成最高位
    }  
   datas[i] = temp; 
 }
}

总和LCD1602和DHT11代码完成项目要求

main.c

extern buf;

//重定向printf
int fputc(int ch,FILE*f)
{
    unsigned char temp[1] = {ch};
    HAL_UART_Transmit(&huart1,temp,strlen(temp),0xffff);
    return ch;
}

void main()
{
    unsigned char mssage[10];
    while(1)
    {
        HAL_UART_Receive_IT(&huart1, &buf, 1)//开启串口中断
        Read_Data_From_DHT();
        if(datas[1] >= 30)//如果温度超过30度,继电器闭合
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
        else
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
        memset(message, 0, sizeof(message));
        sprintf(mssage,"T:%d.%d",(unsigned int)datas[2],(unsigned int)datas[3]);
        LCD1602_showLine(1,0,message);
        memset(message, 0, sizeof(message));
        sprintf(mssage,"H:%d.%d",(unsigned int)datas[0],(unsigned int)datas[1]);
        LCD1602_showLine(2,0,message);
        printf("T:%d.%d",(unsigned int)datas[2],(unsigned int)datas[3]);
        printf("H:%d.%d",(unsigned int)datas[0],(unsigned int)datas[1]);
        HAL_Delay(100);
    }
}

uart.c

uint8_t buf=0;
//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200
// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字节数目
uint16_t UART1_RX_STA=0;//串口接收标志位
//重写串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//判断是不是串口1产生的中断
	if(huart->Instance == USART1)
	{
	//判断中断是否接收完成,接收完成USART_RX_STA最高位会置1
		if((UART1_RX_STA & 0x8000) == 0)//如果没有接收完成就进入接收流程
		{
	//如果接收到回车:0X0D
			if(UART1_RX_STA & 0x4000)//出现的问题!!为真不一定是1 
			{
				if(buf == 0x0a)//如果接收到换行
				 //如果换行和回车都收到了就说明接收完成,那么手动将USART_RX_STA最高位置1
				UART1_RX_STA |= 0x8000;
				else
				UART1_RX_STA = 0;	//如果没有收到换行就置0重新来过
			}else//如果没有收到回车
			{
				//先判断这个字符是不是回车
				if(buf == 0x0d)
				{
					UART1_RX_STA |= 0x4000;//如果是回车,就手动将bit14置1
                   
                     // 继电器控制指令
                    if(!strcmp((uint8_t *)UART1_RX_Buffer, "L-1"))
                    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
                    if(!strcmp((uint8_t *)UART1_RX_Buffer, "L-0"))
                    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
                    memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
                    UART1_RX_STA = 0;
				}
				else
				{
					UART1_RX_Buffer[UART1_RX_STA & 0x3fff] = buf;
					UART1_RX_STA++;
					
					if(UART1_RX_STA > UART1_REC_LEN - 1)//如果光标到最后一位那么就光标返回,200-1是因为字符数组最后一位是'\0'
					{
						UART1_RX_STA = 0;
					}
				}	
			} 
		}		
	HAL_UART_Receive_IT(&huart1, &buf, 1);//重新开启中断接收
	}
}

HC08只需要连接一个IO口,然后手机连接蓝牙,就可以通过手机端app发送接收指令,蓝牙传输就是串口传输

注意:

1.HC08的波特率是9600,工程的波特率记得改为9600

2.printf重定向必须勾选

 

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

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

相关文章

PP模块-生产主数据之一-物料主数据

物料主数据的配置主要在 MM 模块中进行管理&#xff0c;一般由MM顾问或MDM的顾问负责流程梳理、规则讨论、并主导完成数据收集工作。所以在SAP系统项目的实施过程中&#xff0c;根据系统对物料主数据数特有的配置对象要求&#xff0c;与业务负责人进行讨论并达成一致&#xff0…

FreeRTOS如何解决访问冲突/线程不安全(临界段、互斥锁、挂起调度、看门人任务)

在多任务&#xff08;多线程&#xff09;系统中&#xff0c;存在一个隐患&#xff0c;那就是多线程的访问&#xff08;在FreeRTOS中就是任务&#xff09;。当一个任务A开始访问一个资源&#xff08;外设、一块内存等&#xff09;&#xff0c;但是A还没有完成访问&#xff0c;B任…

精通 TensorFlow 2.x 计算机视觉:第二部分

原文&#xff1a;Mastering Computer Vision with TensorFlow 2.x 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;…

【RabbitMQ学习日记】—— 再见RabbitMQ

一、发布确认高级篇 在生产环境中由于一些不明原因&#xff0c;导致 rabbitmq 重启&#xff0c;在 RabbitMQ 重启期间生产者消息投递失败&#xff0c;导致消息丢失&#xff0c;需要手动处理和恢复如何才能进行 RabbitMQ 的消息可靠投递呢&#xff1f; 特别是在这样比较极端的情…

MYSQL:数据类型与运算符、MySQL函数

一.部分需要学会的操作&#xff08;以举例形式列出&#xff09;&#xff1a; insert into tmp15 values(This is good,50); /*向tmp15插入note 为 “This is good”&#xff0c;price为50的元素*/ 注&#xff1a;需要严格对应字段和元素属性的位置 select * from tmp15 /*查…

【Diffusion Model】Learning notes

来自 扩散模型 Diffusion Model 1-1 概述 扩散模型是什么&#xff1f; 本质是生成模型&#xff0c;拟合目标分布&#xff0c;然后生成很多数据符合这个分布 训练测试阶段&#xff1f; 和 GAN 相比优势是什么&#xff1f; generator 和 discriminator 两者都得训练的比较均衡…

JDK8到JDK17有哪些吸引人的新特性?

作者&#xff1a;京东零售 刘一达 前言 2006年之后SUN公司决定将JDK进行开源&#xff0c;从此成立了OpenJDK组织进行JDK代码管理。任何人都可以获取该源码&#xff0c;并通过源码构建一个发行版发布到网络上。但是需要一个组织审核来确保构建的发行版是有效的, 这个组织就是J…

Excel VBA 之Interior 对象设置底色

Interior 对象 代表一个对象的内部 针对interior对象&#xff0c;我们用得最多的是它的颜色&#xff0c;下面就来讨论一下。 1.ColorIndex 索引颜色值 Sub 索引颜色值()For i 1 To 56Cells(i, 1).Interior.ColorIndex iCells(i, 2) iNext iFor i 1 To 56Cells(i, 3).Interi…

算法训练第六十天 | 84.柱状图中最大的矩形

单调栈part0384.柱状图中最大的矩形题目描述思路暴力解法双指针解法单调栈84.柱状图中最大的矩形 题目链接&#xff1a;84.柱状图中最大的矩形 参考&#xff1a;https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E…

《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.24.12集群(一主多从)》

一、架构图 如下图所示&#xff1a; 如下图所示&#xff1a; 二、环境信息 1、部署规划 主机名IP地址操作系统内核版本软件说明etcd01192.168.1.62Ubuntu 20.04.5 LTS5.15.0-69-genericetcdetcd02192.168.1.63Ubuntu 20.04.5 LTS5.15.0-69-genericetcdetcd03192.168.1.64Ubunt…

kettle链接mysql Public Key Retrieval is not allowed

kettle 报错信息页面&#xff1a; 出现 Public Key Retrieval 的场景可以概括为在禁用 SSL/TLS 协议传输切当前用户在服务器端没有登录缓存的情况下&#xff0c;客户端没有办法拿到服务器的公钥。具体的场景如下&#xff1a; 新建数据库用户&#xff0c;首次登录&#xff1b;数…

课程推荐 | 机器视觉与边缘计算应用

点击蓝字关注我们,让开发变得更有趣文案 | 李擎排版 | 李擎文案来源 | https://www.icourse163.org/course/FUDAN-1456632162OpenVINO™╱ 前言 ╱机器视觉是目前人工智能重要的应用领域&#xff0c;在很多领域都有丰富的成功应用案例。其中深度学习的目标检测算法是非常实用的…

ubuntu(20.04)-shell脚本(1)-基本概念

目录 1.概述 2.shell脚本调用形式 3.shell语法初识 3.1 定义以开头&#xff1a;#&#xff01;/bin/bash 3.2 单个“#”号代表注释当前行 4.变量 4.1 只读变量 4.2 环境变量&#xff1a; env 4.3 预测变量&#xff1a; 4.4 变量扩展&#xff1a; 是否存在&#xff0c;字符串…

通过JMH框架 测试公平锁与非公平锁的性能(附测试代码和源码分析)

目录 先上测试代码&#xff1a; 上依赖&#xff1a; 输出结果&#xff1a;(注意不要debug运行&#xff0c;直接运行代码&#xff0c;否则报错) 源码-公平锁的 lock 方法&#xff1a; 源码-非公平锁的lock方法&#xff1a; 总结 非公平锁和公平锁的两处不同&#xff1a; …

docker入门之一:docker基础概念与安装

1. Docker简单介绍 1.1. 什么是docker&#xff1f;1.2. Docker和传统虚拟机1.3. 为什么使用docker1.4. docker架构 2. Docker安装 2.1. docker版本命名2.2. docker安装2.3. docker卸载2.4. docker镜像加速器 1. Docker简单介绍 1.1. 什么是docker&#xff1f; google go语言…

24-Tomcat

目录 1.Tomcat是什么&#xff1f; 2.版本号 3.下载 4.目录介绍 4.1.bin目录 4.2.conf目录 4.3.logs目录 4.4.webapps目录 5.启动服务器 PS&#xff1a;解决Tomcat乱码问题 PS&#xff1a;Tomcat点击启动&#xff0c;控制台一闪而过&#xff0c;啥也没有解决方案 PS…

【花雕学AI】4月5日,ChatGPT中国财经背景分析:昨天沪指重返3300点,这说明了什么?

在这里插入图片描述 附录&#xff1a; 一、ChatGPT是一个可以和你聊天的人工智能程序&#xff0c;它可以用文字回答你的问题&#xff0c;也可以根据你的提示写出文章、歌词、代码等内容。ChatGPT是由一个叫OpenAI的机构开发的&#xff0c;它使用了一种叫做GPT的技术&…

TCP协议的相关特性(续)

TCP协议的相关特性&#x1f50e;滑动窗口&#x1f50e;流量控制&#x1f50e;拥塞控制&#x1f50e;延时应答&#x1f50e;捎带应答&#x1f50e;面向字节流(粘包问题)&#x1f50e;异常情况&#x1f50e;总结关于 确认应答 超时重传, 连接管理 请参考: 点击这里 &#x1f50e…

IT知识百科:什么是基站?

一、基站介绍 基站&#xff08;Base Station&#xff09;&#xff0c;也称为基站站点或基站设备&#xff0c;是无线通信网络中的关键设备之一。基站用于与移动设备&#xff08;如手机、无线网卡等&#xff09;进行通信和数据传输&#xff0c;实现无线通信覆盖。 二、基站的功…

基于Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;能够在不同操作系统和平台使用&#xff0c;简洁的语法和解释性语言使其成为理想的脚本语言。除了标准库&#xff0c;还有丰富的第三方库&#xff0c;Python在数据处理、科学计算、数学建模、数据挖…