当前位置:   article > 正文

基于STM32F103C8T6通过WIFI模块(ESP8266)控制小车_基于stm32f103c8t6和esp8266的物联网无线控制小车

基于stm32f103c8t6和esp8266的物联网无线控制小车

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

        主要想玩一下遥控汽车通过stm32c8t6连接wifi模块控制小车前进、后退、左转、右转。


一、材料准备

硬件:

        1.STM32F103C8T6最小核心板

        2.ESP8266(原子云固件)

        3.L298N驱动

        4.ST-Link下载器

软件:

        1.固件烧写工具

        2.串口助手

        3.网络调试助手

左边马达:
PA8----->ENA      //定时器1引脚
PC14---->IN1
PC15---->IN2

右边马达:
PA0----->ENB    //定时器2引脚
PB12---->IN1
PB13---->IN2

串口3:

PB10---->RX   //RX为esp8266RX引脚
PB11---->TX

二、原子云固件下载

       1. 可以到正点原子官网下载固件以及下载软件。

                http://www.openedv.com/docs/modules/iot/atk-esp.html

        2.这是我打包好的程序源码以及上述所用的软件

            ​​​​​​​       https://pan.baidu.com/s/1NcFIn4GRzuG9y_DV1aSB6w

                        提取码:1234

三、实验步骤

 1.基本AT指令

     我用的是STA+TCP透传模式:

                AT          //检测wifi模块是否存在

                AT+CWMODE=1  //设置ESP8266为STA模式

                AT+RST             //重启模块

                AT+CWJAP=”wifi名称“,”wifi密码“   //连接wifi

                AT+CIPSTART=”TCP“,”ip地址“,端口       //连接TCP服务器

                AT+CIPMODE=1       //开启透传

           例子:

  1. while(esp8266_send_cmd("AT","OK",100));
  2. printf("wifi存在!\r\n\r\n");
  3. //设置ESP8266为STA模式
  4. while(esp8266_send_cmd("AT+CWMODE=1","OK",50));
  5. printf("STA模式\r\n\r\n");
  6. while(esp8266_send_cmd("AT+RST","ready\r\n",200));
  7. printf("复位成功\r\n\r\n");
  8. //连接WIFI
  9. while(esp8266_send_cmd("AT+CWJAP=\"www\",\"20020318\"","WIFI GOT IP",300))
  10. {
  11. printf("wifi连接失败\r\n\r\n");
  12. printf("wifi连接成功\r\n");
  13. //www          为我的wifi名称
  14. //20020318        为我的wifi密码
  15. //WIFI GOT IP 为原子云固件连接上wifi后返回的答复
  16. //300        为等待时间
  17. while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"10.121.35.2\",8080","CONNECT",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
  18. printf("TCP连接失败\r\n");
  19. }
  20. printf("TCP连接成功\r\n\r\n");
  21. while(esp8266_send_cmd("AT+CIPMODE=1","OK",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
  22. }
  23. printf("透传模式\r\n\r\n");

           ps:一定要注意答复的地方要与原子云固件了的答复一样,否则会连接失败,可以先用usb-ttl与esp8266通过电脑测试一下回复。注意改为自己需要连接的wifi和tcp服务器。

2.串口接收中断

            我使用的是串口3与wifi通信,由于使用cubemx生成代码,所以比较简单,只需要注意开启串口接收中断即可。

  1. ///////串口1重定向用于打印信息
  2. int fputc(int ch,FILE *f)
  3. {
  4. HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);
  5. //HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,0xffff);
  6. return ch;
  7. }
  8. ////////此函数用于向esp8266发送指令
  9. void u3_printf(char* fmt,...)
  10. {
  11. uint16_t i,j;
  12. va_list ap;
  13. va_start(ap,fmt);
  14. vsprintf((char*)USART3_TX_BUF,fmt,ap);
  15. va_end(ap);
  16. i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度
  17. for(j=0;j<i;j++) //循环发送数据
  18. {
  19. while((USART3->SR&0X40)==0); //循环发送,直到发送完毕
  20. USART3->DR=USART3_TX_BUF[j];
  21. }
  22. }
  23. /////此函数接收esp8266返回的答复
  24. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  25. {
  26. if(huart->Instance == USART3)
  27. {
  28. if((USART3_RX_STA&0x8000)==0)
  29. {
  30. if(USART3_RX_STA<USART_REC_LEN)
  31. {
  32. TIM3->CNT = 0;
  33. if(USART3_RX_STA == 0)
  34. {
  35. HAL_TIM_Base_Start_IT(&htim3);
  36. }
  37. USART3_RX_BUF[USART3_RX_STA++] = aRxBuffer[0];
  38. }
  39. else
  40. {
  41. USART3_RX_STA |= 0x8000;
  42. }
  43. }
  44. }
  45. HAL_UART_Receive_IT(&huart3,(uint8_t *)&aRxBuffer,1);
  46. }

                中间用到定时器的目的是每隔100ms不管接没接收完成,都强制让串口3接收完成。

  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  2. {
  3. if(htim->Instance == TIM3)
  4. {
  5. USART3_RX_STA |= 0x8000;
  6. HAL_TIM_Base_Stop_IT(&htim3);
  7. }
  8. }

 3.esp8266代码

  1. //向ESP8266发送命令
  2. //cmd:发送的命令字符串;ack:期待的应答结果,如果为空,则表示不需要等待应答;waittime:等待时间(单位:10ms)
  3. //返回值:0,发送成功(得到了期待的应答结果);1,发送失败
  4. u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
  5. {
  6. u8 res=0;
  7. USART3_RX_STA=0;
  8. u3_printf("%s\r\n",cmd); //发送命令
  9. if(ack&&waittime) //需要等待应答
  10. {
  11. while(--waittime) //等待倒计时
  12. {
  13. HAL_Delay(10);
  14. if(USART3_RX_STA&0X8000)//接收到期待的应答结果
  15. {
  16. if(esp8266_check_cmd(ack))
  17. {
  18. //printf("ack:%s\r\n",(u8*)ack);
  19. break;//得到有效数据
  20. }
  21. USART3_RX_STA=0;
  22. }
  23. }
  24. if(waittime==0)res=1;
  25. }
  26. return res;
  27. }
  28. //ESP8266发送命令后,检测接收到的应答
  29. //str:期待的应答结果
  30. //返回值:0,没有得到期待的应答结果;其他,期待应答结果的位置(str的位置)
  31. u8* esp8266_check_cmd(u8 *str)
  32. {
  33. char *strx=0;
  34. if(USART3_RX_STA&0X8000) //接收到一次数据了
  35. {
  36. USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符
  37. strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
  38. }
  39. return (u8*)strx;
  40. }

