STM32 驱动 GY 您所在的位置:网站首页 gpio_otype_od STM32 驱动 GY

STM32 驱动 GY

#STM32 驱动 GY| 来源: 网络整理| 查看: 265

1.特别说明

​ 要是不想看原理和过程,直接下拉找代码吧,都是测试过的,很稳定,有硬件I2C驱动的,也有软件模拟I2C驱动的,基于STM32F103系列和STM32F4系列实现,基于标准库实现,条理清晰。

2.软硬件硬件准备

​ (1) Kile 5.27

​ (2) 串口助手

​ (3) STM32F103与STM32F4系列单片机

​ (4) CH340 串口转 TTL 工具

​ (5) BH1750-即-GY-302光照传感器

3.了解驱动原理 3.1.程序设计思路

这是官方数据手册给的驱动说明,这是基于标准I2C设计的传感器,也就是说它支持标准全速400KHz速率通信(实测确实没问题);这个流程图大概说的是程序设计:

​ 1.上电初始化

​ 2.掉电再上电(软指令,可省略步骤)

​ 3.发送测量命令(单次测量或者连续测量)

​ 4.读取测量数据

3.2.引脚接线说明 VCC 5V~3.3V GND GND SCL PB6 SDA PB7 ADDR VCC/GND

首先这个模块比较友好,支持3V3到5V供电,其次特别注意ADDR这个引脚的接线:

接高电平的硬件地址和接低电平的硬件地址是不一样的:

​ 接高电平硬件地址:0X5C (注意:这是高 7 位地址数据)

​ 接低电平硬件地址:0X23 (注意:这是高 7 位地址数据)

器件地址(7位-用左移1位-最后1位为读写位–1为读-0为写)

3.3驱动时序

写指令流程

1.发送起始信号 ————> 2.发送写指令地址(接收ACK信号)

​ 3.发送操作指令(接收ACK信号) ————> 4.发送停止信号

读指令流程:

​ 1.发送起始信号 ——> 2.发送读指令地址(接收ACK信号)

​ 3.接收高 8 位数据(发送ACK信号) ——> 4.接收低 8 位数据(发送NACK)

​ 5.发送结束信号

3.3.指令集说明 功能 寄存器地址指令 注释说明 断电 0000_0000 没有活动状态。 接通电源 0000_0001 正在等待测量命令。 重置 0000_0111 重置数据寄存器值。在关机模式下,不能接受重置命令。 连续H分辨率模式 0001_0000 以1lx的分辨率开始测量。测量时间通常为120ms。 连续h分辨率模式2 0001_0001 在0.5lx的分辨率下开始测量。测量时间通常为120ms。 连续L分辨率模式 0001_0011 以4lx的分辨率开始测量。测量时间通常为16ms。 一次H分辨率模式 0010_0000 以1lx的分辨率开始测量。测量时间通常为120ms。测量后自动设置为关机模式。 一次H分辨率模式2 0010_0001 在0.5lx的分辨率下开始测量。测量时间通常为120ms。测量后自动设置为关机模式。 一次性L分辨率模式 0010_0011 以4lx的分辨率开始测量。测量时间通常为16ms。测量后自动设置为关机模式。 更改测量时间(高位) 01000_MT[7,6,5] 改变测量时间。※请参考“调整测量结果对光学窗口的影响”。 更改测量时间(低位) 011_MT[4,3,2,1,0] 更改测量时间。※请参考“调整测量结果对光学窗口的影响”。 3.4数据转换

