0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

事件驱动和键盘管理设计案例分析

AGk5_ZLG_zhiyua 来源:未知 作者:刘勇 2017-11-20 09:02 次阅读

周立功教授新书《面向AMetal框架与接口编程(上)》,对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开发思想,聚焦自己的“核心域”,改变自己的编程思维,实现企业和个人的共同进步。

第四章为面向接口的编程,本文内容包括:4.4 事件驱动和4.5 键盘管理。

4.4 事件驱动

>>> 4.4.1 中断与事件驱动

1. 中断

到目前为止,几乎所有的程序都依赖轮询通信。那些代码只是一遍一遍地巡检外围功能部件,并在需要的时候为外围设备提供服务。可想而知,轮询访问不仅消耗了大量的 MCU资源,而且将导致非常不稳定的反应时间。

为了有效地解决上述可能导致整个系统瘫痪的问题,计算机专家提出了一种“实时”的解决方案,通过“中断”使可预见的反应时间维持在几微秒之内。所谓中断是指当 MCU 正在处理某件事情的时候,外部发生的某一“事件”请求 MCU 迅速去处理,于是 MCU 暂时中止当前的工作,转去处理所发生的事件。当中断服务处理完该事件以后,再回到原来被中止的地方继续原来的工作。

但也有可能突发事务请求中断时,可能出现在正常程序流程的任何地方,在正常程序流程中可以选择响应或不响应这个中断请求,突发事件的处理可能会改变整个程序的状态,从而也改变了后续的正常程序流程。

比如,在一次会议上你正在按照计划做报告,这时手机铃声响了,此时,你有两种选择,一是你觉得正在进行的报告更重要,你可以挂断电话或干脆关机,等会后再去处理这个来电;二是你认为这个电话很重要或很快就可处理完毕(不影响做报告),你可以暂停报告转而接听这个电话,当接听完毕后,你再继续做报告,前提是你必须记住接电话前讲到哪里了,当然如果你足够机敏的话,在这次通话中你所接收到的信息可能会改变你随后的报告内容。

由此可见,通过中断方式允许系统在执行主程序时可以响应并处理其它任务,进而中断驱动系统给人们一种假象,MCU 可以同时执行多个任务。而事实上 MCU 不能同时执行 1条以上的指令,它只是暂停主程序转去执行其它程序,完成后再返回继续执行主程序。

从这个角度来看,中断响应非常类似于函数的调用过程。它们两者之间的差别在于中断的响应是由“事件”发起的,而不像函数调用那样,它是在主程序流程中预先设定的,中断是系统响应一些和主程序异步事件,这些事件何时将主程序中断是预先未知的。有了中断就可以实现主机与外设并行工作,支持多程序并发运行,支持实时处理功能。

2. 事件驱动

在现实生活中,“发生的某件事情”就是事件,事实上很多程序都对“发生的事情”做出反应。比如,移动或点击鼠标、按键、或经过一定的时间都是基于事件的驱动程序。

事件驱动程序只是“原地不动”,什么也不做,等待有事件发生,一旦事件确实发生了,它们就会做出反应,完成所有必要的工作来处理这个事件。其实,Windows 操作系统就是事件驱动程序的一个很好的示例,当启动计算机运行 Windows 时,它只是“原地不动”,不会启动任何程序,你也不会看到鼠标光标在屏幕上移动。不过,如果你开始移动或点击鼠标,就会有情况发生。

为了让事件驱动程序“看到”有事件发生,它必须“寻找”这些事件,程序必须不断地扫描计算机内存中用于事件发生的部分,即只要程序在运行就会不断寻找事件。显然,只要移动或点击了鼠标或按下了按键,就会发生事件,这些事件在哪里呢?比如,在内存中存储事件的部分就是事件队列,事件队列就是发生的所有事件的列表,这些事件按它们发生的顺序排列。

如果需要编写一个游戏,则程序必须知道用户什么时候按下一个按键或移动了鼠标。而这些按键动作、点击或移动鼠标都是事件,而且程序必须知道如何应对这些事件,它必须处理事件,程序中处理某个事件的部分称为 事件处理器。而事实上并不是发生的每一个事件都要处理,比如,在桌面移动鼠标就会产生成百上千个事件,因为事件循环运行得非常快。每一个瞬间即使鼠标只是移动了一点点,也会生成一个新的事件。不过你的程序可能并不关心鼠标的每一个小小的移动,它可能只关心用户什么时候点击某个部分,因此你的程序可以忽略鼠标移动事件,只关注鼠标点击事件。

