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

建立了公司网站化工原料东莞网站建设

建立了公司网站,化工原料东莞网站建设,安全的网站建设,一建报考条件及专业要求文章目录 1、前言2、使用gpio-keys驱动2.1、dts配置2.2、识别原理2.3、应用层驱动实现2.4、编译测试 3、使用rotary-encoder驱动3.1、dts配置3.2、app测试程序编写3.3、编译测试 4、总结 1、前言 本来是没有这篇文章的。最近在rk3576下调试ec11旋转编码器时,一直没…

文章目录

  • 1、前言
  • 2、使用gpio-keys驱动
    • 2.1、dts配置
    • 2.2、识别原理
    • 2.3、应用层驱动实现
    • 2.4、编译测试
  • 3、使用rotary-encoder驱动
    • 3.1、dts配置
    • 3.2、app测试程序编写
    • 3.3、编译测试
  • 4、总结

1、前言

本来是没有这篇文章的。最近在rk3576下调试ec11旋转编码器时,一直没有效果,或者一开始可以,之后又不行了。首先我使用的ec11是基于AB相输出的,其次rk3576连接到AB相的引脚不是原生IO脚,是通过xl9535 gpio扩展芯片连接的,关于bug的调试可以参考《Linux下xl9535 gpio扩展芯片bug调试》。本文介绍基于原生IO引脚的ec11旋转编码器调试,总共有两种方式,一种是基于gpio-keys驱动,一种基于rotary-encoder驱动,这两个驱动都是内核自带的。

2、使用gpio-keys驱动

gpio-keys是按键驱动。所以使用此种方法只是把A相和B相的输出分别当作一个按键,并注册进input子系统。最终是在应用层实现驱动。

2.1、dts配置

# ec11的按键
Rotary_SW {compatible = "gpio-keys";status = "okay";#address-cells = <1>;#size-cells = <0>;rotary_sw {label = "rotary_sw";linux,code=<KEY_0>;debounce-interval = <5>;gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;interrupt-parent = <&gpio3>;interrupts = <6 IRQ_TYPE_LEVEL_LOW>;};
};Rotary_A {compatible = "gpio-keys";status = "okay";#address-cells = <1>;#size-cells = <0>;rotary_a {label = "rotary_a";linux,code=<250>;debounce-interval = <1>;gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;interrupt-parent = <&gpio4>;interrupts = <6 IRQ_TYPE_EDGE_RISING>;};
};Rotary_B {compatible = "gpio-keys";status = "okay";#address-cells = <1>;#size-cells = <0>;rotary_b {label = "rotary_b";linux,code=<251>;debounce-interval = <1>;gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;interrupt-parent = <&gpio4>;interrupts = <4 IRQ_TYPE_EDGE_RISING>;};
};

属性含义可参考:https://www.kernel.org/doc/Documentation/devicetree/bindings/input/gpio-keys.txt

2.2、识别原理

A相和B相输出的信号存在90度的相位差。当编码器顺时针旋转时,A相的信号会比B相的信号超前90度;而当编码器逆时针旋转时,A相的信号会比B相的信号滞后90度。

当检测到A相从低电平变为高电平时,如果此时B相为低电平,则编码器顺时针旋转:

当检测到B相从低电平变为高电平时,如果此时A相为低电平,则编码器逆时针旋转:

2.3、应用层驱动实现

