飞道的博客

STM32--软件IIC与硬件IIC驱动BH1750芯片

590人阅读  评论(0)

一.光照传感器分析

查看芯片手册,总结GY_30使用注意的几个点:考虑断电通电、单次连续、读取数据时间

1.设置芯片为通电模式、

2.重置数字寄存器值

3.设置连续 H分辨率模式

4.等待一次测量时间max 180ms

5完整过程

  • 发送起始信号,发送器件地址与读方向,检测应答。发送高分辨率指令,检测应答,发送结束信号
  • 延时等待180ms
  • 发送起始信号,发送器件地址与写方向,检测应答。接收高八位,检测应答。接收第八位,检测非应答,发送结束信号

  
  1. / **** **** **** **** **** **** BH1750初始化函数 **** **** **** **** **** ***
  2. 根据需要参考pdf进行参数修改
  3. *****************************************************************/
  4. void BH1750_Init(void)
  5. {
  6. BH1750_Write _COM(SlaveAddress,0x01); //开电源
  7. BH1750_Write _COM(SlaveAddress,0x07); //重置数字寄存器值
  8. BH1750_Write _COM(SlaveAddress,0x10); //连续模式
  9. Delay_ms(180); //等到测量结束
  10. }
  11. /** **** **** **** **** **** ** BH1750写指令函数 ** **** **** **** **** **** *
  12. Dev_Adder:模块IIC通讯地址
  13. Common: 需要发送的控制指令
  14. ******************************************************************/
  15. void BH1750_Write_COM(unsigned char Dev_Adder,unsigned char Common)
  16. {
  17. IIC_Start(); //起始信号
  18. IIC_Send_Data(Dev_Adder); //发送从设备地址(从设备地址+读写控制位)
  19. if( IIC_Get _ACK() ) //检测应答
  20. {
  21. goto WR_End;
  22. }
  23. IIC_Send_Data(Common); //发送测试指令
  24. if( IIC_Get_ACK() ) //检测应答
  25. {
  26. goto WR_End;
  27. }
  28. WR_End:
  29. IIC_Stop(); //发送结束信号
  30. }
  31. /************************ BH1750读数据函数 ***********************
  32. Dev_Adder:模块IIC通讯地址
  33. ******************************************************************/
  34. u16 BH1750_Read_Data(unsigned char Dev_Adder)
  35. {
  36. unsigned char Buff[2] = {0};
  37. u16 Data = 0;
  38. IIC_Start(); //起始信号
  39. IIC_Send_Data(Dev_Adder | 0x01); //发送从设备地址(从设备地址+读写控制位)
  40. if( IIC_Get _ACK() ) //检测应答
  41. {
  42. goto WR_End;
  43. }
  44. /* 读取光照数据 */
  45. Buff[0]= IIC_Read_Data(1); //读取高字节光照数据 并发送应答信号
  46. Buff[1] = IIC_Read_Data(0); //读取低字节光照数据 并发送非应答信号
  47. WR_End:
  48. IIC_Stop(); //发送结束信号
  49. Delay_ms(5);
  50. /* 合并光强数据 */
  51. Data = Buff[0];
  52. Data = (Data << 8) | Buff[1]; //合成数据,即光照数据
  53. return Data; //光照强度数值
  54. }

 

