STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块

硬件平台

  1. 野火STM32F1系列开发板
  2. 正点STM32F1系列开发板
  3. STM32F103ZET6核心板
  4. GY-39环境监测传感器模块
    STM32产品
    在这里插入图片描述

在这里插入图片描述

GY-39环境监测传感器模块

  1. GY-39 是一款低成本,气压,温湿度,光强度传感器模块。工作电压 3-5v,功耗小,安装方便。
  2. 其工作原理是,MCU 收集各种传感器数据,统一处理,直接输出计算后的结果。此模块,有两种方式读取数据,即**串口 UART(TTL 电平)**或者 IIC(2 线)。串口的波特率有 9600bps 与 115200bps,可配置,有连续,询问输出两种方式,可掉电保存设置。可适应不同的工作环境,与单片机及电脑连接。
  3. 模块另外可以设置单独传感器芯片工作模式,作为简单传感器模块,MCU 不参与数据处理工作
  4. 参考资料网站 https://www.gysensor.cn/air-gy39/
    在这里插入图片描述

技术参数(传感器精度请参考芯片手册)

在这里插入图片描述

模块引脚声明

Pin1VCC电源+ (3v-5v)
Pin2CT串口UART_TX / IIC_SCL
Pin3DR串口UART_RX / IIC_SDA
Pin4GND电源地
Pin5NC保留,不要连接
Pin6INTmax44009光强芯片中断 S1=0(接GND时启用)
Pin7SDA芯片数据线S1=0(接GND时启用)
Pin8SCL芯片时钟线S1=0(接GND时启用)
PinAS0串口/MCU_IIC模式选择,接地为MCU_IIC模式
PinBS1仅使用传感器芯片选择

模块通信协议描述

  1. 串口通信
    (1) 串口通信参数(默认波特率值 9600bps,可通过软件设定)
    波特率:9600 bps 校验位:N 数据位:8 停止位:1
    波特率:115200 bps 校验位:N 数据位:8 停止位:1
    (2) 模块输出格式,每帧包含 8-13 个字节(十六进制):
    ① .Byte0: 0x5A 帧头标志
    ②. Byte1: 0x5A 帧头标志
    ③. Byte2: 0x15 本帧数据类型(参考含义说明)
    ④. Byte3: 0x04 数据量
    ⑤. Byte4: 0x00~0xFF 数据前高 8 位
    ⑤. Byte5: 0x00~0xFF 数据前低 8 位
    ⑥. Byte6: 0x00~0xFF 数据后高 8 位
    ⑦. Byte7: 0x00~0xFF 数据后低 8 位
    ⑧. Byte8: 0x00~0xFF 校验和(前面数据累加和,仅留低 8 位)

    (3) Byte2 代表的含义说明

    Byte20x150x450x55
    说明光照强度温度,湿度,气压,海拔IIC地址

    (4) 数据计算方法
    ①光照强度计算方法(当 Byte2=0x15 时,数据:Byte4~Byte7) :
    Lux=(前高8位<<24) | (前低8位<<16) | (后高8位<<8) | 后低8位 单位lux
    例:一帧数据

    	<5A- 5A- 15 -04- 00 -00- FE- 40- 0B >
    

    Lux=(0x00<<24)|(0x00<<16)|(0xFE<<8)|0x40
    Lux=Lux/100 =650.88 (lux)
    ②温度、气压、湿度、海拔,计算方法(当 Byte2=0x45 时):
    温度:Byte4~Byte5
    T=(高 8 位<<8)|低 8 位
    T=T/100 单位℃

    气压:Byte6~Byte9
    P=(前高 8 位<<24) | (前低 8 位<<16) | (后高 8 位<<8) | 后低 8 位
    P=P/100 单位 pa

    湿度:Byte10~Byte11
    Hum=(高 8 位<<8)|低 8 位
    Hum=Hum/100 百分制

    海拔:Byte12~Byte13
    H=(高 8 位<<8)|低 8 位 单位 m
    例:一帧数据

     < 5A -5A -45 -0A -0B -2D -00 -97 -C4 -3F -12- 77 -00- 9C- FA >
    

    T=(0x0B<<8)|0x2D=2861
    温度 T=2861/100=28.61 (℃)
    P=(0x00<<24)|(0x97<<16)|(C4<<8)|3F=9946175
    气压 P=9946175/100=99461.75 (pa)
    Hum=(0x12<<8)| 77=4727
    湿度 Hum=4727/100=47.27 (%)
    海拔 H=(0x00<<8)|0x9c=156 (m)

