一、准备工作:(1)机智云上下载生成的源码包

        (2)一个wifi模块,本例程使用(正点原子的ESP8266模块)

        (3)一块STMF103的开发板、核心板(STM32F103C8T6升级板)

        (4)一个keil工程,将机智云的源码移植至该工程中

源码包:

二、在源码中主要关注两个文件

1.Gizwits
2.Utils

三、重点修改两个.c文件  

1.gizwits_product.c  2.gizwits_protocol.c

四、移植步骤

1.将Gizwits 和Utils两个文件夹复制到自己的工程目录下,下图为我的一级工程目录。

2.在keil中分别导入这两个目录下的.c和.h文件。

 

 3.添加入我们工程之后,编译会出现错误,错误原因是找不到一些.h文件或函数,因此我们直接把这些给删除或替换掉。

在gizwits_product.h中#include <stm32f1xx.h>替换成我们单片机的头文件,我使用#include "stm32f103x.h"

 4.在gizwits_product.c文件中有一些删除一些程序

 

 

 

 

 到此,我们也就基本完成移植的删减工作。下面要实现一个1ms定时器和一个与WIFI模块通讯的串口。

5.定时器实现(完整程序)

(1)定时器初始化

/*timer2.c*/

/*定时器TIM2*//* TIM2中断优先级配置 */
void TIM2_NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                                      
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;      
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


/*中断周期为1ms*/
void TIM2_Configuration(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
    TIM_DeInit(TIM2);
    TIM_TimeBaseStructure.TIM_Period=1000;    //自动重装载寄存器周期的值(计数值) 
    /* 累计 TIM_Period个频率后产生一个更新或者中断 */
    TIM_TimeBaseStructure.TIM_Prescaler= (72 - 1);    //时钟预分频数 72M/72      
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);    // 清除溢出中断标志 
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM2, ENABLE);    // 开启时钟    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE);    //先关闭等待使用  
}

void TIM2_Init(void)
{
        TIM2_NVIC_Configuration(); /* TIM2 定时配置 */
        TIM2_Configuration();     
        START_TIME;     /* TIM2 开始计时 */
}

(2)实现定时器开关(个人)

/*timer2.h*/

#include "stm32f10x.h"

#define START_TIME  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);TIM_Cmd(TIM2, ENABLE)
#define STOP_TIME  TIM_Cmd(TIM2, DISABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE)

void TIM2_NVIC_Configuration(void);
void TIM2_Configuration(void);
void TIM2_Init(void);

(3)中断处理,gizTimerMs();在#include "gizwits_product.h"文件中,实现WIFI系统的计时。

 

void TIM2_IRQHandler(void)
{
    if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) 
    {    
                gizTimerMs();
                TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);    
    }             
}

6.串口实现

(1)串口初始化(USART3)

/*usart3.c*/
void USART3_Config(u32 BaudRate)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        USART_InitTypeDef USART_InitStruct;
        NVIC_InitTypeDef NVIC_InitStruct;
    
        /*打开USART3时钟*/
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
        /*打开CPIOB时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;  //Tx
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_Init(GPIOB, &GPIO_InitStruct);
    
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;        //Rx
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_Init(GPIOB, &GPIO_InitStruct);
    
        /*设置波特率*/
        USART_InitStruct.USART_BaudRate = BaudRate;
        /*不使用硬件流*/
        USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        /*RX TX都使能*/
        USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
        /*不使用校验*/
        USART_InitStruct.USART_Parity = USART_Parity_No;
        /*1位停止位*/
        USART_InitStruct.USART_StopBits = USART_StopBits_1;
        /*8位数据位*/
        USART_InitStruct.USART_WordLength = USART_WordLength_8b;
        /*初始化USART*/
        USART_Init(USART3, &USART_InitStruct);
        /*清除USARTx的挂起标志*/
        USART_ClearFlag(USART3, USART_IT_RXNE);
        /*打开中断事件,接收不为空时,打开中断*/
        USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
        /*指定中断源,也可认为是中断号*/
        NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
        /*中断使能*/
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        /*设置中断优先级类型*/
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
        /*设置中断优先级*/
        NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
        /*初始化中断向量*/
        NVIC_Init(&NVIC_InitStruct);
        /*使能USART3*/
        USART_Cmd(USART3,ENABLE);
}

(2)发送函数

/*usart3.c*/

/*发送数据*/
void USART3_Send(u8 *buf,uint16_t len)
{
        u16 t;
    
        for(t = 0;t < len;t++) //循环发送
        {
                /*检测当前串口为空闲*/
                while(USART_GetFlagStatus(USART3,USART_FLAG_TC) == RESET);
                USART_SendData(USART3,buf[t]);//发送USARTx的数据
        }
        /*等待发送完成*/
        while(USART_GetFlagStatus(USART3,USART_FLAG_TC) == RESET);
}

(3)中断接收函数

#include "gizwits_protocol.h"

