当前位置:   article > 正文

stm32与esp8266WIFI模块

stm32与esp8266WIFI模块

硬件介绍

WIFI模块ESP-01S

使用AT指令控制1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客

项目需求

通过ESP-01SWIFI模块控制LED状态模拟插座

串口1用于与ESP8266通讯,串口2连接PC,用于打印log,查看系统状态

项目接线

WIFI模块TXRX分别接到单片机的RX1和TX1

CH340TXDRXD分别接到单片机的RX2和TX2

项目注意事项 

1. 在这个项目里,烧写完单片机之后,不光要点击复位,还要重启单片机电源,以确保WIFI模块重新启动

2. 在以后的工作中一般不直接在中断服务函数里处理数据,而是在收到数据后直接丢给队列,再处理数据

3. 在中断服务函数里尽量减少使用延时函数及打印函数

4. 2,3条在本项目中并没有实现,因为还没有学到Linux的队列概念,只是先留个印象

5. 由于之前的WIFI模块波特率改成了9600,所以现在连接CH340修改回 115200(使用AT指令修改)

 AP模式下控制的实现(透传)

CubeMX

1. 惯例配置(时钟,gpio,系统时钟)

2. 打开两个串口(uart1和uart2),并在WIFI模块对应的串口1打开中断

 3. 由于在中断处理函数中使用了Delay函数,得调整中断的优先级(非必要不使用,容易造成未知错误)

4. 惯例配置,导出工程(路径,编程软件)

Keil

要在魔术棒中将MiroLIB勾选,使得可以重写printf

代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. //串口接收缓存(1字节)
  4. uint8_t buf=0;
  5. //定义最大接收字节数 200,可根据需求调整
  6. #define UART1_REC_LEN 200
  7. // 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
  8. uint8_t UART1_RX_Buffer[UART1_REC_LEN];
  9. // 接收状态
  10. // bit15, 接收完成标志
  11. // bit14, 接收到0x0d
  12. // bit13~0, 接收到的有效字节数目
  13. uint16_t UART1_RX_STA=0;
  14. char buffer[12];
  15. char connect_net[] = "AT+CWJAP=\"bbb\",\"56893233\"\r\n"; //入网指令 \r\n新行
  16. char connect_servere[] = "AT+CIPSTART=\"TCP\",\"192.168.93.248\",8880\r\n";//连接服务器指令
  17. char Transparent_mode[] = "AT+CIPMODE=1\r\n"; //透传模式指令
  18. char data_transmission[] = "AT+CIPSEND\r\n"; //数据传输开始指令 //数据传输
  19. char reset[] = "AT+RST\r\n"; //重启模块指令
  20. char AT_OK_flag = 0; //OK返回值的标志位
  21. char AT_Connect_Net_Flag = 0; //WIFI GOT IP返回值的标志位
  22. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  23. {
  24. // 判断中断是由哪个串口触发的
  25. if(huart->Instance == USART1)
  26. {
  27. // 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
  28. if((UART1_RX_STA & 0x8000) == 0)
  29. {
  30. // 如果已经收到了 0x0d (回车),
  31. if(UART1_RX_STA & 0x4000)
  32. {
  33. // 则接着判断是否收到 0x0a (换行)
  34. if(buf == 0x0a)
  35. {
  36. // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
  37. UART1_RX_STA |= 0x8000;
  38. //程序运行到此处,代表数据已经完整接收,可以开始判断//
  39. //查看是否收到WIFI GOT IP
  40. if(strcmp(UART1_RX_Buffer,"WIFI GOT IP") == 0){
  41. HAL_UART_Transmit(&huart2, "111\r\n",strlen("111\r\n"), 100);
  42. AT_Connect_Net_Flag = 1;
  43. }
  44. //查看是否收到OK
  45. if(strcmp(UART1_RX_Buffer,"OK") == 0){
  46. HAL_UART_Transmit(&huart2, "222\r\n",strlen("222\r\n"), 100);
  47. AT_OK_flag = 1;
  48. }
  49. //灯控指令
  50. if(strcmp(UART1_RX_Buffer,"open") == 0){
  51. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
  52. }
  53. if(strcmp(UART1_RX_Buffer,"close") == 0){
  54. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
  55. }
  56. //如果联网失败,收到FAIL
  57. if(!strcmp(UART1_RX_Buffer,"FAIL")){
  58. HAL_UART_Transmit(&huart2, "error\r\n",strlen("error\r\n"), 100);
  59. int i;
  60. for(i = 0;i <5;i++){
  61. HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
  62. HAL_Delay(1000);}
  63. printf(reset);
  64. }
  65. memset(UART1_RX_Buffer,0,UART1_REC_LEN);
  66. UART1_RX_STA = 0;
  67. }
  68. else
  69. // 否则认为接收错误,重新开始
  70. UART1_RX_STA = 0;
  71. }
  72. else // 如果没有收到了 0x0d (回车)
  73. {
  74. //则先判断收到的这个字符是否是 0x0d (回车)
  75. if(buf == 0x0d)
  76. {
  77. // 是的话则将 bit14 位置为1
  78. UART1_RX_STA |= 0x4000;
  79. }
  80. else
  81. {
  82. // 否则将接收到的数据保存在缓存数组里
  83. UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
  84. UART1_RX_STA++;
  85. // 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
  86. if(UART1_RX_STA > UART1_REC_LEN - 1)
  87. UART1_RX_STA = 0;
  88. }
  89. }
  90. }
  91. // 重新开启中断
  92. HAL_UART_Receive_IT(&huart1, &buf, 1);
  93. }
  94. }
  95. int fputc(int ch, FILE *f)
  96. {//注意,printf的重写是针对串口1的,也就是wifi的,对于串口2的数据发送不能用printf
  97. unsigned char temp[1]={ch};
  98. HAL_UART_Transmit(&huart1,temp,1,0xffff);
  99. return ch;
  100. }
  101. int main(void)
  102. {
  103. HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
  104. // 开启接收中断
  105. HAL_UART_Receive_IT(&huart1, &buf, 1);
  106. HAL_UART_Transmit(&huart2, "START\r\n",strlen("START\r\n"), 100);
  107. printf(connect_net); //发送联网AT指令并等待成功
  108. while(!AT_Connect_Net_Flag) HAL_Delay(50);//此处这个delay必须得加,不然程序会卡死
  109. while(!AT_OK_flag) HAL_Delay(50);//此处这个delay必须得加,不然程序会卡死
  110. HAL_UART_Transmit(&huart2, "5555\r\n",strlen("5555\r\n"), 100);
  111. AT_OK_flag = 0;
  112. //发送连服务器指令并等待成功
  113. printf(connect_servere);
  114. while(!AT_OK_flag) HAL_Delay(50);
  115. HAL_UART_Transmit(&huart2, "6665\r\n",strlen("6665\r\n"), 100);
  116. AT_OK_flag = 0;
  117. //发送透传模式指令并等待成功
  118. printf(Transparent_mode);
  119. while(!AT_OK_flag) HAL_Delay(50);
  120. HAL_UART_Transmit(&huart2, "7775\r\n",strlen("7775\r\n"), 100);
  121. AT_OK_flag = 0;
  122. //发送数据传输指令并等待成功
  123. printf(data_transmission);
  124. while(!AT_OK_flag) HAL_Delay(50);
  125. while (1)
  126. {
  127. printf("hhhhhhhhhhhhaaaaaaaaaa");
  128. HAL_UART_Transmit(&huart2, "hello shion\r\n",strlen("hello shion\r\n"), 100);
  129. HAL_Delay(3000);
  130. }
  131. }

