赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
主要想玩一下遥控汽车通过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
http://www.openedv.com/docs/modules/iot/atk-esp.html
2.这是我打包好的程序源码以及上述所用的软件
https://pan.baidu.com/s/1NcFIn4GRzuG9y_DV1aSB6w
提取码:1234
我用的是STA+TCP透传模式:
AT //检测wifi模块是否存在
AT+CWMODE=1 //设置ESP8266为STA模式
AT+RST //重启模块
AT+CWJAP=”wifi名称“,”wifi密码“ //连接wifi
AT+CIPSTART=”TCP“,”ip地址“,端口 //连接TCP服务器
AT+CIPMODE=1 //开启透传
例子:
- while(esp8266_send_cmd("AT","OK",100));
- printf("wifi存在!\r\n\r\n");
-
- //设置ESP8266为STA模式
- while(esp8266_send_cmd("AT+CWMODE=1","OK",50));
- printf("STA模式\r\n\r\n");
-
- while(esp8266_send_cmd("AT+RST","ready\r\n",200));
- printf("复位成功\r\n\r\n");
-
- //连接WIFI
- while(esp8266_send_cmd("AT+CWJAP=\"www\",\"20020318\"","WIFI GOT IP",300))
- {
- printf("wifi连接失败\r\n\r\n");
- }
- printf("wifi连接成功\r\n");
-
- //www 为我的wifi名称
- //20020318 为我的wifi密码
- //WIFI GOT IP 为原子云固件连接上wifi后返回的答复
- //300 为等待时间
-
- while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"10.121.35.2\",8080","CONNECT",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
- printf("TCP连接失败\r\n");
- }
- printf("TCP连接成功\r\n\r\n");
-
- while(esp8266_send_cmd("AT+CIPMODE=1","OK",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
- }
- printf("透传模式\r\n\r\n");

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

我使用的是串口3与wifi通信,由于使用cubemx生成代码,所以比较简单,只需要注意开启串口接收中断即可。
- ///////串口1重定向用于打印信息
- int fputc(int ch,FILE *f)
- {
- HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);
- //HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,0xffff);
- return ch;
- }
-
- ////////此函数用于向esp8266发送指令
- void u3_printf(char* fmt,...)
- {
- uint16_t i,j;
- va_list ap;
- va_start(ap,fmt);
- vsprintf((char*)USART3_TX_BUF,fmt,ap);
- va_end(ap);
- i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度
- for(j=0;j<i;j++) //循环发送数据
- {
- while((USART3->SR&0X40)==0); //循环发送,直到发送完毕
- USART3->DR=USART3_TX_BUF[j];
- }
- }
-
-
- /////此函数接收esp8266返回的答复
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance == USART3)
- {
- if((USART3_RX_STA&0x8000)==0)
- {
- if(USART3_RX_STA<USART_REC_LEN)
- {
- TIM3->CNT = 0;
- if(USART3_RX_STA == 0)
- {
- HAL_TIM_Base_Start_IT(&htim3);
- }
- USART3_RX_BUF[USART3_RX_STA++] = aRxBuffer[0];
- }
- else
- {
- USART3_RX_STA |= 0x8000;
- }
- }
- }
- HAL_UART_Receive_IT(&huart3,(uint8_t *)&aRxBuffer,1);
- }

中间用到定时器的目的是每隔100ms不管接没接收完成,都强制让串口3接收完成。
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if(htim->Instance == TIM3)
- {
- USART3_RX_STA |= 0x8000;
- HAL_TIM_Base_Stop_IT(&htim3);
- }
- }
- //向ESP8266发送命令
- //cmd:发送的命令字符串;ack:期待的应答结果,如果为空,则表示不需要等待应答;waittime:等待时间(单位:10ms)
- //返回值:0,发送成功(得到了期待的应答结果);1,发送失败
- u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
- {
- u8 res=0;
- USART3_RX_STA=0;
- u3_printf("%s\r\n",cmd); //发送命令
- if(ack&&waittime) //需要等待应答
- {
- while(--waittime) //等待倒计时
- {
- HAL_Delay(10);
- if(USART3_RX_STA&0X8000)//接收到期待的应答结果
- {
- if(esp8266_check_cmd(ack))
- {
- //printf("ack:%s\r\n",(u8*)ack);
- break;//得到有效数据
- }
- USART3_RX_STA=0;
- }
- }
- if(waittime==0)res=1;
- }
- return res;
- }
-
-
- //ESP8266发送命令后,检测接收到的应答
- //str:期待的应答结果
- //返回值:0,没有得到期待的应答结果;其他,期待应答结果的位置(str的位置)
- u8* esp8266_check_cmd(u8 *str)
- {
- char *strx=0;
- if(USART3_RX_STA&0X8000) //接收到一次数据了
- {
- USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符
- strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
- }
- return (u8*)strx;
- }

strstr()函数:

简单来说就是你传入的参数如果与esp8266发送给串口3的USART3_RX_BUF里字符匹配,则会成功返回。
- while(esp8266_send_cmd("AT","OK",100));
- printf("wifi存在!\r\n\r\n");
-
- //设置ESP8266为STA模式
- while(esp8266_send_cmd("AT+CWMODE=1","OK",50));
- printf("STA模式\r\n\r\n");
-
- while(esp8266_send_cmd("AT+RST","ready\r\n",200));
- printf("复位成功\r\n\r\n");
-
-
- //连接WIFI
- while(esp8266_send_cmd("AT+CWJAP=\"www\",\"20010318\"","WIFI GOT IP",300)){
- printf("wifi连接失败\r\n\r\n");
-
- }
- printf("wifi连接成功\r\n");
-
- while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"10.121.35.19\",8080","CONNECT",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
- printf("TCP连接失败\r\n");
- }
- printf("TCP连接成功\r\n\r\n");
-
- while(esp8266_send_cmd("AT+CIPMODE=1","OK",200)){//这命令要等到手机端与esp8266建立连接后才会返回0,结束循环
- }
- printf("透传模式\r\n\r\n");
-
- while (1)
- {
- if(USART3_RX_STA & 0x8000)
- {
- switch(USART3_RX_BUF[0])
- {
- case 'G':run();
- break;
- case 'S':stop();
- break;
- case 'B':back();
- break;
- case 'L':left();
- break;
- case 'R':right();
- break;
- }
- USART3_RX_STA = 0 ;
- }
- }

- #include "motor.h"
-
- //pc14/pc15左走前轮 pb12/pb13
- void run()
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
-
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
- }
-
- void stop()
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
-
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
- }
-
- void back()
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET);
-
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
- }
-
- void left()
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
-
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
- }
-
- void right()
- {
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET);
-
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
- }

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