(5) 命令字节,由外部控制器发送至 GY-39 模块(十六进制)
在这里插入图片描述
在这里插入图片描述
2. IIC通信
在这里插入图片描述

硬件测试

接线示意图

在这里插入图片描述

代码

#include "main.h"void I2C_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* 使能与 I2C有关的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );  /* PC3-I2C_SCL、PC5-I2C_SDA*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6| GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); SCL_H;SDA_H;
}
void delay_1us(uint8_t x)//粗略延时,iic_40K
{uint8_t i=20;x=i*x;while(x--);
}
IIC起始函数//
/*
IIC起始:当SCL处于高电平期间,SDA由高电平变成低电平出现一个下降沿,然后SCL拉低
*/
uint8_t I2C_Start(void)
{SDA_H; delay_1us(5);	//延时保证时钟频率低于40K,以便从机识别SCL_H;delay_1us(5);//延时保证时钟频率低于40K,以便从机识别if(!SDA_read) return 0;//SDA线为低电平则总线忙,退出SDA_L;   //SCL处于高电平的时候,SDA拉低delay_1us(5);if(SDA_read) return 0;//SDA线为高电平则总线出错,退出SCL_L;delay_1us(5);return 1;
}
//**************************************
//IIC停止信号
/*
IIC停止:当SCL处于高电平期间,SDA由低电平变成高电平出现一个上升沿
*/
//**************************************
void I2C_Stop(void)
{SDA_L;SCL_L;delay_1us(5);SCL_H;delay_1us(5);SDA_H;//当SCL处于高电平期间,SDA由低电平变成高电平             //延时
}
//**************************************
//IIC发送应答信号
//入口参数:ack (0:ACK 1:NAK)
/*
应答:当从机接收到数据后,向主机发送一个低电平信号
先准备好SDA电平状态,在SCL高电平时,主机采样SDA
*/
//**************************************
void I2C_SendACK(uint8_t i)
{if(1==i)SDA_H;	             //准备好SDA电平状态,不应答else SDA_L;  						//准备好SDA电平状态,应答 	SCL_H;                    //拉高时钟线delay_1us(5);                 //延时SCL_L ;                  //拉低时钟线delay_1us(5);    
} 
///等待从机应答
/*
当本机(主机)发送了一个数据后,等待从机应答
先释放SDA,让从机使用,然后采集SDA状态
*/
/
uint8_t I2C_WaitAck(void) 	 //返回为:=1有ACK,=0无ACK
{uint16_t i=0;SDA_H;	        //释放SDASCL_H;         //SCL拉高进行采样while(SDA_read)//等待SDA拉低{i++;      //等待计数if(i==500)//超时跳出循环break;}if(SDA_read)//再次判断SDA是否拉低{SCL_L; return RESET;//从机应答失败,返回0}delay_1us(5);//延时保证时钟频率低于40K,SCL_L;delay_1us(5); //延时保证时钟频率低于40K,return SET;//从机应答成功,返回1
}
//**************************************
//向IIC总线发送一个字节数据
/*
一个字节8bit,当SCL低电平时,准备好SDA,SCL高电平时,从机采样SDA
*/
//**************************************
void I2C_SendByte(uint8_t dat)
{uint8_t i;SCL_L;//SCL拉低,给SDA准备for (i=0; i<8; i++)         //8位计数器{if(dat&0x80)//SDA准备SDA_H;  else SDA_L;SCL_H;                //拉高时钟,给从机采样delay_1us(5);        //延时保持IIC时钟频率,也是给从机采样有充足时间SCL_L;                //拉低时钟,给SDA准备delay_1us(5); 		  //延时保持IIC时钟频率dat <<= 1;          //移出数据的最高位  }					 
}
//**************************************
//从IIC总线接收一个字节数据
//**************************************
uint8_t I2C_RecvByte()
{uint8_t i;uint8_t dat = 0;SDA_H;//释放SDA,给从机使用delay_1us(1);         //延时给从机准备SDA时间            for (i=0; i<8; i++)         //8位计数器{ dat <<= 1;SCL_H;                //拉高时钟线,采样从机SDAif(SDA_read) //读数据    dat |=0x01;      delay_1us(5);     //延时保持IIC时钟频率		SCL_L;           //拉低时钟线,处理接收到的数据delay_1us(5);   //延时给从机准备SDA时间} return dat;
}
//**************************************
//向IIC设备写入一个字节数据
//**************************************
uint8_t Single_WriteI2C_byte(uint8_t Slave_Address,uint8_t REG_Address,uint8_t data)
{if(I2C_Start()==0)  //起始信号{I2C_Stop(); return RESET;}           I2C_SendByte(Slave_Address);   //发送设备地址+写信号if(!I2C_WaitAck()){I2C_Stop(); return RESET;}I2C_SendByte(REG_Address);    //内部寄存器地址,if(!I2C_WaitAck()){I2C_Stop(); return RESET;}I2C_SendByte(data);       //内部寄存器数据,if(!I2C_WaitAck()){I2C_Stop(); return RESET;}I2C_Stop();   //发送停止信号return SET;
}
//**************************************
//从IIC设备读取一个字节数据
//**************************************
uint8_t Single_ReadI2C(uint8_t Slave_Address,uint8_t REG_Address,uint8_t *REG_data,uint8_t length)
{if(I2C_Start()==0)  //起始信号{I2C_Stop(); return RESET;}          I2C_SendByte(Slave_Address);    //发送设备地址+写信号if(!I2C_WaitAck()){I2C_Stop(); return RESET;} I2C_SendByte(REG_Address);     //发送存储单元地址if(!I2C_WaitAck()){I2C_Stop(); return RESET;} if(I2C_Start()==0)  //起始信号{I2C_Stop(); return RESET;}            I2C_SendByte(Slave_Address+1);  //发送设备地址+读信号if(!I2C_WaitAck()){I2C_Stop(); return RESET;}while(length-1){*REG_data++=I2C_RecvByte();       //读出寄存器数据I2C_SendACK(0);               //应答length--;}*REG_data=I2C_RecvByte();  I2C_SendACK(1);     //发送停止传输信号I2C_Stop();                    //停止信号return SET;
}
#ifndef _GY39_H
#define _GY39_H	 
#include "main.h"#define SCL_H         GPIOB->BSRR = GPIO_Pin_6
#define SCL_L         GPIOB->BRR  = GPIO_Pin_6#define SDA_H         GPIOB->BSRR = GPIO_Pin_7
#define SDA_L         GPIOB->BRR  = GPIO_Pin_7#define SCL_read      GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)
#define SDA_read      GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)void I2C_GPIO_Config(void);
void I2C_Stop(void);
uint8_t Single_WriteI2C_byte(uint8_t Slave_Address,uint8_t REG_Address,uint8_t data);
uint8_t Single_ReadI2C(uint8_t Slave_Address,uint8_t REG_Address,uint8_t *REG_data,uint8_t length);#endif
/*************************************** Copyright ****************************** *    * FileName   : main.c   * Version    : v5.0		* Author     : dele			* Date       : 2023-07-19   
*******************************************************************************/
/*
STLink 连接 SWDIO PA13 SWCLK PA14 不要使用这两个端口
*/
//--------------------------------------------------------------------------------------------------
//  包含头文件    |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |   9   
//--------------------------------------------------------------------------------------------------
#include "main.h"//--------------------------------------------------------------------------------------------------
//  定义引用变量    |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |   9   
//--------------------------------------------------------------------------------------------------
float gy_temp,gy_hum;
float aht_temp,aht_hum;//温湿度  //==================================================================================================
//  实现功能: 硬件初始化配置
//  函数说明: Hareware_Iint
//  函数备注: 
//--------------------------------------------------------------------------------------------------
//  |   -   |   -   |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |   9   
void Hareware_Iint(void)
{delay_init();//延时函数初始化	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级USART1_Config(115200);//串口初始化波特率为115200 USART2_Config(115200);//ESP8266 通讯串口2  波特率为115200 printf("串口1配置			[OK] \r\n");printf("串口2配置			[OK] \r\n");LED_Init();//LED端口初始化printf("LED_Init			[OK] \r\n");Beep_Init();//蜂鸣器初始化printf("Beep_Init			[OK] \r\n");KEY_Init();	//按键初始化printf("KEY_Init			[OK] \r\n");LCD_Init();  //液晶屏初始化printf("LCD_Init			[OK] \r\n");I2C_GPIO_Config();AHT_I2C_UserConfig();printf("AHT_I2C_UserConfig			[OK] \r\n");//TIM1_Int_Init(1999,35999);//定时1s//printf("TIM1_Int_Init			[OK] \r\n");W25QXX_Init();//W25QXX初始化printf("W25QXX初始化			[OK] \r\n");POINT_COLOR=RED; GBK_Lib_Init();   printf("硬件GBK字库初始化			[OK] \r\n");    //硬件GBK字库初始化--(如果使用不带字库的液晶屏版本,此处可以屏蔽,不做字库初始化) 	tp_dev.init();//触摸屏初始化printf("触摸屏初始化			[OK] \r\n");}
//==================================================================================================
//  实现功能: 传感器数据采集
//  函数说明: SensorGet_Data
//  函数备注: 
//--------------------------------------------------------------------------------------------------
//  |   -   |   -   |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |   9   
//================================================================================================== 
typedef struct
{uint32_t Press;uint16_t Temperature;uint16_t Humidity;uint16_t Altitude;
} gy_module;gy_module Bme={0,0,0,0};
//==================================================================================================
//  实现功能: 主函数
//  函数说明: main
//  函数备注: 
//--------------------------------------------------------------------------------------------------
//  |   -   |   -   |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |   9   
//================================================================================================== 
int main(void)
{	   Hareware_Iint();printf("Hareware_Iint  [OK] \r\n");uint8_t  raw_data[13]={0};uint16_t data_16[2]={0};uint32_t Lux;while(1){if(Single_ReadI2C(0xb6,0x04,raw_data,10)){Bme.Temperature=(raw_data[0]<<8)|raw_data[1];data_16[0]=(((uint16_t)raw_data[2])<<8)|raw_data[3];data_16[1]=(((uint16_t)raw_data[4])<<8)|raw_data[5];Bme.Press=(((uint32_t)data_16[0])<<16)|data_16[1];Bme.Humidity=(raw_data[6]<<8)|raw_data[7];Bme.Altitude=(raw_data[8]<<8)|raw_data[9];}if(Single_ReadI2C(0xb6,0x00,raw_data,4))data_16[0]=(((uint16_t)raw_data[0])<<8)|raw_data[1];data_16[1]=(((uint16_t)raw_data[2])<<8)|raw_data[3];Lux=(((uint32_t)data_16[0])<<16)|data_16[1];gy_temp = Bme.Temperature/100;gy_hum  = Bme.Humidity/100;printf("Temperature:%.2fDegC \r\n  ",(float)Bme.Temperature/100);printf("Prees:%.2fPa  \r\n",(float)Bme.Press/100);printf("Humidity: %.2f     \r\n ",(float)Bme.Humidity/100);printf("Altitude: %.2f m   \r\n ",(float)Bme.Altitude);printf("LightLux: %.2f lux \r\n ",(float)Lux/100);  delay_ms(200);}}

测试效果

代码参考链接
在这里插入图片描述

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

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

相关文章

thinkphp 上传图片

public function upload_img(){// 读取图片资源// 存储路径$path "uploads/avatar";$file request()->file(background_img);// 存储图片$info $file->rule(uniqid)->move($path);// 存储成功if ($info) {//获取到上传图片的路径名称$name_img $path . …

linux查看ipynb文件

linux查看ipynb文件 使用jupyter查看 使用jupyter查看 安装 pip install jupyter添加配置好的环境到jupyter notebook的kernel中&#xff1a; python -m ipykernel install --user --name mmdet --display-name "mmdet"运行jupyter notebook &#xff08;在ipynb…

WebSocket理论和实战

一 WebSocket理论 1.1 什么是http请求 http链接分为短链接、长链接&#xff0c;短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接&#xff08;但是是单向的&#xff0c;只能从客户端向服务端发消息&#x…

pycharm import的类库修改后要重启问题的解决方法

通过将以下行添加到pycharm中的settings-> Build,Excecution,Deployment-> Console-> Python Console中&#xff0c;可以指示Pycharm在更改时自动重新加载模块&#xff1a; %load_ext autoreload %autoreload 2

ubuntu 设置系统时间矫正

1、安装ntpdate&#xff0c;同步标准时间 2、修改时区 3、在.profile文件中写入上面提示的信息&#xff0c;保存退出、更新配置文件或者重启生效 3.1、或者配合上面的cp那条命令&#xff0c;用下面的命令保存到底层 $ hwclock --systohc 4、重启之后&#xff0c;查看日期时间已…

中间件上云部署 rocketmq

中间件上云部署 rocketmq rocketmq部署一、rokectmq介绍二、rokectmq特性三、使用rocketmq理由四、rocketmq 核心概念五、rocketmq角色六、rocketmq集群部署方式七、rocketmq集群部署7.1 环境说明7.2 构建rocketmq镜像7.3 获取rocketmq-dashboard镜像7.4 rocketmq部署描述文件编…

linux安装mysql以及使用navicat连接mysql

目录 一、下载mysql 二、安装mysql 三、使用Navicat连接MySQL 四、常见问题 1、启动服务时报错 Failed to start mysql.service: Unit not found. 的解决方法。 2、登录过程出现&#xff1a;access denied for user’root’‘localhost’(using password:Yes) 的解决方…

Redis的缓存问题

说起Redis的缓存&#xff0c;我们知道前端发出的请求到后端&#xff0c;后端先从Redis中查询&#xff0c;如果查询到了则直接返回&#xff0c;如果Redis中未查询到&#xff0c;就去数据库中查询&#xff0c;如果数据库中存在&#xff0c;则返回结果并且更新到Redis缓存当中&…

《遗留系统现代化》读书笔记(基础篇)

目录 为什么要对遗留系统进行现代化&#xff1f; 什么是遗留系统&#xff1f; 遗留系统的现代化价值 总结 遗留系统的四化建设 代码现代化 架构现代化 DevOps 现代化 团队结构现代化 总结 本文地址&#xff1a;《遗留系统现代化》读书笔记&#xff08;基础篇&#xff…

通讯录(纯C语言实现)

相信大家都有过通讯录&#xff0c;今天我来带大家实现以下最简单的通讯录&#xff0c;通过本篇文章&#xff0c;相信可以让大家对C语言有进一步的认识。 话不多说&#xff0c;我们先放函数的实现 #define _CRT_SECURE_NO_WARNINGS 1 #include "Contact.h"int Chea…

高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测教程

详情点击链接&#xff1a;高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测 第一&#xff1a;预测平台及安装 一、高精度气象预测基础 综合气象观测数值模拟模式&#xff1b; 全球预测模式、中尺度数值模式&#xff1b; 二、自动化预测平台 Linux系统 Crontab…

记一次rabbitmq消息发送成功,消费丢失问题

记一次rabbitmq消息发送成功&#xff0c;消费丢失问题 背景 测试数据归档&#xff0c;偶现数据未归档 排查 idea线上调试&#xff0c;log日志&#xff0c;数据库消息发送记录&#xff0c;代码分块重复执行看哪块出的问题&#xff0c;结果均无问题&#xff0c;最后使用rabbi…

AI销售工具:驱动销售团队效率和个性化服务的未来

在数字化时代&#xff0c;AI销售工具成为推动销售行业发展的重要力量。这些创新工具融合了人工智能技术和销售流程&#xff0c;以提高销售团队的效率和提供个性化服务为目标。随着科技的不断进步&#xff0c;AI销售工具正引领着销售行业走向一个更加智能和高效的未来。 AI驱动的…

数据结构 ~ 栈、队列

栈 一个后进先出的数据结构、JS中没有栈&#xff0c;可以使用 Array 模拟 const stack [] stack.push(1) // 入栈 stack.push(2) // 入栈 const item1 stack.pop() // 出栈 const item2 stack.pop() // 出栈以上代码可以使用 nodeJs 断点调试&#xff08;F5启动&#xff0…

【Linux】进程信号

文章目录 1. 信号的理解1.1 什么是进程信号1.2 见见进程信号1.3 信号的发送与记录1.4 信号的处理1.4.1 信号的三种处理方式1.4.2 核心转储 2. 信号的产生2.1 终端按键产生信号2.2 系统调用产生信号2.3 软件异常产生信号2.4 硬件异常产生信号 3. 信号的保存3.1 信号其他相关概念…

电子锁语音芯片方案,低功耗声音提示ic,WT588F02B-8S

随着科技的不断发展&#xff0c;电子锁已成为现代社会中&#xff0c;安全性和便利性并存的必备设备。如何为电子锁行业增添智能化、人性化的功能已成为行业内的热门话题。 在这个迅速发展的市场中&#xff0c;深圳唯创知音推出了一款语音交互方案——WT588F02B-8S 低功耗声音提…

UnxUtils工具包,Windows下使用Linux命令

1. 前言 最近写批处理多了&#xff0c;发现Windows下的bat批处理命令&#xff0c;相比Linux的命令&#xff0c;无论是功能还是多样性&#xff0c;真的差太多了。但有时候又不得不使用bat批处理&#xff0c;好在今天发现了一个不错的工具包&#xff1a;UnxUtils&#xff0c;这个…

Python多线程 threading 和多进程 multiprocessing

1. 并发 vs 并行 线程是程序执行的最小单位&#xff0c;一个进程可以由一个或多个线程组成&#xff0c;各个线程之间也是交叉执行。 并发&#xff0c;相当于单核CPU&#xff0c;宏观同时执行&#xff0c;微观高速切换 交替执行。多线程、高并发这些词语更多地出现在服务端程序…

06-C++ 基本算法 - 二分法

&#x1f4d6; 前言 在这个笔记中&#xff0c;我们将介绍二分法这种基本的算法思想&#xff0c;以及它在 C 中的应用。我们将从一个小游戏猜数字开始&#xff0c;通过这个案例来引出二分法的概念。然后我们将详细讲解什么是二分法以及它的套路和应用。最后&#xff0c;我们还会…

在 3ds Max 中创建逼真的玻璃材质

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 尽管本教程基于 3ds Max&#xff0c;但相同的设置适用于许多其他 3D 产品。 注意&#xff1a;单击每个步骤中的缩略图可查看更大的屏幕截图&#xff0c;其中包括视口和用户界面的相关部分。 步骤 1由于本教…