实验效果: 

注意!要记得将服务器打开,不然一直连接不上(以至于折磨了我好长时间调试)


在电脑串口和网络调试助手可以看到不断发来的心跳包。

同时,串口1作为单片机和WIFI的通信,而串口2作为日志发回电脑的串口助手,串口1每发送并成功接收了回应,串口2就会返回电脑成功的信息,这样用户就可以可视化的看到连接进行到了哪一步,这算是用两路串口实现了以前白盒测试和黑盒测试的效果。

 当在网络助手发送“open”加上回车时,继电器会打开;反之输入“close”加上回车,继电器会闭合

STA模式下控制的实现

在这种模式下,ESP作为路由器,由电脑连接ESP的WIFI,作为Client来接收和发送。

以下是之前学习WIFI模块时总结的,关于ESP作为STA模式下的相关命令

 

CubeMX

同上

Keil

通过白盒测试可知:在ESP作为STA的模式下,WIFI助手发送的数据在串口中显示的是有特定格式的:

如果发送“open”加回车,那么显示的是:+IPD,0,6:open

如果发送“close”加回车,那么显示的是:+IPD,0,7:close

因此,在KEIL中的代码中,字符串的比较不能直接和open close比较,而是和以上两个字符串进行比较!!!

代码

  1. #include <stdio.h>
  2. #include <string.h>
  3. //串口接收缓存(1字节)
  4. uint8_t buf=0;
  5. //定义最大接收字节数 200,可根据需求调整
  6. #define UART1_REC_LEN 200
  7. // 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
  8. uint8_t UART1_RX_Buffer[UART1_REC_LEN];
  9. // 接收状态
  10. // bit15, 接收完成标志
  11. // bit14, 接收到0x0d
  12. // bit13~0, 接收到的有效字节数目
  13. uint16_t UART1_RX_STA=0;
  14. char buffer[12];
  15. char connect_net[] = "AT+CWJAP=\"bbb\",\"56893233\"\r\n"; //入网指令 \r\n新行
  16. char mode[] = "AT+CWMODE=2\r\n"; //路由器模式指令
  17. char mul_con[] = "AT+CIPMUX=1\r\n"; //使能多链接
  18. char server[] = "AT+CIPSERVER=1\r\n"; //建立TCPServer default port = 333
  19. char send[] = "AT+CIPSEND=0,5\r\n"; //发送数据
  20. char end[] = "AT+CIPCLOSE=0\r\n"; //断开连接
  21. char AT_Connect_Net_Flag = 0; //WIFI GOT IP返回值的标志位
  22. char AT_OK_flag = 0; //OK返回值的标志位
  23. char Client_Connent_Flag = 0; //客户端接入返回值标志位
  24. // 接收完成回调函数,收到一个数据后,在这里处理
  25. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  26. {
  27. // 判断中断是由哪个串口触发的
  28. if(huart->Instance == USART1)
  29. {
  30. // 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
  31. if((UART1_RX_STA & 0x8000) == 0)
  32. {
  33. // 如果已经收到了 0x0d (回车),
  34. if(UART1_RX_STA & 0x4000)
  35. {
  36. // 则接着判断是否收到 0x0a (换行)
  37. if(buf == 0x0a)
  38. {
  39. // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
  40. UART1_RX_STA |= 0x8000;
  41. //程序运行到此处,代表数据已经完整接收,可以开始判断//
  42. //查看是否收到WIFI GOT IP
  43. if(strcmp(UART1_RX_Buffer,"WIFI GOT IP") == 0){
  44. HAL_UART_Transmit(&huart2, "111\r\n",strlen("111\r\n"), 100);
  45. AT_Connect_Net_Flag = 1;
  46. }
  47. //查看是否收到OK
  48. if(strcmp(UART1_RX_Buffer,"OK") == 0){
  49. HAL_UART_Transmit(&huart2, "222\r\n",strlen("222\r\n"), 100);
  50. AT_OK_flag = 1;
  51. }
  52. //灯控指令
  53. if(strcmp(UART1_RX_Buffer,"+IPD,0,6:open") == 0){
  54. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
  55. }
  56. if(strcmp(UART1_RX_Buffer,"+IPD,0,7:close") == 0){
  57. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
  58. }
  59. //如果联网失败,收到FAIL
  60. if(!strcmp(UART1_RX_Buffer,"0,CONNECT")){
  61. Client_Connent_Flag = 1;
  62. }
  63. memset(UART1_RX_Buffer,0,UART1_REC_LEN);
  64. UART1_RX_STA = 0;
  65. }
  66. else
  67. // 否则认为接收错误,重新开始
  68. UART1_RX_STA = 0;
  69. }
  70. else // 如果没有收到了 0x0d (回车)
  71. {
  72. //则先判断收到的这个字符是否是 0x0d (回车)
  73. if(buf == 0x0d)
  74. {
  75. // 是的话则将 bit14 位置为1
  76. UART1_RX_STA |= 0x4000;
  77. }
  78. else
  79. {
  80. // 否则将接收到的数据保存在缓存数组里
  81. UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
  82. UART1_RX_STA++;
  83. // 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
  84. if(UART1_RX_STA > UART1_REC_LEN - 1)
  85. UART1_RX_STA = 0;
  86. }
  87. }
  88. }
  89. // 重新开启中断
  90. HAL_UART_Receive_IT(&huart1, &buf, 1);
  91. }
  92. }
  93. int fputc(int ch, FILE *f)
  94. {//注意,printf的重写是针对串口1的,也就是wifi的,对于串口2的数据发送不能用printf
  95. unsigned char temp[1]={ch};
  96. HAL_UART_Transmit(&huart1,temp,1,0xffff);
  97. return ch;
  98. }
  99. int main(void)
  100. {
  101. HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
  102. // 开启接收中断
  103. HAL_UART_Receive_IT(&huart1, &buf, 1);
  104. HAL_UART_Transmit(&huart2, "START\r\n",strlen("START\r\n"), 100);
  105. printf(mode);//发送客户端模式指令并等待成功
  106. while(!AT_OK_flag) HAL_Delay(50);
  107. AT_OK_flag = 0;
  108. HAL_UART_Transmit(&huart1, "mode set success\r\n", strlen("mode set success\r\n"), 100);
  109. printf(mul_con);
  110. while(!AT_OK_flag) HAL_Delay(50);
  111. AT_OK_flag = 0;
  112. printf(server);
  113. while(!Client_Connent_Flag) HAL_Delay(50);
  114. AT_OK_flag = 0;
  115. if(Client_Connent_Flag){
  116. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
  117. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
  118. }
  119. while (1)
  120. {
  121. printf(send);//发送数据
  122. HAL_Delay(2000);
  123. printf("wdnmd");//发给串口1的,共2个字节
  124. HAL_Delay(2000);
  125. }
  126. }

 

实现效果

打开单片机点击复位,使得电脑连上”esp8266“的WIFI,然后在网络助手中输入相关信息之后点击连接:(要提前连好wifi的情况)1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客STA模式具体连接再次参考这个

当在网络助手发送“open”加上回车时,LED1会打开;反之输入“close”加上回车,LED1会关闭

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/405278
推荐阅读
相关标签
  

闽ICP备14008679号