一.软件IIC


  
  1. / **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***
  2. 函数功能: SDA初始化
  3. *******************************************************************/
  4. void SDA_IN(void)
  5. {
  6. GPIO_InitTypeDef GPIO_InitStruct;
  7. /*SDA-----PB11 */ //浮空输入
  8. GPIO_InitStruct.GPIO_Pin = IIC_SDA;
  9. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  10. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
  12. }
  13. /*******************************************************************
  14. 函数功能: SDA初始化
  15. *******************************************************************/
  16. void SDA_OUT(void)
  17. {
  18. GPIO_InitTypeDef GPIO_InitStruct;
  19. /*SDA-----PB11 */ //推挽输出 50MHZ
  20. GPIO_InitStruct.GPIO_Pin = IIC_SDA;
  21. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  22. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  23. GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
  24. }
  25. /*******************************************************************
  26. 函数功能: 电容按键接口初始化
  27. *******************************************************************/
  28. void IIC_Init(void)
  29. {
  30. GPIO_InitTypeDef GPIO_InitStruct;
  31. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能B时钟
  32. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟
  33. GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
  34. /*SDA-----PB11 */ //推挽输出 50MHZ
  35. GPIO_InitStruct.GPIO_Pin = IIC_SDA;
  36. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  37. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  38. GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
  39. /*CLK-----PB10 */ //推挽输出 50MHZ
  40. GPIO_InitStruct.GPIO_Pin = IIC_CLK;
  41. GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
  42. CLK_H;
  43. SDA_H;
  44. }
  45. /*******************************************************************
  46. 函数功能: 起始信号
  47. *******************************************************************/
  48. void IIC_Start(void)
  49. {
  50. SDA_OUT();
  51. SDA_H; //串行数据线高电平(空闲信号)
  52. CLK_H; //串行时钟线高电平(空闲信号)
  53. Delay_us(5);
  54. SDA_L; //串行数据线拉出下降沿
  55. Delay_us(5);
  56. CLK_L; //串行时钟线拉出下降沿
  57. }
  58. /*******************************************************************
  59. 函数功能: 结束信号
  60. *******************************************************************/
  61. void IIC_Stop(void)
  62. {
  63. SDA_OUT(); //输出模式
  64. CLK_L; //串行时钟线低电平
  65. SDA_L; //串行数据线低电平
  66. CLK_H; //串行时钟线高电平
  67. Delay_us(5);
  68. SDA_H; //串行数据线高电平 上升沿
  69. Delay_us(5);
  70. }
  71. /*******************************************************************
  72. 函数功能: 发送应答信号
  73. *******************************************************************/
  74. void IIC_Send_ACK(void)
  75. {
  76. CLK_L;
  77. SDA_OUT(); //输出模式
  78. SDA_L; //串行数据线低电平
  79. Delay_us(5);
  80. CLK_H; //串行时钟线线高电平 上下
  81. Delay_us(5);
  82. CLK_L; //串行时钟线线低电平
  83. }
  84. /*******************************************************************
  85. 函数功能: 发送非应答信号
  86. *******************************************************************/
  87. void IIC_Send_NoACK(void)
  88. {
  89. CLK_L;
  90. SDA_OUT();
  91. SDA_H; //串行数据线为高电平
  92. Delay_us(5);
  93. CLK_H;
  94. Delay_us(5);
  95. CLK_L;
  96. }
  97. /*******************************************************************
  98. 函数功能: 发送8位数据
  99. *******************************************************************/
  100. void IIC_Send_Data(u8 dat)
  101. {
  102. u8 i;
  103. SDA_OUT();
  104. CLK_L;
  105. for(i = 0; i < 8; i++) //分8次传输数据 一位一位传递 串行
  106. {
  107. // Delay_us(5);//SCL拉低后SSDA要立马改变,(等待时间不能超过0.9us)?????
  108. if(dat & 0x80) //先发最高位 1000 0000
  109. {
  110. SDA_H; //写1
  111. }
  112. else
  113. {
  114. SDA_L; //写0
  115. }
  116. dat <<= 1; //左移操作 次高位-->最高位
  117. Delay_us(5);
  118. CLK_H;
  119. Delay_us(5);
  120. CLK_L;
  121. Delay_us(5);
  122. }
  123. }
  124. /*******************************************************************
  125. 函数功能: 等待应答
  126. *******************************************************************/
  127. u8 IIC_Get_ACK(void)
  128. {
  129. u8 ERRTIME = 0; //超时变量
  130. SDA_IN();
  131. //SDA_L;// 没有影响
  132. Delay_us(5);
  133. CLK_H;
  134. Delay_us(5);
  135. while( READ_SDA() )
  136. {
  137. ERRTIME++;
  138. if(ERRTIME >=250)
  139. {
  140. IIC_Stop();
  141. return 1;
  142. }
  143. }
  144. CLK_L;
  145. return 0;
  146. }
  147. /*******************************************************************
  148. 函数功能: 读取8位数据
  149. *******************************************************************/
  150. u8 IIC_Read_Data(u8 ack)
  151. {
  152. unsigned char i,date = 0;
  153. SDA_IN();
  154. for(i = 0; i < 8; i++)
  155. {
  156. CLK_L;
  157. Delay_us(5);
  158. CLK_H;
  159. date <<= 1;
  160. Delay_us(5);
  161. if( READ_SDA() )
  162. {
  163. date ++;
  164. }
  165. //Delay_us(2);
  166. }
  167. if(ack)
  168. {
  169. IIC_Send_ACK(); //发送应答
  170. }
  171. else
  172. {
  173. IIC_Send_NoACK(); //发送非应答
  174. }
  175. return date;
  176. }

