【物联网智能网关-17】.NET Micro Framework之MDK C++二次开发

简介: .NET Micro Framework虽然好学易用,但是在一些需要实时,需要高性能的应用领域,却有些勉为其难。毕竟.NET Micro Framework上层应用程序由底层CLR(TinyCLR)解释执行,执行效率被打个折扣是在所难免的。

.NET Micro Framework虽然好学易用,但是在一些需要实时,需要高性能的应用领域,却有些勉为其难。毕竟.NET Micro Framework上层应用程序由底层CLR(TinyCLR)解释执行,执行效率被打个折扣是在所难免的。

美国GHI公司(国外.NET Micro Framework硬件产品主要生厂商)为此提供了一个称为RLP方案(https://www.ghielectronics.com/docs/50/rlp-enhanced )。可以让.NET Micro Framework的应用程序调用MDK编写的C++程序,主要是解决性能问题,把一些比较运行比较耗时的代码采用C++完成,功能相对简单。

而我们所提供的方案和他们不同,我们是通过流式驱动的方式用MDK开发C++程序。用户程序采用标准的流式驱动接口进行相关调用。并且流式驱动提供事件机制,底层和上层可以通过事件进行交互。

另外就是为MDK C++程序提供了丰富的.NET Micro Framework PAL层接口,可以让用户随心所欲地开发出功能强大的程序。

在此之前我已经写过两篇相关的文章,用户可以先行了解一下:《.NET Micro Framework动态调用C/C++底层代码(原理篇)》和《【物联网智能网关-11】流式驱动之用户驱动(MDK C++开发)》。

和上一篇文章介绍的功能函数相比,又扩展了一些比较实用的功能,比如I2C、SPI接口,底层中断打开关闭,HAL_COMPLETION、HAL_CONTINUATION类似底层多线程支持和中断程序用户态执行,功能函数由原来的61个扩展到了80个。具体功能接口如下:

struct IGeneralStream_Function
{
  INT32  iParam1;
  LPCSTR sParam1;
  
  //--- 
  void (*Notice_GenerateEvent)(UINT32 data1, UINT32 data2);
  void (*lcd_printf)(char const * format,...);
  void (*debug_printf)(char const* format, ... ); 
  void (*HAL_Time_Sleep_MicroSeconds_InterruptEnabled)(UINT32 uSec);
  UINT32 (*Events_WaitForEvents)(UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds);
  void (*disable_interrupts)();
  void (*enable_interrupts)();
  void* (*private_malloc)(size_t len);
  void  (*private_free)( void*  ptr);
  //--- lock ---
  BOOL (*DISABLE_INTERRUPTS)(void* context);
  BOOL (*ENABLE_INTERRUPTS)(void* context);
 
  //HAL_COMPLETION/HAL_CONTINUATION
  UINT32 (*HAL_COMPLETION_Initialize)(HAL_CALLBACK_FPN EntryPoint,void* Argument);
  void (*HAL_COMPLETION_Uninitialize)(UINT32 handle);
  void (*HAL_COMPLETION_EnqueueDelta)(UINT32 handle,UINT32 uSec);
  UINT32 (*HAL_CONTINUATION_Initialize)(HAL_CALLBACK_FPN EntryPoint,void* Argument);
  void (*HAL_CONTINUATION_Uninitialize)(UINT32 handle);
  void (*HAL_CONTINUATION_Enqueue)(UINT32 handle);
 
  //--- mem ---
  int (*hal_snprintf)( char* buffer, size_t len, const char* format, ... );
  int (*hal_stricmp)( const char * dst, const char * src );
  int (*hal_strncmp_s)( const char* str1, const char* str2, size_t num );
  size_t (*hal_strlen_s)(const char * str);       
  void *(*memcpy)(void * dst, const void * src, size_t len);
  void *(*memset)( void * dst, int value, size_t len );   
 
  //--- Flash ---
  INT32 (*YFSoft_Flash_Erase)( UINT32 address, UINT32 count);
  INT32 (*YFSoft_Flash_Read)( UINT32 address, UINT32 count,UINT8 *buffer);
  INT32 (*YFSoft_Flash_Write)( UINT32 address, UINT32 count,UINT8 *buffer); 
 
  //--- GPIO ---
  void (*CPU_GPIO_DisablePin)(GPIO_PIN Pin, GPIO_RESISTOR ResistorState, UINT32 Direction, GPIO_ALT_MODE AltFunction);
  BOOL (*CPU_GPIO_EnableInputPin)(GPIO_PIN Pin, BOOL GlitchFilterEnable, GPIO_INTERRUPT_SERVICE_ROUTINE ISR, GPIO_INT_EDGE IntEdge, GPIO_RESISTOR ResistorState);
  void (*CPU_GPIO_EnableOutputPin)(GPIO_PIN Pin, BOOL InitialState);
  BOOL (*CPU_GPIO_GetPinState)(GPIO_PIN Pin);
  void (*CPU_GPIO_SetPinState)(GPIO_PIN Pin, BOOL PinState);
 
  //--- TIMER ---
  BOOL (*CPU_TIMER_Initialize)(UINT32 timer, UINT32 ARR,UINT16 PSC,HAL_CALLBACK_FPN ISR, void* ISR_Param );
  BOOL (*CPU_TIMER_Uninitialize)(UINT32 timer );
  void (*CPU_TIMER_Start)(UINT32 timer);
  void (*CPU_TIMER_Stop)(UINT32 timer);   
  UINT32 (*CPU_TIMER_GetState)(UINT32 timer);
  void (*CPU_TIMER_SetState)(UINT32 timer,UINT32 state);
  
  //--- USART ---   
  BOOL (*USART_Initialize)( int ComPortNum, int BaudRate, int Parity, int DataBits, int StopBits, int FlowValue );
  BOOL (*USART_Uninitialize)( int ComPortNum );
  int  (*USART_Write)( int ComPortNum, const char* Data, size_t size );
  int  (*USART_Read)( int ComPortNum, char* Data, size_t size );
  BOOL (*USART_Flush)( int ComPortNum );
  int  (*USART_BytesInBuffer)( int ComPortNum, BOOL fRx );
  void (*USART_DiscardBuffer)( int ComPortNum, BOOL fRx ); 
 
  //--- AD/DA ---
  BOOL (*DA_Initialize)( ANALOG_CHANNEL channel, INT32 precisionInBits );
  void (*DA_Write)( ANALOG_CHANNEL channel, INT32 level );
  BOOL (*AD_Initialize)( ANALOG_CHANNEL channel, INT32 precisionInBits );
  INT32 (*AD_Read)( ANALOG_CHANNEL channel );
  
  //--- PWM ----
  BOOL (*PWM_Initialize)( PWM_CHANNEL channel );
  BOOL (*PWM_Uninitialize)( PWM_CHANNEL channel );
  BOOL (*PWM_ApplyConfiguration)( PWM_CHANNEL channel, GPIO_PIN pin, UINT32& period, UINT32& duration, PWM_SCALE_FACTOR &scale, BOOL invert );
  BOOL (*PWM_Start)( PWM_CHANNEL channel, GPIO_PIN pin );
  void (*PWM_Stop)( PWM_CHANNEL channel, GPIO_PIN pin );
  GPIO_PIN (*PWM_GetPinForChannel)( PWM_CHANNEL channel );
  
  //--- SPI ----
  BOOL (*CPU_SPI_nWrite16_nRead16)( const SPI_CONFIGURATION& Configuration, UINT16* Write16, INT32 WriteCount, UINT16* Read16, INT32 ReadCount, INT32 ReadStartOffset );
  BOOL (*CPU_SPI_nWrite8_nRead8)( const SPI_CONFIGURATION& Configuration, UINT8* Write8, INT32 WriteCount, UINT8* Read8, INT32 ReadCount, INT32 ReadStartOffset );
 
  //--- I2C ----
  BOOL (*I2C_Initialize)();
  BOOL (*I2C_Uninitialize)();
  BOOL (*I2C_Execute)(UINT16 address,UINT8 *inBuffer,int inCount,UINT8 *outBuffer,int outCount,UINT32 clockRateKhz,int timeout);
 
  //--- TinyGUI ----
  void (*LCD_ClearEx)(UINT32 color);    
  void (*LCD_SetPixel)(INT32 x,INT32 y,UINT32 color);
  UINT32 (*LCD_GetPixel)(INT32 x,INT32 y);
  void (*LCD_DrawLine)(INT32 x1,INT32 y1,INT32 x2,INT32 y2,UINT32 color);
  void (*LCD_DrawRectangle)(INT32 x,INT32 y,INT32 width,INT32 height,UINT32 color);
  void (*LCD_DrawEllipse)(INT32 x,INT32 y,INT32 width,INT32 height,UINT32 color);
  void (*LCD_DrawImage)(INT32 x,INT32 y,UINT8 *bytData);
  void (*LCD_DrawImageEx)(INT32 x,INT32 y,UINT8 *bytData,UINT32 MaskColor);
  void (*LCD_DrawString)(INT32 x,INT32 y,LPCSTR s,UINT32 color);
  void (*LCD_DrawStringEx)(INT32 x,INT32 y,UINT32 color,UINT8 *fontdata,int width,int height,int count); //2012-08-06
  void (*LCD_FillRectangle)(INT32 x,INT32 y,INT32 width,INT32 height,UINT32 color);
  void (*LCD_FillEllipse)(INT32 x,INT32 y,INT32 width,INT32 height,UINT32 color);
  void (*LCD_GetFrameBufferEx)(UINT8 *bytData,UINT32 offset,UINT32 size);
  void (*LCD_SuspendLayout)();
  void (*LCD_ResumeLayout)();   
};

下面简单介绍一下驱动开发步骤。

1、 在MDK 4.xx版本创建一个新项目,添加generalstream.h头文件,然后再添加模板文件UserDriver.cpp。如下图所示
image.png
2、 选定MCU类型,可以根据实际硬件选择STM32F103/STM32F207/STM32F407/STM32F405。

image.png
(凌霄智能终端采用的芯片就是STM32F405RG)

3、 输入对应的平台宏定义
image.png
4、 配置针对具体硬件所设置的离散加载配置文件
image.png
凌霄智能终端的离散加载文件的内容如下:

  LR_IROM10x08010000 0x00010000  {    ; load region size_region

  ER_IROM1 0x08010000 0x00010000  {    ; load address = execution address

   .ANY (+RO)

  }

  RW_IRAM1 0x20000400 0x00002000  {  ; RWdata

   .ANY (+RW +ZI)

  }

}

表示程序加载的位置在0x08010000,大小为64K,RAM空间为0x20000400起始的8K空间。

注:用户驱动除了这部分RAM可用外,还可以直接通过接口提供的内存操作函数,分配堆上的内存。

5、  编写用户驱动(C/C++),下面是一个综合示例,用到了GPIO操作、显示操作、时钟中断操作和事件通知。

#include "GeneralStream.h"
//--//
#if defined(YF_Campsis103) || defined(YF_Campsis405)
#define COM_PORT  COM1
#else
#define COM_PORT  COM3
#endif
 
volatile UINT32 Num;
void TIMER_ISR(void* param)
{
#if defined(YF_Campsis103) || defined(YF_Campsis405)
   MF->CPU_GPIO_SetPinState(PC0,!MF->CPU_GPIO_GetPinState(PC0));
#else
   MF->CPU_GPIO_SetPinState(PF6,!MF->CPU_GPIO_GetPinState(PF6));
#endif
   MF->CPU_TIMER_SetState(TIM3,0);
 
   if(Num++>30)
   {
      Num=0;
      //触发事件
      MF->Notice_GenerateEvent(UserDriver_Hander,123);
   }
}
 
//--// 
//Open1永远也不会被调用
int GeneralStream_Open1_UserDriver(LPCSTR config) 
{ 
  return 0;
}    
 
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);
  
  //初始化LED灯