#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <unistd.h>  
#include <string.h>  
#include <linux/input.h>  
#include <pthread.h>  
#include <errno.h>  
#include <signal.h>#define EC11_SW_EVENT   "/dev/input/event7"  
#define EC11_A_EVENT    "/dev/input/event6"  
#define EC11_B_EVENT    "/dev/input/event5"  // 线程ID
pthread_t ec11_sw_obj, ec11_a_obj, ec11_b_obj;  // 文件描述符
int ec11_sw_fd, ec11_a_fd, ec11_b_fd;
int count = 0;                                      // 累计步数// 编码器状态变量
int ec11_sw_value = 0;  
int ec11_a_value = 1;  
int ec11_b_value = 1;  
int ec11_direction = 0;                             // 0:不动作 1:顺时针旋转 2:逆时针旋转 3:按键按下顺时针旋转 4:按键按下逆时针旋转 5:按键按下
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;   void sigint_handler(int sig_num) 
{    pthread_cancel(ec11_sw_obj);pthread_cancel(ec11_a_obj);pthread_cancel(ec11_b_obj);close(ec11_sw_fd);      close(ec11_a_fd);close(ec11_a_fd);pthread_join(ec11_sw_obj, NULL);pthread_join(ec11_a_obj, NULL);pthread_join(ec11_b_obj, NULL);printf("all thread exit\n");exit(0);  
}void *ec11_scan_thread(void *arg) 
{  int fd = *(int*)arg;                          struct input_event ie;      while (1) {  if (read(fd, &ie, sizeof(struct input_event)) == sizeof(struct input_event)) {  if (ie.type == EV_KEY) {  pthread_mutex_lock(&lock);      // 处理按键事件if (fd == ec11_sw_fd && ie.code == 4) {  ec11_sw_value = ie.value;  if (ec11_sw_value == 1 && ec11_a_value == 1 && ec11_b_value == 1)   // 按键按下ec11_direction = 5;  } // 处理A相事件else if (fd == ec11_a_fd && ie.code == 250) {  if (ie.value == 0 && ec11_b_value == 1)             // 顺时针旋转{  ec11_a_value = 0;  ec11_direction = (ec11_sw_value == 1) ? 3 : 1;  // 判断按键状态  } else if (ie.value == 1) ec11_a_value = 1;  } // 处理B相事件else if (fd == ec11_b_fd && ie.code == 251) {  if (ie.value == 0 && ec11_a_value == 1)             // 逆时针旋转{  ec11_b_value = 0;  ec11_direction = (ec11_sw_value == 1) ? 4 : 2;  // 判断按键状态  } else if (ie.value == 1) ec11_b_value = 1;  }  pthread_mutex_unlock(&lock);   }  }  }   
}  int main(int argc, char **argv) 
{  int ret;ec11_sw_fd = open(EC11_SW_EVENT, O_RDONLY);  ec11_a_fd = open(EC11_A_EVENT, O_RDONLY);  ec11_b_fd = open(EC11_B_EVENT, O_RDONLY);  if (ec11_sw_fd < 0 || ec11_a_fd < 0 || ec11_b_fd < 0) {  printf("Failed to open input device\n");  return -1;  }pthread_create(&ec11_sw_obj, NULL, ec11_scan_thread, &ec11_sw_fd);  pthread_create(&ec11_a_obj, NULL, ec11_scan_thread, &ec11_a_fd);  pthread_create(&ec11_b_obj, NULL, ec11_scan_thread, &ec11_b_fd);  signal(SIGINT, sigint_handler);         // 注册信号处理函数                                         while (1) {  pthread_mutex_lock(&lock);          switch (ec11_direction)             {  case 1: count++;printf("顺时针转 : %d\n", count); break;  case 2: count--;printf("逆时针转 : %d\n", count); break;  case 3: count++;printf("按键按下顺时针转 : %d\n", count); break;  case 4: count--;printf("按键按下逆时针转 : %d\n", count); break;  case 5: printf("按键按下\n"); break;  default: break;  }  ec11_direction = 0;                 pthread_mutex_unlock(&lock);        usleep(10000); }  return 0;  
}

2.4、编译测试

# 如果使用buildroot系统,需要交叉编译。
# 这里使用的是ubuntu系统,直接使用gcc编译。
gcc -o build ec11.c

3、使用rotary-encoder驱动

rotary-encoder驱动是一个在内核态实现旋转编码器驱动。可以输出相对位置或者绝对位置,以下以输出相对位置举例。最终也是注册进input子系统。

3.1、dts配置

rotary@0 {compatible = "rotary-encoder"; gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>, <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;linux,axis = <0>; /* REL_X */rotary-encoder,encoding = "gray";rotary-encoder,relative-axis;interrupt-parent = <&gpio4>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_rotary>;
};&pinctrl {rotary {pinctrl_rotary:pinctrl_rotary {rockchip,pins = <4 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;};};
}

属性含义可参考:https://www.kernel.org/doc/Documentation/devicetree/bindings/input/rotary-encoder.txt

3.2、app测试程序编写

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>int main(int argc, char *argv[])
{struct input_event ie;int fd;if (argc != 2) {fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);exit(-1);}fd = open(argv[1], O_RDONLY);if (fd < 0) {fprintf(stderr, "can not open %s\n", argv[1]);exit(-1);}while (1){if (read(fd, &ie, sizeof(struct input_event)) == sizeof(struct input_event))printf("type:%d code:%d value:%d\n", ie.type, ie.code, ie.value);}
}

3.3、编译测试

# 如果使用buildroot系统,需要交叉编译。
# 这里使用的是ubuntu系统,直接使用gcc编译。
gcc -o build ec11_app.c

4、总结

参考文章:

Linux 输入设备调试详解(零基础开发)Rotary_Encoder旋转编码器驱动(EC11)通用GPIO为例 挂载input输入子系统_rotary encoder with display-CSDN博客


文章转载自:

http://pi2JYWlu.wnhgb.cn
http://qsiQBMIE.wnhgb.cn
http://rEE7OGAC.wnhgb.cn
http://CKyEQ6Bc.wnhgb.cn
http://wpQL9Tek.wnhgb.cn
http://qkuPvESu.wnhgb.cn
http://5t34MTBs.wnhgb.cn
http://TohLEDZs.wnhgb.cn
http://Ow0iikyW.wnhgb.cn
http://akGwQFu1.wnhgb.cn
http://FbgiYmYt.wnhgb.cn
http://GW7L7WoI.wnhgb.cn
http://G7bQA0Yx.wnhgb.cn
http://Lqjxpuns.wnhgb.cn
http://7p6gbtzP.wnhgb.cn
http://lvLXiYQV.wnhgb.cn
http://rOHyv1Ab.wnhgb.cn
http://sLxnzSJj.wnhgb.cn
http://vy4Mb0jt.wnhgb.cn
http://bR4JLuUY.wnhgb.cn
http://Y2v6IFw1.wnhgb.cn
http://B4Q7RvwA.wnhgb.cn
http://h2zp9mIV.wnhgb.cn
http://hvJvCPWn.wnhgb.cn
http://AZi2FWoY.wnhgb.cn
http://18VpPSaS.wnhgb.cn
http://mSGcrvEL.wnhgb.cn
http://nOw9iu8s.wnhgb.cn
http://h0l5iohF.wnhgb.cn
http://xGl5sXC2.wnhgb.cn
http://www.dtcms.com/wzjs/654076.html

相关文章:

  • cn后缀做网站网站开发终止协议书
  • 如何用ps做网站平面图建网站哪家好行业现状
  • 专业微网站手机网站免费
  • 成都网站怎么推广南京建设交易中心网站
  • 包头土右旗建设局网站广州市品牌网站建设公司
  • dedecms 网站地图插件济南集团网站建设流程
  • 企业网站优化包括哪三个层面wordpress中调用分类目录文章列表
  • 最火的传奇手游网站长沙门户网站
  • 湖南餐饮网站建设大学网站建设多少钱
  • 鞍山+网站建设龙岩网站建设运营
  • 2021网站建设前景怎么样网页图片批量下载
  • 紫色网站模板项目网络的关键路径
  • 网站建设教程答允苏州久远网络竞价推广遇到恶意点击怎么办
  • 做网站的是如何赚钱的石家庄网站建设设计
  • 做空气开关那个网站推广比较好山西省这房和城乡建设厅网站
  • 赤峰网站设计个人摄影网站制作
  • 做网站怎么这么贵团工作网站建设意见
  • 温州通业建设工程有限公司网站做网站的前途
  • 企业网站建设专业中交建设设计院有限公司网站
  • 网站建设及推广培训班东莞东城区
  • 专业的网站建设企业中国4a广告公司100强
  • 上海易雅达网站建设公司深圳最新新闻事件
  • 建设网站如何盈利网站搭建交流群
  • 北京网站的建立的杭州化工网站建设
  • 网站制作策划方案最佳线上网站制作模板
  • 设计师接单网站做网站要会哪些软件
  • 网站验证码插件建筑工程网格化管理
  • wordpress 网站搬迁搜索引擎优化缩写
  • 望京做网站的公司哪家好北京核子华曦检测所
  • 如何创建自己的公司网站开网站需要准备什么