广东圆心科技网站开发网站模板设计,钢管公司网站建设,郑州粒米seo外包,软件外包公司排名STM32案例学习 GY-39环境监测传感器模块
硬件平台
野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块
GY-39 是一款低成本#xff0c;气压#xff0c;温湿度#xff0c;光强度传感器模块。工作电压 3-5v…STM32案例学习 GY-39环境监测传感器模块
硬件平台
野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块
GY-39 是一款低成本气压温湿度光强度传感器模块。工作电压 3-5v功耗小安装方便。其工作原理是MCU 收集各种传感器数据统一处理直接输出计算后的结果。此模块有两种方式读取数据即**串口 UARTTTL 电平**或者 IIC2 线。串口的波特率有 9600bps 与 115200bps可配置有连续询问输出两种方式可掉电保存设置。可适应不同的工作环境与单片机及电脑连接。模块另外可以设置单独传感器芯片工作模式作为简单传感器模块MCU 不参与数据处理工作。参考资料网站 https://www.gysensor.cn/air-gy39/
技术参数传感器精度请参考芯片手册 模块引脚声明
Pin1VCC电源 3v-5vPin2CT串口UART_TX / IIC_SCLPin3DR串口UART_RX / IIC_SDAPin4GND电源地Pin5NC保留不要连接Pin6INTmax44009光强芯片中断 S10接GND时启用Pin7SDA芯片数据线S10接GND时启用Pin8SCL芯片时钟线S10接GND时启用PinAS0串口/MCU_IIC模式选择接地为MCU_IIC模式PinBS1仅使用传感器芯片选择
模块通信协议描述 串口通信 (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) 数据计算方法 ①光照强度计算方法当 Byte20x15 时,数据:Byte4~Byte7 Lux(前高8位24) | (前低8位16) | (后高8位8) | 后低8位 单位lux 例一帧数据 5A- 5A- 15 -04- 00 -00- FE- 40- 0B Lux(0x0024)|(0x0016)|(0xFE8)|0x40 LuxLux/100 650.88 (lux) ②温度、气压、湿度、海拔计算方法当 Byte20x45 时 温度Byte4~Byte5 T(高 8 位8)|低 8 位 TT/100 单位℃ 气压Byte6~Byte9 P(前高 8 位24) | (前低 8 位16) | (后高 8 位8) | 后低 8 位 PP/100 单位 pa 湿度Byte10~Byte11 Hum(高 8 位8)|低 8 位 HumHum/100 百分制 海拔Byte12~Byte13 H(高 8 位8)|低 8 位 单位 m 例一帧数据 5A -5A -45 -0A -0B -2D -00 -97 -C4 -3F -12- 77 -00- 9C- FA T(0x0B8)|0x2D2861 温度 T2861/10028.61 (℃) P(0x0024)|(0x9716)|(C48)|3F9946175 气压 P9946175/10099461.75 (pa) Hum(0x128)| 774727 湿度 Hum4727/10047.27 (%) 海拔 H(0x008)|0x9c156 (m)
(5) 命令字节由外部控制器发送至 GY-39 模块十六进制 2. IIC通信
硬件测试
接线示意图 代码
#include main.hvoid 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 i20;xi*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(1i)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 i0;SDA_H; //释放SDASCL_H; //SCL拉高进行采样while(SDA_read)//等待SDA拉低{i; //等待计数if(i500)//超时跳出循环break;}if(SDA_read)//再次判断SDA是否拉低{SCL_L; return RESET;//从机应答失败返回0}delay_1us(5);//延时保证时钟频率低于40KSCL_L;delay_1us(5); //延时保证时钟频率低于40Kreturn SET;//从机应答成功返回1
}
//**************************************
//向IIC总线发送一个字节数据
/*
一个字节8bit,当SCL低电平时准备好SDASCL高电平时从机采样SDA
*/
//**************************************
void I2C_SendByte(uint8_t dat)
{uint8_t i;SCL_L;//SCL拉低给SDA准备for (i0; i8; i) //8位计数器{if(dat0x80)//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 (i0; i8; 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_Address1); //发送设备地址读信号if(!I2C_WaitAck()){I2C_Stop(); return RESET;}while(length-1){*REG_dataI2C_RecvByte(); //读出寄存器数据I2C_SendACK(0); //应答length--;}*REG_dataI2C_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);//设置中断优先级分组为组22位抢占优先级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_COLORRED; 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);}}测试效果
代码参考链接