事件驱动程序中,对于所关心的各种事件会有相应的事件处理器。如果你有一个游戏使用键盘上的方向来控制一艘船的移动,可能要为 keyDown 事件写一个处理器;相反,如果使用鼠标控制这艘船,就可能为 mouseMove 事件写一个事件处理器。

另一种有用的事件是软件定时器事件,定时器会按设定的间隔生成事件,就像闹钟一样,如果设定好闹钟,并将闹钟打开,每天它都会在固定的时刻响起来。比如,(宏观上)同时处理两个事件。其中,一个为键盘输入事件,另一个为时间事件,用于显示运行的时间,每秒显示一次。

显然,可以在 main()函数设置一个循环,依次检查是否有键盘输入和时间是否到 1 秒?其实都可以直接调用固定的函数来实现“键盘输入处理代码”和“时间处理代码”,但这样不够灵活,此时可以用中断机制来实现,即由硬件来实现对事件的检测并调用指定的函数,这样一来使用注册回调函数机制也就成为了必然。而注册回调函数就是事先用一个函数指针变量保存指定的函数,然后在事件发生时,通过这个函数指针变量调用指定的函数。

>>>4.4.2 软件定时器

我们知道,数码管显示主要做两件事,其一,每隔 5ms 调用一次 digitron_disp_scan()动态扫描显示函数,其次,当需要改变显示内容时,则调用缓冲区操作接口,修改缓冲区中的内容。由于 MCU 设计了类似于闹钟那样的特定性的周期性的中断时钟节拍源,因此由时钟节拍源实现的定时器也是一个周期性的定时器,并产生周期性的中断,这个中断可以看做系统心脏的脉动。即当计数值等于定时时间时,则定时器立即触发中断,计数器重新开始计数,如此周而复始循环计数。

显然,可以使用定时器的周期性的中断实现自动扫描显示,即每隔 5ms 触发中断自动调用 digitron_disp_scan(),这样就可以将 MCU 解放出来执行其它的任务,从而得到更好的性能,其相应的接口函数详见表 4.3。程序员先调用软件定时器函数,然后等待操作完成。通常程序员提供一个由函数指针指定的回调函数,当操作完成后,中断系统会调用回调函数。

表 4.3 软件定时器接口函数

1. am_softimer_t 类型

从面向对象的角度来看,类相当于 C 语言的结构体,这里的 am_softimer_t 是用 typedef自定义的一个对用户隐藏的结构体类型。即:

在使用软件定时器时,需要使用该类型定义一个软件定时器实例(对象),实例的本质是定义一个结构体变量。比如:

显然,对象是类型的实例,即 timer 是 am_softimer_t 类型的一个实例。

2. 初始化软件定时器

事先将指定的函数保存在函数指针 p_func 中(注册),当定时时间到时,则通过 p_func调用指定的函数,即注册函数回调机制。

其中的 p_timer 为使用 am_softimer_t 类型定义的软件定时器实例,当定时时间到,则调用 p_func 指向的函数(注册回调函数),am_pfnvoid_t 是 AMetal 声明的函数指针类型,其定义(am_types.h)如下:

由此可见,p_func 指向的函数类型是无返回值,具有一个 void*型参数的函数。p_arg为用户自定义的参数,在定时时间到调用回调函数时,会将此处设置的 p_arg 作为作为参数传递给回调函数;如果不使用此参数,则设置为 NULL。如果返回 AM_OK,说明软件定时器初始化成功;如果返回-AM_EINVAL,说明由于参数错误导致初始化失败。初始化函数的使用范例详见程序清单 4.26。

程序清单 4.26 am_softimer_init ()函数范例程序

其中的 am_softtimer_init()函数(A)与用户自定义的任务函数(C)同属于上层模块的函数,timer_callback()函数(B)为下层模块的函数。由于事先已经将 timer_callback()的地址 time_callback 保存在 p_func 中了,因此,当 am_softtimer_init()调用 timer_callback()时,仅需将用户自定义的任务函数的入口地址作为实参传递给 timer_callback()的形参,即可通过函数指针变量 p_arg 在某个时刻回调用户自定义的任务函数,即在函数 A 调用函数 B 中直接调用回调函数 C。即只要在每次调用 timer_callback()时,给出不同的函数名作为实参,即可回调相应的函数,却不必修改 timer_callback()。

