第一、二章优化拓展开发环境:
主控 | STM32F103C8T6 |
WIFI模块 | ESP01S |
开发语言 | C |
开发编译器· | KEIL |
组网方式 | WIFI |
服务器协议 | MQTT |
硬件连接
STM32 | ESP01S |
3.3V | 3.3V |
GND | GND |
GPIO2 (USRAT2-TX) | RX |
GPIO3 (USART3-RX) | TX |
本章要点:
- 对ESP01S的AT指令的反馈指令进行验证解析
- 对ESP的USART2通信串口进行printf端口重映射
- 对调试用的USART1通信串口编写USART_printf函数并且解析%d、%s等可变参数
抽象理解
1、对ESP01S的AT指令的反馈指令进行验证解析
进入循环函数:在STM32对ESP01S进行USART通信发送完AT指令后,进行串口监听,然后接收AT反馈指令,接着调用strstr()函数对指令进行解析,当解析到AT指令任务实现的反馈指令后,才执行下一步,跳出循环函数
_Bool ESP8266_SendCmd(char *cmd, char *res, u16 time)
{ Usart2_SendString((unsigned char *)cmd, strlen((const char *)cmd));while(time--){if(ESP8266_WaitRecive() == REV_OK) //如果收到数据{if(strstr((const char *)esp8266_buf, res) != NULL) //如果检索到关键词{ESP8266_Clear(); //清空缓存return 0;}}delay_ms(10);}return 1;
}
2、对ESP的USART2通信串口进行printf端口重映射
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{ int handle; }; FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{ x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
// while((USART2->SR&0X40)==0);//循环发送,直到发送完毕
// USART2->DR = (u8) ch;while((USART2->SR&0X40)==0);//循环发送,直到发送完毕 (若需要使用usart串口通信进行信息验证调试则取消注释,正常使用请关闭,避免printf打印两次)USART2->DR = (u8) ch; return ch;
}
#endif
3、对调试用的USART1通信串口编写USART_printf函数并且解析%d、%s等可变参数
#include <stdarg.h> //C库重写
#include <mystdlib.h> void USART1_printf (char * Data, ... )
{const char *s;int d; char buf[16];va_list ap;va_start(ap, Data);while ( * Data != 0 ) // 判断是否到达字符串结束符{ if ( * Data == 0x5c ) //'\'{ switch ( *++Data ){case 'r': //回车符USART_SendData(USART1, 0x0d);Data ++;break;case 'n': //换行符USART_SendData(USART1, 0x0a); Data ++;break;default:Data ++;break;} }else if ( * Data == '%'){ //switch ( *++Data ){ case 's': //字符串s = va_arg(ap, const char *);for ( ; *s; s++) {USART_SendData(USART1,*s);while( USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );}Data++;break;case 'd': //十进制d = va_arg(ap, int);myitoa(d, buf, 10);for (s = buf; *s; s++) {USART_SendData(USART1,*s);while( USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );}Data++;break;default:Data++;break;} }else USART_SendData(USART1, *Data++);while ( USART_GetFlagStatus ( USART1, USART_FLAG_TXE ) == RESET );}
}
代码:
由于在stm32内,无法使用stdlib.h的C语言库,因此我们重写编写了stdlib.h库的部分函数
mystdlib.h
#ifndef __MYSTDLIB_H
#define __MYSTDLIB_H/*
将整数转化为字符串:
num,转换对象
str,转换后存储字符串的数组
radix,转换(给于的字符串)的长度
*/
char *myitoa(int num,char *str,int radix)
{ /* 索引表 */ char index[]="0123456789abcdefghijklmnopqrstuvwxz"; unsigned unum; /* 中间变量 */ int i=0,j,k; /* 确定unum的值 */ if(radix==10&&num<0) /* 十进制负数 */ { unum=(unsigned)-num; str[i++]='-'; } else unum=(unsigned)num; /* 其它情况 */ /* 逆序 */ do { str[i++]=index[unum%(unsigned)radix]; unum/=radix; }while(unum); str[i]='\0'; /* 转换 */ if(str[0]=='-') k=1; /* 十进制负数 */ else k=0; /* 将原来的“/2”改为“/2.0”,保证当num在16~255之间,radix等于16时,也能得到正确结果 */ char temp; for(j=k;j<=(i-k-1)/2.0;j++) { temp=str[j]; str[j]=str[i-j-1]; str[i-j-1]=temp; } return str;
} /*
将字符串转换成整数
str,转换的字符串数组目标
返回值:为转换后的整数;
*/
int myatoi(char * str)
{int n=0;//保存整形 char firstChar = *str;//记录str的第一个字符if (firstChar == '+' || firstChar == '-')//+123 -123{++str;}while(*str == '0')//00123 -00123{++str;}while (*str){char temp = *str;if (*str < '0' || *str> '9'){puts("literal does not match format string ") ;return n;//该字符串含有非数字字符,不能转为整数}else{temp -= '0';n = n * 10 + temp;//将字符串转为整形}str++;}if (firstChar == '-'){n = -n;}return n;
}#endif
如果要本第一、二章优化拓展的完整工程文件,可以直接到百度网盘提取(解压密码同下)
链接:https://pan.baidu.com/s/1ECxx125pRlKVo366fzyTiw?pwd=1016
提取码:1016
本文为作者独立编写
本BLOG上所有的原创文章未经本人许可,不得用于商业用途及传统媒体。网络媒体转载请注明出处,否则属于侵权行为。