首页 文章 精选 留言 我的

精选列表

搜索[api网关],共10000篇文章
优秀的个人博客,低调大师

【物联网智能网关-15】WAV播放器(WinForm+WavPlay库实例)

2002年在首钢实施焦炉四大机车自动化项目的时候,为了使系统更加友好,便增加了语音提示功能。不过控制设备是PLC,所以语音模块是通过IO进行控制的。接触WAV解码,是在2009年,为TI DM355平台移植.NET Micro Framework系统,同事进行驱动移植,我封装上层C#接口,不过那时候技术有限,封装的接口只能同步播放。 当前市场上的语音模块一般分两种,一种是可录音的模块,录上音,触发一下,就可以播放。另外一种就是烧录WAV文件(或其它自定义格式的语音数据)。前者往往很难做到分段录音分段播放,而后一种,由于是部署文件,所以相对容易的分段控制。控制方式一种是IO方式,另一种就是串口发命令控制。 最近和一个朋友合作开发一个医疗上的上肢康复设备,需要用到语音提示功能。最初想到的也是采用语音模块控制,便花了一百多元购买了两个语音模块进行研究,语音模块虽然有些小贵,但是价格和音质还可以,既可以用IO控制,也可以通过RS485发指令控制。不过朋友感觉外接一个模块的方式不大好,建议加一个解码芯片或PWM驱动控制。 因此便开始研究语音控制技术,由于.NET Micro Framework已经支持了DA输出功能,而STM32芯片时钟中断功能也比较强大,所以就尝试做WAV解码。没有想到实际做出的效果竟然非常好,特别是用外接音箱播放的时候,几乎可以媲美一些播放器的音质。 系统直接支持语音播放,可以非常方便实现各种功能,比如做一个报时功能,由于可能在任一个时间要求报时,所以不可能像整点报时一样,做20多个语音文件到时播放即可。更好的做法就是把各个语音分成单元,到时候用程序控制拟合播放。不仅仅是报时,如电子秤称重报数、计算器语音报时、智能家居控制中的智能提示,都需要语音。并且由文件系统支持,100多兆字节的存储空间,可以存放很多语音文件。不像一些语音模块,存储空间都是比较有限的,比如我采购的那款价格相对较高的语音模块,存储空间才8M。 下面我以一个WAV播放器为实例,介绍WAV播放类库的使用。 第一步:准备WAV声音文件 我们可以借助一些声音转换工具,把常见的MP3格式的文件转换为WAV格式的文件。比如GoldWave软件,声音文件最好重新采样,建议速率为16000Hz(最好不要大于44100Hz),如下图所示: 保存的格式,建议为:PCM unsigned 8bit,mono。16位、双声道播放(需要两路DA),WavPlay函数也是支持的,不过感觉没有必要,一是文件会增大几倍,但是音质改善并不大。 第二步:把WAV声音文件下载到文件系统 如果WAV文件不大,把WAV文件作为资源文件(WAV文件添加资源的时候,要修改扩展名,以二进制资源的方式加入)也是可以的,WavPlay函数可直接播放字节数组数据。但是对一些比较大的WAV文件,如一首歌曲,一般就得3M Byte左右的大小了,是不能添加到资源中去的。 我们还是用在博文《Html5:Canvas+WebSocket实现远程实时通信》中介绍的YFFileViewer工具,参见下图。 第三步:设计播放界面 我们采用YFSoft.WinForm库进行界面编写(WinForm相关博文,请参见《WinForm for .NET MF 功能一览》)。界面设计,我们还是先用桌面版的程序进行设计,设计好后,把代码加入.NET Micro Framework工程。 第四步:播放代码编写 (1) 枚举文件系统根目录下所有的WAV文件 string[] files = Directory.GetFiles("\\ROOT"); foreach (string file in files) { if (file.Substring(file.Length - 3, 3).ToLower() == "wav") { listBox1.Items.Add(file); } } (2) 播放和停止播放 private void button1_Click(object sender, EventArgs e) { WavPlay.Play(listBox1.Text,true); tm.Enabled = true; progressBar1.Value = 0; button1.Enabled = false; button2.Enabled = true; } private void button2_Click(object sender, EventArgs e) { WavPlay.Stop(); tm.Enabled = false; button1.Enabled = true; button2.Enabled = false; } WavPlay库下载:http://www.sky-walker.com.cn/MFRelease/library/v42/YFSoft.WavPlay.rar 示例源码下载:http://www.sky-walker.com.cn/MFRelease/Sample/YFWavPlay.rar 程序运行后界面如下: 注:DA输出可以接音箱,也可以接耳机,不过直接驱动扬声器,则声音有些小,需要加一个功放模块(可以单击这里,购买功放+喇叭套件)。 目前紫藤207平台已经支持屏幕横竖屏切换了,系统启动的时候,先检查是不是竖屏,如果不是,则自动切换(YFAccessFlash工具也可以配置横竖屏模式),相关代码如下: //检查LCD是否竖屏显示模式 YFStream.Utility.LCD_ViewMode mode = YFStream.Utility.Instance.GetLcdMode(); if (mode != YFStream.Utility.LCD_ViewMode.Portrait) { YFStream.Utility.Instance.SetLcdMode(YFStream.Utility.LCD_ViewMode.Portrait); //重启系统 Microsoft.SPOT.Hardware.PowerState.RebootDevice(false); Thread.Sleep(Timeout.Infinite); } 实际的运行效果如何,请看相关视频: 播放链接:http://v.youku.com/v_show/id_XNDgwODgyOTky.html ----------------------------------------------------------------- MF简介:http://blog.csdn.net/yefanqiu/article/details/5711770 MF资料:http://www.sky-walker.com.cn/News.asp?Id=25 相关硬件:http://www.sky-walker.com.cn/Products.asp?Id=24 本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/1073543,如需转载请自行联系原作者

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

