一、前述

  使用的是7.11版本的lvgl,使用旋转编码器(EC11)做为外部输入设备,平时使用触摸屏的多,但触摸屏小贵(是我太穷了),还得加个触摸芯片,也麻烦,不如旋转编码器合算,当然编码器也不如触摸屏方便。因为是第一次使用编码器做为输入设备,网上也搜不到相关的内容,只有官网上有一些实例,自己就看着改,折腾了一下,弄好了,记录一下。

二、实现步骤

  (1) 初始化编码器做为输入设备。
  (2) 设置相关函数。
  (5) 创建一个"组",把"组"挂载到输入设备上。
  (4) 将各个控件加入到创建的"组"中。

三、具体实现代码

(1)、初始化编码器做为外部输入设备

  用过lvgl的应该都知道初始化一个输入设备应该要做哪些工作,只需要修改很少的东西就可以实现,这里就直接贴代码了。
  打开lv_port_indev.c文件,在lv_port_indev_init()这个初始化函数里添加注册编码器输入设备的代码。

lv_indev_t * indev_encoder;
int32_t encoder_diff;
lv_indev_state_t encoder_state;
void lv_port_indev_init(void)
{lv_indev_drv_t indev_drv;lv_indev_drv_init(&indev_drv);indev_drv.type = LV_INDEV_TYPE_ENCODER;//设备类型 编码器indev_drv.read_cb = encoder_read;//回调函数indev_encoder = lv_indev_drv_register(&indev_drv);
}

(2)、设置相关函数

  lv_port_indev.c文件中是有输入设备回调函数的例子,但是都不完整,需要补充,编码器的话有个encoder_read()函数,如下。

static bool encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{data->enc_diff = encoder_diff;data->state = encoder_state;encoder_diff = 0;/*Return `false` because we are not buffering and no more data to read*/return false;
}

  和原先的程序相比,只是加入了把"encoder_diff"这个变量置0这一行代码,如果不置0,一直是正数或负数,会识别为一直在转动,那么会一直在控件之间进行切换。
  然后还需要一个检测编码器是否转动或按下的程序,如下。

void Key_Scanf(void)
{static bool but_flag = true;if(digitalRead(EC_K)==0)    //编码器的按键encoder_state = LV_INDEV_STATE_PR; //按下elseencoder_state = LV_INDEV_STATE_REL;    //松开if(digitalRead(EC_A)==0&&digitalRead(EC_B)==1&&but_flag)    //编码器左转{encoder_diff--;but_flag = false;}else if(digitalRead(EC_A)==1&&digitalRead(EC_B)==0&&but_flag)//编码器右转{encoder_diff++;but_flag = false;}else if(digitalRead(EC_A)==1&&digitalRead(EC_B)==1)but_flag = true;
}

  在上面这段代码中,通过检测编码器的相关引脚,判断是否转动或按下,然后修改相关变量值,实现编码器的接入。用过编码器应该就能看懂。
  这里使用的是查询的方式,需要定时调用这个检测编码器状态的函数。使用中断来检测更好(如果使用中断就需要修改代码了),没有中断就只能定时调用了。当然定时调用也是没问题的。
  在上面代码中的"but_flag"变量我是用来防止同时触发好几次的,因为是定时调用的,间隔过小会触发好几次,所有就加了这个静态变量防止发生这种现象。
  "encoder_state "这个变量是检测编码器是否按下。
  "encoder_diff"这个变量是检测编码器是否旋转和旋转方向,有正有负,没有转动时应该为0。注意在其他地方使用记得声明一下变量。
  到此与输入设备相关的函数就设置好了,下面就是有关"组"的了。

(3)、创建、挂载"组"

  使用编码器需要使用"组"来配合。首先创建一个"组",在把这个组加载到前面创建的输入设备中,代码如下。

//指针
lv_group_t * group;
//创建一个group
group= lv_group_create();
//将group加载到输入设备中。注意,下面这个函数的第一个参数是注册输入设备时返回的指向新输入设备的指针,不要写错了
lv_indev_set_group(indev_encoder,group);