3. 启动软件定时器

启动定时器并设置定时时间(单位 ms),然后定时器开始计数。当计数值等于定时时间时,则定时器立即触发中断,计数器重新开始计数,如此周而复始循环计数。当定时器触发中断时,则程序跳转到调用 am_softimer_init()时 p_func 指向的函数,其函数原型为:

p_timer 为使用 am_softimer_t 类型定义的软件定时器实例,ms 为定时时间,单位 ms。如果返回 AM_OK,说明启动定时器成功;如果返回-AM_EINVAL,说明失败参数错误。设置定时器以实现数码管自动扫描显示的代码详见程序清单 4.27。

程序清单 4.27 自动扫描显示实现

程序中,digitron_softimer_set()函数初始化并启动了一个软件定时器,并在定时器回调函数中调用了数码管扫描函数,进而实现了数码管自动扫描。

为了更方便的使用自动扫描,可以将 digitron_softimer_set()合并到 digitron_init()中,形成一个新的 digitron_init_with_softimer(),当用户需要数码管初始化后自动扫描时,只需调用该带软件定时器的初始化函数即可,详见程序清单 4.28。

程序清单 4.28 digitron1.h 文件内容

如程序清单 4.29 所示为再次迭代的 0~59 秒循环显示程序。

程序清单 4.29 0~59 秒计数器范例程序(3)

既然程序是每隔 1s 计数器加 1 后更新缓冲区数据的,那么同样可以使用软件定时器实现每秒加 1 的操作,迭代后的代码详见程序清单 4.30。

程序清单 4.30 0~59 秒计数器范例程序(4)

当启动软件定时器后,秒计数器加1和更新缓冲区数据的工作自动在timer_sec_callback()函数中完成,不再需要主程序干预。现在 while(1)主循环什么事情都不用做,同样实现了 0~59的循环显示。这样一来,数码管就会独立地工作了,那么在 while(1)主循环中,就可以直接去做其它事情。以后遇到“每隔一定时间做某件事”的问题,均可使用软件定时器来实现。

虽然用软件定时器实现自动扫描显示的方法非常巧妙,流程也更加清晰,且程序还可以去做其它的事情,但却是以牺牲程序空间为代价的,即软件定时器要占用一个硬件定时器,以及 438 个字节的 Flash 和 12 个字节的 RAM。同时在使用软件定时器时,由于新建一个软件定时器必须定义一个定时器实例,每个定时器实例还要占用 24 字节,因此要根据硬件资源做出取舍。

4. 关闭软件定时器

当软件定时器关闭时,如果再次启动,则调用 am_softimer_start()重新启动。即:

其中的 p_timer 为使用 am_softimer_t 类型定义的软件定时器实例,如果返回 AM_OK,说明停止定时器;如果返回-AM_EINVAL,即参数错误导致关闭失败,详见程序清单 4.31。

程序清单 4.31 am_softimer_stop ()范例程序

现在不妨在程序清单 4.30 的基础上,再增加一个小功能,即每秒加一、蜂鸣器“嘀”一声,详见程序清单 4.32。

程序清单 4.32 0~59 秒计数器+蜂鸣器综合范例程序(1)

通过运行发现,虽然计数器在每秒加 1 时,蜂鸣器也会发出“嘀”的一声,但数码管的某位却会熄灭一下。如果觉得看起来还不够明显,不妨将蜂鸣器的鸣叫时间增加到 500ms。奇怪!为何连显示都不正常了呢?

虽然此前在 main()函数的 while(1)主循环中也使用了延时,但在主程序的延时期间,软件定时器定时时间到而产生的中断事件是可以抢占 MCU 的,所以不会影响其它事件的继续运行。如果在中断环境中调用 buzzer_beep(),程序必须等到蜂鸣器鸣叫结束后才会返回,这样一来就会使回调函数产生 100ms 的延时,从而导致 MCU 被完全占用,不仅 while(1)主循环无法执行,而且连其它的中断事件也无法执行。比如,另一个软件定时器中的数码管动态扫描也就无法执行了,所以在这 100ms 时间内,无法实现数码管动态扫描,于是只有一个数码管显示,另外一个数码管无法显示而处于熄灭的状态。

