linux驱动 -- IICBH1750
1:linux下的IIC
linux中最重要的思想就是分层思想,一般开发者对接的是中间层也就是接口,linux不关注底层,这个底层一般是内核与厂家联合初始化的。
通过设备树提供IIC信息,然后再提供一些接口
在驱动结构体中:厂商提供IIC的信息,再匹配设备树提供的信息,会自动去匹配对应的设备文件。
2:linux下的IIC的中间层接口
linux下的IIC接口是平台设备总线类型的,需要注册驱动信息,从而匹配设备信息
2.1 接口函数
头文件:
#include "linux/i2c.h"
IIC的驱动的信息注册函数:
int i2c_add_driver(struct i2c_driver *driver)
函数功能:
向内核注册IIC 驱动信息,主要是去匹配设备树的IIC信息。
函数参数:
driver:
注册内核I2C设备信息,主要对应的是入口、出口、匹配信息
struct i2c_driver {//匹配函数int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);int (*probe_new)(struct i2c_client *client);//注销函数int (*remove)(struct i2c_client *client);struct device_driver driver{const char *name;//一般填写const struct of_device_id *of_match_table;//匹配 compatible }const struct i2c_device_id *id_table{char name[I2C_NAME_SIZE];} }
返回值:
成功返回 0
失败返回 非0
匹配成功后的probe(struct i2c_client * client)
其中的信息结构体:
struct i2c_client {unsigned short addr;//设备树传递过来的从机地址!struct i2c_adapter *adapter;//他就是 IICx 的抽象的内核结构体//有了他 你就可以任意的操作内核 IIC 了!//有了它你就可以调用 i2c_transfer//做数据的读写收发了! }
函数功能:用于内核层的IIC的读写
函数原型:
int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs,int num );
函数的参数:
adapt:IIC的抽象结构体
msgs:
struct i2c_msg {__u16 addr; //从机地址__u16 flags;//标志 : 0/1 -> 写 / 读__u16 len; //读写的数据长度__u8 *buf;//读写缓冲区 }
num:有结果msg需要发送。
3:BH1750
3.1: BH1750 介绍

3.2 核心信息
从机地址:
两种从机地址可以选择
默认我们没有接 ADDR: 0100011 = 0x23
工作流程:
设置 BH1750 的工作模式
写入 BH1750 指令 0x11(高分辨率模式 2), 产生停止
等待 180ms->BH1750 就开始以这个模式正常工作
BH1750 不断采集外部光照数据给主机返回
主机每隔 120ms 找从机要一次数据即可
注意返回的数据是 16bit
工作模式:
4:IIC驱动BH1750设备代码示例
//bh1750光照传感器
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/of.h"
#include "linux/cdev.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/of_gpio.h"
#include "linux/device/class.h"
#include "linux/device.h"
#include "linux/platform_device.h"
#include "linux/miscdevice.h"
#include "asm/uaccess.h"
#include "linux/irq.h"
#include "linux/interrupt.h"
#include "linux/sched.h"
#include "linux/wait.h"
#include "linux/i2c.h"
#include "linux/delay.h"
struct i2c_client * bh1750_client;
struct miscdevice *misc;
struct file_operations *fops;
struct i2c_adapter *adap;
int bh1750_open (struct inode * ind, struct file *file)
{//初始化bh1750发送0X10// i2c_smbus_write_block_data();uint8_t cmd =0x10;struct i2c_msg msgs;msgs.addr = bh1750_client->addr;//从机地址msgs.buf = &cmd;msgs.len =1;msgs.flags = 0;//代表写入数据int rem = i2c_transfer(bh1750_client->adapter,&msgs,1);mdelay(200);//延时200msrem =rem;return 0;
}
int bh1750_close (struct inode * ind, struct file *file)
{return 0;
}
ssize_t bh1750_read (struct file * fil, char __user * buff, size_t size, loff_t * lof)
{//读取从机的数据//返回的数据是16bit的uint8_t readbuf[2] ={0};uint16_t value;struct i2c_msg msgs;msgs.addr = bh1750_client->addr;msgs.buf = readbuf;msgs.len = 2;msgs.flags = 1;int rem = i2c_transfer(bh1750_client->adapter,&msgs,1);value = readbuf[0]<<8 | readbuf[1];int ret = copy_to_user(buff,&value,2);ret =0;rem =rem;return 0;
}int bh1750_probel(struct i2c_client *client)
{printk("检测到信息\r\n");bh1750_client = client;// node= dev->dev.of_node;//承接设备树信息//注册杂项设备misc = kzalloc(sizeof(struct miscdevice),GFP_KERNEL);fops = kzalloc(sizeof(struct file_operations),GFP_KERNEL);fops->open = bh1750_open;fops->owner = THIS_MODULE;fops->release = bh1750_close;fops->read = bh1750_read;misc->minor = 255;misc->name = "xyd_bh1750";misc->fops = fops;return misc_register(misc);
}struct of_device_id id_tible={.compatible = "xydbh1750",//匹配名字
};struct i2c_driver bh1750_driver = {.probe_new = bh1750_probel,.driver = {.name = "xyd_bh1750",.of_match_table = &id_tible,},
};
//加载函数
static int __init bh1750_init(void)
{//添加设备树i2c_add_driver(&bh1750_driver);// platform_driver_register(&bh1750);return 0;
}
static void __exit bh1750_exit(void)
{// platform_driver_unregister(&bh1750);
}
module_init(bh1750_init);
module_exit(bh1750_exit);
MODULE_LICENSE("GPL");