(4)、将控件加入到"组"中

  把控件加入到"组"中使用void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj);这个函数。例如下面的程序。

 /* 创建一个按钮 */btn_exit = lv_btn_create(lv_scr_act(),NULL);lv_obj_set_size(btn_exit,40,20);lv_obj_align(btn_exit, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);label_btn_exit = lv_label_create(btn_exit,NULL);lv_label_set_text(label_btn_exit,"exit");/* 把控件添加到组中 */lv_group_add_obj(group,btn_exit);/* 创建一个开关 */sw_motor = lv_switch_create(lv_scr_act(), NULL);lv_obj_set_size(sw_motor,45,26);lv_obj_align(sw_motor, NULL, LV_ALIGN_CENTER, 30, -10);/* 把控件添加到组中 */lv_group_add_obj(group,sw_motor);

  在上面程序中,创建了"按钮"和"开关"两个控件,都加入到先前创建的"组"中,这样,在这个界面,转动编码器那么就在会这两个控件之间进行切换选择。
  加入"组"中的先后顺序,就对应着你使用编码器在各个对象之间进行切换的先后顺序。最先加入的会先被选择,后加入的就会排在后面,就是这样的选择顺序。

三、遇到的一些问题及解决办法

  要注意,并不是所有的控件都能加入"组"中。不应该说不能,应该说加入"组"也没用,我试了试,比如这个"标签"这个控件,加入到"组"中就没效果,聚焦不会切换到这个"标签"。这个"组"还有编辑模式,不知道是不是切换到编辑模式后在把"标签"控件加入到"组"中才有效果,这个我没有试。
  还有一个非常重要的地方,那就是使用"页签"时,不能单纯的把"页签"加入到"组"中就完事了。这个地方好坑啊,最开始我就是用的"页签"做界面切换,然后怎么设置"组"都没用,不能正常切换显示,后来看了官方的一个有关编码器做为输入设备的例程才知道有问题,在这个例程中是把这个"页签"加入到"组"了,但是不单单如此,程序中还特地写了一个回调函数用来切换"页签"的显示页面,看到这个我才发觉不能正常使用。我也没找到好的办法,官方例程都没这样用,那应该就是不行了。虽然正经方法不行,但是可以使用一些歪点子,那就是在页签切换界面,不使用编码器做为输入设备,或者直接把扫描编码器的程序替换了,换成切换"页签"的子页面的程序,等进入了下一界面,再把扫描编码器的程序换回来,懂得都懂,不多说了。(补充:后来发现应该是同一个页面的子控件不会自动聚焦,超出屏幕范围的控件就不能正常的显示,不像使用触摸屏那样可以滑动整个页面来进行选择,所以对此加入了一个用于聚焦显示的回调函数,每次改变选择的"组"中的成员时,就会调用这个函数,通过相关函数获取所选择的对象并进行聚焦显示。这样就不会有控件无法显示的情况了。这个编码器的例程在"lv_demo_keypad_encoder.c"这个文件里,可以看一下。)
  还有一个问题,就是如果有不止一个"组"加载到了同一个"输入设备",可能会窜着来。上面我说了我使用的"页签",然后选中"页签"的某一个子页面时切换到另一个界面,然后我有好几个页面,每个页面都要控件,每个页面的控件我都单独创建了一个"组",然后分开放,结果我发现,虽然不在一个"组"中,但是却可以直接从一个"组"的控件切换到另一个"组"的控件中,而且我发现改变一下把不同的"组"加载到"输入设备"的顺序后,现象还又变了,真有意思,可能是因为挂载到同一个输入设备中导致的,需要注意一下。对此我用了最笨的方法,那就是多创建几个"输入设备",一个对应一个"组",在不同的界面,“使能"不同的"输入设备”,完成"分时复用",只需要加很少的代码,效果杠杠滴。

四、结语

  在本文中没有给出一个完整的demo,因为还有MCU、显示设备,每个人的都不一定一样,所有就只叙述了关键部分。只要看懂了,是一点问题也没有。
  上面几个遇到的问题,也不清楚是哪里不对,反正都有法子解决,就没有深究,如果有清楚的,有好的解决办法的,可以留言告诉我,感谢。
  使用EC11旋转编码器时,可以在两个信号线上加个RC低通滤波,R:10K,C:0.01uf,效果会好很多,手册上就是这样的。
  如果我哪里没说清楚,还有什么问题,可以留言,这个会通过邮箱提示我,我看到会回复的。
  
  使用编码器的简单例子:https://download.csdn.net/download/wojueburenshu/85772073
  上面这个程序中,用的单色OLED和旋转编码器。感觉单色屏幕使用起来不是很方便,有些控件显示有问题,就没多研究了。
  
  以上纯属个人经验,并且个人能力也有限,可能出现差错,如有问题请指正,我就改。
  
下面放几个链接。
英文的lvgl说明文档,7.11版本:https://docs.lvgl.io/latest/en/html/index.html
中文的lvg说明l文档,7.11版本:http://lvgl.100ask.net/7.11/index.html
(下面链接里面的的案例不像上面那个可以在线操作,但好歹是中文的。)

