收藏官网首页
查看: 13045|回复: 0

[经验分享] 机智云程序移植到合泰单片机HT32F52352上

610

主题

657

帖子

3万

积分

版主

Rank: 7Rank: 7Rank: 7

积分
33415
跳转到指定楼层
楼主
 楼主| 发表于 2021-6-28 16:18:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
教您5分钟接入机智云,实现傻瓜式开发
本帖最后由 Kara 于 2021-6-28 16:43 编辑

机智云程序移植到合泰单片机HT32F52352上

一、    WiFi模块烧录机智云的固件
WiFi模块用的是正点原子的ATK-ESP-01,Flash的大小是8Mbit,机智云对应的固件可在此下载。
   
如点击资源下载没有反应,则在资源下载处右键,选择这三个中的任意一个都可下载。
WiFi模块的连接如下,


解压刚刚下载的固件包,用ESPFlashDownloadTool直接下载GAgent_00ESP826_04020034_8MbitUser1_combine_201806091441.bin文件即可,下载地址0x0000,Flash大小选择8Mbit,选择对应的COM口。
之后点击START即可开始下载,若一直处于等待上电同步,则将RST引脚接地再断开即可解决。

二、下载系统的代码包
1、创建新产品
产品分类随意,技术方案选择WiFi/移动网络方案
2、创建数据点
产品信息——>数据点
3、下载与之匹配的代码包
服务——>MCU开发——>硬件方案:独立MCU方案——>硬件平台:其他平台——>填入Product Secret——>生成代码包
之后下载即可!
三、新建一个USART文件和一个TIMER文件
1、我们需要用一个USART口与wifi模块通信从而将 wifi 串口接收到数据写入到缓冲区中,同时将数据上传到云端。
合泰的HT32F52352有4个串口,2个USART(通用同步异步收发器)和2个UART(通用异步收发器);我选的是USART1,串口的波特率必须是9600.
(以下是移植好后的usart.c文件)


#include "usart.h"#include"delay.h"#include "ht32f52352_sk.h"#include"ht32_board_config.h"#include "gizwits_protocol.h"
//C库#include<stdarg.h>
/* Global variables----------------------------------------------------------------------------------------*/uc8  *gURTx_Ptr;vu32 gURTx_Length = 0;u8  *gURRx_Ptr;vu32 gURRx_Length = 0;vu32gURRx_RElength=0;vu32 gIsTxFinished = FALSE;
/* Private variables---------------------------------------------------------------------------------------*/uc8gHelloString[] = "Hello, this is USART Tx/Rx FIFO example. Please enter 5characters...\r\n";u8 gTx_Buffer[128];u8 gRx_Buffer[128];
//USART0初始化void USART0_Configuration(void){  gURRx_Ptr = gRx_Buffer;
  #if 0  CKCU_SetPeripPrescaler(CKCU_PCLK_UxARTn, CKCU_APBCLKPRE_DIV2);  #endif
  {   CKCU_PeripClockConfig_TypeDef CKCUClock= {{0}};    CKCUClock.Bit.AFIO = 1;    CKCUClock.Bit.PA=1;    CKCUClock.Bit.USART0=1;    CKCU_PeripClockConfig(CKCUClock,ENABLE);  }
  GPIO_PullResistorConfig(HT_GPIOA,GPIO_PIN_3, GPIO_PR_UP);
  AFIO_GPxConfig(USART_GPIO_GROUP,USART_TX_PIN, AFIO_FUN_USART_UART); AFIO_GPxConfig(USART_GPIO_GROUP, USART_RX_PIN, AFIO_FUN_USART_UART);
  USART_InitTypeDefUSART_InitStructure={0};  
  USART_InitStructure.USART_BaudRate =115200; USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;  USART_InitStructure.USART_StopBits =USART_STOPBITS_1; USART_InitStructure.USART_Parity = USART_PARITY_NO;  USART_InitStructure.USART_Mode =USART_MODE_NORMAL;  USART_Init(COM0_PORT,&USART_InitStructure);
  NVIC_EnableIRQ(COM0_IRQn);   //Enable 中断设置
  USART_IntConfig(COM0_PORT,USART_INT_RXDR , ENABLE);// Enable UxART Tx and Rx interrupt
  USART_TxCmd(COM0_PORT, ENABLE); // 使能 COM1_PORT  发送和接收  USART_RxCmd(COM0_PORT,ENABLE);  }
