59 linux i2c设备驱动之dht12驱动
来源:互联网 发布:java字符串比较大小 编辑:程序博客网 时间:2024/06/14 07:23
dth12的工作模式除了单总线外,还可以使用i2c接口的工作模式.
dht12的引脚说明
//////////////////////////
上图说明dht12芯片内部有5个寄存器,寄存器地址从0x00 ~ 0x04, 分别存放湿度数据,温度数据,校验和
同时需要特别注意:上面说dht12的设备地址为0xB8, 此地址已是包含读写位了,通常设备址地址只是7位的. 所以dht12的i2c设备地址为0x5c.
///////////////////////
绿色的点为开始信号,红色的点为停止信号.
时序说明: 首先控制器发出开始信号, 接着发出0xB8(设备地址和读写位的写模式组成), 收到从机的应答信号后,再发出数据0(表示从地址为0x00的寄存器开始读),收到应答信号后,再接着重新发出开始信号, 应答后,再发出0xB9(设备地址和读组成), 收到应答后,接收从机发回的5上字节数据.最后发出停止信号.
//////////////////////////////////////////////////////
在linux内核里声明dht12设备, 设备名为”mydht12”, 设备地址为0x5c.
dht12的简单设备驱动:
test.c
#include <linux/init.h>#include <linux/module.h>#include <linux/i2c.h>int myprobe(struct i2c_client *cli, const struct i2c_device_id *id){ struct i2c_msg msg[2]; char addr = 0, data[5], i;//按dht12的读时序要求, 只需调用i2c_transfer函数一次, 和发出两条消息. printk("in myprobe ...%s, %x\n", id->name, id->driver_data); msg[0].addr = cli->addr; msg[0].flags = 0; msg[0].len = 1; msg[0].buf = &addr; //指定从地址为0x00的寄存器开始读 msg[1].addr = cli->addr; msg[1].flags = I2C_M_RD; //读 msg[1].len = 5; //共接收5字节数据 msg[1].buf = data; if (i2c_transfer(cli->adapter, msg, 2) < 0) return -ENODEV; for (i = 0; i < 5; i++) printk("%d ", data[i]); printk("\n"); return 0;}int myremove(struct i2c_client *cli){ printk("in myremove ...\n"); return 0;}struct i2c_device_id ids[] = { {"mydht12", 0x22}, {},};struct i2c_driver mydrv = { .probe = myprobe, .remove = myremove, .driver = { .name = "mydrv", .owner = THIS_MODULE, }, .id_table = ids,};module_i2c_driver(mydrv);MODULE_LICENSE("GPL");
/////////////////////////////////////////////////////////////////////////////////
加入字符设备接口的设备驱动代码:
test.c
#include <linux/init.h>#include <linux/module.h>#include <linux/i2c.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/mutex.h>#include <linux/slab.h>#include <linux/device.h>#define MYMA 1314#define COUNT 1typedef struct { struct mutex mutex; struct cdev cdev; struct i2c_client *cli; struct class *cls;}dht12_data_t;ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off){ struct cdev *cdev = fl->f_path.dentry->d_inode->i_cdev; dht12_data_t *data = container_of(cdev, dht12_data_t, cdev); int ret, sum, i; struct i2c_msg msgs[2]; char data_rcv[5], addr = 0; struct i2c_client *cli = data->cli; //上锁,防止重入 mutex_lock(&data->mutex); msgs[0].addr = cli->addr; msgs[0].flags = 0; msgs[0].len = 1; msgs[0].buf = &addr; msgs[1].addr = cli->addr; msgs[1].flags = I2C_M_RD; msgs[1].len = 5; msgs[1].buf = data_rcv; ret = i2c_transfer(cli->adapter, msgs, 2); if (ret != 2) goto out; //检查校验和 sum = 0; for (i = 0; i < 4; i++) sum += data_rcv[i]; if (sum != data_rcv[4]) { ret = -EINVAL; goto out; } sprintf(buf, "humi: %d.%d ; temp: %d.%d\n", data_rcv[0], data_rcv[1], data_rcv[2], data_rcv[3]); ret = strlen(buf);out: mutex_unlock(&data->mutex); return ret;}struct file_operations fops = { .owner = THIS_MODULE, .read = myread,};int myprobe(struct i2c_client *cli, const struct i2c_device_id *id){ static int mi = 0; //记录次设备号 dht12_data_t *data; dev_t devid; int ret; //注册设备号 devid = MKDEV(MYMA, mi); ret = register_chrdev_region(devid, COUNT, cli->name); if (ret < 0) goto err0; //准备每个匹配设备的数据 data = kzalloc(sizeof(*data), GFP_KERNEL); if (NULL == data) { ret = -ENOMEM; goto err1; } //字符设备初始化 cdev_init(&data->cdev, &fops); data->cdev.owner = THIS_MODULE; ret = cdev_add(&data->cdev, devid, COUNT); if (ret < 0) goto err2; //初始化互斥锁 mutex_init(&data->mutex); //创建设备文件 data->cls = class_create(THIS_MODULE, cli->name); device_create(data->cls, NULL, devid, NULL, "%s.%d", cli->name, mi++); data->cli = cli; i2c_set_clientdata(cli, data); //dev_set_drvdata(&cli->dev, data); return 0;err2: kfree(data);err1: unregister_chrdev_region(devid, COUNT);err0: return ret;}int myremove(struct i2c_client *cli){ dht12_data_t *data = i2c_get_clientdata(cli); //dev_get_drvdata(&cli->dev); //移除设备文件 device_destroy(data->cls, data->cdev.dev); class_destroy(data->cls); cdev_del(&data->cdev); unregister_chrdev_region(data->cdev.dev, COUNT); kfree(data); return 0;}struct i2c_device_id ids[] = { {"mykkk", 0x11}, {"mydht12", 0x22}, {},};struct i2c_driver mydrv = { .probe = myprobe, .remove = myremove, .driver = { .name = "mydrv", .owner = THIS_MODULE, }, .id_table = ids,};module_i2c_driver(mydrv);MODULE_LICENSE("GPL");
阅读全文
0 0
- 59 linux i2c设备驱动之dht12驱动
- linux设备驱动之I2C
- linux i2c设备驱动
- Linux I2C 设备驱动
- linux i2c设备驱动 .
- linux I2C设备驱动
- Linux 设备驱动 - I2C
- linux i2c设备驱动
- linux i2c设备驱动
- linux i2c设备驱动
- linux驱动-I2C设备
- Linux Kernel 设备驱动之I2C之i2c设备文件
- linux设备驱动之 i2c设备驱动 at24c08驱动程序分析
- Linux 设备驱动篇之-------I2c设备驱动(待续)
- Linux 设备驱动篇之I2c设备驱动
- Linux 设备驱动篇之I2c设备驱动
- Linux 设备驱动篇之-------I2c设备驱动(待续) .
- Linux 设备驱动篇之I2c设备驱动
- UVALive6886 Golf Bot[FFT]
- C#里WinForm开发中如何实现控件随窗体大小的改变而自动适应其改变
- HTTPS协议性能与优化
- 解决OneNote“未安装桌面体验功能”问题
- 抽象代数学习笔记(3)映射
- 59 linux i2c设备驱动之dht12驱动
- (1)Linux的初步了解
- 低延时的RTMP网络直播
- python自然语言处理 第四章基本语法
- maven-assembly-plugin打包插件配置
- 20年程序员的碎碎念
- android 获取其他应用程序的缓存大小以及清理应用缓存
- 二维码好高大尚,我也想生成一个
- 加固+多渠道打包+Bugly统计+热修复