二.硬件IIC

1.初始化


  
  1. void IIC_Init(void)
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. I2C_InitTypeDef I2C_InitStructure;
  5. //初始化时钟
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  7. RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
  8. //配置IO口功能
  9. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 |GPIO_Pin_11;
  10. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  11. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  12. GPIO_Init(GPIOB,&GPIO_InitStructure);
  13. I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //IIC模式
  14. I2C_InitStructure.I2C_OwnAddress1 = 0x0A; //作为从机地址
  15. I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //地址的位数
  16. I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //选择有应答信号
  17. I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_16_9; //配置高低电平比例
  18. I2C_InitStructure.I2C_ClockSpeed = 200000; //配置时钟
  19. I2C_Init(I2C2,&I2C_InitStructure);
  20. I2C_Cmd(I2C2,ENABLE);
  21. // I2C_AcknowledgeConfig(I2C2,ENABLE);
  22. }

2.驱动器件


  
  1. typedef unsigned char BYTE;
  2. typedef unsigned short WORD;
  3. void Single_Write_BH1750(u8 REG_Address)
  4. {
  5. while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));
  6. //起始信号
  7. I2C_GenerateSTART(I2C2,ENABLE);
  8. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
  9. //发送设备地址+写信号
  10. I2C_Send7bitAddress(I2C2,SlaveAddress,I2C_Direction_Transmitter);
  11. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
  12. //内部寄存器地址
  13. I2C_SendData(I2C2,REG_Address);
  14. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
  15. //发送停止信号
  16. I2C_GenerateSTOP(I2C2,ENABLE);
  17. }
  18. //*********************************************************
  19. //
  20. //连续读出BH1750内部数据
  21. //
  22. //*********************************************************
  23. BYTE BUF[ 8]; //接收数据缓存区
  24. int dis_data; //变量
  25. void Multiple_read_BH1750(void)
  26. {
  27. u8 i;
  28. while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));
  29. //起始信号
  30. I2C_GenerateSTART(I2C2,ENABLE);
  31. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
  32. //发送设备地址+读信号
  33. I2C_Send7bitAddress(I2C2,SlaveAddress,I2C_Direction_Receiver);
  34. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);
  35. for (i= 0; i< 3 -1; i++) //连续读取2个地址数据,存储中BUF
  36. {
  37. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
  38. BUF[i] = I2C_ReceiveData(I2C2);
  39. }
  40. I2C_AcknowledgeConfig(I2C2,DISABLE);
  41. while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
  42. BUF[i] = I2C_ReceiveData(I2C2);
  43. //停止信号
  44. I2C_GenerateSTOP(I2C2,ENABLE);
  45. I2C_AcknowledgeConfig(I2C2,ENABLE);
  46. delay_ms( 5);
  47. }
  48. //初始化BH1750,根据需要请参考pdf进行修改****
  49. void Init_BH1750(void)
  50. {
  51. IIC_Init();
  52. Single_Write_BH1750( 0x01);
  53. Single_Write_BH1750( 0x10); // H- resolution mode
  54. delay_ms( 180);
  55. }
  56. float BH1750_Value;
  57. void BH1750_Read(void)
  58. {
  59. Multiple_read_BH1750(); //连续读出数据,存储在BUF中
  60. dis_data=BUF[ 0];
  61. dis_data=(dis_data<< 8)+BUF[ 1]; //合成数据,即光照数据
  62. BH1750_Value=( float)dis_data/ 1.2;
  63. }

 


转载:https://blog.csdn.net/qq_45604814/article/details/116132328
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场