机智云官方生成的MCU代码(hal库)移植为STM32标准库教程

机智云官方生成的MCU代码(hal库)移植为STM32标准库教程

手上刚好有STM32F103VCT6和ESP8266模块想要接入机智云,但是由于不熟悉HAL库,于是参考机智云官方提供的文档,移植STM32固件库,以下是移植步骤:

生成"通用平台代码"

在这里插入图片描述

下载并解压

在这里插入图片描述

将Gizwits和Utils复制进自己创建好的STM32工程内

在这里插入图片描述

工程内加入文件和路径

在这里插入图片描述
在这里插入图片描述

打开机智云生成的main函数,并将其覆盖自己创建工程的main函数

在这里插入图片描述
在这里插入图片描述

编写串口和定时器

串口通讯要求:
波特率:9600
8位数据长
1个停止位
无奇偶校验位
无硬件流控制
收发模式

MCU方案需要用户实现一个串口,用于设备MCU与WIFI模组之间数据通信。在串口中断服务函数中调用 gizPutData() 函数实现串口数据的接收并且写入协议层数据缓冲区。串口发送函数和中断服务函数如下

/**
 * USART2发送len个字节.
 * buf:发送区首地址
 * len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
 **/
void USART2_Send_Data(u8 *buf,u16 len)
{
    u16 t;
    for(t=0;t<len;t++)        //循环发送数据
    {           
         while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);      
         USART_SendData(USART2,buf[t]);
     }     
     while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);          
}

/**
 * USART2中断服务函数和串口发送报文函数实现如下:
 **/
void USART2_IRQHandler(void)                	//串口2中断服务程序
{			
		while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);//等待数据发送完成
		aRxBuffer = USART_ReceiveData(USART2);
		gizPutData((uint8_t *)&aRxBuffer,1);//**需定义全局变量aRxBuffer,数据类型为 uint8_t,gizPutData函数位于 gizwits_protocol.c 中**
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
}

另外,需要编写串口的发送函数, uartWrite() 函数中调用串口发送函数。需要特别注意的是 gizwits_product.c 文件中 uartWrite() 函数是伪函数,用户需根据自己实现的串口发送函数完善 uartWrite(),请注意相关注释信息,以防出错。具体实现如下:
注意:示例中的 0x55 条件处理,即出现0xFF的数据时后面要加 0x55,这个操作一定要保留。

int32_t uartWrite(uint8_t *buf, uint32_t len)
{
    uint32_t i = 0;
    uint8_t temp=0x55;
    if(NULL == buf)
    {
        return -1;
    }
    
    #ifdef PROTOCOL_DEBUG
    GIZWITS_LOG("MCU2WiFi[%4d:%4d]: ", gizGetTimerCount(), len);
    for(i=0; i<len; i++)
    {
        GIZWITS_LOG("%02x ", buf[i]);
    }
    GIZWITS_LOG("\n");
    #endif

    for(i=0; i<len; i++)
    {
        //USART_SendData(UART, buf[i]);//STM32 test demo
        //Serial port to achieve the function, the buf[i] sent to the module
		USART2_Send_Data(buf+i,1);//需添加串口发送函数
        if(i >=2 && buf[i] == 0xFF)
        {
          //Serial port to achieve the function, the 0x55 sent to the module
          //USART_SendData(UART, 0x55);//STM32 test demo
          //0x55 条件处理,即出现0xFF的数据时后面要加 0x55
		  USART2_Send_Data(&temp,1);//需添加串口发送函数
        }
    }
    
    return len;
}

如果用户需要打印日志调试信息,用户需实现GIZWITS_LOG函数,只需修改 gizwits_protocol.h 中对应的宏定义即可,如下:

#define GIZWITS_LOG printf  //<运行日志打印
/* 网上有 printf 函数的使用教程,这边不再赘述 */

定时器要求:1ms中断一次
定时器中断服务函数如下

//定时器2中断服务程序		    
void TIM2_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//是更新中断
	{	 
		gizTimerMs();//gizTimerMs位于 gizwits_product.c 中
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIM2更新中断标志    
	}	    
}
 

配置入网功能(必要)