extern uint8_t aRxBuffer;  //该参数在gizwits_product.c中定义
//串口中断函数
void USART3_IRQHandler()
{
                /*等待发送完成*/
                while(USART_GetFlagStatus(USART3,USART_FLAG_TC));
                /*接收数据*/
                aRxBuffer = USART_ReceiveData(USART3); 
                /*等待接收完成*/
                gizPutData((uint8_t *)&aRxBuffer,1);
                /*清空中断位*/
                USART_ClearITPendingBit(USART3,USART_IT_RXNE); //清除USARTx的中断挂起位
}  

(4)usart3.h

#ifndef __USART3_H__
#define __USART3_H__

#include "stm32f10x.h"

void USART3_Config(u32 BaudRate);
void USART3_Send(u8 *buf,uint16_t len);

#endif

 

6.一键配网设置,就是实现一个按键功能,调用配网函数即可。配网函数为#include "gizwits_product.h"中的int32_t gizwitsSetMode(uint8_t mode)。

(1)key.c

#include "key.h"
#include "led.h"
#include "SysTick.h"
#include "usart1.h"
#include "E2prom.h"
#include "EPS8266.h"
#include "gizwits_product.h"

void Key_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能PC端口时钟

    GPIO_InitStructure.GPIO_Pin = KEY_PIN;                        //选择对应的引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     //上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(KEY_IOA, &GPIO_InitStructure);                   //初始化PC端口
}

/*******************************************************************************
* 函 数 名         : KEY_Scan
* 函数功能           : 按键扫描检测
* 输    入         : mode=0:单次按下按键
                     mode=1:连续按下按键
* 输    出         : 0:未有按键按下
                     KEY_UP_PRESS:KEY_UP键按下
                     KEY0_PRESS:KEY0键按下
                     KEY1_PRESS:KEY1键按下
*******************************************************************************/
unsigned char Key_Scan(u8 mode)
{
    static unsigned char KeyUp_En = 1;

        if(mode == 1)KeyUp_En = 1;
    
    if((KeyUp_En==1) && (KEY_UP == 0))
    {
                delay_ms(20);
        KeyUp_En = 0;
        if(KEY_UP == 0)
        {
                        LED2(0);
                        gizwitsSetMode(WIFI_AIRLINK_MODE);  //一键配网
                        return KEY_UP_PRESS;
        }
    }
    else if((KeyUp_En==0) &&(KEY_UP == 1))KeyUp_En = 1;
        return 0;
}

(2)Key.h

#ifndef __KEY_H__
#define __KEY_H__

#include "system.h"

#define KEY_PIN    GPIO_Pin_0
#define KEY_IOA    GPIOA

#define KEY_UP PAin(0)

#define KEY_UP_PRESS 1

extern void Key_GPIO_Config(void);
extern unsigned char Key_Scan(u8 mode);

#endif

配网时将LED打开,如果配网成功,关闭LED。在gizwits_product.c中的gizwitsEventProcess()函数中。该函数时整个系统的核心,完成数据的下传处理和数据的上报工作,以及系统状态的检测。

 

 五、gizwits_product.c文件函数的完善。

(1)上报信息采集函数,这里我只有一个数据上报点(温度值),因此只有一个参数。

/*采集要上报的数据,如温度,湿度等等*/
void userHandle(void)
{
       currentDataPoint.valueTEMP = MyTemp;//Add Sensor Data Collection
}

(2)在userInit(void)中调用该文件的串口初始化和定时器初始化函数。

void userInit(void)
{
    memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));

    timerInit();
    uartInit();
}

(3)timerInit();

void timerInit(void)    //定时器初始化
{
    TIM2_Init();
}

(4)uartInit();

/**
* @brief USART init function

* Serial communication between WiFi modules and device MCU
* @param none
* @return none
*/
void uartInit(void) //串口初始化
{
    USART3_Config(9600);
}

(5)发送函数

/**
* @brief Serial port write operation, send data to WiFi module
*
* @param buf      : buf address
* @param len      : buf length
*
* @return : Return effective data length;-1,return failure
*/
int32_t uartWrite(uint8_t *buf, uint32_t len)
{
    uint32_t i = 0;
    uint8_t crc = 0x55;

    if(NULL == buf)
    {
        return -1;
    }

    for(i = 0; i < len; i++)
    {
        USART3_Send(buf+i,1);
        if(i >= 2  && buf[i] == 0xFF)
        {
            USART3_Send(&crc,1);
        }
    }
    return len;
}

六、main.c文件

#include "stm32f10x.h"
#include "led.h"
#include "SysTick.h"
#include "key.h"
#include "E2prom.h"
#include "usart1.h"
#include "usart3.h"
#include "Timer1.h"
#include "gizwits_product.h"
#include "common.h"

int main(void)
{
    SystemInit();    // 配置系统时钟为72M
    userInit();
    gizwitsInit();  
    while(1)
    {
        userHandle();    
        //在该函数中实现数据的上报和下行处理
        gizwitsHandle((dataPoint_t *)&currentDataPoint); //将数据上报
    }
}

至此,移植到STM32F103完成。有兴趣的同学想了解WIFI如何配网的,可自己参考对用资料和源程序。

 

posted on 2021-12-31 10:40  xiao_fei  阅读(710)  评论(0编辑  收藏  举报