找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3047|回复: 3
打印 上一主题 下一主题
收起左侧

STM32f103RCT6+BH1750光照传感器+IIC通信OLED显示 源程序

  [复制链接]
跳转到指定楼层
楼主
需要的硬件:STM32f103rct6开发板、BH1750光照传感器、IIC接口的0.96oled显示屏
使用BH1750光照传感器采集光照信息,然后通过oled显示屏显示光照值/lx
BH1750的硬件连接:
SCL——PC12
SDA——PC11
ADDR——GND (注:本程序AD地址为0x46为接地地址,如果把该引脚接VCC就需要修改bh1750.h文件中BH1750_Addr的值为0xB8,具体见数据手册P13)
oled显示屏的硬件连接:
SCL——PB0
SDA——PB1

电路原理图如下:


代码包含main.c、bh1750.h、bh1750.c、oled.h、oled.c、oledfont.h
制作出来的实物图如下:


程序如下:
bh1750.h
  1. #ifndef __BH1750_H
  2. #define __BH1750_H
  3. #include "sys.h"
  4.         
  5. #define BH1750_OFF  0x00    //断电
  6. #define BH1750_Addr 0x46    //ALT  ADDRESS引脚接地时地址为0x46,接电源时地址为0xB8
  7. #define BH1750_ON   0x01        //通电
  8. #define BH1750_CON  0x10        //连续H分辨率模式
  9. #define BH1750_ONE  0x20        //一次H分辨率模式
  10. #define BH1750_RSET 0x07        //重置
  11.                                  
  12. //IO方向设置
  13. #define SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
  14. #define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

  15. //IO操作函数         
  16. #define IIC_SCL    PCout(12) //SCL
  17. #define IIC_SDA    PCout(11) //SDA         
  18. #define READ_SDA   PCin(11)  //输入SDA

  19. extern u32 result_lx;

  20. //IIC所有操作函数
  21. void IIC_Init(void);                //初始化IIC的IO口                                 
  22. void IIC_Start(void);                                //发送IIC开始信号
  23. void IIC_Stop(void);                                  //发送IIC停止信号
  24. void IIC_Send_Byte(u8 txd);                        //IIC发送一个字节
  25. u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  26. u8 IIC_Wait_Ack(void);                                 //IIC等待ACK信号
  27. void IIC_Ack(void);                                        //IIC发送ACK信号
  28. void IIC_NAck(void);                                //IIC不发送ACK信号

  29. void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
  30. u8 IIC_Read_One_Byte(u8 daddr,u8 addr);         


  31. void Start_BH1750(void);                        //上电,设置清除数据寄存器
  32. void Read_BH1750(void);                               //连续的读取内部寄存器数据
  33. void Convert_BH1750(void);

  34. #endif