【物联网智能网关-10】构建.NET MF平台下的流式驱动模型

无论是做linux下的驱动开发,还是Windows CE平台下的驱动开发,对流式驱动模型一定非常熟悉。在此架构下,把所有的硬件设备都看成文件,和设备的交互其实就是读写文件,也就是数据流动。这样开发驱动不仅简单实用,并且用户也用一致的接口访问硬件,大大降低了学习代价。但是在.NET Micro Framework平台下,却没有提供这样的驱动开发接口,用户如果想在应用层操作硬件,必须要做一个专门的接口库(Interop),如果有n个设备,对应的驱动接口库文件也必须n个,如果一个应用程序和n个设备通信,那就必须引用n个库了。另外如果库接口有更改,那么上层和底层代码还必须重新编译才能使用。 正是基于流式驱动的一些优点和Interop驱动接口开发的繁杂,所以我在.NET Micro Framework系统上构建了一套流式驱动架构。尤为值得一提的是,在流式驱动架构的基础上,还实现了的用户可以在MDK IDE环境下,采用C++开发流式驱动(参见相关文章《.NET Micro Framework动态调用C/C++底层代码》)。 流式驱动应用层的C#接口代码如下: public sealed class GeneralStream { publicGeneralStream(); public event GeneralStreamEventHandlerNotice; public int Close(); public int IOControl(intcode); public int IOControl(intcode, int parameter); public int IOControl(intcode, byte[] inBuffer, intinCount, byte[] outBuffer, int outCount); public int Open(stringname); public int Open(string name,int config); public int Open(string name,string config); public int Read(byte[]buffer, int offset, intcount); public int Write(byte[]buffer, int offset, intcount); } 以上接口其实和WinCE平台下的流式接口非常类似了,但是比较有特色的是,还提供了一个事件通知接口,这样就为各种硬件驱动开发提供了更灵活的支持。有了这个流式接口,一般情况下,为上层C#语言提供专有的硬件底层功能,就不需要再编写接口相关的代码了,直接写相关的C/C++代码,然后编译链接即可。 当前已经基于流式驱动接口,实现了10个设备和功能模块的驱动,下面先简单介绍一下,后续将详细写文章一一介绍。 序号 名称 说明 备注 000 UserDriver 用户流式驱动开发接口 MDK下的C++开发 001 Watchdog 看门狗驱动 002 Ultrasonic 超声波模块驱动 测距 003 DHT11 温湿度模块驱动 004 GPIO GPIO特殊功能驱动 比如可以配置开漏 005 Counter 高速计数器 006 ADIS16227 ADIS16227模块驱动 基于特殊的SPI接口 007 MAX7219 MAX71219芯片驱动 LED和点阵控制 008 PCD8544 Norkia5110显示模块驱动 009 LCD1602 LCD1602模块驱动 在开发ADIS16227、Norkia5110和LCD1602模块驱动的过程中,深切感受到,给用户留一个C++驱动开发接口非常重要,因为这类驱动,上层应用一是没有现成的接口,二是直接用C#是不能实现的,所以必须底层移植,如果没有现成用户接口,就必须依赖厂商了,这很大层度上限制了用户的开发的主动性和灵活性,还有对产品及项目的把控性。 关于这部分内容,我在用户流式驱动开发接口(UserDriver)的文章中会详细介绍。 ----------------------------------------------------------- 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/1004388,如需转载请自行联系原作者

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

