`
mmdev
  • 浏览: 12894550 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

【物联网智能网关-05】扫描键盘编程设计

 
阅读更多

.NET Micro Framework模拟器提供了5个模拟按键(上、下、左、右和确认按键),所以一般.NET MF开发板也只需要提供5个按键就可以了,而这5个键,也是直接和CPU的pin脚相连,用GPIO的输入相关的函数就可以操作了,使用非常简单。

但是对一些特殊的应用,如一些.NET Micro Framework教育箱或一些工业实际用的系统,5个按键显然太少了点。但是如果需要十几个按键,如果直连芯片pin脚,显然占用的资源比较多了,也会导致其它的功能无法使用了,这时候最常用的就是扫描键盘了。


上述扫描键盘的原理图应该是最简单的一种了,复杂一点的,在行或列上,通过一个上拉电阻接VCC。这样,我们只需要8个pin脚,就可以获取16个按键的信息了。

一般实现的思路也比较简单:就是把行(或列)接芯片输出pin脚,把列(或行)接芯片输入pin脚,输出pin脚依次输出低(或高,需要看电路中接的上拉还是下拉电阻)电平,然后检查输入pin脚的电平变化。如果有变化,那么就说明,该列和该行的按键被按下了。

往往这个判断就放在while循环或线程里,不断的去运行。对一些单片而言,如果实现的功能单一,这样做也无可厚非,但是对一个系统平台来说,如果也这样做,显然对系统的资源占用还是比较厉害的。

所以最好的办法还是要采用中断的方式,平时的时候不去判断,靠中断触发,一旦中断触发了,然后再启动一轮判断,确定是哪一个按键被按下了。

1、扫描方式实现按键获取

public class ScanKeypad

{

public event NativeEventHandlerOnInterrupt;

OutputPort[]rows = null;

InputPort[]cols = null;

publicScanKeypad(Cpu.Pin[]Output_Pins, Cpu.Pin[]Input_Pins)

{

rows = newOutputPort[] { newOutputPort(Output_Pins[0], false), new OutputPort(Output_Pins[1], false), new OutputPort(Output_Pins[2], false), new OutputPort(Output_Pins[3], false) };

cols = newInputPort[] { newInputPort(Input_Pins[0], true, Port.ResistorMode.PullUp), newInputPort(Input_Pins[1], true, Port.ResistorMode.PullUp), newInputPort(Input_Pins[2], true, Port.ResistorMode.PullUp), newInputPort(Input_Pins[3], true, Port.ResistorMode.PullUp) };

ThreadthreadKeypad = new Thread(new ThreadStart(KeypadScan));

threadKeypad.Start();

}

voidKeypadScan()

{

intkey = -1, oldKey = -1;

while(true)

{

key = -1;

for(int i = 0; i < rows.Length; i++)

{

rows[i].Write(false);

for(int j = 0; j < cols.Length; j++)

{

if (!cols[j].Read())

{

key = i *rows.Length + j;

break;

}

}

rows[i].Write(true);

if(key > -1) break;

}

if(key > -1 && key != oldKey)

{

if(OnInterrupt != null) OnInterrupt((uint)key, 1, DateTime.Now);

oldKey = key;

}

elseif (oldKey > -1 && key == -1)

{

if(OnInterrupt != null) OnInterrupt((uint)oldKey, 0, DateTime.Now);

oldKey = -1;

}

Thread.Sleep(100);

}

}

}

2、中断方式实现按键获取

public class InterruptKeypad

{

public event NativeEventHandlerOnInterrupt;

OutputPort[]rows = null;

InterruptPort[]cols = null;

Cpu.Pin[] Pins = null;

uintkey = 0;

publicInterruptKeypad(Cpu.Pin[]Output_Pins, Cpu.Pin[]Input_Pins)

{

rows = newOutputPort[] { newOutputPort(Output_Pins[0], false), new OutputPort(Output_Pins[1], false), new OutputPort(Output_Pins[2], false), new OutputPort(Output_Pins[3], false) };

cols = newInterruptPort[Input_Pins.Length];

Pins = Input_Pins;

for(int i = 0; i < Input_Pins.Length; i++)

{

cols[i] = new InterruptPort(Input_Pins[i],true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);

cols[i].OnInterrupt += new NativeEventHandler(InterruptKeypad_OnInterrupt);

}

}

privateuint GetPinIndex(uintpin)

{

for(uint i = 0; i < Pins.Length; i++)

{

if(pin == (uint)Pins[i]) returni;

}

return0;

}

voidInterruptKeypad_OnInterrupt(uint data1, uint data2, DateTimetime)

{

if(data2 == 1)

{

for(int i = 0; i < cols.Length; i++)

{

cols[i].OnInterrupt -= new NativeEventHandler(InterruptKeypad_OnInterrupt);

}

//--

uintcol = GetPinIndex(data1);

for(int i = 0; i < rows.Length; i++)

{

rows[i].Write(true);

if(cols[col].Read())

{

key = (uint)(i * rows.Length + col);

Thread threadKeypad = new Thread(new ThreadStart(KeypadRun));

threadKeypad.Start();

break;

}

}

//--

for(int i = 0; i < rows.Length; i++)rows[i].Write(false);

for(int i = 0; i < cols.Length; i++)

{

cols[i].OnInterrupt += new NativeEventHandler(InterruptKeypad_OnInterrupt);

}

}

}

voidKeypadRun()

{

OnInterrupt(key, 1, DateTime.Now);

OnInterrupt(key, 0, DateTime.Now);

}

}

注意,中断方式中,触发事件必须放在线程里执行,否则会有问题(如果在Winform中使用,最好不用线程,而用winfrom提供的timer,否则就无法直接操作UI了,那就必须用委托方式了,和windows上的编程类似)。

问题点1:由于我们采用的键盘并没有加上拉(或下拉)电阻电路,在最初做这个程序的时候,InputPort(Input_Pins[1], true,Port.ResistorMode.PullUp),最后一个参数,底层并没有实现内部上拉,下拉和悬空功能,所以设置是无效的。这就造成了,在按钮没有按下时,输入pin脚的状态是未知的,有时候是1,有时候是0,程序是无法正确运行的。

此外STM32F103和STM32F207的GPIO寄存器差别很大,内部实现上拉、下拉的设置也是不同的。分别实现后,发现内部上拉正常,设置下拉效果不明显,pin脚的状态还是未知的。所以我们实现的程序都设置为上拉。

问题点2:在实现中断方式的扫描键盘的代码的时候,发现PB6、PC0和PB1三个pin脚触发中断异常,但是在NativeSample层面又正常。目前没有发现这三个pin脚有何特别之处,此问题以后待查。所以如果采用中断方式,这三个pin脚不能使用。

注:该问题已修正,需要更新固件(版本V1.6.10以上),另外示例需要参考最新的扫描键盘示例。

以上两种方式都是在应用层面实现的,其实如果扫描键盘的pin脚固定,更好的方式可以在底层用C++实现,并且还可以把8个物理pin脚,虚拟出16个pin脚来,用法和物理的pin脚完全一样。

官方SimpleWPFApplication示例,是一个比较典型的WPF应用,但是需要5个按键才能操作,我们的紫藤207系统仅提供了一个物理按钮,所以是无法操作的。接上扫描键盘后,我们就有可能完整的演示这个示例了,不过由于我们使用的是扫描键盘,所以原程序无法使用,必须做如下修改才可以。

public sealed class GPIOButtonInputProvider

{

public readonly DispatcherDispatcher;

privateDispatcherOperationCallback callback;

privateInputProviderSite site;

privatePresentationSource source;

publicGPIOButtonInputProvider(PresentationSourcesource)

{

this.source= source;

site = InputManager.CurrentInputManager.RegisterInputProvider(this);

callback = newDispatcherOperationCallback(delegate(objectreport)

{

InputReportArgsargs = (InputReportArgs)report;

returnsite.ReportInput(args.Device, args.Report);

});

Dispatcher = Dispatcher.CurrentDispatcher;

Cpu.Pin[] Output_Pins = { (Cpu.Pin)GPIO_NAMES.PC8,(Cpu.Pin)GPIO_NAMES.PC9, (Cpu.Pin)GPIO_NAMES.PB7,(Cpu.Pin)GPIO_NAMES.PC2 };

Cpu.Pin[] Input_Pins = { (Cpu.Pin)GPIO_NAMES.PC3,(Cpu.Pin)GPIO_NAMES.PA0, (Cpu.Pin)GPIO_NAMES.PA5,(Cpu.Pin)GPIO_NAMES.PA6 };

InterruptKeypadkey = new InterruptKeypad(Output_Pins,Input_Pins);

key.OnInterrupt += new NativeEventHandler(key_OnInterrupt);

}

voidkey_OnInterrupt(uint data1, uint data2, DateTimetime)

{

RawButtonActionsaction = (data2 != 0) ? RawButtonActions.ButtonUp: RawButtonActions.ButtonDown;

RawButtonInputReportreport = new RawButtonInputReport(source,time, GetButton(data1), action);

Dispatcher.BeginInvoke(callback, new InputReportArgs(InputManager.CurrentInputManager.ButtonDevice,report));

}

ButtonGetButton(uint data)

{

switch(data)

{

case2:

returnButton.VK_UP;

case5:

returnButton.VK_LEFT;

case6:

returnButton.VK_SELECT;

case10:

returnButton.VK_DOWN;

case7:

returnButton.VK_RIGHT;

}

returnButton.None;

}

}

把GpioButtonInputProvider.cs里面的程序这样修改后,就可以使用了。

效果图如下:

实际运行视频链接如下:

http://v.youku.com/v_show/id_XNDI3ODU4OTg4.html

从视频可以看出,STM32F207平台运行WPF程序还是蛮流畅的。

-------------------------------------------------------------------------------

下载地址:http://www.sky-walker.com.cn/MFRelease/Sample/ScanKey_WPFTest.rar

MF简介:http://blog.csdn.net/yefanqiu/article/details/5711770

MF资料:http://www.sky-walker.com.cn/News.asp?Id=25



分享到:
评论

相关推荐

    xiuno模板知乎蓝魔改版源码附多个插件.zip

    xiuno模板知乎蓝魔改版源码附多个插件

    webview支持html5视频播放实例.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    PLC04-1 S7200.ppt

    PLC04-1 S7200.ppt

    CODESYS-2.3.9.61 WAGO-SW0759-0333-V20200326-Codesys-S-2020

    CODESYS_2.3.9.61 WAGO_SW0759-0333_V20200326_Codesys_S_2020

    DSP原理及应用总复习.ppt

    DSP原理及应用总复习.ppt

    基于Python从纯文本中提取出人物关系网络,并用Gephi 将生成的网络可视化源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Python从纯文本中提取出人物关系网络,并用Gephi 将生成的网络可视化源码+使用文档+全部资料(优秀项目).zip基于Python从纯文本中提取出人物关系网络,并用Gephi 将生成的网络可视化源码+使用文档+全部资料(优秀项目).zip基于Python从纯文本中提取出人物关系网络,并用Gephi 将生成的网络可视化源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过mac/window10/11测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    可二次开发springmvc实现登陆.rar

    标题:基于SpringMVC的可二次开发登录系统本系统采用流行的Java Web框架——SpringMVC,构建了一个可二次开发的登录模块。通过细致的模块化设计,确保了系统的高内聚、低耦合特性,为进一步的功能扩展提供了便利。系统实现了用户认证与授权的基础流程,并支持自定义的认证机制和权限控制,以适应不同场景的安全需求。界面友好、操作简洁,后端采用事务管理保证数据的一致性和安全性。此外,该系统还包含了详细的文档和注释,便于理解和维护。无论是作为毕业设计还是课程项目,它都是一个展示个人技术能力和快速学习能力的绝佳选择。重新回答||

    基于dijkstra算法求最短路径,可以求任意两点间的最短路径.rar

    基于dijkstra算法求最短路径,可以求任意两点间的最短路径.rar

    气动机械臂设计(机械CAD图纸).doc

    气动机械臂设计(机械CAD图纸).doc

    voicemod 变声器.zip

    voicemod 变声器.zip

    ssg-web workspace 日程管理系统

    会话管理,html,js,过滤器,servlet,ajax,tomcat

    仿赶集生活客户端的介绍动画界面.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    25.医院信息化管理系统的设计与实现-Springboot+ Mysql+Java+ B/S源码(含数据库脚本)+开发文档+lw

    25.医院信息化管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码(含数据库脚本)+开发文档+lw(高分毕设项目) 详细设计文档介绍链接:http://t.csdnimg.cn/OnXTu 内容概要: 全套项目源码+详尽文档,一站式解决您的学习与项目需求。 基于B/S即所谓浏览器/服务器模式,应用java技术,选择MySQL作为后台数据库。系统主要包括首页,个人中心,用户管理,医生管理,科室管理,医生信息管理,挂号信息管理,取消挂号管理,问诊记录管理,病房管理,药房管理,管理员管理等功能模块。 适用人群: 计算机、通信、人工智能、自动化等专业的学生、老师及从业者。 使用场景及目标: 无论是毕设、期末大作业还是课程设计,一键下载,轻松部署,助您轻松完成项目。 项目代码经过调试测试,确保直接运行,节省您的时间和精力。 其他说明: 项目整体具有较高的学习借鉴价值,基础能力强的可以在此基础上修改调整,以实现不同的功能。

    基于CNN卷积神经网络花朵花卉识别系统GUI界面.zip代码119

    基于CNN卷积神经网络花朵花卉识别系统,有数据集进行训练,可以增加其它花朵图像数据。 基于CNN卷积神经网络花朵花卉识别系统,有数据集进行训练,可以增加其它花朵图像数据。 基于CNN卷积神经网络花朵花卉识别系统,有数据集进行训练,可以增加其它花朵图像数据。

    Object-CC++对象库,实现类似于Java的Object类的Object

    【Object-C】C++对象库,实现类似于Java的Object类的Object, (a C++ Object library, implementating an Object similar to Java s Object class,) 文件列表: CMakeLists.txt (1300, 2023-10-16) LibObjClangPlugin/ (0, 2023-10-16) LibObjClangPlugin/CMakeLists.txt (3290, 2023-10-16) LibObjClangPlugin/ClangParser/ (0, 2023-10-16) LibObjClangPlugin/ClangParser/FindReplace/ (0, 2023-10-16) LibObjClangPlugin/Makefile (17354, 2023-10-16) LibObjClangPlugin/clang_format.sh (1387, 2023-10-16) LibObjClangPlugin/customParser.cpp (94410,

    多维报表.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    按住说话,开始录音,停止录音,显示到列表,点击列表项播放。.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    Deep Fake文本转语音.txt

    Deep Fake文本转语音.txt

    安卓伪加密工具.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    基于matlab 2Dijkstra最短路径算法的matlab程序,希望对大家有所帮助.zip

    基于matlab 2Dijkstra最短路径算法的matlab程序,希望对大家有所帮助.zip

Global site tag (gtag.js) - Google Analytics