(uint16_t)Data_LX = (uint16_t)(H_data /* 先判断总线是否忙 */ while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); /* 发送Start信号,切换到主模式(M/SL 位置 1) */ I2C_GenerateSTART(I2C1, ENABLE); /* 等待EV5事件,IIC开始信号已经发出 */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /* 发送器件地址,发送方向: I2C_Direction_Transmitter */ I2C_Send7bitAddress(I2C1, (BH1750_Addr_GND_REG BH1750_WriteByte(BH1750_Power_OFF_REG); } /** BH1750数据寄存器复位 **/ void BH1750_RESET(void) { BH1750_WriteByte(BH1750_MODULE_RESET_REG); } /** BH1750初始化 **/ void BH1750_Init(void) { I2C_Configuration(); delay_ms(100); BH1750_Power_OFF(); BH1750_Power_ON(); BH1750_RESET(); BH1750_WriteByte(BH1750_CONTINUE_H_MODE2); } /** 获取光照强度 **/ /** 分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 **/ float Light_Intensity(void) { return (float)(BH1750_Read_Data() / 1.2f ); } /*************************************END***********************************************/ BH1750.h #ifndef __BH1750_H #define __BH1750_H #include "stm32f10x.h" #include "delay.h" /* 器件地址(7位-用左移1位-最后1位为读写位--1为读-0为写) */ #define BH1750_Addr_GND_REG 0X23 //ADDR引脚接低电平 #define BH1750_Addr_VCC_REG 0X5C //ADDR引脚接高电平 /****** 指令集宏定义*****/ #define BH1750_Power_OFF_REG 0x00 //断电指令 #define BH1750_Power_ON_REG 0x01 //通电,等待测量命令 #define BH1750_MODULE_RESET_REG 0x07 //重置数据寄存器,关机模式下,不能接受重置命令 /************************************************* 不同模式下分辨率不同(也即精度不同) 高分辨率模式2:分辨率是0.5lx 高分辨率模式:分辨率1lx 低分辨率模式:分辨率4lx 不同模式只是精度不一样,对于计算没有区别 ***************************************************/ /** 工作模式指令集 **/ #define BH1750_CONTINUE_H_MODE 0x10 //连续H分辨率模式 #define BH1750_CONTINUE_H_MODE2 0x11 //连续H分辨率模式2 #define BH1750_CONTINUE_L_MODE 0x13 //连续L分辨率模式 #define BH1750_ONE_TIME_H_MODE 0x20 //一次H分辨率模式 #define BH1750_ONE_TIME_H_MODE2 0x21 //一次H分辨率模式2 #define BH1750_ONE_TIME_L_MODE 0x23 //一次性L分辨率模式 /** 函数声明区 **/ void I2C_Configuration (void); void BH1750_WriteByte (uint8_t addr); uint16_t BH1750_Read_Data (void); void BH1750_Power_ON (void); void BH1750_Power_OFF (void); void BH1750_RESET (void); void BH1750_Init (void); float Light_Intensity (void); #endif 4.1.2 适用STM32F103系列的软件IIC驱动 ( BH1750.h 头文件基本一样) BH1750.c #include "BH1750.h" /**************************************************************************** ** 函数名称:BH1750_WriteByte() ** 函数功能:BH1750 写数据 ** 参数说明: ** uint8_t addr: 寄存器地址 ** ** 返回值:无 ** IIC函数说明: ** I2C_GetFlagStatus(IIC_x, IIC_Flag_x)-- 检查标志位是否置 1 ** *****************************************************************************/ void BH1750_WriteByte(uint8_t addr) { IIC_Start(); // 1.发送起始信号 IIC_Send_Byte(BH1750_Addr_GND_REG BH1750_WriteByte(BH1750_Power_ON_REG); } /** BH1750断电 **/ void BH1750_Power_OFF(void) { BH1750_WriteByte(BH1750_Power_OFF_REG); } /** BH1750数据寄存器复位 **/ void BH1750_RESET(void) { BH1750_WriteByte(BH1750_MODULE_RESET_REG); } /** BH1750初始化 **/ void BH1750_Init(void) { IIC_Init(); delay_ms(100); BH1750_Power_OFF(); BH1750_Power_ON(); BH1750_RESET(); BH1750_WriteByte(BH1750_CONTINUE_H_MODE2); } /** ** 获取光照强度 ** 分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 **/ float Light_Intensity(void) { return (float)(BH1750_Read_Data() / 1.2f ); } /*************************************END***********************************************/

头文件基本一样,只需要导入软件模拟 IIC 的头文件就行,(#include "IIC.h"),工程导入模拟IIC.c文件

IIC.c #include "IIC.h" /** * 函数说明:软件模拟 IIC * * 函数功能:GPIO 初始化 * * 注意事项:GPIO 可自行选择 * * 记录: GPIO 引脚初始化,相同的归 * 属GPIOX尽量放同一语句中; **/ void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //SCL & SDA GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //推挽/开漏 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //速度 10 MHz GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高 } /** * 函数说明:产生IIC起始信号 * * 原理说明: 当 SCL 是高电平状态时, * 数据线 SDA 由高拉低; **/ void IIC_Start(void) { SDA_OUT(); /* SDA 线输出模式 */ IIC_SDA = 1; /* 先拉高 SDA 状态 */ IIC_SCL = 1; /* 再拉高 SCL 状态 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SDA = 0; /* 后拉低 SDA 状态 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SCL = 0; /* 钳住I2C,发送或接收 */ } /** * 函数说明:产生IIC停止信号 * * 原理说明: SCL线为高电平状态时, SDA 线 * 由低电平向高电平跳变(上升沿) **/ void IIC_Stop(void) { SDA_OUT(); /* SDA 线输出模式 */ IIC_SCL = 0; /* 先拉低 SCL 状态 */ IIC_SDA = 0; /* 先拉低 SDA 状态 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SCL = 1; /* 后拉高 SCL 状态 */ IIC_SDA = 1; /* 后拉高 SDA 状态 */ IIC_Delay(); /* 延时保持电平状态 */ } /** * 函数说明:等待应答信号到来 * * 原理说明: 先将数据线拉高,延时等待稳定,然后将时钟线拉高, * 延时等待稳定,最后采样数据线电平状态,如果是高 * 电平,未应答,如果是低电平,应答; * * 返回值:0, 接收应答失败 * 1, 接收应答成功 **/ uint8_t IIC_Wait_Ack(void) { uint16_t ErrorTime; SDA_IN(); /** SDA 线输入模式 **/ IIC_SDA = 1; /* 先拉高 SDA 状态 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SCL = 1; /* 后拉高 SCL 状态 */ IIC_Delay(); /* 延时保持电平状态 */ while(Read_SDA) /* 采样 SDA 电平状态 */ { ErrorTime ++; if(ErrorTime > 250) { IIC_Stop(); /* 非应答,结束通信 */ return 0; } } IIC_SCL = 0; /** 钳住,等待发或收 **/ return 1; /** 接收到应答信号 **/ } /** * 函数说明:产生 ACK 应答 * * 原理说明:SCL 在高电平期间 SDA 始终处于低电平 * (SCL 保持时间 SDA_OUT(); /** SDA 线输出模式 **/ IIC_SCL = 0; /* 数据线 SCL 拉低 */ IIC_SDA = 1; /* 数据线 SDA 拉高 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SCL = 1; /* 时钟线 SCL 拉高 */ IIC_Delay(); /* 延时保持电平状态 */ IIC_SCL = 0; /* 时钟线 SCL 拉低 */ } /** * 函数功能:IIC发送一个字节 * 参数说明:Txd 无符号 8 位 * * 返回值:1, 有应答 * 0, 无应答 **/ void IIC_Send_Byte(uint8_t Txd) { uint8_t T; SDA_OUT(); /** 数据线SDA输出态 **/ IIC_SCL = 0; /** 时钟线 SCL 拉低 **/ for(T = 0; T < 8; T++) /** 由高到低发送数据 */ { IIC_SDA = (Txd & 0x80) >> 7;/** 每次发送最高位 **/ Txd Receive++; /** 高电平,则最低位为1 **/ } IIC_Delay(); /* 延时保持电平状态 */ } if (!ACK) IIC_NAck(); /** 发送 NACK **/ else IIC_Ack(); /** 发送 ACK **/ return Receive; } IIC.h #ifndef __IIC_H #define __IIC_H #include "stm32f10x.h" #include "delay.h" #include "sys.h" /********************************* ** 引脚选择: ** ** SCL ---> PXx ** ** SDA ---> PXx ** **********************************/ /*******************************保持时间***********************************/ #define IIC_Delay() { delay_us(5); } /*************************** IO方向设置(GPIOx * 4) ****************************/ /** PXx 上拉输入模式 **/ #define SDA_IN() {GPIOB -> CRL &= 0X0FFFFFFF; GPIOB -> CRL |= (u32)8 GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; RCC_AHB1PeriphClockCmd(BH1750_GPIO_CLOCK, ENABLE); /*使能 GPIOB 时钟*/ RCC_APB1PeriphClockCmd(BH1750_IIC_CLOCK, ENABLE); /*使能 IIC_x 时钟*/ /* STM32F401CCU6芯片的硬件I2C1: I2C1:PB6 -- SCL PB7 -- SDA I2C1:PB8 -- SCL PB9 -- SDA I2C2:PB10 --SCL PB3 -- SDA I2C3:PA8 ---SCL PB4 -- SDA **/ GPIO_InitStructure.GPIO_Pin = BH1750_SCL | BH1750_SDA; //IIC引脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //高速模式 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出 GPIO_Init(BH1750_GPIOx, &GPIO_InitStructure); /** 连接 AFx,这里必须要开启引脚重映射 **/ //GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource8, GPIO_AF_I2C1); //GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource9, GPIO_AF_I2C1); GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource6, GPIO_AF_I2C1); GPIO_PinAFConfig(BH1750_GPIOx, GPIO_PinSource7, GPIO_AF_I2C1); I2C_DeInit(BH1750_IIC); //使用I2Cx I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //选择IIC模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //占空比 1/2 I2C_InitStructure.I2C_OwnAddress1 = 0x30; //主机的I2C地址,随便写的 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //应答信号使能 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //IIC 7 位寻址 I2C_InitStructure.I2C_ClockSpeed = 10000; //设置最大400K I2C_Cmd(BH1750_IIC, ENABLE); //使能IIC I2C_Init(BH1750_IIC, &I2C_InitStructure); //初始化 IIC 相关 }

头文件(.h文件)改动

/********************************** BH1750.h 改动 ***************************************/ /************************************硬件使用到的相关************************************/ #define BH1750_GPIOx GPIOB // GPIOx #define BH1750_GPIO_CLOCK RCC_AHB1Periph_GPIOB //GPIOx_CLOCK #define BH1750_IIC_CLOCK RCC_APB1Periph_I2C1 // IIC_CLOCK #define BH1750_SCL GPIO_Pin_6 // GPIO_SCL #define BH1750_SDA GPIO_Pin_7 // GPIO_SDA #define BH1750_IIC I2C1 // IIC_X

软件IIC模拟改动

/************************************ IIC.c 改动 ****************************************/ void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /** 自定义 GPIO 初始化**/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13; //SCL&&SDA GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //设置2MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //引脚上拉 GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化IO IIC_SCL = 1; //上拉 SCL IIC_SDA = 1; //上拉 SDA } /************************************ IIC.h 改动 ****************************************/ /********************************* ** 引脚选择: ** ** SCL ---> PXx ** ** SDA ---> PXx ** **********************************/ /************************* IO方向设置(GPIOx * 2) ****************************/ /** PXx输入模式 **/ #define SDA_IN() {GPIOB -> MODER &=~(3 MODER |= 0 您可能感兴趣的内容: 《基于大疆RoboMaster开发板C型的BMI088数据读取:超详细指南》 绝对让你明明白白,脚把脚带你盯着 I2C 时序图将 I2C 程序给扣出来(基于STM32的模拟I2C) 使用STM32的HAL库驱动1.54英寸TFT屏(240*240 ST7789V) STM32与DHT11传感器联动,在LCD屏上实时显示温湿度信息 基于STM32的全面智能农业系统:上位机与下位机完美结合


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有