查看: 914|回复: 0
收起左侧

RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-8-28 11:27:55 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-8-28 11:34 编辑

    前言:

    上一节,我们使用串口工具发送AT指令操作ESP-01S,本节,使用GD32VF103代替传偶工具完成和ESP-01S模块的交互过程。


    一、基础知识1.交互流程简介

    (1)设备上电,先控制8266的复位引脚为低电平,让模块复位


    (2)发送指令:ATE0,取消回显


    (3)发送指令:AT+CWMODE=2,设置ESP01S为AP模式


    (4)发送指令:AT+CIPMUX=1,设置多路连接,AP模式最多支持5个设备连接


    (5)发送指令:AT+CWSAP=“ESP01S_test”,“12345678”,1,3,启动一个WIFI热点


    (6)发送指令:AT+CIPSERVER=1,8089,启动TCP Server


    (7)发送指令:AT+CIPSERVER=1,8089,启动TCP Server


    (8)大循环中检测是否收到ESP01S数据,收到数据后立刻返回。


    2.程序框架简介

    程序主要包括如下4个功能模块:ESP01S初始化、串口处理、Event回调函数、事件处理;


    串口处理模块包括串口接收和定时器判断一帧数据是否接收完成功能,Event回调函数主要用来通知应用层系统的状态,方便应用层做出相应,


    比如设备检测到其他TCP Client客户端接入模块,可以控制LED状态,事件处理模块主要包含应用程序大循环,


    大循环中检测系统事件状态,根据事件状态再大循环中做出响应。


    国内芯片技术交流-RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②risc-v单片机中文社区(1)


    二、系统功能模块详述
    1.Event回调函数

    本程序使用了函数指针,应用层将事件处理函数传到hal_common.c中int hal_sys_contex_init(sys_status_fun fun, void *user_data)函数


    1. void system_status_callback(int sock, int event)
    2. {
    3.     system_context->sock_id = sock;
    4.     system_context->event = event;
    5. switch (event)
    6.     {
    7. case STA_CONNECTED:
    8.         rt_kprintf("Sock %d connected!\r\n", sock);
    9. break;
    10. case STA_CLOSED:
    11.         rt_kprintf("Sock %d closed!\r\n", sock);
    12. break;
    13. case STA_DATA_ARRIVED:
    14.         rt_kprintf("Sock %d data arrived!\r\n", sock);
    15. break;
    16. default:
    17. break;
    18.     }
    19. }

    20. typedef enum {
    21.     STA_CONNECTED,
    22.     STA_CLOSED,
    23.     STA_DATA_ARRIVED, // clients send data to wifi
    24.     STA_EVENT_MAX,
    25. }sys_event_e;

    26. typedef void (*sys_status_fun)(int sock, int event);

    27. typedef struct sys_ctx{
    28. int sock_id;
    29.     sys_event_e event;
    30. char data_buf[SYS_CTX_UART_RECV_SIZE];
    31.     sys_status_fun sys_status_cb;
    32. void *user_data;
    33. }sys_ctx_t;

    34. int hal_sys_contex_init(sys_status_fun fun, void *user_data)
    35. {
    36.     sys_contex.sys_status_cb = fun;
    37.     sys_contex.user_data = user_data;
    38. return 0;
    39. }

    40. int main(void)
    41. {
    42.     hal_sys_contex_init(system_status_callback, RT_NULL);

    43. while(1)
    44.     {

    45.     }
    46. }
    复制代码


    2.串口处理

    串口处理模块包括串口接收和定时器判断一帧数据是否接收完成功能,串口接收函数代码如下:


    1. #define RX_BUF_MAX_LEN     1024         //最大接收缓存字节数

    2. struct STRUCT_USART_Fram_S             //串口数据帧的处理结构体
    3. {
    4. char  Data_RX_BUF [ RX_BUF_MAX_LEN ];
    5. uint16_t FramLength;
    6. struct {
    7. uint8_t FramStartFlag;
    8. uint8_t FramFinishFlag;
    9.     } InfBit;
    10. } ;

    11. struct STRUCT_USART_Fram_S Esp8266_Frame_Record;

    12. void USART2_IRQHandler()
    13. {
    14. uint8_t ch = -1;
    15. if(RESET != usart_interrupt_flag_get(EVAL_COM2, USART_INT_FLAG_RBNE))
    16.     {
    17.         ch =  usart_data_receive(EVAL_COM2);
    18. //      if ( Esp8266_Frame_Record.FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符
    19. //      {
    20.             Esp8266_Frame_Record .Data_RX_BUF [ Esp8266_Frame_Record.FramLength ]  = ch;
    21. //      }
    22.         Esp8266_Frame_Record.FramLength ++;
    23. if (Esp8266_Frame_Record.FramLength >= 1024)
    24.         {
    25.             Esp8266_Frame_Record.FramLength = 0;
    26.         }
    27.         cnt = Esp8266_Frame_Record.FramLength;
    28. //      rt_kprintf(".......uart recv : %c, count is %d\r\n", ch, cnt);
    29.         Esp8266_Frame_Record.InfBit.FramStartFlag = 1;
    30.     }
    31. }
    复制代码


    中断处理函数中,将接收的数据放到Esp8266_Frame_Record .Data_RX_BUF中,


    然后将Esp8266_Frame_Record.InfBit.FramStartFlag置1,这个标志位再定时器中会用到,可以用来判断接收一帧数据是否完成。


    一帧数据接收是否完成的判断逻辑是:定时器会定期检测,如果FramStartFlag为1,说明串口正在接收数据,没接收一个数据,FramLength加1,因此,当进入定时器中断函数,判断FramStartFlag为1情况下FrameLength如果不再增加,说明一帧数据接收完成。


    1. static void timeout1(void *parameter)
    2. {
    3. int sock_id = -1;
    4.     char buff[128] = { 0x00 };
    5. int len = 0;
    6.     sys_event_e event = STA_EVENT_MAX;

    7. //  rt_kprintf("timer's cnt is %d, FrameLength is %d\r\n", cnt, Esp8266_Frame_Record.FramLength);
    8. if (1 == Esp8266_Frame_Record.InfBit.FramStartFlag)
    9.     {
    10. if (cnt == Esp8266_Frame_Record.FramLength && cnt != 0)
    11.         {
    12.             cnt = 0;
    13.             Esp8266_Frame_Record .Data_RX_BUF [ Esp8266_Frame_Record.FramLength ]  = 0x00;
    14.             rt_kprintf("timer --------> data %s\r\n", Esp8266_Frame_Record.Data_RX_BUF);
    15. if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "CONNECT"))
    16.             {
    17.                 sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%d,%s", &sock_id, buff);
    18.                 event = STA_CONNECTED;
    19.             }else if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "CLOSED"))
    20.             {
    21.                 sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%d,%s", &sock_id, buff);
    22.                 event = STA_CLOSED;
    23.             }else if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "+IPD"))
    24.             {
    25.                 rt_memset(hal_sys_contex_get()->data_buf, 0x00, SYS_CTX_UART_RECV_SIZE);
    26.                 sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%*[^+]+IPD,%d,%d:%[^\r]", &sock_id, &len, hal_sys_contex_get()->data_buf);
    27.                 event = STA_DATA_ARRIVED;
    28.                 rt_kprintf("parsed +IPD :%s\r\n", hal_sys_contex_get()->data_buf);
    29.             }
    30.             // call sys_status_cb
    31. if (hal_sys_contex_get()->sys_status_cb)
    32.             {
    33.                 hal_sys_contex_get()->sys_status_cb(sock_id, event);
    34.             }

    35.             Esp8266_Frame_Record.InfBit.FramFinishFlag = 1;
    36.             Esp8266_Frame_Record.InfBit.FramStartFlag = 0;
    37.         }else
    38.         {
    39.             cnt = Esp8266_Frame_Record.FramLength;
    40.         }
    41.     }else
    42.     {
    43.         cnt = 0;
    44.         Esp8266_Frame_Record.FramLength = 0;
    45.     }
    46. }
    复制代码


    注意:事件处理本质上是在此调用hal_sys_contex_get()->sys_status_cb(sock_id, event)映射到应用层的void system_status_callback(int sock, int event)函数。


    3.事件处理

    事件处理的核心再while(1)中,根据系统当前事件状态做出响应,本节是检测到事件为数据类型时候,将数据原路返回。


    1. int main(void)
    2. {
    3. /* enable the LED clock */
    4.     rcu_periph_clock_enable(RCU_GPIOA);
    5. /* configure LED GPIO port */
    6.     gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
    7.     gpio_bit_reset(GPIOA, GPIO_PIN_1);
    8. // create iwdt_thread
    9.     dynamic_thread = rt_thread_create("led_thread", led_process_thread_entry,
    10.                                         RT_NULL, 512, 2, 10);
    11.     rt_thread_startup(dynamic_thread);
    12. // init sys_ctx
    13.     hal_sys_contex_init(system_status_callback, RT_NULL);
    14.     system_context = hal_sys_contex_get();
    15.     hal_timer_init();
    16.     ESP8266_Init();
    17.     rt_thread_mdelay(1000);
    18.     ESP8266_Ate0();
    19.     tcp_server_init();
    20.     tcp_server_start();

    21. while(1)
    22.     {
    23. if (STA_DATA_ARRIVED == system_context->event)
    24.         {
    25. // send back
    26.             ESP8266_SendString ( DISABLE, system_context->data_buf, rt_strlen(system_context->data_buf), system_context->sock_id );
    27.         }
    28.         rt_thread_mdelay(10);
    29.     }
    30. return 0;
    31. }
    复制代码


    三、运行

    下载程序完毕后,重启设备,ESP01S启动一个WIFI热点,并启动TCP Server,log如下:


    国内芯片技术交流-RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②risc-v单片机中文社区(2)



    电脑连接热点,使用网络助手连接192.168.4.1:8089


    国内芯片技术交流-RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②risc-v单片机中文社区(3)


    网络助手发送数据给ESP01S


    国内芯片技术交流-RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②risc-v单片机中文社区(4)

    关闭网络助手,应用程序也可以检测到,如下Log所示

    国内芯片技术交流-RISC-V单片机快速入门05-玩转ESP8266 WIFI模块②risc-v单片机中文社区(5)


    四、结语

    一叶孤沙出品:一沙一世界,一叶一菩提

    本篇完,感谢关注:RISC-V单片机中文网




    上一篇:RISC-V ISA 学习笔记(2) 乘除法标准扩展“M”和原子扩展“A”
    下一篇:RISC-V单片机快速入门06-控制ESP8266启动Http Server
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-20 06:15 , Processed in 0.590054 second(s), 44 queries .

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