【物联网智能网关-11】流式驱动之用户驱动(MDK C++开发)

微软体系的产品给人的感觉一直是易学易用,但是其执行性能却屡受诟病。所以一些对性能要求相对较高的硬件产品研发,一般都是采用linux体系的技术,或者是无操作系统开发,其开发语言也绝大数是C/C++(启动代码或中断部分的代码有时会用汇编代码实现)。但是对工控集成类的项目开发来说,由于项目开发周期比较短,对稳定性要求比较高,如果全部采用C/C++开发,不仅对开发人员的能力要求比较高,并且开发和调试的代价非常大。所以PC平台的,大都是用组态系统搭建,嵌入式系统则是采用嵌入式组态软件,其定制化的软件则采用WinCE等易用的嵌入式系统来开发了,但是对再小型的嵌入式系统,由于选择目前比较少,也只有选用传统的C/C++来开发了。 2001年.NET Micro Framework的开始研发,其实就是基于比尔盖茨所谓的.NET战略,上至服务器大型系统,下至嵌入式领域的芯片都希望是.NET系统,都可以用C#等.NET开发语言进行开发。所以最开始.NET Micro Framework系统就是开发硬件产品的,MSN Direct产品、SideShow,还有一些高端遥控器,键盘,都是采用.NET Micro Framework系统开发(相关介绍,请参见《MSN Direct项目简介》),虽然用.NET Micro Framework系统开发比较容易,但是要达到同样的性能,必须要求系统的主频更快,RAM更大,这对批量生产的硬件产品来说,长远发展来看,不是一个好选择。 我个人认为微软官方的.NET Micro Framework产品类开发的定位是错误的,这一点我可以看到微软在Windows领域的开发也是放弃了全用.NET托管代码实现的诉求,大部分底层或对性能要求很高的代码,依然采用原生C/C++实现(目前iOS和安卓系统的开发,基于性能的考虑,很多开发人员都开始用原生C/C++进行开发)。 用.NET Micro Framework开发用户需求变化少,不需要二次开发接口的产品来说,是非常不适合的,特别是销售量数量非常大的产品,因为随着产品的销量不断增加,前期开发成本所占的成本比重将越来越小。但是对用户需求变化大,用户需要有二次开发,或者是销量比较少的产品来说,用.NET Micro Framework优势就比较明显了。特别是工控集成类的产品,.NET Micro Framework系统有天然的优势(这是我7年工控领域的工作经历深切感受到的)。 PC领域的组态化技术已经非常成熟了,目前已经在向组态软件的第二代或第三代进行发展。但是在嵌入式领域,特别是低端MCU方面,这方面做得远远不够,我工作的定位就是致力于嵌入式领域组态化,并且我认为.NET Micro Framework系统是实现这个愿景的最好的一种技术支撑。 .NET Micro Framework的平台的C#(或VB.NET)开发虽然开发比较简单,但是其执行性能却是一个必须面对的问题(2009年我在微软总部和MSN Direct开发人员交流的时候,他们对.NET Micro Framework的执行性能颇有微词)。 我的解决方案就是:.NET Micro Framework必须尽可能的封装,C#语言执行的不是大段功能代码,而只是一些工艺流程代码即可,那些功能性的代码尽可能用C/C++实现。C#起到粘连串接的作用即可,这一点和网页开发中的脚本语言的角色非常类似。 目前这类封装,必须是porting开发人员完成,是.NET Micro Framework TinyCLR的不可分的部分,普通用户是不能进行C/C++开发的。而我这篇文章所介绍的重点,就是为普通的开发用户,开启C/C++ 基于.NET Micro Framework编程之门。在《.NET Micro Framework动态调用C/C++底层代码》文章中我介绍了这种技术的实现原理,本篇文章就是基于应用的角度,介绍如果用MDK进行.NET Micro Framework用户驱动开发。 在进行用户流式驱动开发介绍之前,我先比较一下C#和C++开发的性能,让大家有一个直观的感受。 上图C#代码如下: OutputPort io = new OutputPort((Cpu.Pin)GPIO_NAMES.PA6,false); while (true) { io.Write(true); io.Write(false); } C++的代码如下(NativeSample下运行) CPU_GPIO_EnableOutputPin(STM32F20x_GPIO_Driver::PA6,FALSE); while(TRUE) { CPU_GPIO_SetPinState(STM32F20x_GPIO_Driver::PA6,FALSE); CPU_GPIO_SetPinState(STM32F20x_GPIO_Driver::PA6,TRUE); } 硬件平台采用紫藤207(STM32F207 主频120M),通过示波器检查PA6管脚。 从示波器的显示结果来看,二者相差近60倍,所以说在C#层很难实现微秒级别的控制。 另外我也比较了一下C#和C++的for循环的执行效率。 代码很简单,就是:for(x=0;x<1000;x++); 执行次数 C# C++ 倍数 10 316us - - 100 2.5ms 3.5us 714 1000 24ms 33us 727 10000 - 333us - C#层提供的Sleep延时也是毫秒级别的,我做了一个简单的测试,结果如下: Sleep参数 0 1 10 执行时间 176-184 us 1.3ms 10.4ms 注:由于底层时钟中断不断触发,Sleep的时间是不确定的。 相信以上的测试结果,对大家的印象是深刻的。所以说,不考虑C#的封装优点,而是非要用C#和C++实现同样的功能,只能是让大家越来越远离.NET Micro Framework。 -------- 分割线 --------- 在《.NET Micro Framework动态调用C/C++底层代码》这篇文章中,我介绍g_GeneralStream_Function的时候,其支持的函数才15个,并且主要是GPIO和时钟类的函数,这次调整以后,已经扩展支持61个了,并且也可以传递初始化函数的字符串或整型变量参数了,新的g_GeneralStream_Function定义如下: IGeneralStream_Function g_GeneralStream_Function = { -1, NULL, //-- &Notice_GenerateEvent, &lcd_printf, &debug_printf, &HAL_Time_Sleep_MicroSeconds_InterruptEnabled, &Events_WaitForEvents, &disable_interrupts, &enable_interrupts, &private_malloc, &private_free, //mem &hal_snprintf, &hal_stricmp, &hal_strncmp_s, &hal_strlen_s, &memcpy, &memset, //Flash &YFSoft_Flash_Erase, &YFSoft_Flash_Read, &YFSoft_Flash_Write, //GPIO &CPU_GPIO_DisablePin, &CPU_GPIO_EnableInputPin, &CPU_GPIO_EnableOutputPin, &CPU_GPIO_GetPinState, &CPU_GPIO_SetPinState, //TIMER &CPU_TIMER_Initialize, &CPU_TIMER_Uninitialize, &CPU_TIMER_Start, &CPU_TIMER_Stop, &CPU_TIMER_GetState, &CPU_TIMER_SetState, //USART &USART_Initialize, &USART_Uninitialize, &USART_Write, &USART_Read, &USART_Flush, &USART_BytesInBuffer, &USART_DiscardBuffer, //DA/AD &DA_Initialize, &DA_Write, &AD_Initialize, &AD_Read, //PWM &PWM_Initialize, &PWM_Uninitialize, &PWM_ApplyConfiguration, &PWM_Start, &PWM_Stop, &PWM_GetPinForChannel, //TinyGUI &LCD_ClearEx, &LCD_SetPixel, &LCD_GetPixel, &LCD_DrawLine, &LCD_DrawRectangle, &LCD_DrawEllipse, &LCD_DrawImage, &LCD_DrawImageEx, &LCD_DrawString, &LCD_DrawStringEx, &LCD_FillRectangle, &LCD_FillEllipse, &LCD_GetFrameBufferEx, &LCD_SuspendLayout, &LCD_ResumeLayout, }; 有了这些函数支持,就可以在MDK中独立编写 MF的用户流驱动了。当然,你也可以不用这些函数,也可以调用MDK相关的库或STM32提供的库,直接通过寄存器对硬件进行操作(前提是和已有的功能不要冲突就行)。 为了便于在MDK 4.x中开发用户流式驱动,我提供了yfmflib.h和grenralstream.h头文件,也提供了一个UserDriver.cpp模板,用户只要简单修改一下即可。 UserDriver.cpp模板中的代码如下: //说明:代码空间 0x08010000 - 0x08020000 64K // 内存空间 0x20002000 - 0x20004000 8K #include "YFMFLib.h" #include "GeneralStream.h" #define UserDriver_Flag "UserDriver" #define UserDriver_Hander 1 const IGeneralStream_Function *MF=NULL; int GeneralStream_Open1_UserDriver(LPCSTR config) { return 0;} //Open1永远也不会被调用 //int GeneralStream_Open2_UserDriver(int config) { return 0;} int GeneralStream_Close_UserDriver() { return 0;} int GeneralStream_IOControl1_UserDriver(int code, BYTE *inBuffer, int inCount, BYTE *outBuffer, int outCount){return -1;} int GeneralStream_IOControl2_UserDriver(int code, int parameter){return -1;} int GeneralStream_Read_UserDriver(BYTE *buffer, int offset, int count){return -1;} int GeneralStream_Write_UserDriver(BYTE *buffer, int offset, int count){return -1;} int GeneralStream_Open2_UserDriver(int config) { //获取系统函数的指针 MF = (IGeneralStream_Function*)config; //C#下传的参数 MF->lcd_printf("%d,%s\r\n",MF->iParam1,MF->sParam1); MF->debug_printf("%d,%s\r\n",MF->iParam1,MF->sParam1); } extern const IGeneralStream g_GeneralStream_UserDriver; const IGeneralStream g_GeneralStream_UserDriver = { UserDriver_Flag, &GeneralStream_Open1_UserDriver, &GeneralStream_Open2_UserDriver, &GeneralStream_Close_UserDriver, &GeneralStream_IOControl1_UserDriver, &GeneralStream_IOControl2_UserDriver, &GeneralStream_Read_UserDriver, &GeneralStream_Write_UserDriver, }; 为了让大家印象深刻,我们以LCD1602的驱动为示例,进行用户驱动编写(我已经为其专门开发了一个流式驱动,以其为例只是便于说明,后续还将详细介绍LCD1602)。 其实LCD1602的显示就是IO操作,其实理论上在C#层也可以实现,但是通过我以上的性能测试,估计大家会鲜有尝试了。LCD1602的驱动,通过上网搜索,无论是C51、STM32还是Arduino都提供了相关的源码,我们只要把相关的IO操作的函数,转换为我们MF的IO操作函数即可。 主要代码如下: void LCD1602_Write_byte(BYTE data) { MF->CPU_GPIO_SetPinState(LCD1602_E_Pin,TRUE); MF->CPU_GPIO_SetPinState(LCD1602_D7_Pin,(data & 0x80)>0); MF->CPU_GPIO_SetPinState(LCD1602_D6_Pin,(data & 0x40)>0); MF->CPU_GPIO_SetPinState(LCD1602_D5_Pin,(data & 0x20)>0); MF->CPU_GPIO_SetPinState(LCD1602_D4_Pin,(data & 0x10)>0); MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(1); MF->CPU_GPIO_SetPinState(LCD1602_E_Pin,FALSE); MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(1); MF->CPU_GPIO_SetPinState(LCD1602_E_Pin,TRUE); MF->CPU_GPIO_SetPinState(LCD1602_D7_Pin,(data & 0x08)>0); MF->CPU_GPIO_SetPinState(LCD1602_D6_Pin,(data & 0x04)>0); MF->CPU_GPIO_SetPinState(LCD1602_D5_Pin,(data & 0x02)>0); MF->CPU_GPIO_SetPinState(LCD1602_D4_Pin,(data & 0x01)>0); MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(1); MF->CPU_GPIO_SetPinState(LCD1602_E_Pin,FALSE); } void LCD1602_Write_Command(BYTE cmd) { MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(100); MF->CPU_GPIO_SetPinState(LCD1602_RS_Pin,FALSE); LCD1602_Write_byte(cmd); } void LCD1602_Write_Data(BYTE data) { MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(100); MF->CPU_GPIO_SetPinState(LCD1602_RS_Pin,TRUE); LCD1602_Write_byte(data); } void LCD1602_SetXY(BYTE x,BYTE y)//x:0~15,y:0~1 { if(y) LCD1602_Write_Command(0xc0+x);//第二行显示 else LCD1602_Write_Command(0x80+x);//第一行显示 } void LCD1602_Write_Char(BYTE x,BYTE y,char data) { LCD1602_SetXY( x, y); //写地址 LCD1602_Write_Data(data); } void LCD1602_Print(BYTE x,BYTE y,char *s) { if(x>15)x=15; LCD1602_SetXY( x, y ); //写地址 int i=0; while (*s && (x+i++)<16) //写显示字符 { LCD1602_Write_Data( *s++ ); } } void LCD1602_Init() { MF->CPU_GPIO_SetPinState(LCD1602_RW_Pin,FALSE); //只写 MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(100000); LCD1602_Write_Command(0x33); MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(20000); LCD1602_Write_Command(0x32); MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(20000); LCD1602_Write_Command(0x28); LCD1602_Write_Command(0x0C); //显示开 LCD1602_Write_Command(0x01); //清屏 MF->HAL_Time_Sleep_MicroSeconds_InterruptEnabled(20000); } 以上就是LCD驱动相关的代码,下面我们填写接口代码 int GeneralStream_Open2_UserDriver(int obj) { //获取系统函数的指针 MF = (IGeneralStream_Function*)obj; //-- LPCSTR config = MF->sParam1; //不能有空格 // 012345678901234567890123456789012345678901234567890123 //格式RS=PC08,RW=PC09,E=PB06,D4=PB07,D5=PC00,D6=PC02,D7=PC03 if(config[3]!='P' || config[11]!='P' || config[18]!='P' || config[26]!='P' || config[34]!='P' || config[42]!='P' || config[50]!='P') { return -1; } LCD1602_RS_Pin =(GPIO_PIN)((config[4]-'A') * 16 + (config[5]-'0') * 10+ (config[6] - '0')); LCD1602_RW_Pin =(GPIO_PIN)((config[12]-'A') * 16 + (config[13]-'0') * 10+ (config[14] - '0')); LCD1602_E_Pin =(GPIO_PIN)((config[19]-'A') * 16 + (config[20]-'0') * 10+ (config[21] - '0')); LCD1602_D4_Pin =(GPIO_PIN)((config[27]-'A') * 16 + (config[28]-'0') * 10+ (config[29] - '0')); LCD1602_D5_Pin =(GPIO_PIN)((config[35]-'A') * 16 + (config[36]-'0') * 10+ (config[37] - '0')); LCD1602_D6_Pin =(GPIO_PIN)((config[43]-'A') * 16 + (config[44]-'0') * 10+ (config[45] - '0')); LCD1602_D7_Pin =(GPIO_PIN)((config[51]-'A') * 16 + (config[52]-'0') * 10+ (config[53] - '0')); MF->CPU_GPIO_EnableOutputPin(LCD1602_RS_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_RW_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_E_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_D4_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_D5_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_D6_Pin,FALSE); MF->CPU_GPIO_EnableOutputPin(LCD1602_D7_Pin,FALSE); LCD1602_Init(); //初始化液晶 return 0; } int GeneralStream_Write_UserDriver(BYTE *buffer, int offset, int count) { UINT8 x = (BYTE)((offset>>8) & 0xFF); UINT8 y = (BYTE)(offset & 0xFF); buffer[count]=0; if(x>15 || y>1 ) return -1; LCD1602_Print(x,y,(char *)buffer); return 0; } 以上代码在MDK中直接编译,编译后的bin文件,经过转换适当转换,变为MF部署工具所支持的Hex文件,用MFDeploy或YFAccessFlash工具直接部署即可,如下图所示: 基于C++的代码我们已经完成,下一步我们开始写C#代码,以便调用我们写好的C++代码。 代码如下: using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using YFSoft.IO; namespace UserDriverTest { public class Program { public static void Main() { Debug.Print("UserDriver Test ..."); LCD1602 lcd = new LCD1602(); lcd.Print(0, 0, "Hello .NET MF!!!"); lcd.Print(0, 1, "YFSoft 20120920"); while (true) { System.Threading.Thread.Sleep(500); } } } //Width = 16 Height = 2 public class LCD1602 { GeneralStream gs = null; public LCD1602() { gs = new GeneralStream(); int ret = 0; if ((ret = gs.Open("UserDriver", "RS=PC08,RW=PC09,E=PB06,D4=PB07,D5=PC00,D6=PC02,D7=PC03")) <= 0) { Debug.Print("ERR=" + ret.ToString()); gs = null; } } public void Print(byte x, byte y, string s) { if (gs == null) return; byte[] temp = System.Text.UTF8Encoding.UTF8.GetBytes(s); byte[] buff = new byte[temp.Length + 1]; Array.Copy(temp, buff, temp.Length); buff[buff.Length - 1] = 0; gs.Write(buff, x << 8 | y, temp.Length); } } } 代码执行后,其运行效果如下图所示: ------------------------------------------------- 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/1031101,如需转载请自行联系原作者

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