根据串口协议文档规定,MCU可以向模组发送命令为 ESP8266 配网, 调用 gizwitsSetMode(配网模式) 就能进入配网模式,该函数位于 gizwits_protocol.c 中,gizwitsSetMode() 函数功能说明如下:

/**

* @brief WiFi配置接口

* 用户可以调用该接口使WiFi模组进入相应的配置模式或者复位模组

* @param[in] mode 配置模式选择:0x0,模组复位;0x01,SoftAp模式;0x02,AirLink模式

* @return 错误命令码

*/

int32_t gizwitsSetMode(uint8_t mode);

我使用 WIFI_AIRLINK_MODE 模式配网,并且配网时打开提示灯

//外部中断8服务程序 
void EXTI9_5_IRQHandler(void)
{		
		if(EXTI_GetITStatus(EXTI_Line8) != RESET)
		{
			//AirLink mode 一键配网模式
			GIZWITS_LOG("KEY2 PRESS LONG ,AirLink mode\n");
			Led_Open(ReminderLed);//开启提示灯
			gizwitsSetMode(WIFI_AIRLINK_MODE);
			EXTI_ClearITPendingBit(EXTI_Line8); //清除LINE8上的中断标志位	
		}	
}

设置好配网模式后,在 gizwits_product. c 文件的 gizwitsEventProcess() 函数内获得WIFI状态,并做相应的逻辑处理。
例如: 配网成功后关闭提示灯

case WIFI_CON_ROUTER:
		Led_Close(ReminderLed);//配网成功,关闭提示灯
break;

数据下行控制

云端(App)下发数据给MCU, 数据点方式将转换成数据点事件,开发者只需要在 gizwits_product. c 文件的 gizwitsEventProcess () 相应事件下作具体处理即可。
以APP实现控制LED为例,如下:

int8_t gizwitsEventProcess(eventInfo_t *info, uint8_t *gizdata, uint32_t len)
{
  uint8_t i = 0;
  dataPoint_t *dataPointPtr = (dataPoint_t *)gizdata;
  moduleStatusInfo_t *wifiData = (moduleStatusInfo_t *)gizdata;
  protocolTime_t *ptime = (protocolTime_t *)gizdata;
  
#if MODULE_TYPE
  gprsInfo_t *gprsInfoData = (gprsInfo_t *)gizdata;
#else
  moduleInfo_t *ptModuleInfo = (moduleInfo_t *)gizdata;
#endif

  if((NULL == info) || (NULL == gizdata))
  {
    return -1;
  }

  for(i=0; i<info->num; i++)
  {
    switch(info->event[i])
    {
      case EVENT_LivingLed:
        currentDataPoint.valueLivingLed = dataPointPtr->valueLivingLed;
        GIZWITS_LOG("Evt: EVENT_LivingLed %d \n", currentDataPoint.valueLivingLed);
        if(0x01 == currentDataPoint.valueLivingLed)
        {
         			 //user handle
					Led_Open(LivingLed);
        }
        else
        {
          			//user handle 
					Led_Close(LivingLed);					
        }
        break;
      case EVENT_BedroomLed:
        currentDataPoint.valueBedroomLed = dataPointPtr->valueBedroomLed;
        GIZWITS_LOG("Evt: EVENT_BedroomLed %d \n", currentDataPoint.valueBedroomLed);
        if(0x01 == currentDataPoint.valueBedroomLed)
        {
          			//user handle
					Led_Open(BedroomLed);
        }
        else
        {
          			//user handle 
					Led_Close(BedroomLed);					
        }
        break;
       // .........以下代码省略

数据上行控制

该工程源码在 Gizwits\gizwits_product.c 文件的 userHandle() 函数中实现传感器数据上报,原则上用户只需要关心如何采集数据。当需要上报传感器数据时,调用 userHandle() 即可
以灯的状态赋值为例( 只读型数据点 的操作会被云端自动生成),如下:

/**

* 用户数据获取

* 此处需要用户实现除可写数据点之外所有传感器数据的采集,可自行定义采集频率和设计数据过滤算法

* @param none

* @return none

*/

void userHandle(void)
{
     currentDataPoint.valueLivingLed = 0x01;
}

参考链接:http://docs.gizwits.com/zhcn/deviceDev/GoKit3_DEV_SDK_Common_transplant.html

  • 10
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值