西宁专业网站建设域名备案掉了网站还可以用
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:10
当前位置: 首页 > news >正文
西宁专业网站建设,域名备案掉了网站还可以用,网站ui设计欣赏,沈阳关键词优化报价目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板编辑 四、驱动编写 1、添加keyio函数 2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代…目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板编辑 四、驱动编写 1、添加keyio函数 2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代码如下 五、应用编写 总体代码如下 验证 一、硬件原理 打开原理图找到KEY 可以看到KEY0是接到UART1 CTS上 打开参考手册找到IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B 看到是可以复用为GPIO1_IO18的 根据IOMUXC_SW_PAD_CTL_PAD_UART1_CTS_B配置的电气属性为0xF080具体属性如下 配置UART1_CTS_B的IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 11 默认22K上拉 *bit [13]: 1 pull功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 000 关闭输出 bit [0]: 0 低转换率 二、添加设备树 1、创建pinctrl 先查找UART1_CTS对应的宏这个在arch/arm/boot/dts/imx6ul-pinfunc.h 在iomuxc里添加keygrp 2、创建节点 创建key节点 3、检查 添加完之后在文件里分别搜索MX6UL_PAD_UART1_CTS_B__GPIO1_IO018和gpio1 18检查一下是否有存在使用避免占用 打开开发板检查创建是否存在 编译复制 三、修改工程模板 修改makefile 复制基本的字符驱动模板到key.c 四、驱动编写 自行编写好基本的字符设备 1、添加keyio函数 在驱动入口前添加 96行of_find_node_by_path 函数通过路径来查找指定的节点“key”返回找到的节点 102行of_get_named_gpio函数获取设备树中“key-gpios”属性信息0为其第一个信息获取到的 GPIO 编号 108行gpio_request 函数在使用 GPIO 之前申请GPIO 管脚设名字“key0”返回值0申请成功 114行gpio_direction_input函数设置 GPIO 为输入返回值0设置成功 2、添加调用 在驱动入口函数里面后部添加 在驱动入口里面调用 keyio函数 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 方便原子操作值不是固定的 6、初始化原始变量 初始化keyvalue,把宏INVAKEY赋值给keyvalue在驱动入口函数定义 7、打开操作 设置私有数据 8、读操作 61行获取私有数据 63-67行 gpio_get_value函数返回值为 GPIO 的输入电平状态1 为高电平0 为低电平。如果按下不放就是1进入while等待释放释放为0取反进入while中执行 atomic_set函数把KEY0VALUE赋值给keyvalue。否则直接执行 atomic_set函数把宏INVAKEY赋值给keyvalue 69行atomic_read函数读取keyvalue值赋给value 71行copy_to_user函数把value的值拷贝给用户空间成功执行拷贝操作则返回0 总体代码如下 #include linux/module.h #include linux/kernel.h #include linux/init.h #include linux/fs.h #include linux/uaccess.h #include linux/io.h #include linux/cdev.h #include linux/device.h #include linux/of.h #include linux/of_address.h #include linux/of_irq.h #include linux/slab.h #include linux/of_address.h #include linux/of_gpio.h #include linux/atomic.h#define KEY_CNT 1 / 设备号个数 / #define KEY_NAME key / 名字 /#define INVAKEY 0x00 #define KEY0VALUE 0XF0/ key设备结构体 / struct key_dev {dev_t devid; / 设备号 /struct cdev cdev; / cdev */struct class class; / 类 */struct device device; / 设备 /int major; / 主设备号 /int minor; / 次设备号 */struct device_node nd; / 设备节点 /int key_gpio; / key所使用的GPIO编号 /atomic_t keyvalue; / 按键值 / } key; / key设备 //** description : 打开设备 param - inode : 传递给驱动的inode* param - filp : 设备文件file结构体有个叫做private_data的成员变量* 一般在open的时候将private_data指向设备结构体。* return : 0 成功;其他 失败*/ static int key_open(struct inode *inode, struct file filp) {filp-private_data key;return 0; }/** description : 从设备读取数据 param - filp : 要打开的设备文件(文件描述符)* param - buf : 返回给用户空间的数据缓冲区* param - cnt : 要读取的数据长度* param - offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/ static ssize_t key_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) {int value;struct key_dev *dev filp-private_data;int ret 0;if(gpio_get_value(dev-key_gpio) 0){/按下/while(!gpio_get_value(dev-key_gpio));atomic_set(dev-keyvalue,KEY0VALUE);}else{atomic_set(dev-keyvalue,INVAKEY);}value atomic_read(dev-keyvalue);ret copy_to_user(buf,value,sizeof(value));return ret; }/** description : 向设备写数据* param - filp : 设备文件表示打开的文件描述符* param - buf : 要写给设备写入的数据* param - cnt : 要写入的数据长度* param - offt : 相对于文件首地址的偏移* return : 写入的字节数如果为负值表示写入失败*/ static ssize_t key_write(struct file *filp, const char __user *buf, size_t cnt, loff_t offt) {return 0; }/** description : 关闭/释放设备 param - filp : 要关闭的设备文件(文件描述符)* return : 0 成功;其他 失败*/ static int key_release(struct inode *inode, struct file filp) {return 0; }/ 设备操作函数 */ static struct file_operations key_fops {.owner THIS_MODULE,.open key_open,.read key_read,.write key_write,.release key_release, };/key io初始化/ static int keyio_init(struct key_dev *dev) { int ret 0; /初始化atomic/atomic_set(key.keyvalue,INVAKEY);dev-nd of_find_node_by_path(/key);if (dev-nd NULL){ret -EINVAL;goto fail_nd;}dev-key_gpio of_get_named_gpio(dev-nd, key-gpios, 0);if (dev-key_gpio 0){ret -EINVAL;goto fail_gpio;}ret gpio_request(dev-key_gpio, key0);if (ret){ret -EBUSY;printk( IO %d cant request\r\n, dev-key_gpio);}ret gpio_direction_input(dev-key_gpio);if (ret){ret -EINVAL;goto fail_input;}return 0; fail_input:gpio_free(dev-key_gpio); fail_gpio: fail_nd:device_destroy(key.class, key.devid);return ret; }/** description : 驱动入口函数* param : 无* return : 无/ static int __init key_init(void) {int ret 0;/ 初始化原子变量 /atomic_set(key.keyvalue,INVAKEY);/ 注册字符设备驱动 /key.major 0;/ 1、创建设备号 /if (key.major){ / 定义了设备号 /key.devid MKDEV(key.major, 0);register_chrdev_region(key.devid, KEY_CNT, KEY_NAME);}else{ / 没有定义设备号 /alloc_chrdev_region(key.devid, 0, KEY_CNT, KEY_NAME); / 申请设备号 /key.major MAJOR(key.devid); / 获取分配号的主设备号 /key.minor MINOR(key.devid); / 获取分配号的次设备号 /}if(ret 0){goto fail_devid;}printk(major %d , minor %d \r\n, key.major, key.minor);/ 2、初始化cdev */key.cdev.owner THIS_MODULE;cdev_init(key.cdev, key_fops);/初始化的 cdev 结构体变量//* 3、添加一个cdev */cdev_add(key.cdev, key.devid, KEY_CNT);/添加字符设备/if(ret){goto fail_cdevadd;}/* 4、创建类 /key.class class_create(THIS_MODULE, KEY_NAME);if (IS_ERR(key.class)){ret PTR_ERR(key.class);goto fail_class;}/ 5、创建设备 /key.device device_create(key.class, NULL, key.devid, NULL, KEY_NAME);if (IS_ERR(key.device)){ret PTR_ERR(key.device);goto fail_device;}ret keyio_init(key);if (ret 0){goto fail_device;}printk(key_init\r\n);return 0; fail_device:class_destroy(key.class); fail_class:cdev_del(key.cdev); fail_cdevadd:unregister_chrdev_region(key.devid,KEY_CNT); fail_devid:return ret; }/** description : 驱动出口函数 param : 无* return : 无/ static void __exit key_exit(void) {/ 注销字符设备驱动 /cdev_del(key.cdev);/ 删除cdev /unregister_chrdev_region(key.devid, KEY_CNT); / 释放设备号 */device_destroy(key.class, key.devid);/摧毁设备/class_destroy(key.class);/删除类/gpio_free(key.key_gpio);/释放io/ }module_init(key_init); module_exit(key_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(zuozhongkai);五、应用编写 总体代码如下 #include sys/types.h #include sys/stat.h #include fcntl.h #include stdio.h #include unistd.h #include stdlib.h #include string.h#define INVAKEY 0x00 #define KEY0VALUE 0XF0/*argc:应用程序参数个数argv数组元素个数argv:具体参数,也可以写作char **argv./keyAPP filename ./keyAPP /dev/key */ int main(int argc, char *argv[]) {int fd,retvalue;char *filename;unsigned char databuf[1];int value0;/判断命令行输入参数是否正确/if(argc ! 2){printf(error usage!\r\n);return -1;}/用指针指向文件/filename argv[1];/打开文件/fd open(filename , O_RDWR);if(fd 0){printf(file open failed\r\n,filename);return -1;}/循环读取/while(1){read(fd,value,sizeof(value));if(value KEY0VALUE){printf(KEY0 press , value %d\r\n,value);}}/关闭文件/close(fd);return 0; } 循环读取处用read读取内核拷贝的数据 验证 可以看到按下按键就会打印value的值 这里埋下一个伏笔运行测试APP会占用99%的CPU资源 后续章节进行介绍
- 上一篇: 西宁网站系统建设网站营销方案设计公司
- 下一篇: 西宁专业做网站的企业管理软件开发
相关文章
-
西宁网站系统建设网站营销方案设计公司
西宁网站系统建设网站营销方案设计公司
- 技术栈
- 2026年03月21日
-
西宁网站开发淘宝上网站建设好便宜
西宁网站开发淘宝上网站建设好便宜
- 技术栈
- 2026年03月21日
-
西宁网站建设属于什么的网页制作工具
西宁网站建设属于什么的网页制作工具
- 技术栈
- 2026年03月21日
-
西宁专业做网站的企业管理软件开发
西宁专业做网站的企业管理软件开发
- 技术栈
- 2026年03月21日
-
西宁最好网站建设公司哪家好广水做网站
西宁最好网站建设公司哪家好广水做网站
- 技术栈
- 2026年03月21日
-
西网站建设公司wordpress快速翻译
西网站建设公司wordpress快速翻译
- 技术栈
- 2026年03月21日
