和县网站定制,wordpress菜单教程,论坛网站制作模板,优秀的平面广告设计DHT11的通信协议是单总线协议#xff0c;可以用之前学习的pinctl和gpio子系统完成某IO引脚上数据的读与写。 一.在设备树下添加dht11的设备结点
1.流程图 2.设备树代码
#xff08;1#xff09;.在设备树的 iomuxc结点下添加 pinctl_dht11 #xff08;2#xff09;.在根… DHT11的通信协议是单总线协议可以用之前学习的pinctl和gpio子系统完成某IO引脚上数据的读与写。 一.在设备树下添加dht11的设备结点
1.流程图 2.设备树代码
1.在设备树的 iomuxc结点下添加 pinctl_dht11 2.在根节点下添加 dht11 结点 3.在内核源码根目录下重新编译设备树文件
linuxubuntu:~/IMX6ULL/my_linux_kernel$ make dtbs
4.将新的 dtb 文件更新到开发板上检查是否有 dht11 这个结点 启动后在/proc/device-tree/目录中查看是否有 dht11 这个节点。
二.编写 dht11 时序代码
#define DHT11_DelayMs(t) mdelay(t)
#define DHT11_DelayUs(t) udelay(t) #define DHT11_PIN_HIGH 1
#define DHT11_PIN_LOW 0 #define DHT11_IO_OUT() gpio_direction_output(dht11.dht11_gpio, 1);
#define DHT11_IO_IN() gpio_direction_input(dht11.dht11_gpio)
#define DHT11_WRITE(bit) gpio_set_value(dht11.dht11_gpio, bit)
#define DHT11_READ() gpio_get_value(dht11.dht11_gpio)/*** description: 等待响应
*/
//等待响应
static int dht11_wait_for_ready(void)
{ int timeout;timeout 400;while (DHT11_READ() timeout) // 等待低电平到来 {udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout1 %d\n, __LINE__);return -1; // 超时 }timeout 1000; //1000while (!DHT11_READ() timeout) // 等待高电平到来 {udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout2 %d\n, __LINE__);return -1; // 超时 }timeout 1000;while (DHT11_READ() timeout) // 等待高电平结束{udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout3 %d\n, __LINE__);return -1; // 超时 }return 0;
}/*** description: 起始信号
*/
static int dht11_start(void)
{DHT11_IO_OUT();DHT11_WRITE(0);mdelay(25);DHT11_WRITE(1);udelay(35);DHT11_IO_IN(); // 设置为输入 udelay(2);if (dht11_wait_for_ready()) return -1;return 0;
}/*** description: 读取一个字节
*///读取数据
static int dht11_read_byte(unsigned char *byte)
{unsigned char i;unsigned char bit 0;unsigned char data 0;int timeout 0; for (i 0; i 8; i){timeout 1000; while (DHT11_READ() timeout) // 等待变为低电平 {udelay(1);--timeout;}if (!timeout) {printk(dht11_read_byte timeout1 %d\n, __LINE__); return -1; // 超时 }timeout 1000;while (!DHT11_READ() timeout) // 等待变为高电平 {udelay(1);--timeout;}if (!timeout) {printk(dht11_read_byte timeout2 %d\n, __LINE__);return -1; // 超时 }udelay(40);bit DHT11_READ();data 1; if (bit) {data | 0x01;}}*byte data;return 0;
}//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值0,正常;1,读取失败
static int dht11_read_data(void)
{ unsigned char data[5] {0};int i 0,ret 0;// 启动信号 if (dht11_start() ! 0){printk(dht11 start failed\n);ret -EFAULT;}// 读出5字节数据for (i 0; i 5; i) {if (dht11_read_byte(data[i])){printk(read data err\n);ret -EAGAIN;}}if (data[4] ! (data[0]data[1]data[2]data[3])){printk(check data failed\n);ret -EAGAIN;}dht11.humidity data[0];dht11.temperature data[2];return 0;
} 三.总的驱动代码
1.流程图 2.代码
#include linux/types.h
#include linux/kernel.h
#include linux/delay.h
#include linux/ide.h
#include linux/init.h
#include linux/module.h
#include linux/errno.h
#include linux/gpio.h
#include linux/cdev.h
#include linux/device.h
#include linux/of.h
#include linux/of_address.h
#include linux/of_gpio.h
#include linux/semaphore.h
#include asm/mach/map.h
#include linux/timer.h
#include asm/uaccess.h
#include asm/io.h#define DHT11_CNT 1
#define DHT11_NAME dht11#define DHT11_DelayMs(t) mdelay(t)
#define DHT11_DelayUs(t) udelay(t) #define DHT11_PIN_HIGH 1
#define DHT11_PIN_LOW 0 #define DHT11_IO_OUT() gpio_direction_output(dht11.dht11_gpio, 1);
#define DHT11_IO_IN() gpio_direction_input(dht11.dht11_gpio)
#define DHT11_WRITE(bit) gpio_set_value(dht11.dht11_gpio, bit)
#define DHT11_READ() gpio_get_value(dht11.dht11_gpio)/* dht11设备结构体 */
struct dht11_dev
{dev_t devid;struct cdev cdev;struct class *class;struct device *device;int major;int minor;struct device_node *nd;int dht11_gpio;uint16_t humidity, temperature; //检测到的温湿度数据
};struct dht11_dev dht11;/*** description: 等待响应
*/
//等待响应
static int dht11_wait_for_ready(void)
{ int timeout;timeout 400;while (DHT11_READ() timeout) // 等待低电平到来 {udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout1 %d\n, __LINE__);return -1; // 超时 }timeout 1000; //1000while (!DHT11_READ() timeout) // 等待高电平到来 {udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout2 %d\n, __LINE__);return -1; // 超时 }timeout 1000;while (DHT11_READ() timeout) // 等待高电平结束{udelay(1);--timeout;}if (!timeout) {printk(dht11_wait_for_ready timeout3 %d\n, __LINE__);return -1; // 超时 }return 0;
}/*** description: 起始信号
*/
static int dht11_start(void)
{DHT11_IO_OUT();DHT11_WRITE(0);mdelay(25);DHT11_WRITE(1);udelay(35);DHT11_IO_IN(); // 设置为输入 udelay(2);if (dht11_wait_for_ready()) return -1;return 0;
}/*** description: 读取一个字节
*///读取数据
static int dht11_read_byte(unsigned char *byte)
{unsigned char i;unsigned char bit 0;unsigned char data 0;int timeout 0; for (i 0; i 8; i){timeout 1000; while (DHT11_READ() timeout) // 等待变为低电平 {udelay(1);--timeout;}if (!timeout) {printk(dht11_read_byte timeout1 %d\n, __LINE__); return -1; // 超时 }timeout 1000;while (!DHT11_READ() timeout) // 等待变为高电平 {udelay(1);--timeout;}if (!timeout) {printk(dht11_read_byte timeout2 %d\n, __LINE__);return -1; // 超时 }udelay(40);bit DHT11_READ();data 1; if (bit) {data | 0x01;}}*byte data;return 0;
}//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值0,正常;1,读取失败
static int dht11_read_data(void)
{ unsigned char data[5] {0};int i 0,ret 0;// 启动信号 if (dht11_start() ! 0){printk(dht11 start failed\n);ret -EFAULT;}// 读出5字节数据for (i 0; i 5; i) {if (dht11_read_byte(data[i])){printk(read data err\n);ret -EAGAIN;}}if (data[4] ! (data[0]data[1]data[2]data[3])){printk(check data failed\n);ret -EAGAIN;}dht11.humidity data[0];dht11.temperature data[2];return 0;
}/*** description: DHT11初始化函数
*/
static int dht11io_init(void)
{/* 找到设备树中的结点 */dht11.nd of_find_node_by_path(/dht11);if(NULL dht11.nd){return -EINVAL;}/* 获取io编号 */dht11.dht11_gpio of_get_named_gpio(dht11.nd,dht11-gpio,0);if(0 dht11.dht11_gpio){printk(can not get dht11 io\r\n);return -EINVAL;}printk(dht11 gpio num %d \r\n,dht11.dht11_gpio);/* 初始化io */gpio_request(dht11.dht11_gpio,dht11a);gpio_direction_output(dht11.dht11_gpio,1); //初始化为输出高电平return 0;
}/*** description: 打开DHT11设备* param - inode : 传递给驱动的inode* param - filp : 设备文件* return : 0 成功其他 失败
*/
static int dht11_open(struct inode *inode,struct file *filp)
{int ret 0;filp-private_data dht11;ret dht11io_init();if(0 ret){return ret;}return 0;
}/*** description: 读取dht11的数据* param - filp : 文件描述符* param - buf : 传递给用户空间的缓冲区* param - cnt : 要读取的字节数* param - offt : 相对于文件首地址的偏移量* return : 读取到的字节数
*/
static ssize_t dht11_read(struct file *filp,char __user *buf,size_t cnt,loff_t *offt)
{int ret 0;uint16_t databuf[2] {0,0};dht11_read_data();databuf[0] dht11.humidity;databuf[1] dht11.temperature;ret copy_to_user(buf,databuf,sizeof(databuf));return ret;
}/*** description: 释放设备* param - filp : 设备文件* return : 0 成功其他 失败
*/
static int dht11_release(struct inode *inode,struct file *filp)
{return 0;
}/* 绑定操作函数 */
struct file_operations dht11_fops
{.owner THIS_MODULE,.open dht11_open,.read dht11_read,.release dht11_release,
};/*** description: 驱动入口函数* param - : 无* return : 无
*/
static int __init dht11_init(void)
{/* 注册字符设备驱动 *//* 1.创建设备号 */if(dht11.major){dht11.devid MKDEV(dht11.major,0);register_chrdev_region(dht11.devid,DHT11_CNT,DHT11_NAME);}else{alloc_chrdev_region(dht11.devid,0,DHT11_CNT,DHT11_NAME);dht11.major MAJOR(dht11.devid);dht11.minor MINOR(dht11.devid);}printk(dht11 major %d,minor %d\r\n,dht11.major,dht11.minor);/* 2.初始化cdev */dht11.cdev.owner THIS_MODULE;cdev_init(dht11.cdev,dht11_fops);/* 3.添加一个cdev */cdev_add(dht11.cdev,dht11.devid,DHT11_CNT);/* 4.创建类 */dht11.class class_create(THIS_MODULE,DHT11_NAME);if(IS_ERR(dht11.class)){return PTR_ERR(dht11.class);}/* 5.创建设备 */dht11.device device_create(dht11.class,NULL,dht11.devid,NULL,DHT11_NAME);if(IS_ERR(dht11.device)){return PTR_ERR(dht11.device);}return 0;
}/*** description: 驱动出口函数
*/
static void __exit dht11_exit(void)
{/* 注销字符设备驱动 */gpio_free(dht11.dht11_gpio);cdev_del(dht11.cdev);unregister_chrdev_region(dht11.devid,DHT11_CNT);device_destroy(dht11.class,dht11.devid);class_destroy(dht11.class);
}module_init(dht11_init);
module_exit(dht11_exit);
MODULE_LICENSE(GPL);
MODULE_AUTHOR(kaneki); Makefile
KERNELDIR : /home/linux/IMX6ULL/my_linux_kernel
CURRENT_PATH :$(shell pwd)
obj-m : dht11.o
build: kernel_modules
kernel_modules:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) modules
clean:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean