STM32与正点原子ESP8266的结合

1、准备

        STM32F103C8T6单片机

        ATK-ESP8266(原子云固件)

        杜邦线

2、接线

        ESP8266

                IO_0        烧录固件使用,不需连接

                RST        模块复位,接任意IO,低电平有效

                RXD        模块接收,接PB10

                TXD        模块发送,接PB11

                GND        电源地

                VCC        电源5V

        STM32F103C8T6

3、原子云

        注册原子云,建立ESP8266设备

        设备名称和密码任意,

        在分组管理创建一个分组添加这个设备。

4、控制ESP8266初始化

        1、连接 RST 的 IO 拉低再拉高,使模块复位

        2、AT指令测试:(串口 PB10)发送 “AT”,(串口 PB11)收到 “OK”;

        3、设置 Station 工作模式:发 AT+CWMODE=1,回 OK;

        4、软件复位:发 AT+RST,回 OK;

        5、关闭回显:发 ATE0,回 OK;

        6、连接WIFI:发 AT+CWJAP="WIFI_ID","WIFI_Password",回 WIFI GOT IP

                WIFI_ID 和 WIFI_Password 对应连接的 WIFI 名字和密码

        7、获取IP地址:发 AT+CIFSR,回 OK

        8、连接原子云:发AT+ATKCLDSTA="ID","Password",回CLOUD CONNECTED

                ID 和 Password 对应原子云设备编号和密码

        以上接收都没问题后就可以后,单片机就可以通过串口3和原子云通信。

5、控制代码

        1、串口3正常初始化,波特率115200,开启串口中断和串口空闲中断,可以使用CubeMX生成;

        2、串口收发函数( UART3_Rx_flg在串口空闲置1 )

// UART3
uint8_t UART3_Rx_Buf[UART3_Rx_COUNT] = {0}; //USART3存储接收数据
uint8_t UART3_data = 0;       //USART3接收数据缓存
uint16_t UART3_Rx_cnt = 0;                  //USART3接受数据计数器
uint8_t UART3_Rx_flg = 0;                   //USART3接收完成标志

uint8_t UART3_Tx_Buf[UART3_Tx_COUNT] = {0}; //USART3发送缓冲



/**
 * @brief   UART3 printf
 * @param   fmt: 待打印的数据
 * @retval  无
 */
void usart3_printf(char *fmt, ...)
{
    va_list ap;
    uint16_t len;
    
    va_start(ap, fmt);
    vsprintf((char *)UART3_Tx_Buf, fmt, ap);
    va_end(ap);
    
    len = strlen((const char *)UART3_Tx_Buf);
    HAL_UART_Transmit(&huart3, UART3_Tx_Buf, len, HAL_MAX_DELAY);
}


/**
 * @brief   UART3 清标志位
 * @param   无
 * @retval  无
 */
void usart3_close_flag(void)
{
    UART3_Rx_cnt = 0;
    UART3_Rx_flg = 0;
}


/**
 * @brief   UART3 接收到的一帧数据
 * @param   无
 * @retval  NULL: 未接收到一帧数据
 *          其他: 接收到的一帧数据
 */
uint8_t *usart3_uart_dat(void)
{
    if (UART3_Rx_flg == 1)
    {
        UART3_Rx_Buf[UART3_Rx_cnt] = '\0';
        return UART3_Rx_Buf;
    }
    else
    {
        return NULL;
    }
}


/**
 * @brief       获取 UART3 接收到的一帧数据的长度
 * @param       无
 * @retval      0   : 未接收到一帧数据
 *              其他: 接收到的一帧数据的长度
 */
uint16_t usart3_uart_dat_len(void)
{
    if (UART3_Rx_flg == 1)
    {
        return UART3_Rx_cnt;
    }
    else
    {
        return 0;
    }
}

        3、ESP8266初始化(8266子函数在正点原子ESP8266随便一个板型例程找,一样)

#define WIFI_ID(a)       (a ? "vivo X80" : "JC-R&D")            //WIFI名称
#define WIFI_PASSWORD(a) (a ? "YQY1122334455" : "jc12345678")   //WIFI密码
#define WIFI_SERVER_ID        "11111111111111111111"    //原子云设备编号
#define WIFI_SERVER_PASSWORD  "12345678"                //原子云设备密码


/**
 * @brief       ATK-MW8266D初始化
 * @retval      0: ATK-MW8266D初始化成功,函数执行成功
 *              1: ATK-MW8266D初始化失败,函数执行失败
 */
