一、GY39介绍
GY-39 是一款气压,温湿度,光照强度传感器模块。工作电压 3-5v,功耗小,安装方便。 其工作原理是,MCU 收集各种传感器数据,统一处理,直接输出计算后的结果。
GY39有两种方式读取数据,即串口 UART或者 IIC。
二、GY39使用串口通信
(1)串口命令讲解
sum 代表校验和(前面数据累加和,仅保留低8位)
(2)串口接收数据包讲解
(3)实操证明
将USB转TTL连接
发送a5 83 28
串口调试助手就会接收到以下数据
(4)计算方法
1. 计算光照强度(当 Byte2=0x15 )
2. 计算温度、气压、湿度、海拔(当 Byte2=0x45 时)
3. 计算温度和湿度
三、GY39使用IIC通信
四、串口通信代码
(1) GY39.h
#ifndef __GY39_H
#define __GY39_H
#include "sys.h"
#define USART6_MAX_RECV_LEN 30 //最大接收缓存字节数
#define USART6_MAX_SEND_LEN 30 //最大发送缓存字节数
#define USART6_RX_EN 1 //0,不接收;1,接收.
extern char USART6_RX_BUF[USART6_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN字节
extern vu16 USART6_RX_STA; //接收数据状态
void GY39_Init(void);
void GY39_Get_Temp_humi(int *temp,int *humi);
#endif
(2) GY39.c
#include "gy39.h"
#include <stdarg.h>
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "lcd.h"
//串口接收缓存区
char USART6_RX_BUF[USART6_MAX_RECV_LEN]; //接收缓冲,最大USART6_MAX_RECV_LEN个字节.
char USART6_TX_BUF[USART6_MAX_SEND_LEN]; //发送缓冲,最大USART6_MAX_SEND_LEN字节
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART6_RX_STA=0;
void USART6_IRQHandler(void)
{
char res;
if(USART_GetITStatus(USART6,USART_IT_IDLE) != RESET)
{
res = USART_ReceiveData(USART6); //读取接收到的数据,必须接受,否则会出错
USART6_RX_BUF[USART6_RX_STA++]=0;
USART6_RX_STA|=1<<15;
}
else if(USART_GetITStatus(USART6, USART_IT_RXNE))
{
res =USART_ReceiveData(USART6);
USART6_RX_BUF[USART6_RX_STA++]=res; //记录接收到的值
if((USART6_RX_STA&0x7FFF)>USART6_MAX_RECV_LEN)//还可以接收数据
{
USART6_RX_STA|=1<<15; //强制标记接收完成
}
}
}
void GY39_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6);
USART_DeInit(USART6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOC,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;//波特率一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);//开启中断
USART_ITConfig(USART6, USART_IT_IDLE, ENABLE);//开启总线空闲中断
//设置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART6_RX_STA=0; //清零
}
//串口3,printf 函数
//确保一次发送数据不超过USART6_MAX_SEND_LEN字节
void u6_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART6_TX_BUF,fmt,ap);
va_end(ap);
i=strlen((const char*)USART6_TX_BUF); //此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
while(USART_GetFlagStatus(USART6,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
USART_SendData(USART6,USART6_TX_BUF[j]);
}
}
void GY39_Get_Temp_humi(int *temp, int *humi)
{
if(USART6_RX_STA & 0x8000)
{
*temp = ((int)(USART6_RX_BUF[4]) << 8 | (int)(USART6_RX_BUF[5])) / 100;
*humi = ((int)(USART6_RX_BUF[10]) << 8 | (int)(USART6_RX_BUF[11])) / 100;
USART6_RX_STA=0;
memset(USART6_RX_BUF,0,sizeof(USART6_RX_BUF));
}
}
(3) main.c
GY39_Init();
while(1)
{
GY39_Get_Temp_humi(&temperature,&humidity);
LCD_ShowxNum(130,70,temperature,3,16,0);
LCD_ShowxNum(130,90,humidity,3,16,0);
}