打印
[AT32M412]

【AT-START-M412测评】+光照强度传感器及其检测

[复制链接]
184|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 jinglixixi 于 2025-6-2 12:22 编辑

#申请原创#

BH1750是一款基于 I2C 接口的数字式环境光传感器,它适于获得环境光照强度的检测,受光学窗口的影响其检测最小为 0.11 lx,最大为 100000 lx。
该传感器的引脚定义如图1所示,它与开发板的连接关系为:
SCL ---PB8
SDA---PB9
为便于直观观察检测结果,由OLED进行显示,它与开发板的连接关系为:
SCL ---PA5
SDA---PA6


图1 引脚定义


图2 所用接口

为便于引脚的分配和使用,这里采用模拟I2C的方式来实现光照强度的检测。
配置所用引脚的函数为:
void BH1750_Init(void)
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_8|GPIO_PINS_9;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOB, &gpio_init_struct);
}

有别于OLED屏的显示驱动,在进行光照检测时,数据引脚既要工作在输出模式,也要工作在输入模式。
为此,需要配置相应的工作模式函数,以便进行工作模式切换。
设置为输入模式的函数为:
void IIC_INPUT_MODE_SET()
{
gpio_init_type gpio_init_struct;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_9;
gpio_init(GPIOB, &gpio_init_struct);
}

设置为输出模式的函数为:
void IIC_OUTPUT_MODE_SET()
{
  gpio_init_type gpio_init_struct;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_9;
  gpio_init(GPIOB, &gpio_init_struct);
}


设置引脚输出高低电平和检测引脚状态的语句定义为:
#define SCL_Set()       GPIOB->scr = GPIO_PINS_8
#define SCL_Clr()       GPIOB->clr = GPIO_PINS_8
#define SDA_Set()       GPIOB->scr = GPIO_PINS_9
#define SDA_Clr()       GPIOB->clr = GPIO_PINS_9
#define IIC_SDA_IN      gpio_input_data_bit_read(GPIOB, GPIO_PINS_9)

模拟I2C处理的辅助辅助函数如下:
void BH1750_Start()
{
IIC_OUTPUT_MODE_SET();
SDA_Set();
SCL_Set();
delay_us(5);
SDA_Clr();
delay_us(5);
SCL_Clr();
}

void BH1750_Stop()
{
IIC_OUTPUT_MODE_SET();
SDA_Clr();
SCL_Set();
delay_us(5);
SDA_Set();
delay_us(5);
}

void BH1750_SendACK(char ack)
{
IIC_OUTPUT_MODE_SET();
SCL_Clr();
if(ack)
{
SDA_Set();
}
else
{
SDA_Clr();
}
delay_us(2);
SCL_Set();
delay_us(5);
SCL_Clr();
}

char BH1750_RecvACK()
{
int cnt=0;
IIC_OUTPUT_MODE_SET();
SDA_Set();
delay_us(1);
SCL_Set();
IIC_INPUT_MODE_SET();
delay_us(1);
while(IIC_SDA_IN)
{
cnt++;
delay_us(1);
if(cnt>=250)
{
BH1750_Stop();
return 1;
}
}
SCL_Clr();
return 0;
}

模拟I2C发送字节数据的函数为:
void BH1750_SendByte(char data)
{
char i;
IIC_OUTPUT_MODE_SET();
SCL_Clr();
delay_us(2);
for (i=0;i<8;i++)
{
if(data&0x80)
{
SDA_Set();
}
else
{
SDA_Clr();
}
data <<= 1;
SCL_Set();
delay_us(2);
SCL_Clr();
delay_us(2);
}
}

模拟I2C读取字节数据的函数为:
char BH1750_RecvByte()
{
char i;
char data = 0;
IIC_INPUT_MODE_SET();
for (i=0;i<8;i++)
{
SCL_Clr();
delay_us(2);
SCL_Set();
data <<= 1;
SCL_Set();
if(IIC_SDA_IN) data|=0x01;
delay_us(2);
}
SCL_Clr();
return data;
}

写入寄存器地址的函数为:
void Single_Write_BH1750(char REG_Address)
{
BH1750_Start();
BH1750_SendByte(SlaveAddress);
BH1750_RecvACK();
BH1750_SendByte(REG_Address);
BH1750_RecvACK();
BH1750_Stop();
}

读取BH1750多字节数据的函数为:
void Multiple_Read_BH1750()
{
BH1750_Start();
BH1750_SendByte(SlaveAddress+1);
BH1750_RecvACK();
BUF[0] = BH1750_RecvByte();
BH1750_SendACK(0);
BUF[1] = BH1750_RecvByte();
BH1750_SendACK(1);
BH1750_Stop();
delay_ms(5);
}

实现光强检测与显示的函数为:
void Get_Sunlight_Value()
{
int dis_data=0;
float temp;
char i=0;
unsigned int sd;
Single_Write_BH1750(0x01);
Single_Write_BH1750(0x10);
delay_ms(180);
Multiple_Read_BH1750();
for(i=0;i<3;i++)dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1];
temp=(float)dis_data/1.2;
sd=temp;
OLED_ShowNum(20,2,sd,5,16);
}

实现光强检测与显示的主程序为:
int main(void)
{
system_clock_config();
at32_board_init();
oled_config();
OLED_Init();
OLED_Clear();
OLED_ShowString(0,0,"AT32M412",16);
OLED_ShowString(0,2,"L=",16);
BH1750_Init();
while(1)
{
at32_led_toggle(LED2);
delay_ms(200);
at32_led_toggle(LED3);
delay_ms(200);
at32_led_toggle(LED4);
delay_ms(200);
Get_Sunlight_Value();
}
}

经程序的编译和下载,其检测结果如图4所示。

图3 连接形式


图4 检测结果



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

489

主题

2864

帖子

38

粉丝