Clion开发STM32之ESP8266系列(四)

这篇具有很好参考价值的文章主要介绍了Clion开发STM32之ESP8266系列(四)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上一篇: Clion开发STM32之ESP8266系列(三)

本篇主要内容

  1. 实现esp8266需要实现的函数
  2. 串口3中断函数的自定义(这里没有使用HAL提供的)
  3. 封装esp8266服务端的代码和测试

正文

主要修改部分

核心配置头文件(添加一些宏定义)

  1. sys_core_conf.h文件中

Clion开发STM32之ESP8266系列(四)

Clion开发STM32之ESP8266系列(四)

实现esp8266需要实现的函数

Clion开发STM32之ESP8266系列(四)

源码

/*******************************************************************************
 * @author scl
 * @email shchlu188@163.com
 *      @brief 实现esp8266的驱动
 ******************************************************************************/
#include "module_esp8266.h"
#include "bsp.h"

extern data_frame_t esp_rx_frame;

static void sys_delay(uint32_t ms) {
    HAL_Delay(ms);
}

/**
 * @brief esp8266 驱动外设初始化
 */
void esp8266_driver_init() {
    /*设置系esp8266延时回调*/
    esp8266_set_delay_call(sys_delay);
    /*配置 CH_PD 引脚*/
    gpio_init(GPIOB, GPIO_PIN_8, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);
    /* 配置 RST 引脚*/
    gpio_init(GPIOB, GPIO_PIN_9, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);
    /*串口配置*/
    com3_init(115200);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);
    /*开启串口中断*/
    UART_ENABLE_IT(USART3, UART_IT_RXNE);    /** 开启串口中断*/
    UART_ENABLE_IT(USART3, UART_IT_IDLE);   /** 开启串口空闲中断*/
}

/**
 * @brief esp8266 复位引脚
 * @param flag true: 置高; false: 置低
 */
void esp8266_rst_pin(bool flag) {
    if (flag) {
        pin_high(GPIOB, GPIO_PIN_9);
    } else {
        pin_low(GPIOB, GPIO_PIN_8);
    }
}

/**
 * @brief esp8266 使能引脚
 * @param flag true: 使能
 */
void esp8266_ch_enable(bool flag) {
    if (flag) {
        pin_high(GPIOB, GPIO_PIN_8);
    } else {
        pin_low(GPIOB, GPIO_PIN_8);
    }
}


/**
 * @brief esp8266 发送数据
 * @param data
 * @param len
 */
void esp8266_send(void *data, uint16_t len) {
    HAL_UART_Transmit(com_handle_get(com3), data, len, 1000);
}

/**
 * @brief 清空接收缓冲区
 */
void esp8266_clear_buf(void) {
    esp_rx_frame.InfAll = 0;
}

/**
 * @brief esp8266 接收数据
 * @return 接收数据
 */
char *esp8266_rec() {
    if (esp_rx_frame.InfBit.frame_finished_flag != 0) {
        /*添加结束符*/
        esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len] = '\0';
        esp_rx_frame.InfAll = 0;// 清除一次标志位
        return esp_rx_frame.p_rx_buf;
    }
    return NULL;
}

/**
 * @brief esp8266 构造指令的缓存区
 * @return
 */
char *esp8266_get_cmd_buf() {
    static char esp8266_buf[200] = {0};
    return esp8266_buf;
}

对应的串口3中断函数的编写

Clion开发STM32之ESP8266系列(四)

extern data_frame_t esp_rx_frame;

static inline void esp8266_tcp_server_IRQHandler() {
    uint8_t ucTemp;
    if (UART_GET_FLAG(USART3, UART_FLAG_RXNE)) {
        ucTemp = READ_REG(USART3->DR);// 读取数据
        if (esp_rx_frame.InfBit.frame_len < (esp_rx_frame.rx_buf_len - 1)) {
            esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len++] = ucTemp;
        }
    }
    //数据帧接收完毕
    if (UART_GET_FLAG(USART3, UART_FLAG_IDLE)) {
        esp_rx_frame.InfBit.frame_finished_flag = 1;
        // 添加结束符
        esp_rx_frame.p_rx_buf[esp_rx_frame.InfBit.frame_len] = '\0';
        //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)
        _UART_CLEAR_PEFLAG(USART3);
    }
}

void USART3_IRQHandler(void) {
    /* HAL库中断处理函数*/
    // HAL_UART_IRQHandler(&com3_handle);
    /* 自定义中断处理函数*/
    esp8266_tcp_server_IRQHandler();
}