#if defined(YF_Campsis103) || defined(YF_Campsis405)
  MF->CPU_GPIO_EnableOutputPin(PC0,TRUE); 
#else
  MF->CPU_GPIO_EnableOutputPin(PF6,TRUE);
  MF->CPU_GPIO_EnableOutputPin(PF7,TRUE);
  MF->CPU_GPIO_EnableOutputPin(PF8,TRUE); 
#endif        
 
  //时钟定时
  Num = 0;
  MF->CPU_TIMER_Initialize(TIM3,200,(SYSTEM_TIM_CLOCK_HZ/2000-1),TIMER_ISR,NULL);
  MF->CPU_TIMER_Start(TIM3);
 
  //初始化串口
  MF->USART_Initialize(COM_PORT,115200,USART_PARITY_NONE,8,USART_STOP_BITS_ONE,USART_FLOW_NONE);
 
  //显示界面
  MF->LCD_ClearEx(Color_Black);
  MF->LCD_DrawString(10,10,"UserDriver Test",Color_Blue);
 
  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)
{
    char data[3]={65,66,67};
    MF->USART_Write(COM_PORT, data, 3);
 
    MF->lcd_printf("[4]%d-%d\r\n",code,parameter);
    MF->debug_printf("[4]%d-%d\r\n",code,parameter);
    
    char str[32];
    MF->hal_snprintf(str,32,"%d-%d",code,parameter);
    MF->LCD_FillRectangle(100,80,100,20,Color_Black);    
    MF->LCD_DrawString(100,80,str,Color_Red);
 
#if defined(YF_Wisteria207) || defined(YF_Wisteria407)
    MF->CPU_GPIO_SetPinState(PF7,! MF->CPU_GPIO_GetPinState(PF7));
    MF->CPU_GPIO_SetPinState(PF8,! MF->CPU_GPIO_GetPinState(PF8));
#endif
    return code+parameter;
}
 
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 main(void)
{
  //空
}  
 