strstr()函数:

简单来说就是你传入的参数如果与esp8266发送给串口3的USART3_RX_BUF里字符匹配,则会成功返回。

4.主函数

  1.   while(esp8266_send_cmd("AT","OK",100));
  2. printf("wifi存在!\r\n\r\n");
  3. //设置ESP8266为STA模式
  4. while(esp8266_send_cmd("AT+CWMODE=1","OK",50));
  5. printf("STA模式\r\n\r\n");
  6. while(esp8266_send_cmd("AT+RST","ready\r\n",200));
  7. printf("复位成功\r\n\r\n");
  8. //连接WIFI
  9. while(esp8266_send_cmd("AT+CWJAP=\"www\",\"20010318\"","WIFI GOT IP",300)){
  10. printf("wifi连接失败\r\n\r\n");
  11. }
  12. printf("wifi连接成功\r\n");
  13. while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"10.121.35.19\",8080","CONNECT",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
  14. printf("TCP连接失败\r\n");
  15. }
  16. printf("TCP连接成功\r\n\r\n");
  17. while(esp8266_send_cmd("AT+CIPMODE=1","OK",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
  18. }
  19. printf("透传模式\r\n\r\n");
  20. while (1)
  21. {
  22. if(USART3_RX_STA & 0x8000)
  23. {
  24. switch(USART3_RX_BUF[0])
  25. {
  26. case 'G':run();
  27. break;
  28. case 'S':stop();
  29. break;
  30. case 'B':back();
  31. break;
  32. case 'L':left();
  33. break;
  34. case 'R':right();
  35. break;
  36. }
  37. USART3_RX_STA = 0 ;
  38. }
  39. }

5.电机驱动模块

  1. #include "motor.h"
  2. //pc14/pc15左走前轮 pb12/pb13
  3. void run()
  4. {
  5. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
  6. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
  7. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
  8. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
  9. }
  10. void stop()
  11. {
  12. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
  13. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
  14. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
  15. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
  16. }
  17. void back()
  18. {
  19. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
  20. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
  21. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
  22. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
  23. }
  24. void left()
  25. {
  26. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
  27. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
  28. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
  29. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
  30. }
  31. void right()
  32. {
  33. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
  34. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
  35. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
  36. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
  37. }

总结

        其实esp8266还是比较容易应用,多看几遍用户手册和AT指令集,咱就可以简单的入个门了;以下是我遇到的问题:1.串口接收回调函数里面一定不要乱判结束符!!!因为你的数据可能还没有接收完成就被你判结束了。具体可以打断点调试工程。 2.注意固件里每个指令的响应,不然弄错了会连不上你的wifi或者tcp。

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

闽ICP备14008679号