//USART0中断函数void USART0_IRQHandler(void){  if(USART_GetFlagStatus(COM0_PORT ,USART_FLAG_RXDR) != RESET) //接收中断  {   if(gURRx_Length >= sizeof(gRx_Buffer))  gURRx_Length = 0; //防止串口被刷爆    gRx_Buffer[gURRx_Length++]= COM0_PORT->DR;
    USART_ClearFlag(COM0_PORT,USART_FLAG_RSADD);  }}
//USART1初始化void USART1_Configuration(void){  CKCU_PeripClockConfig_TypeDef CKCUClock={{0}};  CKCUClock.Bit.AFIO = 1;  CKCUClock.Bit.PA=1;  COM1_CLK(CKCUClock)  = 1; //开启COM0 时钟  CKCU_PeripClockConfig(CKCUClock, ENABLE);
  GPIO_PullResistorConfig(HT_GPIOA,GPIO_PIN_5, GPIO_PR_UP);
  AFIO_GPxConfig(USART1_GPIO_GROUP,USART1_TX_PIN, AFIO_FUN_USART_UART); AFIO_GPxConfig(USART1_GPIO_GROUP, USART1_RX_PIN, AFIO_FUN_USART_UART);
  USART_InitTypeDefUSART_InitStructure={0};
  USART_InitStructure.USART_BaudRate =9600; //波特率必须是9600 USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;  USART_InitStructure.USART_StopBits =USART_STOPBITS_1; USART_InitStructure.USART_Parity = USART_PARITY_NO;  USART_InitStructure.USART_Mode =USART_MODE_NORMAL;  USART_Init(COM1_PORT,&USART_InitStructure);
  NVIC_EnableIRQ(COM1_IRQn);   //Enable 中断设置      USART_IntConfig(COM1_PORT, USART_INT_RXDR, ENABLE);// Enable UxART Tx and Rx interrupt
  USART_TxCmd(COM1_PORT, ENABLE); // 使能 COM1_PORT  发送和接收   USART_RxCmd(COM1_PORT,ENABLE);
}
//USART1中断服务函数void USART1_IRQHandler(void){  uint8_t res; if(USART_GetFlagStatus(COM1_PORT , USART_FLAG_RXDR) != RESET) //接收中断  {    res =USART_ReceiveData(COM1_PORT);         gizPutData(&res, 1);//数据写入到缓冲区    USART_ClearFlag(COM1_PORT,USART_FLAG_RSADD);  }}

//UsartPrintf函数,相当于printfvoidUsartPrintf(HT_USART_TypeDef* USARTx, char *fmt,...){  unsigned char UsartPrintfBuf[296];  va_list ap; unsigned char *pStr = UsartPrintfBuf;
  va_start(ap, fmt);  vsnprintf((char *)UsartPrintfBuf,sizeof(UsartPrintfBuf), fmt, ap);              //格式化  va_end(ap);
  while(*pStr != 0)  {   USART_SendData(USARTx, *pStr++);   while(USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET);  }
}

2、协议层的运行需要一个系统时间,事件单位为毫秒,所以我们需要用用定时器来实现1ms的精准定时。
HT32F52352有5个定时器,他们是MCTM(马达控制定时器)、GPTM(PWM产生和捕捉定时器)、SCTM(单通道产生与捕捉定时器 )、BFTM(基本功能定时器)、 WDT(看门狗定时器),实现1ms的精准定时我们选用BFTM即可。
(以下是移植好后的TIMER.c文件)


#include "TIMER.h"#include"ht32f5xxxx_bftm.h"#include "gizwits_product.h"