//--//
const IGeneralStream_Function *MF=NULL;
const IGeneralStream g_GeneralStream_UserDriver __attribute__ ((at(IGeneralStream_Address)))  =
{
    UserDriver_Flag,
    &GeneralStream_Open1_UserDriver,
    &GeneralStream_Open2_UserDriver,     
    &GeneralStream_Close_UserDriver,     
    &GeneralStream_IOControl1_UserDriver,  
    &GeneralStream_IOControl2_UserDriver,  
    &GeneralStream_Read_UserDriver,
    &GeneralStream_Write_UserDriver,    
};

6、 编译用户驱动,生成UserDriver.bin文件。

7、 采用YFAccessFlash部署UserDriver.bin文件。
image.png
选定UserDriver.bin文件然后直接部署即可。

注:如果这不是初次部署运行用户驱动,需要先终止当前程序的执行,否则部署会出现问题(凌霄103的设备需要先部署应用,然后再部署用户驱动)。

8、 用户程序编写(C#)

 public class Program
    {    
        public static void Main()
        {
            Debug.Print("UserDriver Test ...");
            GeneralStream gs = new GeneralStream();
            if (gs.Open("UserDriver") <= 0)
            {
                Debug.Print("Open UserDriver failed!");
                return;
            }
            gs.Notice += new GeneralStreamEventHandler(gs_Notice);
            Debug.Print("Open UserDriver OK!");
            int e = 0;
            byte[] bytData= new byte[8];
            while (true)
            {
                Debug.Print(gs.IOControl(100, e++).ToString());
                gs.Read(bytData, e, 10);
                System.Threading.Thread.Sleep(1000); 
            }
        }
        static void gs_Notice(uint hander, uint data, DateTime timestamp)
        {
            Debug.Print(hander.ToString() + " - " + data.ToString());
        }
    }

9、 用户程序写好后,直接在VS 2010中编译执行。
image.png
硬件运行效果图(如下):
image.png
 ---------------------------------------------------------------------------------------------

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

MF资料:http://www.yfiot.com/DownloadList.asp?Id=2&page=1

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
6天前
|
人工智能 监控 物联网
深度探索人工智能与物联网的融合:构建未来智能生态系统###
在当今这个数据驱动的时代,人工智能(AI)与物联网(IoT)的深度融合正引领着一场前所未有的技术革命。本文旨在深入剖析这一融合背后的技术原理、探讨其在不同领域的应用实例及面临的挑战与机遇,为读者描绘一幅关于未来智能生态系统的宏伟蓝图。通过技术创新的视角,我们不仅揭示了AI与IoT结合的强大潜力,也展望了它们如何共同塑造一个更加高效、可持续且互联的世界。 ###
|
18天前
|
安全 物联网 物联网安全
智能物联网安全:物联网设备的防护策略与最佳实践
【10月更文挑战第26天】随着物联网(IoT)技术的快速发展,智能设备已广泛应用于智能家居、工业控制和智慧城市等领域。然而,设备数量的激增也带来了严重的安全问题,如黑客攻击、数据泄露和恶意控制,对个人隐私、企业运营和国家安全构成威胁。因此,加强物联网设备的安全防护至关重要。
42 7
|
18天前
|
传感器 存储 运维
智能物联网:LoRaWAN技术在低功耗广域网中的应用
【10月更文挑战第26天】本文详细介绍了LoRaWAN技术的基本原理、应用场景及实际应用示例。LoRaWAN是一种低功耗、长距离的网络层协议,适用于智能城市、农业、工业监控等领域。文章通过示例代码展示了如何使用LoRaWAN传输温湿度数据,并强调了其在物联网中的重要性和广阔前景。
49 6
|
17天前
|
传感器 数据采集 监控
数据采集器和物联网网关的区别
数据采集器主要用于从各种数据源收集数据。这些数据源可以是传感器(如温度传感器、压力传感器等)、仪表(如电表、水表等)或者其他具有数据输出功能的设备。物联网网关是连接感知层(包含各种传感器和数据采集设备)和网络层(如互联网、局域网等)的关键设备。
44 4
|
18天前
|
存储 JSON 运维
智能物联网平台:Azure IoT Hub在设备管理中的实践
【10月更文挑战第26天】随着物联网技术的发展,Azure IoT Hub成为企业管理和连接数百万台设备的强大平台。本文介绍Azure IoT Hub的设备管理功能,包括设备注册、设备孪生、直接方法和监控诊断,并通过示例代码展示其应用。
21 4
|
17天前
|
传感器 监控 物联网
智能物联网:LoRaWAN技术在低功耗广域网中的应用
【10月更文挑战第27天】LoRaWAN技术是低功耗广域网(LPWAN)的重要代表,以其远距离通信、低功耗和低成本部署等优势,广泛应用于智能城市、农业监测和环境监测等领域。本文介绍LoRaWAN的工作原理及其实际应用,并提供示例代码展示如何使用LoRaWAN进行数据传输。
28 2
|
18天前
|
数据采集 传感器 监控
与传统的物联网相比,IIoT 智能化有何特点
IIoT(工业互联网)相较于传统物联网,其智能化特点主要体现在:更强大的数据处理能力、更精准的实时监控与预测分析、更高的安全性和可靠性,以及更深度的行业应用集成,推动了智能制造和工业4.0的发展。
|
5天前
|
物联网 智能硬件
物联网技术:连接智能生活的桥梁
物联网技术:连接智能生活的桥梁
|
1月前
|
存储 边缘计算 物联网
阿里云物联网平台:推动万物互联的智能化解决方案
随着物联网技术的快速发展,阿里云物联网平台为企业提供了一体化的解决方案,包括设备接入、数据管理和智能应用等核心功能。平台支持海量设备接入、实时数据采集与存储、边缘计算,并具备大规模设备管理、高安全性和开放生态等优势。广泛应用于智能制造、智慧城市和智能家居等领域,助力企业实现数字化转型。
156 5
|
17天前
|
安全 物联网 物联网安全
智能物联网安全:物联网设备的防护策略与最佳实践
【10月更文挑战第27天】随着物联网技术的快速发展,智能设备已广泛应用于生活和工业领域。然而,物联网设备的安全问题日益凸显,主要威胁包括中间人攻击、DDoS攻击和恶意软件植入。本文探讨了物联网设备的安全防护策略和最佳实践,包括设备认证和加密、定期更新、网络隔离以及安全标准的制定与实施,旨在确保设备安全和数据保护。
34 0

热门文章

最新文章

相关产品

  • 物联网平台