首页 文章 精选 留言 我的

精选列表

搜索[云原生智能网关],共10009篇文章
优秀的个人博客,低调大师

【物联网智能网关-03】GPRS模块中文短信收发

在去年年初,就已经推出V1.0.0的GPRS库,不过在这个版本上只是实现了西文短信收发和字符串方式的GPRS数据通信,功能还相对不完善(参见我以前的博文《GPRS通信实现》)。最近升级的版本,对以上功能进行了大幅度的升级改进,比如支持PDU方式收发短信(支持中文)、彩信发送、二进制方式 GPRS数据收发、短信按类型提取、短信删除和短信事件通知等等功能。 考虑到功能比较多,我们分三篇文章来介绍最新的GPRS库的功能,这一篇我们先介绍和短信收发相关的内容。 库函数中和短信收发相关的方法如下: (1)设置短消息中心地址 声明:int SetCenterNum (sring CenterNum) 参数:CenterNum– 短消息中心地址 返回:操作返回值 0 – 发送成功 -1 - 设置失败 说明:短消息中心地址。联通和移动不同地区,号码都不同,一般情况下,不需要专门设置 (2)发送短信(PDU方式) 声明:int SendMessage (sring phone,string msg) 参数:phone – 电话号码 msg – 要发送的字符串 返回:操作返回值 0 – 发送成功 -1 – 字符长度为0或大于70个字节 -2 – 设置短消息格式失败 - 3 –发送短信失败 说明:发送短信。支持中文字符发送。 (3)读取短信 声明:int ReceiveMessage(out GsmMessage[] msgs,MessageType msgType) 参数:msgs – 信息集合,每一项都包括,短信发送的电话,发送时间和内容 msgType – 消息类型:未读消息,已读消息,未发消息,已发消息,全部消息 返回:返回指定类型的短信字符串集合。 说明:接收短信。目前支持中英文短信接收。 (4)删除短信 声明:int DeleteMessage () 参数:无 返回:操作返回值 0 – 删除0个消息 -1 – 设置PDU模式失败 >0 – 删除的短消息个数 说明:删除全部的短消息。 除了方法外,还有一个短信收到事件,具体声明如下: (1)短信收到通知 声明:SMSMessageReceivedEventHandler MessageReceived 参数:object sender – GPRS类的实例 说明:短信接收通知 为了便于说明库的使用,我们设定一个场景,来进行相关代码的功能演示。 场景是这样设定的: (1)、程序不断采集温湿度数据,一旦超出预先设置好的范围,就会短信通知报警。 (2)、手机发送短信,控制继电器,可以远程打开和关闭加湿器。 具体代码如下(其中温湿度采集部分,详情请参见:通过AD采集获取温湿度): (1)、GPRS模块初始化相关代码 int ret = 0; gprs = new GPRS("COM3", 115200, GPRS.GprsType.SIM300_V6_x); //打开GPRS模块 if ((ret = gprs.Open()) != 0) { Debug.Print("Open Failed:" + ret.ToString()); gprs.Close(); screen.DrawText("打开GPRS模块失败", font, Colors.Red, 20, 60); screen.Flush(); return; } Debug.Print("Open OK"); screen.DrawText("打开GPRS模块成功", font, Colors.Green, 20, 60); screen.Flush(); //判断是否在线,超时时间10s if ((ret = gprs.IsOnline(10000)) != 0) { Debug.Print("AT Failed:" + ret.ToString()); gprs.Close(); screen.DrawText("GPRS模块不在线", font, Colors.Red, 20, 100); screen.Flush(); return; } Debug.Print("AT OK"); screen.DrawText("GPRS模块在线", font, Colors.Green, 20, 100); screen.Flush(); //GPRS模块初始化 if ((ret = gprs.Initialize()) != 0) { Debug.Print("Initialize Failed:" + ret.ToString()); gprs.Close(); return; } Debug.Print("Initialize OK"); screen.DrawText("GPRS初始化成功", font, Colors.Green, 20, 140); screen.Flush(); //显示信号强度 //Debug.Print("Signal:" + gprs.Signal.ToString()); gprs.MessageReceived += new SMSMessageReceivedEventHandler(gprs_MessageReceived); (2)、GPRS模块短信接收并控制部分 static void gprs_MessageReceived(object sender) { int ret = 0; GsmMessage[] msgs = null; //读未读的短消息 if ((ret = gprs.ReceiveMessage(out msgs, GPRS.MessageType.REC_UnRead)) < 0) { Debug.Print("ReceiveMessage Failed:" + ret.ToString()); } else { if (ret > 0) { foreach (GsmMessage msg in msgs) { Debug.Print(msg.ToString()); } //gprs.SendMessage(msgs[0].phone, msgs[0].ToString()); switch (msgs[0].message) { case "开": opSwitch.Write(true); State = true; break; case "关": opSwitch.Write(false); State = false; break; } } } //删除短消息 //gprs.DeleteMessage(); } (3)湿度报警相关代码 //湿度报警 if (H > 60 && !AlarmFlag) { //发送报警短信(实际应用时,请填入实际的电话号) gprs.SendMessage("158XXXXXXX", "当前湿度:" + H.ToString("F2")); AlarmFlag = true; } if (AlarmFlag && H < 50) { AlarmFlag = false; } 实际运行效果图: 说明:硬件平台采用最新的紫藤207系统;GPRS模块采用Sim300 V6.02版本的模块;继电器模块采用5V驱动,可控制220V 10A的电器,一般家用小功率电器可以直接使用;温湿度模块采用了相对低价的AD接口的模块。 下一篇博文,将介绍GPRS模块是如何发送彩信的,敬请期待。 本文源码:http://www.sky-walker.com.cn/MFRelease/Sample/YF_GPSR01.rar 类库下载:http://www.sky-walker.com.cn/MFRelease/library/v42/YFSoft.Hardware.GPRS.rar MF简介:http://blog.csdn.net/yefanqiu/article/details/5711770 MF资料:http://www.sky-walker.com.cn/News.asp?Id=25 本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/882120,如需转载请自行联系原作者