在这种情况下,应尽可能地将相应功能设计为异步模式,即启动软件定时器,设定蜂鸣器鸣叫时间,打开蜂鸣器,函数立即返回。待定时时间到,则自动调用回调函数,然后在回调函数中关闭蜂鸣器并停止定时器。这就是使用软件定时器实现 buzzer_beep_async()的由来,异步模式的优点是无需等待,函数立即返回,即可在任意地方调用该函数了,再也不会因为

延时而带来副作用,详见程序清单 4.33。

程序清单 4.33 实现蜂鸣器异步鸣叫函数

基于此,将 buzzer_beep_async()添加到 buzzer.h 以利于复用,详见程序清单 4.34。

程序清单 4.34 0~59 秒计数器+蜂鸣器综合范例程序(2)

4.5 键盘管理

>>> 4.5.1 独立按键

1. 消抖方法

对于质量不太好或者长期使用簧片氧化磨损的按键来说,常常会产生一种被称为“抖动”的现象。如图 4.12(a)所示为单触点按键的无消抖电路,当按键未按下时,则输出 Y 为高电平;当按下时,则输出 Y 为低电平。但由于按键的机械特性和人手指的不稳定性等综合因素,致使按键盘刚按下的瞬间,因接触不良而产生的反复跳动现象,即“抖动”,同样在按键释放的瞬间也可能产生“抖动”,结果输出 Y 在这一瞬间产生了多个窄脉冲干扰,这些脉冲信号的宽度一般可达毫秒,详见图 4.12 (b)。

图 4.12 无消抖按键电路及波形

“抖动”的脉冲宽度一般有几十到几百微秒,但也可能达到毫秒级,这对运行速度很快的数字电路会产生很大的影响。如果将发生“抖动”现象的按键连接到计数电路的时钟输入端,则检测到每按一次键都会产生一串极不稳定的脉冲。

对实际的产品来说,按键在长时间的使用中永不产生“抖动”是不可能的,但只要预防可能产生的“抖动”即可。抖动其实只持续了一小段时间,软件延时就是在按键产生“抖动”的这段时间里,用“拖延时间”的方法避开,从而消除因“抖动”而产生的错误信号,其示意图详见图 4.13。在按下键的瞬间启动定时器开始延时,延时 td 时间后再判断按键是否仍然按下,若仍按下则本次按键有效,否则本次按键无效。延时消抖由于过程比较复杂,比较适合用软件实现,因此称为软件消抖。

图 4.13 延时消抖

2. 电路原理

一般来说,在用法上按键可分为独立按键和矩阵键盘两大类。LPC824 的 P0_10、P0_11是标准的开漏结构,无内部上拉电阻,因此连接按键时必须加上拉电阻。其它的 14 个 GPIO口均有可编程使能的内部上拉电阻,虽然 MCU 内部有几十 KΩ以上的上拉电阻,但均属于弱上拉,所以在实际的应用中,一般都会外接一个阻值适中的上拉电阻,以提高可靠性。

对于独立按键来说,要求比较简单,既不考虑多个键同时按下,也不考虑长按的情况。仅识别是否有键按下的情况,即有键按下一次执行一次操作。如图 4.14 所示是一个独立按键电路图,只要将 AM824-Core的 J14_1 与 J14_2 短接,则 KEY 键接入 PIO0_1。

图 4.14 独立按键电路图

由于一次按键的时间通常都是上百毫秒,相对于 MCU 来说是很长的,因此不需要时时刻刻不断地检测按键,只需要每隔一定的时间(如 10ms)检测 GPIO 的电平即可。其检测方法如下(1 表示高电平、0 表示低电平):

(1)当无键按下时,由于 PIO0_1 内部自带弱上拉电阻,因此 PIO0_1 为 1;

(2)当 KEY 按下时,则 PIO0_1 为 0。在下一次扫描(延时 10ms 去抖动)后,如果PIO0_1 为 1,说明错误触发;如果 PIO0_1 还是 0,说明确实有键按下,执行相应的操作;

(3)当 KEY 释放时,则 PIO0_1 为 1,在下一次扫描(延时 10ms 去抖动)后,如果PIO0_1 为 0,说明错误触发;如果 PIO0_1 还是 1,说明按键已经释放,执行相应的操作。

3. Key 软件包

AMetal 提供了独立按键初始化和按键扫描函数接口(key1.h),详见程序清单 4.35。

程序清单 4.35 key1.h 接口

如程序清单 4.36 所示为独立按键的范例程序,如果有键按下,则蜂鸣器“嘀”一声;当按键释放后,则 LED0 翻转。