lvgl使用旋转编码器做为外部输入设备相关推荐

  1. 认识EC11旋转编码器编写驱动程序

    前言 抛开工作,以电子爱好者的身份,单片机玩多了都会想着在单片机的外围设备玩出一些花样来. 这其中首先想到的就是"升级"输入输出设备. 这里先说一说我们常给单片机使用的输入设备. ...

  2. 旋转编码器:如何在 Arduino 上使用 Keys KY-040 编码器

    旋转编码器是一种输入设备,您可以在任一方向连续旋转.当您转动设备时,它会生成数字脉冲,以使用两个相控输出信号显示旋转方向.这两个输出还指示单个位置运动,因此您可以在控制面板中使用它们来增加或减少参数. ...

  3. STM32CubeMX EC11旋转编码器开发心路历程(encode模式 外部中断模式 普通IO口模式 定时器模式探索)

    文章目录 ENCODE模式探索 普通IO口探索 定时器使用 外部中断探索 编码器开关的理解 最后的实现方案 这篇文章主要还是记录整个过程以及想法的不断改进,对于一些实际的操作还有代码,我准备都分开写到 ...

  4. STM32移植LVGL+旋转编码器接口对接

    写在前面:本菜鸟结合了许多大佬的文章,成功实现了基于LVGL的GUI设计,小开心~浅浅记录一下!~ 本文以单片机STM32F103VET6为核心,利用ST7796芯片驱动分辨率为480*320的LCD ...

  5. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  6. STM32入门笔记03_EXTI外部中断详解+案例:红外对射计数、旋转编码器计数

    EXTI外部中断 中断的相关概念 中断源: 可以引起中断的事件称为中断源 中断: 在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成 ...

  7. 我要做一个蠕动泵的工作记录(二)做一个arduino 多级菜单(2)旋转编码器

    旋转编码器就是这个东西,正转和反转以及按下动作.英文叫Encoder 主要参考文章:https://www.cnblogs.com/watson8544/p/5454086.html,比论文有用多了. ...

  8. 11旋转编码器原理_旋转编码器的原理是什么?增量式编码器和绝对式编码器有什么区别?...

    先给出结论,最重要的区别在于:增量式编码器没有记忆,断电重启必须回到参考零位,才能找到需要的位置,而绝对式编码器,有记忆,断电重启不用回到零位,即可知道目标所在的位置. 接下来细说一下,主要包含如下的 ...

  9. PLC与旋转编码器的连接

    PLC与旋转编码器的连接--PLC与常用输入设备的连接 旋转编码器是一种光电式旋转测量装置,它将被测的角位移直接转换成数字信号(高速脉冲信号).因此可将旋转编码器的输出脉冲信号直接输入给PLC,利用P ...

最新文章

  1. Android 开发包括哪些方面?如何提升?
  2. IOS贝塞尔曲线圆形进度条和加载动画
  3. getresourceasstream方法_【设计模式】第三篇:一篇搞定工厂模式【简单工厂、工厂方法模式、抽象工厂模式】...
  4. 4.4 Iterator(迭代器)
  5. adb常用命令的介绍及使用
  6. tcp协议的端口状态
  7. NYOJ-找点(贪心)
  8. springmvc07 Json处理
  9. nodejs脚本后台运行
  10. Silverlight5.0正式发布附下载地址
  11. python中scipy库的导入与函数调用方法_python的scipy库安装成功,导入scipy或其函数时却报错的问题...
  12. java pptx转图_Java 将PPT转换为图片格式
  13. 绿色下载:CYY屏幕截图助手1.3
  14. 个人理财管理系统代码
  15. 类型 异常报告 消息 null 描述 服务器遇到一个意外的情况,阻止它完成请求。 例外情况 java.lang.NumberFormatException: null java.base/
  16. 七.Docker网络管理以及固定ip
  17. 学习笔记(29):A110测试-测试课程申请22
  18. 最长上升子序列(O(nlogn))算法并输出最长上升子序列
  19. 范寶興:3分法、4分法在12階穿越界面的浪漫
  20. 前端传来的图片并保存_前端处理后端接口传递过来的图片文件

热门文章

  1. 树莓派实现简单的人脸识别
  2. sersync实时同步 解决单点NFS单点故障问题
  3. 在ubuntu下下载pip
  4. 在word中插入excel文件
  5. 关于PGP的简单使用
  6. CLion等JetBrains IDE学生认证免费使用流程
  7. LC振荡电路 频域计算
  8. C语言自定义数组函数
  9. Java线程之Exchanger
  10. ActiveMQ——如何监控ActiveMQ