1 #ifndef AP3216C_H
2 #define AP3216C_H
3/***************************************************************
4 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
5文件名 : ap3216creg.h
6作者 : 左忠凯
7版本 : V1.0
8描述 : AP3216C寄存器地址描述头文件
9其他 : 无
10论坛 : www.openedv.com
11日志 : 初版V1.0 2019/9/2 左忠凯创建
12 ***************************************************************/
13/* AP3316C寄存器 */
14 #define AP3216C_SYSTEMCONG 0x00 /* 配置寄存器 */
15 #define AP3216C_INTSTATUS 0X01 /* 中断状态寄存器 */
16 #define AP3216C_INTCLEAR 0X02 /* 中断清除寄存器 */
17 #define AP3216C_IRDATALOW 0x0A /* IR数据低字节 */
18 #define AP3216C_IRDATAHIGH 0x0B /* IR数据高字节 */
19 #define AP3216C_ALSDATALOW 0x0C /* ALS数据低字节 */
20 #define AP3216C_ALSDATAHIGH 0X0D /* ALS数据高字节 */
21 #define AP3216C_PSDATALOW 0X0E /* PS数据低字节 */
22 #define AP3216C_PSDATAHIGH 0X0F /* PS数据高字节 */
23
24 #endif
ap3216creg.h没什么好讲的,就是一些寄存器宏定义。然后在ap3216c.c输入如下内容:
示例代码61.5.2.2 ap3216c.c文件代码段
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include "ap3216creg.h"
19/***************************************************************
20 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
21文件名 : ap3216c.c
22作者 : 左忠凯
23版本 : V1.0
24描述 : AP3216C驱动程序
25其他 : 无
26论坛 : www.openedv.com
27日志 : 初版V1.0 2019/9/2 左忠凯创建
28 ***************************************************************/
29 #define AP3216C_CNT 1
30 #define AP3216C_NAME "ap3216c"
31
32struct ap3216c_dev {
33 dev_t devid; /* 设备号 */
34struct cdev cdev; /* cdev */
35struct class *class; /* 类 */
36struct device *device; /* 设备 */
37struct device_node *nd; /* 设备节点 */
38int major; /* 主设备号 */
39void*private_data; /* 私有数据 */
40unsignedshort ir, als, ps; /* 三个光传感器数据 */
41};
42
43staticstruct ap3216c_dev ap3216cdev;
44
45/*
46 * @description : 从ap3216c读取多个寄存器数据
47 * @param – dev : ap3216c设备
48 * @param – reg : 要读取的寄存器首地址
49 * @param – val : 读取到的数据
50 * @param – len : 要读取的数据长度
51 * @return : 操作结果
52 */
53staticint ap3216c_read_regs(struct ap3216c_dev *dev, u8 reg,
void*val,int len)
54{
55int ret;
56struct i2c_msg msg[2];
57struct i2c_client *client =(struct i2c_client *)
dev->private_data;
58
59/* msg[0]为发送要读取的首地址 */
60 msg[0].addr = client->addr; /* ap3216c地址 */
61 msg[0].flags =0; /* 标记为发送数据 */
62 msg[0].buf =® /* 读取的首地址 */
63 msg[0].len =1; /* reg长度 */
64
65/* msg[1]读取数据 */
66 msg[1].addr = client->addr; /* ap3216c地址 */
67 msg[1].flags = I2C_M_RD; /* 标记为读取数据 */
68 msg[1].buf = val; /* 读取数据缓冲区 */
69 msg[1].len = len; /* 要读取的数据长度 */
70
71 ret = i2c_transfer(client->adapter, msg,2);
72if(ret ==2){
73 ret =0;
74}else{
75 printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);
76 ret =-EREMOTEIO;
77}
78return ret;
79}
80
81/*
82 * @description : 向ap3216c多个寄存器写入数据
83 * @param – dev : ap3216c设备
84 * @param – reg : 要写入的寄存器首地址
85 * @param – val : 要写入的数据缓冲区
86 * @param – len : 要写入的数据长度
87 * @return : 操作结果
88 */
89static s32 ap3216c_write_regs(struct ap3216c_dev *dev, u8 reg,
u8 *buf, u8 len)
90{
91 u8 b[256];
92struct i2c_msg msg;
93struct i2c_client *client =(struct i2c_client *)
dev->private_data;
94
95 b[0]= reg; /* 寄存器首地址 */
96 memcpy(&b[1],buf,len); /* 将要写入的数据拷贝到数组b里面 */
97
98 msg.addr = client->addr; /* ap3216c地址 */
99 msg.flags =0; /* 标记为写数据 */
100
101 msg.buf = b; /* 要写入的数据缓冲区 */
102 msg.len = len +1; /* 要写入的数据长度 */
103
104return i2c_transfer(client->adapter,&msg,1);
105}
106
107/*
108 * @description : 读取ap3216c指定寄存器值,读取一个寄存器
109 * @param – dev : ap3216c设备
110 * @param – reg : 要读取的寄存器
111 * @return : 读取到的寄存器值
112 */
113staticunsignedchar ap3216c_read_reg(struct ap3216c_dev *dev,
u8 reg)
114{
115 u8 data =0;
116
117 ap3216c_read_regs(dev, reg,&data,1);
118return data;
119
120 #if0
121struct i2c_client *client =(struct i2c_client *)
dev->private_data;
122return i2c_smbus_read_byte_data(client, reg);
123 #endif
124}
125
126/*
127 * @description : 向ap3216c指定寄存器写入指定的值,写一个寄存器
128 * @param – dev : ap3216c设备
129 * @param – reg : 要写的寄存器
130 * @param – data : 要写入的值
131 * @return : 无
132 */
133staticvoid ap3216c_write_reg(struct ap3216c_dev *dev, u8 reg,
u8 data)
134{
135 u8 buf =0;
136 buf = data;
137 ap3216c_write_regs(dev, reg,&buf,1);
138}
139
140/*
141 * @description : 读取AP3216C的数据,读取原始数据,包括ALS,PS和IR,
142 * :同时打开ALS,IR+PS的话两次数据读取的间隔要大于112.5ms
143 * @param - ir : ir数据
144 * @param - ps : ps数据
145 * @param - ps : als数据
146 * @return : 无。
147 */
148void ap3216c_readdata(struct ap3216c_dev *dev)
149{
150unsignedchar i =0;
151unsignedchar buf[6];
152
153/* 循环读取所有传感器数据 */
154for(i =0; i <6; i++)
155{
156 buf= ap3216c_read_reg(dev, AP3216C_IRDATALOW + i);
157}
158
159if(buf[0]&0X80) /* IR_OF位为1,则数据无效 */
160 dev->ir =0;
161else /* 读取IR传感器的数据 */
162 dev->ir =((unsignedshort)buf[1]<<2)|(buf[0]&0X03);
163
164 dev->als =((unsignedshort)buf[3]<<8)| buf[2];/* ALS数据*/
165
166if(buf[4]&0x40) /* IR_OF位为1,则数据无效 */
167 dev->ps =0;
168else /* 读取PS传感器的数据 */
169 dev->ps =((unsignedshort)(buf[5]&0X3F)<<4)|
(buf[4]&0X0F);
170}
171
172/*
173 * @description : 打开设备
174 * @param – inode : 传递给驱动的inode
175 * @param - filp : 设备文件,file结构体有个叫做private_data的成员变量
176 * 一般在open的时候将private_data指向设备结构体。
177 * @return : 0 成功;其他失败
178 */
179staticint ap3216c_open(struct inode *inode,struct file *filp)
180{
181 filp->private_data =&ap3216cdev;
182
183/* 初始化AP3216C */
184 ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG,0x04);
185 mdelay(50); /* AP3216C复位最少10ms */
186 ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG,0X03);
187return0;
188}
189
190/*
191 * @description : 从设备读取数据
192 * @param – filp : 要打开的设备文件(文件描述符)
193 * @param - buf : 返回给用户空间的数据缓冲区
194 * @param - cnt : 要读取的数据长度
195 * @param – offt : 相对于文件首地址的偏移
196 * @return : 读取的字节数,如果为负值,表示读取失败
197 */
198static ssize_t ap3216c_read(struct file *filp,char __user *buf,
size_t cnt, loff_t *off)
199{
200short data[3];
201long err =0;
202
203struct ap3216c_dev *dev =(struct ap3216c_dev *)
filp->private_data;
204
205 ap3216c_readdata(dev);
206
207 data[0]= dev->ir;
208 data[1]= dev->als;
209 data[2]= dev->ps;
210 err = copy_to_user(buf, data,sizeof(data));
211return0;
212}
213
214/*
215 * @description : 关闭/释放设备
216 * @param - filp : 要关闭的设备文件(文件描述符)
217 * @return : 0 成功;其他失败
218 */
219staticint ap3216c_release(struct inode *inode,struct file *filp)
220{
221return0;
222}
223
224/* AP3216C操作函数 */
225staticconststruct file_operations ap3216c_ops ={
226.owner = THIS_MODULE,
227.open = ap3216c_open,
228.read = ap3216c_read,
229.release = ap3216c_release,
230};
231
232/*
233 * @description : i2c驱动的probe函数,当驱动与
234 * 设备匹配以后此函数就会执行
235 * @param - client : i2c设备
236 * @param - id : i2c设备ID
237 * @return : 0,成功;其他负值,失败
238 */
239staticint ap3216c_probe(struct i2c_client *client,
conststruct i2c_device_id *id)
240{
241/* 1、构建设备号 */
242if(ap3216cdev.major){
243 ap3216cdev.devid = MKDEV(ap3216cdev.major,0);
244 register_chrdev_region(ap3216cdev.devid, AP3216C_CNT,
AP3216C_NAME);
245}else{
246 alloc_chrdev_region(&ap3216cdev.devid,0, AP3216C_CNT,
AP3216C_NAME);
247 ap3216cdev.major = MAJOR(ap3216cdev.devid);
248}
249
250/* 2、注册设备 */
251 cdev_init(&ap3216cdev.cdev,&ap3216c_ops);
252 cdev_add(&ap3216cdev.cdev, ap3216cdev.devid, AP3216C_CNT);
253
254/* 3、创建类 */
255 ap3216cdev.class = class_create(THIS_MODULE, AP3216C_NAME);
256if(IS_ERR(ap3216cdev.class)){
257return PTR_ERR(ap3216cdev.class);
258}
259
260/* 4、创建设备 */
261 ap3216cdev.device = device_create(ap3216cdev.class,NULL,
ap3216cdev.devid,NULL, AP3216C_NAME);
262if(IS_ERR(ap3216cdev.device)){
263return PTR_ERR(ap3216cdev.device);
264}
265
266 ap3216cdev.private_data = client;
267
268return0;
269}
270
271/*
272 * @description : i2c驱动的remove函数,移除i2c驱动此函数会执行
273 * @param – client : i2c设备
274 * @return : 0,成功;其他负值,失败
275 */
276staticint ap3216c_remove(struct i2c_client *client)
277{
278/* 删除设备 */
279 cdev_del(&ap3216cdev.cdev);
280 unregister_chrdev_region(ap3216cdev.devid, AP3216C_CNT);
281
282/* 注销掉类和设备 */
283 device_destroy(ap3216cdev.class, ap3216cdev.devid);
284 class_destroy(ap3216cdev.class);
285return0;
286}
287
288/* 传统匹配方式ID列表 */
289staticconststruct i2c_device_id ap3216c_id[]={
290{"alientek,ap3216c",0},
291{}
292};
293
294/* 设备树匹配列表 */
295staticconststruct of_device_id ap3216c_of_match[]={
296{.compatible ="alientek,ap3216c"},
297{/* Sentinel */}
298};
299
300/* i2c驱动结构体 */
301staticstruct i2c_driver ap3216c_driver ={
302.probe = ap3216c_probe,
303.remove = ap3216c_remove,
304.driver ={
305.owner = THIS_MODULE,
306.name ="ap3216c",
307.of_match_table = ap3216c_of_match,
308},
309.id_table = ap3216c_id,
310};
311
312/*
313 * @description : 驱动入口函数
314 * @param : 无
315 * @return : 无
316 */
317staticint __init ap3216c_init(void)
318{
319int ret =0;
320
321 ret = i2c_add_driver(&ap3216c_driver);
322return ret;
323}
324
325/*
326 * @description : 驱动出口函数
327 * @param : 无
328 * @return : 无
329 */
330staticvoid __exit ap3216c_exit(void)
331{
332 i2c_del_driver(&ap3216c_driver);
333}
334
335/* module_i2c_driver(ap3216c_driver) */
336
337 module_init(ap3216c_init);
338 module_exit(ap3216c_exit);
339 MODULE_LICENSE("GPL");
340 MODULE_AUTHOR("zuozhongkai");