代码示例_i2c读写e2prom驱动


  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/i2c.h>
  4 #include <linux/miscdevice.h>
  5 #include <linux/delay.h>
  6 #include <linux/fs.h>
  7 #include <linux/device.h>
  8 
  9 
 10 //声明一个i2c client指针--保存probe中的i2c client
 11 static struct i2c_client *at24_client;
 12 static struct miscdevice  e2prom_misc;
 13 
 14 
 15 //重写类似于i2c_master_send()/i2c_master_recv()
 16 int at24_i2c_send(struct i2c_client *client, char *buf, int count)
 17 {
 18     int ret;
 19     
 20     struct i2c_adapter *adapter = client->adapter;
 21     struct i2c_msg msg;
 22     
 23     msg.addr = client->addr;
 24     msg.flags = 0; //读1还是写0
 25     msg.len = count; 
 26     msg.buf = buf;
 27     //参数1---适配器--来自于i2c client 
 28     //参数2--数据包
 29     //参数3--数据包的个数
 30     //返回值--正确返回消息的个数,错误返回负数
 31     ret = i2c_transfer(adapter, &msg, 1);
 32 
 33     return ret==1?count:ret;
 34     
 35 }
 36 
 37 int at24_i2c_recv(struct i2c_client *client, char *buf, int count)
 38 {
 39     int ret;
 40     
 41     struct i2c_adapter *adapter = client->adapter;
 42     struct i2c_msg msg;
 43     
 44     msg.addr = client->addr;
 45     msg.flags = 1; //读1还是写0
 46     msg.len = count; 
 47     msg.buf = buf;
 48     //参数1---适配器--来自于i2c client 
 49     //参数2--数据包
 50     //参数3--数据包的个数
 51     //返回值--正确返回消息的个数,错误返回负数
 52     ret = i2c_transfer(adapter, &msg, 1);
 53 
 54     return ret==1?count:ret;
 55 
 56 }
 57 
 58 
 59 const struct file_operations at24_fops = {
 60 
 61 
 62 };
 63 
 64 
 65 int at24_drv_probe(struct i2c_client *client, const struct i2c_device_id *id)
 66 {
 67 
 68     printk("id->name = %s, id->driver_data = 0x%x
", id->name, id->driver_data);
 69 
 70     // 0- 保存i2c_client 
 71     at24_client = client;
 72 
 73     // 1, 与用户交互
 74     e2prom_misc.name = "at24_dev";
 75     e2prom_misc.minor = MISC_DYNAMIC_MINOR,
 76     e2prom_misc.fops = &at24_fops,
 77     misc_register(&e2prom_misc);
 78 
 79     // 2, 与硬件交互(初始化硬件)--最终委托i2c adpater层与硬件打交道
 80     // e2prom上电就能工作,并不需要特定一些初始化
 81     //以下代码主要演示如何操作从设备
 82 
 83 
 84     int ret;
 85     
 86     char sendbuf[10] = {0x8/*写的地址*/, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, 0x8b, 0x9b};
 87 
 88     ret = at24_i2c_send(client, sendbuf, 10);
 89     if(ret < 0)
 90     {
 91         printk("at24_i2c_send error
");
 92         misc_deregister(&e2prom_misc);
 93         return ret;
 94     }
 95 
 96     mdelay(3);
 97     //验证是否写入正确
 98     //先写地址
 99     char addr  = 0x8;
100     ret = at24_i2c_send(client, &addr, 1);
101     if(ret < 0)
102     {
103         printk("at24_i2c_send error
");
104         misc_deregister(&e2prom_misc);
105         return ret;
106     }
107     char recvbuf[8];
108     ret = at24_i2c_recv(client, recvbuf, 8);
109     if(ret < 0)
110     {
111         printk("at24_i2c_recv error
");
112         misc_deregister(&e2prom_misc);
113         return ret;
114     }
115     int i;
116     for(i=0; i<8; i++)
117         printk("recvbuf[%d] = 0x%x
", i, recvbuf[i]);
118     
119     
120     return 0;
121 
122     
123 }
124 
125 
126 
127 int at24_drv_remove(struct i2c_client *client)
128 {
129     misc_deregister(&e2prom_misc);
130     
131     return 0;
132 }
133 
134 
135 
136 const struct i2c_device_id at24_id_table[] = {
137         {"at24c02", 0x2},
138         {"at24c04", 0x4},
139         {"at24c08", 0x5},
140         {"at24c16", 0x6},
141         {},
142 };
143 
144 
145 struct i2c_driver at24_i2c_drv = {
146     .probe = at24_drv_probe,
147     .remove = at24_drv_remove,
148     .driver = {
149         .name = "at24_drv", //一定要有--/sys/bus/i2c/drivers/at24_drv
150     },
151     .id_table = at24_id_table,
152 
153 };
154 
155 
156 static int __init at24_i2c_drv_init(void)
157 {
158 
159     //注册一个i2c driver 
160     return i2c_add_driver(&at24_i2c_drv);
161     
162 
163 }
164 
165 static void __exit at24_i2c_drv_exit(void)
166 {
167     i2c_del_driver(&at24_i2c_drv);
168 }
169 
170 
171 late_initcall(at24_i2c_drv_init);
172 module_exit(at24_i2c_drv_exit);
173 MODULE_LICENSE("GPL");

CROSS_COMPILE = arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc

#指定内核源码路径
KERNEL_DIR = /home/kernel/linux-3.0.8
CUR_DIR = $(shell pwd)

#MYAPP = plat_led_app

MODULE = at24_i2c_drv

all:
    #让make进入内核源码编译,同时将当前目录中的c程序作为内核模块一起编译
    make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
ifneq ($(MYAPP), )    
    $(CC)  -o $(MYAPP) $(MYAPP).c
endif

clean:
    #删除上面编译生成的文件
    make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
    rm -rf $(MYAPP)

install:
    cp *.ko $(MYAPP) /opt/rootfs/drv_module

#指定当前目录下哪个文件作为内核模块编
obj-m += $(MODULE).o

Stay hungry, stay foolish 待续。。。
原文地址:https://www.cnblogs.com/panda-w/p/10950008.html