封装esp8266服务端的代码(针对驱动层再进行一个封装)

头文件

/*******************************************************************************
 * @author scl
 * @email shchlu188@163.com
 ******************************************************************************/

#ifndef STM32F103VET6_ESP8266_ESP8266_SERVICE_H
#define STM32F103VET6_ESP8266_ESP8266_SERVICE_H

#include "service_include.h"
/*wifi 账号*/
#define WIFI_SSID "账号"
/*wifi 密码*/
#define WIFI_PWD "密码"
/*尝试执行次数*/
#define TRY_CNT 3
/*本地IP配置*/
#define LOCAL_SERVER_IP "192.168.199.12"
/*本地端口配置*/
#define LOCAL_SERVER_PORT 8000
/*宏定义调试日志*/
#define esp_ps(fmt, ...) os_ps(fmt,##__VA_ARGS__)
/*************************************ESP 服务端 STA模式**********************************************/
/**
 * @brief esp8266 在sta模式下初始化 sever
 * @return
 */
bool esp_sta_tcp_server_init(void);
/**
 * @brief esp8266 在sta模式下获取ip
 * @param dstIp 保存ip
 * @param len  dstIp的长度
 * @return
 */
bool esp_sta_tcp_server_get_ip(char *dstIp, uint8_t len);
/**
 * @brief esp8266 客户端请求处理
 * @param data 接收的数据
 * @param len  数据长度
 * @return
 */
bool esp_sta_tcp_server_request_handle(char *data, uint16_t len);

#endif //STM32F103VET6_ESP8266_ESP8266_SERVICE_H

源文件

/*******************************************************************************
 * @author scl
 * @email shchlu188@163.com
 ******************************************************************************/

#include "esp8266_service.h"
#include "module_esp8266.h"
#include "bsp.h"

/**
 * @brief 禁止接收数据(静态内联函数)
 */
sys_force_static_inline void esp_disable_rec() {
    UART_DISABLE_IT(USART3, UART_IT_RXNE);
}

sys_force_static_inline void esp_enable_rec() {
    UART_ENABLE_IT(USART3, UART_IT_RXNE);
}

bool esp_sta_tcp_server_init(void) {
    esp_ps("--esp_sta_tcp_server_init start---\r\n");
    /*使能信号*/
    esp8266_ch_enable(true);
    /*测试AT指令*/
    try_cnt_run (esp8266_base_at_cmd_test(10, 500), 1);
    esp_ps("esp8266_base_at_cmd_test ok\r\n");
    /*动态分配IP地址*/
    try_cnt_run(esp8266_dhcp_cur_set(sta_mode, true, -1), TRY_CNT);
    /* 设置为STA模式 */
    try_cnt_run(esp8266_wifi_mode_cur_set(sta_mode, -1), TRY_CNT);
    esp_ps("esp8266_mode_cur_set ok\r\n");
    /* 设备本地设备ip*/
    try_cnt_run(esp8266_ip_sta_cur_set(LOCAL_SERVER_IP, NULL, NULL, -1), TRY_CNT);
    esp_ps("esp8266_ip_sta_cur_set ok\r\n");
    /*连接WiFi*/
    try_cnt_run (esp8266_wifi_join_cur_set(WIFI_SSID, WIFI_PWD, NULL, -1), TRY_CNT);
    esp_ps("esp8266_wifi_join_cur_set ok\r\n");
    /*允许多连接*/
    try_cnt_run (esp8266_mul_connect_set(true, -1), TRY_CNT);
    esp_ps("esp8266_mul_connect_set ok\r\n");
    /*开启服务器模式*/
    try_cnt_run (esp8266_server_tcp_start(true, LOCAL_SERVER_PORT, -1), TRY_CNT);
    esp_ps("esp8266_server_tcp_start ok\r\n");
    /*设置服务器链接超时时间*/
    try_cnt_run (esp8266_server_tcp_timeout_set(20, -1), TRY_CNT);
    esp_ps("esp8266_server_tcp_timeout_set ok\r\n");

    esp_ps("--esp_sta_tcp_server_init end---\r\n");

    return true;
}

bool esp_sta_tcp_server_get_ip(char *dstIp, uint8_t len) {
    esp_ps("--esp_sta_tcp_server_get_ip start---\r\n");
    try_cnt_run (esp8266_ip_sta_inquire(dstIp, len, -1), TRY_CNT);
    esp_ps("--esp_sta_tcp_server_get_ip end---\r\n");
    return true;
}
/**
 * @brief 解析接收的数据
 * @param rec_data 接收的数据
 * @param no_id socket id
 * @param data_len 发送的数据长度
 * @return 实际数据的位置
 */
