本帖最后由 中科院 于 2015-6-24 20:29 编辑
大家可以先看看这两张图
在linux系统下编写I2C驱动,目前主要有两种方法 ,一种是把I2C设备当作一个普通的字符设备来处理 ,另一种是利用linux下I2C驱动体系结构来完成 。下面比较下这两种方法:
第一种方法:
优点:思路比较直接,不需要花很多时间去了解linux中复杂的I2C子系统的操作方法。
缺点 :
要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器(I2C控制器)操作。
要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写出的程序可以移植性差。
对内核的资源无法直接使用,因为内核提供的所有I2C设备器以及设备驱动都是基于I2C子系统的格式。
第一种方法的优点就是第二种方法的缺点,
第一种方法的缺点就是第二种方法的优点。
接着我们上一个帖子谈,有了上面两张图,就显得更加清晰:
stati c int myir_stlm75x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
struct myir_stlm75x_data *pdata = NULL;
printk(KERN_ALERT "%s()n", __func__);
pdata = kmalloc(sizeof(struct myir_stlm75x_data), GFP_KERNEL);
if(!pdata) {
printk(KERN_ERR "No memory!n");
return -ENOMEM;
}
memset(pdata, 0, sizeof(struct myir_stlm75x_data));
pdata->client = client;
/* Init class */
mutex_init(&pdata->mutex);
pdata->class.name = DEV_NAME;
pdata->class.owner = THIS_MODULE;
pdata->class.class_attrs = myir_stlm75x_class_attrs;
ret = class_register(&pdata->class);
if(ret) {
printk(KERN_ERR "class_register failed!n");
goto class_register_fail;
}
i2c_set_clientdata(client, pdata);
//将设备的数据结构挂到i2c_client.dev->p->driver_data下
printk(KERN_ALERT "%s driver initialized successfully!n", DEV_NAME);
return 0;
class_register_fail:
return ret;
}
/* Attributes declaration: Here I have declared only one attribute attr1 */
static struct class_attribute myir_stlm75x_class_attrs[] = {
__ATTR(value_degree, S_IRUGO | S_IWUSR , myir_stlm75x_show, NULL), //use macro for permission
__ATTR_NULL
};
不过有一点本人还是不太理解,Linux早就提供了对于LM75设备的支持,而且我看了Z-TURN上面的datasheet,感觉可以不必要写这额外的一个驱动的?不过Kevin Su 真的是没有多余的代码。我一直感觉,自己写代码要比读别人的代码容易,读他人的代码又是太多不好,太少也无法读,AI领域的代码就是一个很好的例子。
不多说了。读取温度的代码就容易多了:
#include
#include
#include
#include
#include
#define TEMP_FILE "/sys/class/myir-stlm75x/value_degree"
#define ERR_MSG(fmt, args...) fprintf(stderr, fmt, ##args)
#define DBG_MSG(fmt, args...) fprintf(stdout, fmt, ##args)
#define READ_DELAY_US (100*1000) /* 100 ms */
int main(int argc, const char *argv[])
{
int ret = -1, fd = -1;
char degree_str[64] = {0};
/* Open device */
fd = open(TEMP_FILE, O_RDONLY);
if ( fd < 0) {
ERR_MSG("open %s failed!n", TEMP_FILE);
return fd;
}
/* endless loop to read temperature */
for (;;) {
/* Set the read/write pos to the beginning */
lseek(fd, 0, SEEK_SET);
这里就不多说了。其中3轴加速度计等等的I2C通信 设备也是类似的操作过程,
把它作为一个字符文件就可以了。
板卡上面的I2C设备的学习笔记,记录过程就到此,接下来我会转战与PL通信的部分
回帖 (1)
2016-12-23 14:50:20
向你学习
向你学习
举报
更多回帖