当前位置: 首页 > wzjs >正文

深圳网站建设公司联华网址之家大全

深圳网站建设公司联华,网址之家大全,网站开发人员 工资,网页设计实验总结100字文章目录 一、编译替换内核和设备树二、DHT11 温湿度传感器1. DHT11 简介2. 数据格式3. 编程思路 三、驱动代码1. GPIO 实现1.1 驱动层代码1.2 应用层代码 2. 设备树实现2.1 修改设备树2.2 驱动层代码2.3 应用层代码 3. 上机测试 一、编译替换内核和设备树 在编译驱动程序之前…

文章目录

  • 一、编译替换内核和设备树
  • 二、DHT11 温湿度传感器
    • 1. DHT11 简介
    • 2. 数据格式
    • 3. 编程思路
  • 三、驱动代码
    • 1. GPIO 实现
      • 1.1 驱动层代码
      • 1.2 应用层代码
    • 2. 设备树实现
      • 2.1 修改设备树
      • 2.2 驱动层代码
      • 2.3 应用层代码
    • 3. 上机测试

一、编译替换内核和设备树

在编译驱动程序之前要先编译内核,原因有三点:

  • 驱动程序要用到内核文件
  • 编译驱动时用的内核、开发板上运行到内核,要一致
  • 更换板子上的内核后,板子上的其他驱动也要更换

编译内核步骤看我之前写过的文章:

  • 编译替换内核_设备树_驱动_IMX6ULL

二、DHT11 温湿度传感器

1. DHT11 简介

DHT11 是一款可测量温度和湿度的传感器。比如市面上一些空气加湿器,会测量空气中湿度,再根据测量结果决定是否继续加湿。
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,具有超小体积、极低功耗的特点,使用单根总线与主机进行双向的串行数据传输。DHT11测量温度的精度为±2℃,检测范围为-20℃-60℃。湿度的精度为±5%RH,检测范围为5%RH-95%RH,常用于对精度和实时性要求不高的温湿度测量场合。
在这里插入图片描述
DHT11 的硬件电路比较简单,核心要点就是 主机发给 DHT11 的命令格式和 DHT11 返回的数据格式。

2. 数据格式

8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和。
通讯过程时序图:
在这里插入图片描述
检测模块是否存在:需要先发一个开始信号给DHT11,才能接收数据。
在这里插入图片描述

3. 编程思路

知道 DHT11 传感器的数据格式后就可以开始编写程序了。
编程思路如下:

  • 设置GPIO;
  • 主机把 GPIO 设为输出引脚,发送开始信号,然后把 GPIO 设置为输入引脚;
  • 主机判断是否收到 DHT11 的回应信号;
  • 接收到回应信号后,开始读取数据;

三、驱动代码

1. GPIO 实现

1.1 驱动层代码

dht11_drv.c