sys_force_static_inline char *parse_rec_data(char *rec_data, uint8_t *no_id, uint16_t *data_len) {
    static char *pre_str = "+IPD,";
    char *p_data = strstr(rec_data, pre_str);
    // 数据解析错误 +IPD,0,2:12
    if (!p_data) return false;
    /*跳过前缀*/
    p_data += strlen(pre_str);
    /*解析socket id 号*/
    *no_id = strtol(p_data, &p_data, 10);
    if (!*p_data) return false;
    /*解析数据长度 */
    *data_len = strtol(p_data + 1, &p_data, 10);
    if (!*p_data) return false;
    /*获取数据*/
    p_data += 1;
    return p_data;
}

bool esp_sta_tcp_server_request_handle(char *data, uint16_t len) {
    /* 禁止esp多个客户端同时发送数据 */
    uint16_t data_len = 0;/*实际客户端发送的数据长度*/
    uint8_t socket_id;/*实际客户端连接的端口号*/
    bool result_flag = true;
    /*禁止接收,保证同一时间只只处理一个请求 */
    esp_disable_rec();
    /*实际客户端发送的数据位置*/
    char *p_data = parse_rec_data(data, &socket_id, &data_len);
    if (p_data) {
        // todo 这里就是做业务逻辑控制的地方,目前只是回显
        esp_ps("parse_rec_data:%d %d %s\r\n", socket_id, data_len, p_data);
        if (esp8266_server_tcp_send_to(socket_id, p_data, data_len, -1)) {
            esp_ps("response ok\r\n");
        } else {
            esp_ps("response error\r\n");
        }
    } else {
        result_flag = false;
    }
    /*清除这次的请求数据,保证下次数据为最新的*/
    esp8266_clear_buf();
    /*开启请求,保证同一时间只只处理一个请求 */
    esp_enable_rec();
    return result_flag;
}

esp8266驱动配置文件的编写

Clion开发STM32之ESP8266系列(四)

/*******************************************************************************
 * @author scl
 * @email shchlu188@163.com
 ******************************************************************************/
#include "app_conf.h"
#include "module_esp8266.h"
#include "service.h"

/*创建数据接收帧*/
static char rx_buf[1024] = {0};
data_frame_t esp_rx_frame = {.p_rx_buf=rx_buf, .rx_buf_len=1024};

static void driver_init(void) {
    /*esp8266初始化*/
    esp8266_driver_init();
}




/*这句话就是将驱动导出到段中*/
DRIVER_EXPORT(esp8266_driver, driver_init);


/**
 * 测试阶段暂时使用此方法
 * */
void app_run() {
    if (esp_sta_tcp_server_init()) {
        os_ps("--esp_sta_tcp_server_init ok--\r\n");
        while (1) {
            if (esp_rx_frame.InfBit.frame_finished_flag) {
                esp_sta_tcp_server_request_handle(esp_rx_frame.p_rx_buf, esp_rx_frame.InfBit.frame_len);
            }
        }
    } else {
        os_ps("--esp_sta_tcp_server_init error--\r\n");
    }


}

代码测试

  1. 本次设置esp8266模块的IP为192.168.199.12,端口号为8000

主入口函数调整

Clion开发STM32之ESP8266系列(四)### 下载程序

观察日志记录

Clion开发STM32之ESP8266系列(四)

用客户端去连接192.168.199.12:8000

Clion开发STM32之ESP8266系列(四)

客户端

Clion开发STM32之ESP8266系列(四)

查看串口

  1. 接收数据正常

Clion开发STM32之ESP8266系列(四)
Clion开发STM32之ESP8266系列(四)文章来源地址https://www.toymoban.com/news/detail-476414.html

结尾

  1. ESP8266系列的章节也就更新完成,目前基础功能模板工程已经完。
  2. 目前可以根据此工程执行对应的指令控制的逻辑了。
  3. 后续在此基础之上设计一个指令集动态加载服务器接收处理和响应的框架。
  4. 完整的项目已上传到gitee,有需要自行查看开头结尾的git地址.

下个系列的目标

  1. 整合Freertos
  2. 整合Modbus协议和自定义协议框架