优秀的个人博客,低调大师

【物联网智能网关-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 NativeEventHandler OnInterrupt; OutputPort[] rows = null; InputPort[] cols = null; public ScanKeypad(Cpu.Pin[] Output_Pins, Cpu.Pin[] Input_Pins) { rows = new OutputPort[] { new OutputPort(Output_Pins[0], false), new OutputPort(Output_Pins[1], false), new OutputPort(Output_Pins[2], false), new OutputPort(Output_Pins[3], false) }; cols = new InputPort[] { new InputPort(Input_Pins[0], true, Port.ResistorMode.PullUp), new InputPort(Input_Pins[1], true, Port.ResistorMode.PullUp), new InputPort(Input_Pins[2], true, Port.ResistorMode.PullUp), new InputPort(Input_Pins[3], true, Port.ResistorMode.PullUp) }; Thread threadKeypad = new Thread(new ThreadStart(KeypadScan)); threadKeypad.Start(); } void KeypadScan() { int key = -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; } else if (oldKey > -1 && key == -1) { if (OnInterrupt != null) OnInterrupt((uint)oldKey, 0, DateTime.Now); oldKey = -1; } Thread.Sleep(100); } } } 2、中断方式实现按键获取 public class InterruptKeypad { public event NativeEventHandler OnInterrupt; OutputPort[] rows = null; InterruptPort[] cols = null; Cpu.Pin[] Pins = null; uint key = 0; public InterruptKeypad(Cpu.Pin[] Output_Pins, Cpu.Pin[] Input_Pins) { rows = new OutputPort[] { new OutputPort(Output_Pins[0], false), new OutputPort(Output_Pins[1], false), new OutputPort(Output_Pins[2], false), new OutputPort(Output_Pins[3], false) }; cols = new InterruptPort[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); } } private uint GetPinIndex(uint pin) { for (uint i = 0; i < Pins.Length; i++) { if (pin == (uint)Pins[i]) return i; } return 0; } void InterruptKeypad_OnInterrupt(uint data1, uint data2, DateTime time) { if (data2 == 1) { for (int i = 0; i < cols.Length; i++) { cols[i].OnInterrupt -= new NativeEventHandler(InterruptKeypad_OnInterrupt); } //-- uint col = 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); } } } void KeypadRun() { 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脚不能使用。 以上两种方式都是在应用层面实现的,其实如果扫描键盘的pin脚固定,更好的方式可以在底层用C++实现,并且还可以把8个物理pin脚,虚拟出16个pin脚来,用法和物理的pin脚完全一样。 官方SimpleWPFApplication示例,是一个比较典型的WPF应用,但是需要5个按键才能操作,我们的紫藤207系统仅提供了一个物理按钮,所以是无法操作的。接上扫描键盘后,我们就有可能完整的演示这个示例了,不过由于我们使用的是扫描键盘,所以原程序无法使用,必须做如下修改才可以。 public sealed class GPIOButtonInputProvider { public readonly Dispatcher Dispatcher; private DispatcherOperationCallback callback; private InputProviderSite site; private PresentationSource source; public GPIOButtonInputProvider(PresentationSource source) { this.source = source; site = InputManager.CurrentInputManager.RegisterInputProvider(this); callback = new DispatcherOperationCallback(delegate(object report) { InputReportArgs args = (InputReportArgs)report; return site.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 }; InterruptKeypad key = new InterruptKeypad(Output_Pins, Input_Pins); key.OnInterrupt += new NativeEventHandler(key_OnInterrupt); } void key_OnInterrupt(uint data1, uint data2, DateTime time) { RawButtonActions action = (data2 != 0) ? RawButtonActions.ButtonUp : RawButtonActions.ButtonDown; RawButtonInputReport report = new RawButtonInputReport(source, time, GetButton(data1), action); Dispatcher.BeginInvoke(callback, new InputReportArgs(InputManager.CurrentInputManager.ButtonDevice, report)); } Button GetButton(uint data) { switch (data) { case 2: return Button.VK_UP; case 5: return Button.VK_LEFT; case 6: return Button.VK_SELECT; case 10: return Button.VK_DOWN; case 7: return Button.VK_RIGHT; } return Button.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 本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/932037,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册