程序清单 4.36 独立按键范例程序

显然,每隔 10ms 调用一次 key1_scan(),即可根据 key_return 的值判断按键事件的产生,但这又是“每隔一段时间做某事”。如果使用软件定时器定时自动扫描,则无需在 while(1)中每隔 10ms 调用一次 key1_scan(),详见程序清单 4.37。

程序清单 4.37 添加软件定时器后的按键范例程序

程序中新增了一个初始化软件定时器 key1_softimer_set(),并启动软件定时器以 10ms的时间间隔,通过 key1_softimer_callback()回调 key1_scan()实现按键扫描。当按键事件发生(返回值不为 0xFF)时,则调用 key1_process()按键处理程序,根据扫描得到的返回值判断按键事件的发生。在 key1_process()按键处理程序中,当有键按下时,蜂鸣器“嘀”一声;当按键释放时,LED0 翻转。由于 key1_process()是在中断环境的回调函数中调用的,因此不能出现阻塞式语句,必须调用异步模式下的 buzzer_beep_async()。

在这里,与软件定时器相关的代码直接放在主程序中,而在实际使用时,更希望将实现和声明分别放在 key1.c 和 key1.h 中,因此需要增加一个接口函数:

虽然按键与数码管都可以使用软件定时器实现自动扫描,但它们之间却存在一定的差异,数码管只要自动扫描即可,但对于按键自动扫描,当扫描到按键事件发生时,还必须通知应用程序做相应的处理。而实际上在封装模块时,并不知道应用程序要做什么事,唯一的办法是采用注册回调机制。当按键事件发生时,调用相应的注册函数。如果需要使用软件定时器,则在初始化时注册一个函数,以便按键事件发生时调用。定义回调函数类型为:

重新定义带软件定时器的初始化函数类型为:

为了便于使用,将上述函数声明和回调函数类型定义添加到程序清单 4.38 所示的 key1.h中,其相关实现代码添加到程序清单 4.39 所示的 key1.c 中。

程序清单 4.38 key1.h 文件内容

程序清单 4.39 新增使用软件定时器自动扫描的程序(key1.c)

当有键按下时,则蜂鸣器“嘀”一声;当按键释放时,则 LED0 翻转,经过迭代后的代码详见程序清单 4.40。

程序清单 4.40 使用软件定时器自动进行按键扫描范例程序

>>> 4.5.2 矩阵键盘

独立按键必须占用一个 I/O 口,当按键数目较多时,这种每个按键占用一个口的方法就显得很浪费了。如何用尽可能少的 I/O 口去管理较多的按键呢?矩阵形式键盘电路就是使用最多的一种,如图 4.15 所示就是一种典型的矩阵式 2×2 键盘电路。采用矩阵键盘方式进行排列,其中 KR0、KR1 为行线,KL0、KL1 为列线。

图 4.15 2×2 矩阵键盘

该接法将口线分成行线(row)和列线(column),如果将它变成比较容易理解的拓扑结构,就是两组垂直交叉的平行线,每个交叉点就是一个按键位置,按键的两端分别接在行线和列线上。其最大优点是组合灵活,假如有16 个 I/O 可用于扩展做键盘电路,我们可以将它接成 6×10、5×11 或 8×8 等多种接法,当然,使用效率最高的是 8×8 的接法,它最多可实现 64 个按键。

MiniPort-Key 按键模块集成了 4 个按键,通过 MiniPort B(排母)与 AM824-Core 相连,同时引出其余不用的 I/O,实现模块的横向堆叠,其对应 AM824-Core 的 MiniPort 接口的 J4的功能定义详见图 4.16。

图 4.16 按键模块实物与接口定义图

2×2 的矩阵键盘共有 4 个按键,分别为 KEY0~KEY3。KR0、KR1 为行线(row),KL0、KL1 为列线(column)。假设选择 KL0、KL1 为输入,当无键按下时,由于内部弱上拉作用,此时读取电平为高电平。当 KEY0 按下时,KL1 依然为高电平,而 KL0 在 KR0 输出低电平时就会得到低电平。显然,只有 KR0、KR1 输出为低电平时,KL0、KL1 才能得到低电平,这就是逐行扫描键盘的方法,即行线为输出,列线为输入,每次扫描一行,扫描该行时,对应行线输出为低电平,其余行线输出为高电平,然后读取所有列线的电平,若有列线读到低电平,则表明该行与读到低电平的列对应的交叉点有按键按下。逐列扫描法恰好相反,其列线为输出,行线为输入,但基本原理还是一样的。AMetal 针对矩阵键盘提供了相应的 matrixkey.h 接口,详见程序清单 4.41。

