linux i2c 内核初始io,【正点原子Linux连载】第六十一章Linux I2C驱动实验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南 (amobbs.com 阿莫电子论坛)...

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");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值