复制代码
bh1750.c
  1. #include "bh1750.h"
  2. #include "delay.h"

  3. u8 BUF[2]={0};
  4. u16 result=0;
  5. u32 result_lx;

  6. //初始化IIC引脚
  7. void IIC_Init(void)
  8. {                                             
  9.         GPIO_InitTypeDef GPIO_InitStructure;
  10.         
  11.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );        
  12.            
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
  14.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;                   //推挽输出
  15.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.         GPIO_Init(GPIOC, &GPIO_InitStructure);

  17.         IIC_SCL=1;
  18.         IIC_SDA=1;

  19. }
  20. //产生IIC起始信号
  21. void IIC_Start(void)
  22. {
  23.         SDA_OUT();      //sda线输出
  24.         IIC_SDA=1;                    
  25.         IIC_SCL=1;
  26.         delay_us(4);
  27.          IIC_SDA=0;                //START:when CLK is high,DATA change form high to low
  28.         delay_us(4);
  29.         IIC_SCL=0;                //钳住I2C总线,准备发送或接收数据
  30. }         
  31. //产生IIC停止信号
  32. void IIC_Stop(void)
  33. {
  34.         SDA_OUT();                //sda线输出
  35.         IIC_SCL=0;
  36.         IIC_SDA=0;                //STOP:when CLK is high DATA change form low to high
  37.          delay_us(4);
  38.         IIC_SCL=1;
  39.         IIC_SDA=1;                //发送I2C总线结束信号
  40.         delay_us(4);                                                                  
  41. }
  42. //等待应答信号到来
  43. //返回值:1,接收应答失败
  44. //        0,接收应答成功
  45. u8 IIC_Wait_Ack(void)
  46. {
  47.         u8 ucErrTime=0;
  48.         SDA_IN();              //SDA设置为输入  
  49.         IIC_SDA=1;delay_us(1);           
  50.         IIC_SCL=1;delay_us(1);         
  51.         while(READ_SDA)
  52.         {
  53.                 ucErrTime++;
  54.                 if(ucErrTime>250)
  55.                 {
  56.                         IIC_Stop();
  57.                         return 1;
  58.                 }
  59.         }
  60.         IIC_SCL=0;                //时钟输出0            
  61.         return 0;  
  62. }
  63. //产生ACK应答
  64. void IIC_Ack(void)
  65. {
  66.         IIC_SCL=0;
  67.         SDA_OUT();
  68.         IIC_SDA=0;
  69.         delay_us(2);
  70.         IIC_SCL=1;
  71.         delay_us(2);
  72.         IIC_SCL=0;
  73. }
  74. //不产生ACK应答                    
  75. void IIC_NAck(void)
  76. {
  77.         IIC_SCL=0;
  78.         SDA_OUT();
  79.         IIC_SDA=1;
  80.         delay_us(2);
  81.         IIC_SCL=1;
  82.         delay_us(2);
  83.         IIC_SCL=0;
  84. }                                                                              
  85. //IIC发送一个字节
  86. //返回从机有无应答
  87. //1,有应答
  88. //0,无应答                          
  89. void IIC_Send_Byte(u8 txd)
  90. {                        
  91.     u8 t;   
  92.         SDA_OUT();            
  93.     IIC_SCL=0;                        //拉低时钟开始数据传输
  94.     for(t=0;t<8;t++)
  95.     {              
  96.         IIC_SDA=(txd&0x80)>>7;
  97.         txd<<=1;           
  98.                 delay_us(2);          //对TEA5767这三个延时都是必须的
  99.                 IIC_SCL=1;
  100.                 delay_us(2);
  101.                 IIC_SCL=0;        
  102.                 delay_us(2);
  103.     }         
  104. }            
  105. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
  106. u8 IIC_Read_Byte(unsigned char ack)
  107. {
  108.         unsigned char i,receive=0;
  109.         SDA_IN();                     //SDA设置为输入
  110.     for(i=0;i<8;i++ )
  111.         {
  112.         IIC_SCL=0;
  113.         delay_us(2);
  114.                 IIC_SCL=1;
  115.         receive<<=1;
  116.         if(READ_SDA)receive++;   
  117.                 delay_us(1);
  118.     }                                         
  119.     if (!ack)
  120.         IIC_NAck();                //发送nACK
  121.     else
  122.         IIC_Ack();                 //发送ACK   
  123.     return receive;
  124. }

  125. void Cmd_Write_BH1750(u8 cmd)
  126. {
  127.     IIC_Start();                    //起始信号
  128.     IIC_Send_Byte(BH1750_Addr+0);   //发送设备地址+写信号
  129.         while(IIC_Wait_Ack());
  130.     IIC_Send_Byte(cmd);        //内部寄存器地址
  131.         while(IIC_Wait_Ack());
  132.     //BH1750_SendByte(REG_data);       //内部寄存器数据,
  133.     IIC_Stop();                        //发送停止信号
  134.         delay_ms(5);
  135. }

  136. void Start_BH1750(void)                        //上电,设置清除数据寄存器
  137. {
  138.         Cmd_Write_BH1750(BH1750_OFF);         //power off
  139.         Cmd_Write_BH1750(BH1750_ON);         //power on
  140.         Cmd_Write_BH1750(BH1750_RSET);         //reset
  141.         Cmd_Write_BH1750(BH1750_ONE);    //在1lx分辨率下开始测量,测量时间一般为120ms
  142.         delay_ms(200);
  143. }

  144. void Read_BH1750(void)               //读取内部寄存器数据
  145. {
  146.         IIC_Start();                        //起始信号
  147.     IIC_Send_Byte(BH1750_Addr+1);       //发送设备地址+读信号
  148.         while(IIC_Wait_Ack());
  149.         BUF[0]=IIC_Read_Byte(1);  //发送ACK
  150.         BUF[1]=IIC_Read_Byte(0);  //发送nACK

  151.     IIC_Stop();               //停止信号
  152.     delay_ms(5);
  153. }

  154. void Convert_BH1750(void)
  155. {
  156.         
  157.         result=BUF[0];
  158.         result=(result<<8)+BUF[1];            //合成两个字节的数据,即光照数据
  159.         
  160.         result_lx=(u32)((float)result/1.2);
  161. }
复制代码

main.c
  1. #include "led.h"
  2. #include "oled.h"
  3. #include "bh1750.h"
  4. #include "sys.h"
  5. #include "delay.h"

  6. int main(void)
  7. {
  8.         delay_init();
  9.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  10.         OLED_Init();
  11.         IIC_Init();
  12.         LED_Init();
  13.         OLED_Clear();
  14.         OLED_Refresh();
  15.         //Start_BH1750();
  16.         while(1)
  17.         {
  18.                 Start_BH1750();
  19.                 Read_BH1750();
  20.                 Convert_BH1750();
  21.                 Convert_BH1750();
  22.                 OLED_ShowString(0,2,"lightval:",12);
  23.                 OLED_ShowNum(60,2,result_lx,6,12);
  24.                 OLED_ShowString(110,2,"lx",12);
  25.                 OLED_Refresh();
  26.                 LED0=!LED0;
  27.                 delay_ms(200);
  28.         }
  29. }

复制代码
由于oled相关程序过长,限于篇幅此处没有粘贴出来,如果需要可以下载以下工程文件。
工程文件夹如下:


Keil代码下载: STM32f103RCT6+BH1750光照传感器+IIC通信oled显示.7z (605.07 KB, 下载次数: 132)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:689054 发表于 2022-3-11 08:30 | 只看该作者
光太强的话会不会出现超量程?
回复

使用道具 举报

板凳
ID:473377 发表于 2022-3-11 13:14 | 只看该作者
bbc10808 发表于 2022-3-11 08:30
光太强的话会不会出现超量程?

最大值的情况下就是读取的数据结果为高八位和低八位都为11111111 11111111,通过公式计算(1+2^1+2^2+2^3+2^4+...+2^14+2^15)/1.2=65535/1.2=54612.5 lx(参考数据手册p7),本程序中oled有6位数显示区域,所以不会超出量程。
回复

使用道具 举报

地板
ID:504404 发表于 2022-4-23 15:38 | 只看该作者
IIC初始化不能通过,不知道为啥
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表