void Timer_Init(void){   CKCU_PeripClockConfig_TypeDef CKCUClock= {{0}};  CKCUClock.Bit.BFTM1 = 1;  //开启中断时钟 CKCU_PeripClockConfig(CKCUClock, ENABLE);
  NVIC_EnableIRQ(BFTM1_IRQn);
  BFTM_SetCounter(HT_BFTM1, 0);//  BFTM_SetCompare(HT_BFTM1, SystemCoreClock);//定时1s产生中断 BFTM_SetCompare(HT_BFTM1, SystemCoreClock*1000);//定时1ms产生中断 BFTM_IntConfig(HT_BFTM1, ENABLE);//使能中断  BFTM_EnaCmd(HT_BFTM1, ENABLE);//使能BFTM
}
void BFTM1_IRQHandler(void){if(BFTM_GetFlagStatus(HT_BFTM1)!=RESET)    {     BFTM_ClearFlag(HT_BFTM1);//清除中断标志      gizTimerMs();          } }

四、开始移植
product.c文件中:
1、将Timer、usart、Gizwits、Utils四个文件夹加到工程里去

2、由于我们把定时中断服务函数和串口接收中断函数都放到对应的文件里面了,所以要删除product.c文件里的:
TIMER_IRQ_FUN函数
UART_IRQ_FUN函数
3、UartWrite函数里添加串口发送函数
(需要自行添加上头文件ht32f5xxxx_usart.h)
int32_tuartWrite(uint8_t *buf, uint32_t len){   uint32_t i = 0;
    if(NULL == buf)    {       return -1;    }
    #ifdef PROTOCOL_DEBUG   GIZWITS_LOG(COM0_PORT,"MCU2WiFi[%4d:%4d]: ",gizGetTimerCount(), len);    for(i=0;i<len; i++)    {        GIZWITS_LOG(COM0_PORT,"%02x", buf);    }    GIZWITS_LOG(COM0_PORT,"\n");    #endif
    for(i=0; i<len; i++)    {       USART_SendData(COM1_PORT, buf);//使用USART1进行数据的读写   while(USART_GetFlagStatus(COM1_PORT,USART_FLAG_TXDE)==RESET);
        //Serial port to achieve thefunction, the buf sent to the module       if(i >=2 && buf == 0xFF)        {          //Serial port to achieve thefunction, the 0x55 sent to the module         USART_SendData(COM1_PORT, 0x55);//使用USART1进行数据的读写     while(USART_GetFlagStatus(COM1_PORT,USART_FLAG_TXDE)==RESET);        }   }


    return len;}
4、mcuReset中添加软件复位函数
void mcuRestart(void){    NVIC_SystemReset();                                                  }

PS:
合泰的这款M0单片机实现软件复位的方法就是把SCB_AIRCR寄存器的SYSRESETREQ位置1.并且软件复位和硬件复位不一样,软件复位不需要进行FPGA、DSP等的加载,只是一些配置芯片的初始化。软件复位一般是一些块结构,硬件复位的作用区域一般是全局的。
void software_reset(void) {     __DSB();   //防止数据丢失                                                          SCB->AIRCR  = ((0x5FA <<SCB_AIRCR_VECTKEY_Pos)      |  //用0x5FA这个密码开启这个寄存器的锁                  SCB_AIRCR_SYSRESETREQ_Msk);                //SYSRESETREQ置1实现复位
  __DSB();   //防止数据丢失                                                     while(1);                                                   }
5、UserInit函数里写初始化
void userInit(void){   memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));//设备结构体初始化    gizwitsInit();//缓冲区初始化 gizwitsSetMode(WIFI_AIRLINK_MODE); //AirLink方式接入}

6、UserHandle里写入数据上报处理语句
(数据上行,单片机上报数据)
void userHandle(void){    if(wifi_sta)  {       currentDataPoint.valuelight_wave_1=200;    }}

7、GizwitsEventProcess函数里写入控制语句

(数据下行,手机下发控制指令)
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)   {      case EVENT_func_1:        currentDataPoint.valuefunc_1 =dataPointPtr->valuefunc_1;       GIZWITS_LOG(COM0_PORT,"Evt: EVENT_func_1 %d \n",currentDataPoint.valuefunc_1);       if(0x01 == currentDataPoint.valuefunc_1)        {         led_on(LED1_GPIO_PIN); //点亮LED1        }       else        {          led_off(LED1_GPIO_PIN); //关闭LED1        }        break;        ......

common.h文件中
由于我的usatrt.c文件里用的是UsartPrintf函数而不是printf函数,因此需要将common.h文件中的
#define GIZWITS_LOG printf
修改为:
#define GIZWITS_LOG UsartPrintf
并修改product.c和protocol.c文件里对应的语句
五、修改main.c文件
1、添加usart、timer、Gizwits的初始化
2、while函数里进行数据处理并上报
#include "ht32.h"
#include "usart.h"
#include "Delay.h"
#include "led.h"
#include "TIMER.h"
#include "gizwits_product.h"
dataPoint_t currentDataPoint;
uint8_t wifi_sta=0;
static void delay(u32 nCount)
{
vu32 i;
for (i = 0; i < 10000 * nCount; i++){}
}
int main(void)
{
LED_Init();              //LED初始化
led_off(LED1_GPIO_PIN);  //关闭LED1
USART0_Configuration();  //USART0初始化
USART1_Configuration();  //USART1初始化
Timer_Init();            //MS定时初始化
userInit();     //Gizwits初始化
while(1)
{
   userHandle();  
   gizwitsHandle((dataPoint_t *)&currentDataPoint); //上报数据  
}
}


到此程序的移植就完成了,可以下载机智云的APP看一看效果!
————————————————
版权**:本文为CSDN博主「刘一五」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本**。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表