程序清单 4.41 matrixkey.h 接口

如程序清单4.42所示是使用上述接口的范例程序,即当有键按下时,蜂鸣器在发出“嘀”的一声的同时,通过 LED0 和 LED1 的组合显示按键编号。比如,KEY0 键按下时,两个 LED灯均熄灭。KEY1 按下时显示 01,即 LED0 亮,LED1 熄灭,依此类推。

程序清单 4.42 矩阵键盘范例程序

为了节省引脚,还可以将数码管与矩阵键盘结合起来使用,如图4.17 所示的数码管的 2个 com 端与矩阵键盘的列线是复用的,PIO0_17与 PIO0_23 既是数码管的 com0、com1,又是矩阵键盘的列线 KL0、KL1这样设计反而节省了引脚。作为键盘扫描时需将列线配置为输入,作为数码管扫描时需将 com 端设置为输出。

图 4.17 LED 显示器电路

为了不影响数码管的显示,在键盘扫描结束后,必须将管脚恢复为输出状态。这是由

函数实现的。键盘扫描只需要每隔 10ms 进行一次,而数码管扫描需要每隔 5ms 进行一次,当它们同时使用时,可以在按键扫描的 10ms 内进行 2 次数码管扫描。

利用 4 个按键和数码管,实现一个按键调节值的小应用,各个按键的功能定义如下:

  • KEY0:进入设置状态。点击后进入设置状态,默认个位不断闪烁,再次点击后回到正常运行状态;

  • KEY2:切换当前调节的位。当进入设置状态后,当前调节的位会不断地闪烁。点击该键可以切换当前调节的位,由个位切换到十位,或由十位切换到个位;

  • KEY1:也称为+1 键,将当前正在闪烁的位的值加 1;

  • KEY3:也称为-1 键,将当前正在闪烁的位的值减 1。

其相应的范例程序详见程序清单 4.43。

程序清单 4.43 矩阵键盘+数码管范例程序(2)


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 定时器
    +关注

    关注

    23

    文章

    3106

    浏览量

    111846
  • 周立功
    +关注

    关注

    38

    文章

    130

    浏览量

    37035