#include <linux/delay.h>
#include <linux/ktime.h>#include <linux/module.h>
#include <linux/poll.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>struct gpio_desc{int gpio;int irq;char *name;int key;struct timer_list key_timer;
} ;static struct gpio_desc gpios[] = {{115, 0, "gpio_dht11", },
};/* 主设备号          */
static int major = 0;
static struct class *gpio_class;int us_array[40];
int time_array[40];
int us_index;// 复位信号
void dht11_reset(void)
{gpio_direction_output(gpios[0].gpio, 1);
}// 起始信号
void dht11_start(void)
{mdelay(30);gpio_set_value(gpios[0].gpio, 0);mdelay(20);gpio_set_value(gpios[0].gpio, 1);udelay(40);	// 配置引脚为输入,准备接收DHT11传来的数据gpio_direction_input(gpios[0].gpio);	udelay(2);	
}// 响应信号
static int dht11_wait_for_ready(void)
{int timeout = 200;// 等待低电平while(gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}// 等待高电平while(!gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}// 等待低电平while(gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}return 0;
}static int dht11_read_byte(unsigned char *buf)
{int i;unsigned char data = 0;int timeout_us = 200;u64 pre, last;int ns;for (i = 0; i <8; i++){/* 现在是低电平 *//* 等待高电平 */timeout_us = 400;while (!gpio_get_value(gpios[0].gpio) && --timeout_us){udelay(1);}if (!timeout_us){printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -1;}/* 现在是高电平 *//* 等待低电平,累加高电平的时间 */timeout_us = 20000000;pre = ktime_get_boot_ns();while (gpio_get_value(gpios[0].gpio) && --timeout_us){//udelay(1);  /* 实际耗时: 1.6us *///us++;}last = ktime_get_boot_ns();//printk("udelay 1000 ns = %d\n", last-pre);ns = last - pre;if (!timeout_us){return -1;}us_array[us_index] = ns;time_array[us_index++] = 20000000 - timeout_us;if (ns > 40000){/* get bit 1 */data = (data << 1) | 1;}else{/* get bit 0 */data = (data << 1) | 0;}}*buf = data;return 0;}static ssize_t dht11_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{unsigned long flags;int i,err;unsigned char data[5];/* 防止数组越界 */us_index = 0;if (size != 4)return -EINVAL;local_irq_save(flags);	  // 关中断/* 1. 发送高脉冲启动DHT11 */dht11_reset();dht11_start();/* 2. 等待DHT11就绪 */if (dht11_wait_for_ready()){local_irq_restore(flags); // 恢复中断printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -EAGAIN;}/* 3. 读5字节数据 */for (i = 0; i < 5; i++){if (dht11_read_byte(&data[i])){local_irq_restore(flags); // 恢复中断printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -EAGAIN;}}dht11_reset();local_irq_restore(flags); // 恢复中断/* 4. 根据校验码验证数据 */if (data[4] != (data[0] + data[1] + data[2] + data[3])){printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -1;}/* 5. copy_to_user */	/* data[0]/data[1] : 湿度 *//* data[2]/data[3] : 温度 */err = copy_to_user(buf, data, 4);return 4;
}/* 定义自己的file_operations结构体             */
static struct file_operations gpio_key_drv = {.owner	 = THIS_MODULE,.read    = dht11_read,
};/* 在入口函数 */
static int __init dht11_drv_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* set pin */err = gpio_request(gpios[0].gpio, gpios[0].name);gpio_direction_output(gpios[0].gpio, 1);/* 注册file_operations 	*/major = register_chrdev(0, "zgl_dht11", &gpio_key_drv);  /* /proc/devices */gpio_class = class_create(THIS_MODULE, "zgl_dht11_class");if (IS_ERR(gpio_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "zgl_dht11");return PTR_ERR(gpio_class);}device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "mydht11"); /* /dev/mydht11 */return err;
}/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数*/
static void __exit dht11_drv_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class);unregister_chrdev(major, "zgl_dht11");/* free pin */gpio_free(gpios[0].gpio);
}/* 7. 其他完善:提供设备信息,自动创建设备节点                           */module_init(dht11_drv_init);
module_exit(dht11_drv_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("zgl <919426896@qq.com>");

1.2 应用层代码

dht11_test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>/** ./dht11_test /dev/mydht11**/
int main(int argc, char **argv)
{int fd;unsigned char data[4];int i;/* 1. 判断参数 */if (argc != 2) {printf("Usage: %s <dev>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}while (1){if (read(fd, data, 4) == 4){printf("get humidity  : %d.%d\n", data[0], data[1]);printf("get temprature: %d.%d\n", data[2], data[3]);}else {printf("get humidity/temprature: -1\n");}sleep(5);}close(fd);return 0;
}

2. 设备树实现

2.1 修改设备树

在这里插入图片描述

2.2 驱动层代码

dht11_drv.c

#include <linux/delay.h>
#include <linux/ktime.h>#include <linux/module.h>
#include <linux/poll.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>struct gpio_desc{int gpio;int irq;char name[128];int key;struct timer_list key_timer;
} ;static int count;
static struct gpio_desc *gpios;/* 主设备号          */
static int major = 0;
static struct class *gpio_class;int us_array[40];
int time_array[40];
int us_index;// 复位信号
void dht11_reset(void)
{gpio_direction_output(gpios[0].gpio, 1);
}// 起始信号
void dht11_start(void)
{mdelay(30);gpio_set_value(gpios[0].gpio, 0);mdelay(20);gpio_set_value(gpios[0].gpio, 1);udelay(40);	// 配置引脚为输入,准备接收DHT11传来的数据gpio_direction_input(gpios[0].gpio);	udelay(2);	
}// 响应信号
static int dht11_wait_for_ready(void)
{int timeout = 200;// 等待低电平while(gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}// 等待高电平while(!gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}// 等待低电平while(gpio_get_value(gpios[0].gpio) && --timeout){udelay(1);}if(!timeout){return -1;}return 0;
}static int dht11_read_byte(unsigned char *buf)
{int i;unsigned char data = 0;int timeout_us = 200;u64 pre, last;int ns;for (i = 0; i <8; i++){/* 现在是低电平 *//* 等待高电平 */timeout_us = 400;while (!gpio_get_value(gpios[0].gpio) && --timeout_us){udelay(1);}if (!timeout_us){printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -1;}/* 现在是高电平 *//* 等待低电平,累加高电平的时间 */timeout_us = 20000000;pre = ktime_get_boot_ns();while (gpio_get_value(gpios[0].gpio) && --timeout_us){//udelay(1);  /* 实际耗时: 1.6us *///us++;}last = ktime_get_boot_ns();//printk("udelay 1000 ns = %d\n", last-pre);ns = last - pre;if (!timeout_us){return -1;}us_array[us_index] = ns;time_array[us_index++] = 20000000 - timeout_us;if (ns > 40000){/* get bit 1 */data = (data << 1) | 1;}else{/* get bit 0 */data = (data << 1) | 0;}}*buf = data;return 0;}static ssize_t dht11_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{unsigned long flags;int i,err;unsigned char data[5];/* 防止数组越界 */us_index = 0;if (size != 4)return -EINVAL;local_irq_save(flags);	  // 关中断/* 1. 发送高脉冲启动DHT11 */dht11_reset();dht11_start();/* 2. 等待DHT11就绪 */if (dht11_wait_for_ready()){local_irq_restore(flags); // 恢复中断printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -EAGAIN;}/* 3. 读5字节数据 */for (i = 0; i < 5; i++){if (dht11_read_byte(&data[i])){local_irq_restore(flags); // 恢复中断printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -EAGAIN;}}dht11_reset();local_irq_restore(flags); // 恢复中断/* 4. 根据校验码验证数据 */if (data[4] != (data[0] + data[1] + data[2] + data[3])){printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return -1;}/* 5. copy_to_user */	/* data[0]/data[1] : 湿度 *//* data[2]/data[3] : 温度 */err = copy_to_user(buf, data, 4);return 4;
}/* 定义自己的file_operations结构体             */
static struct file_operations gpio_key_drv = {.owner	 = THIS_MODULE,.read    = dht11_read,
};/* 在入口函数 */
static int gpio_drv_probe(struct platform_device *pdev)
{int err = 0;int i;struct device_node *np = pdev->dev.of_node;struct resource *res;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* 从platfrom_device获得引脚信息 * 1. pdev来自c文件* 2. pdev来自设备树*/if (np){/* pdev来自设备树 : 示例reg_usb_ltemodule: regulator@1 {compatible = "100ask,gpiodemo";gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>, <&gpio5 3 GPIO_ACTIVE_HIGH>;};*/count = of_gpio_count(np);if (!count)return -EINVAL;gpios = kmalloc(count * sizeof(struct gpio_desc), GFP_KERNEL);for (i = 0; i < count; i++){gpios[i].gpio = of_get_gpio(np, i);sprintf(gpios[i].name, "%s_pin_%d", np->name, i);}}else{/* pdev来自c文件 static struct resource omap16xx_gpio3_resources[] = {{.start  = 115,.end    = 115,.flags  = IORESOURCE_IRQ,},{.start  = 118,.end    = 118,.flags  = IORESOURCE_IRQ,},		};		*/count = 0;while (1){res = platform_get_resource(pdev, IORESOURCE_IRQ, count);if (res){count++;}else{break;}}if (!count)return -EINVAL;gpios = kmalloc(count * sizeof(struct gpio_desc), GFP_KERNEL);for (i = 0; i < count; i++){res = platform_get_resource(pdev, IORESOURCE_IRQ, i);gpios[i].gpio = res->start;sprintf(gpios[i].name, "%s_pin_%d", pdev->name, i);}}printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* set pin */for (i = 0; i < count; i++){err = gpio_request(gpios[i].gpio, gpios[i].name);gpio_direction_output(gpios[i].gpio, 1);}/* 注册file_operations 	*/major = register_chrdev(0, "zgl_dht11", &gpio_key_drv);  /* /proc/devices */gpio_class = class_create(THIS_MODULE, "zgl_dht11_class");if (IS_ERR(gpio_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "zgl_dht11");return PTR_ERR(gpio_class);}device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "mydht11"); /* /dev/mydht11 */return err;
}/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数*/
static int gpio_drv_remove(struct platform_device *pdev)
{int i;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class);unregister_chrdev(major, "zgl_dht11");/* free pin */for (i = 0; i < count; i++){gpio_free(gpios[i].gpio);}return 0;
}static const struct of_device_id gpio_dt_ids[] = {{ .compatible = "zgl,dht11", },{ /* sentinel */ }
};static struct platform_driver gpio_platform_driver = {.driver		= {.name	= "zgl_dht11_plat_drv",.of_match_table = gpio_dt_ids,},.probe		= gpio_drv_probe,.remove		= gpio_drv_remove,
};static int __init dht11_drv_init(void)
{/* 注册platform_driver */return platform_driver_register(&gpio_platform_driver);
}static void __exit dht11_drv_exit(void)
{/* 反注册platform_driver */platform_driver_unregister(&gpio_platform_driver);
}/* 7. 其他完善:提供设备信息,自动创建设备节点                           */module_init(dht11_drv_init);
module_exit(dht11_drv_exit);MODULE_LICENSE("GPL");

2.3 应用层代码

dht11_test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>/** ./dht11_test /dev/mydht11**/
int main(int argc, char **argv)
{int fd;unsigned char data[4];int i;/* 1. 判断参数 */if (argc != 2) {printf("Usage: %s <dev>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}while (1){if (read(fd, data, 4) == 4){printf("get humidity  : %d.%d\n", data[0], data[1]);printf("get temprature: %d.%d\n", data[2], data[3]);}else {printf("get humidity/temprature: -1\n");}sleep(5);}close(fd);return 0;
}

3. 上机测试

开发板上电,装载驱动,运行程序测试:
在这里插入图片描述

http://www.dtcms.com/wzjs/42872.html

相关文章:

  • 太原网站建设优化seo关键词排名优化制作
  • 共和网站建设公司高明搜索seo
  • 做百度关键词网站网站营销推广
  • 岳池做网站电话天津百度搜索网站排名
  • 在哪找做调查赚钱的网站好西安网站建设哪家好
  • 网站开发职业工资辽宁seo推广
  • jsp网站开发实例.百度网盘学seo哪个培训好
  • 日照做网站的那家做的好优化网站首页
  • 自己建网站开网店seo推广教程seo高级教程
  • 如何通过网站做调查问卷网游推广员
  • 鲅鱼圈网站开发哪家好哦seo整站排名
  • wordpress内网外网访问不了南京seo顾问
  • 深圳英文网站开发公司长尾关键词挖掘精灵官网
  • 网站备案 假身份证百家号官网
  • wordpress 地图 注记优化关键词规则
  • wordpress js css样式温州seo排名优化
  • 计算机网站建设及管理如何做营销
  • 好网站建设公司业务企业产品推广运营公司
  • wordpress虚拟主机排名网站关键词优化排名外包
  • 网站制作优化济南站长工具关键词挖掘
  • 广东网站建设找哪家企业邮箱登录入口
  • 闲鱼网站如何赚钱海南网站建设
  • 做网站网课企查查在线查询
  • 广东住房和城乡建设委员会网站常用的网络营销工具有哪些
  • 傻瓜式网站界面seo课程培训机构
  • 网站内容页面怎么做外链个人网站设计方案
  • 纹身网站建设苏州seo网站系统
  • 电脑上自己做科目一的网站怎么上百度搜索
  • 做慧聪网站多少钱陕西百度代理公司
  • 唐山网站建设方案策划免费网站在线客服系统源码