基于51单片机驱动BH1750采集光强度 LCD1602显示
时间: 2023-11-28 13:05:10 浏览: 113
BH1750数字光强度测试仪设计LCD1602显示51单片机C语言程序完整版.doc
以下是基于51单片机驱动BH1750采集光强度并在LCD1602显示的简单示例代码:
```c
#include <reg51.h> // 导入51单片机头文件
#include <intrins.h> // 导入延时函数头文件
#define SDA P2_1 // BH1750 SDA引脚连接的51单片机IO口
#define SCL P2_0 // BH1750 SCL引脚连接的51单片机IO口
#define ADDR 0x23 // BH1750设备地址,可根据实际情况修改
sbit RS = P1^0; // LCD1602 RS引脚连接的51单片机IO口
sbit RW = P1^1; // LCD1602 RW引脚连接的51单片机IO口
sbit EN = P1^2; // LCD1602 EN引脚连接的51单片机IO口
void init_iic(); // 初始化I2C总线函数
void iic_start(); // I2C总线起始信号函数
void iic_stop(); // I2C总线停止信号函数
void iic_write(unsigned char dat); // I2C总线写数据函数
unsigned char iic_read(); // I2C总线读数据函数
void delay_us(unsigned int us); // 延时函数(微秒级)
void init_lcd(); // 初始化LCD1602函数
void lcd_write_cmd(unsigned char cmd); // 向LCD1602写命令函数
void lcd_write_data(unsigned char dat); // 向LCD1602写数据函数
void lcd_set_pos(unsigned char row, unsigned char col); // 设置LCD1602光标位置函数
void lcd_display_str(char *str); // 在LCD1602上显示字符串函数
int main() {
unsigned int light_val; // 存储光强度值
init_iic(); // 初始化I2C总线
init_lcd(); // 初始化LCD1602
while (1) {
iic_start(); // I2C总线起始信号
iic_write(ADDR); // 向BH1750发送设备地址
iic_write(0x10); // 发送光强度测量模式指令
iic_stop(); // I2C总线停止信号
delay_us(15000); // 等待15ms,让BH1750完成光强度测量
iic_start(); // I2C总线起始信号
iic_write(ADDR | 0x01); // 向BH1750发送读命令
light_val = ((unsigned int)iic_read() << 8) | iic_read(); // 读取光强度值
iic_stop(); // I2C总线停止信号
lcd_set_pos(0, 0); // 设置LCD1602光标位置为第一行第一列
lcd_display_str("Light: "); // 在LCD1602上显示字符串“Light: ”
lcd_set_pos(0, 7); // 设置LCD1602光标位置为第一行第七列
lcd_write_data((light_val >> 8) + '0'); // 显示光强度值高8位
lcd_write_data((light_val & 0xFF) + '0'); // 显示光强度值低8位
lcd_display_str(" lx"); // 在LCD1602上显示字符串“ lx”
delay_us(500000); // 延时500ms
}
return 0;
}
void init_iic() {
SDA = 1; // SDA线拉高
SCL = 1; // SCL线拉高
}
void iic_start() {
SDA = 1; // SDA线拉高
SCL = 1; // SCL线拉高
_nop_(); // 延时
SDA = 0; // SDA线拉低
_nop_(); // 延时
SCL = 0; // SCL线拉低
}
void iic_stop() {
SDA = 0; // SDA线拉低
SCL = 1; // SCL线拉高
_nop_(); // 延时
SDA = 1; // SDA线拉高
_nop_(); // 延时
}
void iic_write(unsigned char dat) {
unsigned char i;
for (i = 0; i < 8; i++) { // 依次发送8个数据位
SDA = (dat & 0x80) ? 1 : 0; // 获取当前位的值,并将其写入SDA线
SCL = 1; // SCL线拉高
_nop_(); // 延时
SCL = 0; // SCL线拉低
dat <<= 1; // 移位,准备发送下一位数据
}
SDA = 1; // 发送完毕,SDA线拉高
SCL = 1; // SCL线拉高
_nop_(); // 延时
SCL = 0; // SCL线拉低
}
unsigned char iic_read() {
unsigned char i, dat = 0;
for (i = 0; i < 8; i++) { // 依次读取8个数据位
SCL = 1; // SCL线拉高
_nop_(); // 延时
dat <<= 1; // 移位,腾出一个位置
dat |= SDA; // 读取SDA线上的数据,并存储到dat变量中
SCL = 0; // SCL线拉低
}
return dat;
}
void delay_us(unsigned int us) {
while (us--);
}
void init_lcd() {
lcd_write_cmd(0x38); // 8位数据总线,2行显示,5x7点阵
lcd_write_cmd(0x0c); // 显示开,光标关,闪烁关
lcd_write_cmd(0x06); // 光标移动时,整个屏幕不移动
lcd_write_cmd(0x01); // 清屏
}
void lcd_write_cmd(unsigned char cmd) {
RS = 0; // 设置RS为0,表示写命令
RW = 0; // 设置RW为0,表示写数据
P0 = cmd; // 将命令写入P0口
EN = 1; // EN拉高
_nop_(); // 延时
EN = 0; // EN拉低
}
void lcd_write_data(unsigned char dat) {
RS = 1; // 设置RS为1,表示写数据
RW = 0; // 设置RW为0,表示写数据
P0 = dat; // 将数据写入P0口
EN = 1; // EN拉高
_nop_(); // 延时
EN = 0; // EN拉低
}
void lcd_set_pos(unsigned char row, unsigned char col) {
unsigned char pos;
if (row == 0) {
pos = 0x80 + col;
} else {
pos = 0xc0 + col;
}
lcd_write_cmd(pos); // 设置光标位置
}
void lcd_display_str(char *str) {
while (*str != '\0') { // 逐个字符显示
lcd_write_data(*str++);
}
}
```
需要注意的是,BH1750的SDA和SCL引脚连接的IO口需要设置为开漏输出模式,否则可能会导致I2C总线通信失败。另外,代码中的delay_us()函数需要根据实际情况调整延时时间,以保证BH1750完成光强度测量。
阅读全文