void ATK_MW8266D_Init(void)
{
    uint8_t flag;       //返回标志
    char ip_buf[16];    //ip地址
    
    
    atk_mw8266d_reset();            /* ATK-MW8266D硬件复位 */
    flag = atk_mw8266d_at_test();   /* ATK-MW8266D AT指令测试 */
    if (flag != ATK_MW8266D_EOK)      // 有错
    {
        OLED_ShowString_fun("8266 Init ERROR");
        printf("ATK-MW8266 Init ERROR\r\n");
        while(1);
    }
    OLED_ShowString_fun("8266 Init OK");
    printf("ATK-MW8266 Init OK\r\n");
    
    
//    flag  = atk_mw8266d_restore();    /* 恢复出厂设置 */
//    flag += atk_mw8266d_at_test();    /* AT测试 */
    flag = atk_mw8266d_set_mode(1);     /* Station模式 */
    flag += atk_mw8266d_sw_reset();     /* 软件复位 */
    flag += atk_mw8266d_ate_config(0);  /* 关闭回显功能 */
    flag += atk_mw8266d_join_ap(WIFI_ID(1), WIFI_PASSWORD(1));  /* 连接WIFI */
    flag += atk_mw8266d_get_ip(ip_buf); /* 获取IP地址 */
    if (flag != 0)      // 有错
    {
        OLED_ShowString_fun("8266 Wifi ERROR");
        printf("ATK-MW8266 Wifi ERROR\r\n");
        while (1);
    }
    OLED_ShowString_fun("8266 Wifi OK");
    printf("ATK-MW8266 Wifi OK\r\n");
    
    
    flag = atk_mw8266d_connect_atkcld(WIFI_SERVER_ID, WIFI_SERVER_PASSWORD);    /* 连接原子云 */
    if (flag != 0)
    {
        OLED_ShowString_fun("8266 Link ERROR");
        printf("ATK-MW8266 Link ERROR\r\n");
        while (1);
    }
    OLED_ShowString_fun("8266 Link OK");
    printf("ATK-MW8266 Link OK\r\n");
    
    usart3_close_flag();    /* 清标志位 */
}



/**
 * @brief       ATK-MW8266D发送AT指令
 * @param       cmd    : 待发送的AT指令
 *              ack    : 等待的响应
 *              timeout: 等待超时时间
 * @retval      0: 函数执行成功
 *              2: 等待期望应答超时,函数执行失败
 */
uint8_t atk_mw8266d_send_at_cmd(char *cmd, char *ack, uint32_t timeout)
{
    uint8_t *ret = NULL;
    
    usart3_close_flag();
    usart3_printf("%s\r\n", cmd);
    
    if ((ack == NULL) || (timeout == 0))
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        while (timeout > 0)
        {
            ret = usart3_uart_dat();
            if (ret != NULL)
            {
                if (strstr((const char *)ret, ack) != NULL)
                {
                    return ATK_MW8266D_EOK;
                }
                else
                {
                    usart3_close_flag();
                }
            }
            timeout--;
            delay_ms(1);
        }
        
        return ATK_MW8266D_ETIMEOUT;
    }
}

        4、主函数

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    uint8_t* buf;
    char oled_buf[64];
    uint8_t run_flag = 0;
    uint8_t flag = 1;


    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_TIM3_Init();
    HAL_TIM_Base_Start_IT(&htim3);

    MX_USART1_UART_Init();
    HAL_UART_Receive_IT(&huart1, (uint8_t *)UART1_temp, REC_LENGTH);
    printf("USART1 Init");

    MX_USART3_UART_Init();
    HAL_UART_Receive_IT(&huart3, &UART3_data, 1);
    HAL_UART_Transmit(&huart3, "USART3 Init", 11, HAL_MAX_DELAY); 

    MX_I2C1_Init();
    OLED_Init();
    OLED_ShowString_fun("OLED_OK!");
    
    ATK_MW8266D_Init();       //ATK-MW8266D初始化



    while(1)
    {
        buf = usart3_uart_dat();   /* 接收来自ATK-MW8266D UART的一帧数据 */
        
        if (buf != NULL)
        {
            sprintf(oled_buf, "%s", buf);
            OLED_ShowString_fun(oled_buf);
            
            if(!strcmp((char*)buf, "open"))
            {
                run_flag = 1;
            }
            
            if(!strcmp((char*)buf, "close"))
            {
                run_flag = 0;
            }
            
            usart3_close_flag();    /* 重开开始接收来自ATK-MW8266D UART的数据 */
        }
    }
}

作者:无敌暴龙战士朵拉

物联沃分享整理
物联沃-IOTWORD物联网 » STM32与正点原子ESP8266的结合

发表回复