互联网物联网关系微妙复杂事实究竟如何

老实说,现在人们总是提到互联网就会想到物联网,认为物联网是互联网的一种衍生,然而事实真是如此吗?总有很多人会问:“物联网”与“互联网”有什么不同?”虽然在技术手段上,一系列的“互联网+”达到的效果与物联网已经接近了,但其思路还是存在差别的。未来会产生更多的终端并不是需要用户去互动,而是实现自动地,智能地直接为人服务。 很多人都会疑惑,在物联网的背景下,需要怎样的思维才能更好的顺应时代的发展。总有很多人会问:“物联网”与“互联网”有什么不同?”关于这个问题,其实很难解释得一清二楚,因为二者太像了,而且关系如此微妙复杂,物联网简直像是互联网概念衍生出来的炒作概念。但事实究竟怎样呢? 先从产品的角度举个现实的例子:现在有某品牌智能空调,你到家之前可以先用手机开启它,它能保证你回家的时候家里室温刚好是你提前设定好的温度,而离家之后也不会因为忘了关空调而心疼电费,因为你随时可以在手机上把它关掉。同时,它还能自己除甲醛,控制空气湿度和氧含量,这种体验当然不赖。 但是这其中还有一些问题。第一是空调无法自动感知环境,就是说你需要自己关注空调的运行状态而且亲自去操作,这其实是你对“空调工作状态”及“家里空气状态”这样的信息进行了判断和处理;第二就是手机只能实现对空调的控制,而不能同时调节通风装置和窗户、空气净化器、加湿器等设备来让室内空气达到最好的状态。 对物联网有深远影响意义的Nest恒温器正在改变这种现状,从Nest和智能空调的例子就可以看出基于互联网的思维与基于物联网的思维有什么不同。 这里简单介绍下Nest。2014年谷歌以32亿美金收购Nest公司被认为是智能家居产业爆发的信号。Nest里面集成了很多类型的传感器,能够不间断地监测它周围室内的温度、湿度、光等环境的变化。比如它可以判断房间中是否有人及人是否有移动,并以此决定是否开启温度调节设备。更重要的是,Nest具有记忆能力和学习能力:用户每次在某个设时间设定了某个温度,它都会记录,再经过一周的时间,它就能根据用户的日常作息习惯和温度喜好,利自身用算法自动生成一个设置方案。只要用户生活习惯没有发生变化,就不再需要手动设置Nest恒温器。 从上面两个例子我们可以看出产品由遥控到自控的转变,这也体现了智能家居1.0到2.0的升级。当然,后续还有互联互通的3.0模式,这也是现在所有从业者努力的方向,现在Nest及旗下智能摄像头Dropcam已经和智能门锁、电灯、电扇、汽车系统等十数件产品开始联动了,其无感化控制才让人们体验真正的智能生活。笔者在此并不是要否定遥控,任何事物的转变都不是一蹴而就的,需要时间来慢慢打磨,毕竟不是所有企业都能走在最前列。真正的物联网时代来临,将达到无控状态。 回到产品上,开发Nest的思维与传统的家电企业是不同的。这也是物联网对互联网的一个巨大优势:感知层的运用。我们的互联网应用开发,很多时候在思维上缺乏这样的认知。这和互联网的发展历程是分不开的,因为互联网发展至今,人都是最主要的参与者。互联网信息的来源很大程度上是基于人的,比如在淘宝买东西,用户在终端给淘宝信息选择自己需要的商品。如果没有了用户,那也就没有了交易,淘宝也就没有意义了。 同样的道理对打车等O2O软件也适用,这就导致为了争抢成为用户进入的入口的各大互联网公司开始烧钱,给各种补贴来让用户养成消费习惯。互联网信息传输有两个特点:一是信息产生的主动性,我们的需求是由我们主动提供给网络服务商的,服务商无法提前知晓或预判;二是信息上传的主动性,我们通过各类网站、APP和客户端向这些服务供应商提供自己的需求信息。 而对物联网而言,这些信息的产生和传输很大程度上主动的。人将更少地参与到信息的采集和分析,大量不必要亲自关注的信息交给设备和网络去处理,从而能够将人从信息爆炸的困局中解脱出来。 这之后先来谈“互联网的思维”是什么,百度词条的解释:“互联网时代的思考方式,不局限在互联网产品、互联网企业。这里指的互联网,不单指桌面互联网或者移动互联网,是泛互联网,因为未来的网络形态一定是跨越各种终端设备的,台式机、笔记本、平板、手机、手表、眼镜等。”从这段描述可以看出,“互联网思维”本身是基于把“终端”联接到网络上。虽然“互联网思维”自身在不断演进,但终归并不适合未来的物联网的网络形态。 更倾向于互动性很强的终端设备 首先,“终端”的定义是模糊的,搜索该词条可以看出,目前对终端的理解更倾向于互动性很强的终端设备。对互联网思维而言,终端就是入口,就是用户。终端是现在互联网的信息接入入口,信息的传递依赖于终端。互联网思维影响下的企业,会在与用户终端的交互上苦下功夫,这就是传统的入口思维,就是流量的思维。这也是我们现在手机热、手表热、手环热、APP热、公众号热等热产生的一个很重要原因。 运用这样的思维方式发展到现在已经非常成熟了,其演变可形成全新的商业模式。往后就是互联网的UGC(User Generated Content指用户原创内容)应用兴起,Facebook、Twitter、天涯、知乎、人人、微博等等。这一批UGC引领了互联网的一个时代,将人们线下的交流搬到线上,让人们能够更方便快捷地表达自己的思想。但是由于缺乏有效的管理机制,大量垃圾信息充斥了人们的生活。特别是一些你毫无兴趣的广告推送,你还不得不忍受。其实商家也很郁闷,花大价钱撒广告,结果只引起少数人关注。而物联网技术的发展,将改变这一现状,这背后其实是信息交换的问题。商家不能掌握用户喜好,用户也不知道商家到底有什么产品,两边一抓瞎,传统广告都是靠蒙。 接下来的就是小米一再强调的“参与感”。为什么需要“参与感”,笔者认为这就是社会在互联网时代的信息爆炸但又不对称造成的。“粉丝经济”能解决一部分信息对称的问题,但也是流量经济的一种。它与以往的形式不同的是,用户能参与到产品的设计和开发上,并能提供自己的体验以供设计者参考。每个人都机会表达自己且信息能够即时传播,这是互联网的红利,但仍受互联网的限制。 再来说说现在火热的众筹经济,这是互联网的思维的进一步演变,它将信息变得更加对称了。这也是一个需求表达弱化的过程,变成选择。但是,由于用户掌握的信息始终有限,而有针对性的选择并不能给一个既已成形的方案提供太多参考,用户或许更加具有“参与感”,而对项目人来说,是缺乏“参与感”的。 为什么这样说,因为参与某个项目的众筹用户已经对该项目本身有较高认同度,很难再对项目提出改进意见或者提出自身不同的需求。众筹能将想要聚集的人聚集在一起,形成了项目粉丝,但其项目的起源很可能来自于一个突发的灵感或一场朋友间的头脑风暴,其需求仍不失发自用户自身的。这可以看作仍是粉丝经济的一种新的延续,是由一个中心去吸引一批用户。而我们知道每个人的需求跨越不同维度,而很多需求都是个性化需求,最后选择的可能是一种折衷方案而不是对自己而言最好的方案。我们知道著名的二八理论和长尾理论,而随着物联网的技术的发展,这两种理论可能对产品将不再继续作用,因为每个人的需求都能够被针对性地满足。 而物联网的技术与互联网最大不同在于信息传递的方式,需求表达这一过程将被弱化,信息传递方式的改变会将商业模式引向哪个方向呢?虽然在技术手段上,一系列的“互联网+”达到的效果与物联网已经接近了,但其思路还是存在差别的。未来会产生更多的终端并不是需要用户去互动,而是实现自动地,智能地直接为人服务。笔者之前提过的边缘计算,也是物联网与互联网的一个不同之处,物与物之间能交流、会通信是物联网的重要特征,这个过程应该不再有人参与其中。 物联网发展到一定阶段将实现由用户到制造商的逆向定制,这是智能制造技术和供应链发展的一大方向。大规模定制意味着更贴近用户需求,而且可根据市场反应实时调整产品策略。 本文转自d1net(转载)

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

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部分的功能。

用户登录
用户注册