原文标题:周立功:面向接口的编程——事件驱动和键盘管理

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    薄膜键盘领域设计#键盘

    薄膜键盘
    泰达克电子材料
    发布于 :2024年01月09日 11:30:41

    当下热门的AI智能键盘到底怎么样?两款AI键盘到手实测

    有很多人会问AI都能用在键盘上了吗,我只想说随着AI的大力发展AI已经开始应用在各行各业中了, AI键盘的方便快捷确实能提升不少效率,小编在使用了一段时间后也是叹为观止,下面来分析测评一下
    的头像 发表于 01-02 17:51 246次阅读
    当下热门的AI智能<b class='flag-5'>键盘</b>到底怎么样?两款AI<b class='flag-5'>键盘</b>到手实测

    电源管理入门:驱动Runtime PM管理

    Runtime PM管理也就是设备驱动里面的电源管理,即设备驱动结构体里面的struct dev_pm_ops,只控制设备自己的电源。这样可以在设备不需要工作的时候可以进入到低功耗状态
    的头像 发表于 11-29 10:13 538次阅读
    电源<b class='flag-5'>管理</b>入门:<b class='flag-5'>驱动</b>Runtime PM<b class='flag-5'>管理</b>

    差分驱动分析

    差分驱动器可以由单端或差分信号驱动。本教程利用无端接或端接信号源分析这两种情况。 情形1:差分输入、无端接信号源 图1显示一个差分驱动器由一个平衡的无端接信号源
    发表于 11-28 15:19 0次下载
    差分<b class='flag-5'>驱动</b>器<b class='flag-5'>分析</b>

    阅读矩阵键盘的应用设计原理

    矩阵键盘以行和列的网格布线(尽管它们实际上不必以那个方向布置,例如在电子钢琴键盘的例子中)。在微控制器上,行或列引脚被永久设置为输入(在本文中,我们将坚持使用行连接实现此目的),而另一组引脚(在本文中,我们将坚持使用列连接实现此目的)在输出(
    的头像 发表于 11-28 11:09 351次阅读
    阅读矩阵<b class='flag-5'>键盘</b>的应用设计原理

    基于单片机的独立键盘与矩阵键盘检测

    独立键盘,是指每一个键位单独由一个IO口控制的按键。
    的头像 发表于 10-31 15:00 463次阅读
    基于单片机的独立<b class='flag-5'>键盘</b>与矩阵<b class='flag-5'>键盘</b>检测

    ARM系统中常用的行列式键盘电路的硬件设计、键盘扫描及键盘测试

    电子发烧友网站提供《ARM系统中常用的行列式键盘电路的硬件设计、键盘扫描及键盘测试.doc》资料免费下载
    发表于 10-26 14:15 0次下载
    ARM系统中常用的行列式<b class='flag-5'>键盘</b>电路的硬件设计、<b class='flag-5'>键盘</b>扫描及<b class='flag-5'>键盘</b>测试

    显示驱动芯片产业分析报告

    显示驱动解决方案:一套完整的显示驱动解决方案,一般由源极驱动器、栅极驱动 器、时序控制芯片和显示屏电源管理芯片组成。而源极
    发表于 10-18 17:31 11次下载
    显示<b class='flag-5'>驱动</b>芯片产业<b class='flag-5'>分析</b>报告

    stm32f107 usbotg键盘如何判断通信失败?

    如题,现在开发了一款键盘,开机之后偶尔不识别,设备管理器出现unknown device。现在有个思路就是键盘自己判断通信失败,然后复位usb。有大佬帮忙介绍一下具体如何操作吗?
    发表于 09-25 07:06

    基于FPGA的4x4矩阵键盘驱动设计

    本次设计采用FPGA驱动4x4矩阵键盘,这个原理其实很简单,但是我在做的时候曾经理解错了一个地方,导致走了一天的弯路,因为感觉比较有意思,所以想在这分享一下。
    的头像 发表于 07-23 11:41 1703次阅读
    基于FPGA的4x4矩阵<b class='flag-5'>键盘</b><b class='flag-5'>驱动</b>设计

    在Proteus软件中如何读取矩阵键盘

    矩阵键盘是读取一系列按键的有效方法,例如读取电话的拨号盘、POS机小键盘、电脑键盘,甚至是电子钢琴上的键盘
    的头像 发表于 07-19 15:26 2046次阅读
    在Proteus软件中如何读取矩阵<b class='flag-5'>键盘</b>?

    LED数显驱动芯片/数码管驱动芯片VK1650,LED驱动键盘扫描,8段4位,8级亮度控制

      产品品牌:永嘉微电/VINKA 产品型号:VK1650 封装形式:SOP16 产品年份:新年份  概述: VK1650是一种带键盘扫描电路接口的 LED 驱动控制专用芯片,内部集成有数
    的头像 发表于 06-10 09:17 1637次阅读
    LED数显<b class='flag-5'>驱动</b>芯片/数码管<b class='flag-5'>驱动</b>芯片VK1650,LED<b class='flag-5'>驱动</b>、<b class='flag-5'>键盘</b>扫描,8段4位,8级亮度控制

    LED驱动电源电路分析

    今天给大家简单分析一个LED驱动电路,供大家学习。
    发表于 05-24 17:07 1624次阅读
    LED<b class='flag-5'>驱动</b>电源电路<b class='flag-5'>分析</b>

    rt-thread SDIO驱动框架分析(贴片SD卡flash驱动\SD Nand flash驱动

    文章目录rt-threadSDIO驱动框架分析之SD卡驱动1.前言2.SDIO通用驱动框架介绍3.文件架构分析4.SDIO设备
    的头像 发表于 04-04 17:41 517次阅读
    rt-thread SDIO<b class='flag-5'>驱动</b>框架<b class='flag-5'>分析</b>(贴片SD卡flash<b class='flag-5'>驱动</b>\SD Nand flash<b class='flag-5'>驱动</b>)

    Flashmagic安装导致无线键盘和鼠标问题如何解决?

    似乎没有任何效果。我想知道 Flashmagic 安装是否与无线键盘和鼠标驱动程序发生了某种冲突。安装 Flashmagic 后是否有其他人遇到过类似问题?如果是这样,您对如何解决问题有什么建议吗?我需要我的键盘和鼠标才能正常工
    发表于 03-31 06:43