到了这里,关于Clion开发STM32之ESP8266系列(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Clion开发STM32之W5500系列(NTP服务封装)

    在w5500基础库中进行封装,获取服务端的时间,来校准本地时间。 本次使用的方案是通过ntp获取时间+定时器更新保证时间准确。

    2024年02月16日
    浏览(28)
  • stm32——esp8266物联网开发,连接onenet云平台(http)做智能家居(1)

    此处感谢b站up主——彼岸有光我们有船(我认为讲的和江科大老师一样好,如果习惯江科大老师的讲法的朋友们都可以看看捏) 提供的教程和最初的正点原子的源码,因为我学习的是江科大的stm32,所以进行了部分改编和部分注释,在此把视频内容简化,进行简单的复习。

    2023年04月08日
    浏览(40)
  • 学习素材之USART篇——通过使用STM32与ESP8266(esp-01s)连接阿里云系列操作来了解USART协议和寄存器操作

    目录 USART详解 一、串口通讯协议简介 串口通讯的物理层 串口通讯的协议层 二、STM32 的 USART 简介 USART功能概述 功能引脚 三、与USART有关的寄存器 USART寄存器地址映像  四、USART寄存器描述 1、USART状态控制器(USART_SR) 2、数据寄存器(USART_DR) 3、波特比率寄存器(USART_BRR) 4、控

    2024年02月16日
    浏览(35)
  • STM32+ESP8266+APP连接阿里云监测环境温湿度系列笔记1:阿里云物联网平台配置及数据上传

            在数据传递过程中阿里云物联网平台相当于服务器,ESP8266为客户端,通过路由器连接服务器时需要在物联网平台创建设备,具体过程如下: 1. 首先 在物联网平台创建公共实例,并点击进入, 图1 2.可见设备接入物联网平台的整体流程如图2中红色方框所示, 接下

    2024年02月04日
    浏览(39)
  • STM32系列(HAL库)——使用ESP8266-01S物联网模块连接Onenet云平台上报DHT11温湿度

    本篇主要讲解如何使用ESP8266-01S物联网模块连接Onenet云平台,并上报DHT11模块的温湿度数据。本文单片机主控采用STM32F405RGT6,使用其他主控的话基本要求有2个串口,一个串口用于调试使用,另一个用于ESP模块通讯。 1.软件 CubeMX Keil5 串口调试助手 Onenet云平台账户 2.硬件 STM32开

    2024年02月02日
    浏览(54)
  • CLion开发工具 | 05 - 使用CLion开发ESP32

    电脑上安装好ESP-IDF环境 本文参考Jetbrains官方视频教程:在 Windows 上用 CLion 开发 ESP32 | CLion教程 | 嵌入式开发 | IDE 复制一份新的helloworld工程。 使用CLion打开该工程。 选择信任该工程。 CLion打开后自动打开了README.md文件,并进行了Cmake自动配置。 ESP-IDF需要临时配置的环境变量

    2024年02月02日
    浏览(39)
  • ESP8266与STM32

    最近想实现esp8266-01s系列和stm32f103c8t6之间进行串口通信,然后在网上看了好多这方面的资料最终都以失败告终。不断尝试下还是实现该功能,同时非常感谢这位博主。 博主链接 实现的最终功能是能够通过手机连上ESP8266作为服务端模式下的wifi,让后在手机上发送相关的指令,

    2024年02月14日
    浏览(38)
  • STM32+ESP8266+华为云

    此部分省略… 搜索框内搜索 物联网平台 点击打开【设备接入IOTDA】 点击进入【管理控制台】 这里进入后可能会提示你进行实名认证,如果不实名认证的话是不可以使用云平台的 我记得第一次使用的话好像还需要创建一个空间啥的,如果创建的话就一切默认就行了 点击右上

    2024年02月04日
    浏览(32)
  • 入门stm32:STM32hal库实现ESP8266与手机通信(不定长数据收发和ESP8266使用的一些问题)

    目录 前言 一、stm32cubeMX的串口配置 二、空闲中断+dma接收 三、ESP8266.c和ESP8266.h ESP8266.h ESP8266.c 注意事项 四、与手机通信例程 步骤:  例程代码main.c 运行结果 五、相关问题 总结 相关的app和源码         前提: 1.掌握串口通信和ESP8266的使用方法 串口通信:单片机串口通信

    2024年02月04日
    浏览(60)
  • 【STM32+ESP8266上云连载①】给ESP8266烧录AT固件

    我在使用ESP8266的时候遇到了一些问题,像给固件烧录、和单片机结合使用MQTT协议给云服务器发送数据等。乐鑫有提供基础的AT固件,可以正常使用模组的一些基本的功能,但是针对MQTT协议需要烧录专门的固件使用。因此,我将自己解决遇到的问题解决方法写一下,希望可以

    2024年02月11日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包