一、硬件介绍
1.MCU:STM32F103C8T6
2.ESP8266:正点原子WIFI模块
3.串口模块:正点原子串口模块
二、准备工作
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
-
ESP8266固件刷写
我用的是安信可的固件,可以在官网上下载。正点原子也提供相关的刷写教程 -
硬件连接
单片机的串口3连接WiFi模块。WiFi模块的Vcc接3.3V。串口1接在串口模块上。
三、STM32主要代码介绍
mcu跟wifi模块的代码实现(涉及串口、定时器):
-
实现思想
单片机向esp8266模块发送at指令,并且在一定的时间内等待esp8266的回复,如果回复错误的指令或者超时回复就把错误通过串口1发送到电脑上。 -
代码介绍
AT指令发送函数
uint8_t esp8266_send_cmd(char *cmd, char *ack, uint16_t waittime) //ESP8266发送指令(底层函数)
{
uint8_t res = 0;
USART3_RX_STA = 0;
memset(USART3_RX_BUF,0,USART3_REC_LEN); //将串口3的缓存空间清0
WIFI_printf("%s\r\n", cmd); //调用WIFI模块专用的发送函数
if(waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
HAL_Delay(10);//HAL库延时函数
if(USART3_RX_STA&0x8000) //接收到期待的应答结果
{
if(esp8266_check_cmd((uint8_t *)ack))
{
printf("回复信息:%s\r\n",(uint8_t *)ack);//反馈应答信息
break; //得到有效数据
}
USART3_RX_STA=0; //串口3标志位清0
}
}
if(waittime==0)res=1;
}
return res;
}
uint8_t* esp8266_check_cmd(uint8_t *str) //ESP8266检查指令(底层函数)
{
char *strx=0;
if(USART3_RX_STA&0X8000) //接收到一次数据了
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF] = 0; //添加结束符
printf("%s\r\n",(char*)USART3_RX_BUF);
strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
}
return (uint8_t*)strx;
}
uint8_t esp8266_quit_trans(void) //ESP8266退出判断(底层函数)
{
while((USART3->SR&0X40)==0); //等待发送空
USART3->DR='+';
HAL_Delay(15); //大于串口组帧时间(10ms)
while((USART3->SR&0X40)==0); //等待发送空
USART3->DR='+';
HAL_Delay(15); //大于串口组帧时间(10ms)
while((USART3->SR&0X40)==0); //等待发送空
USART3->DR='+';
HAL_Delay(500); //等待500ms
return esp8266_send_cmd("AT","OK",20); //退出透传判断
}
接收状态标记、接收缓冲、接收状态标记的宏定义
uint8_t USART1_RX_BUF[USART1_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART1_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART1_NewData;//当前串口中断接收的1个字节数据的缓存
uint8_t USART2_RX_BUF[USART2_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART2_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART2_NewData;//当前串口中断接收的1个字节数据的缓存
uint8_t RS485orBT;//当RS485orBT标志位为1时是RS485模式,为0时是蓝牙模式
uint8_t USART3_RX_BUF[USART3_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART3_RX_STA=0;//接收状态标记//bit15:接收完成标志,bit14:接收到0x0d,bit13~0:接收到的有效字节数目
uint8_t USART3_NewData;//当前串口中断接收的1个字节数据的缓存
串口3跟esp8266通信的底层函数
void WIFI_printf (char *fmt, ...)
{
char buff[USART3_REC_LEN+1]; //用于存放转换后的数据 [长度]
uint16_t i=0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//数据转换
i=strlen(buff);//得出数据长度
if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果长度大于最大值,则长度等于最大值(多出部分忽略)
HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//串口发送函数(串口号,内容,数量,溢出时间)
va_end(arg_ptr);
}
//WIFI模块在TCP模式下的数据发送:TCP发送的规定是先发AT+CIPSEND=数量,等待返回“>“后再发送数据内容。
//调用方法:WIFI_TCP_SEND("123\r\n"); //TCP方式发送字符123和回车换行
void WIFI_TCP_SEND (char *fmt, ...)
{
char buff[USART3_REC_LEN+1]; //用于存放转换后的数据 [长度]
uint16_t i=0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//数据转换
i=strlen(buff);//得出数据长度
if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果长度大于最大值,则长度等于最大值(多出部分忽略)
WIFI_printf("AT+CIPSEND=%d\r\n",i);//先发送AT指令和数据数量
HAL_Delay(100);//等待WIFI模块返回">",此处没做返回是不是">"的判断。稳定性要求高的项目要另加判断。
HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//发送数据内容(串口号,内容,数量,溢出时间)
va_end(arg_ptr);
}
串口1的重定向和串口3、定时器的中断回调函数,文章来源:https://www.toymoban.com/news/detail-426749.html
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口中断回调函数
{
if(huart ==&huart3)//判断中断来源(串口3:WIFI模块)//接收完的一批数据,还没有被处理,则不再接收其他数据
{
if(USART3_RX_STA<USART3_REC_LEN)//还可以接收数据
{
__HAL_TIM_SET_COUNTER(&htim2,0); //计数器清空
if(USART3_RX_STA==0) //使能定时器2的中断
{
__HAL_TIM_ENABLE(&htim2); //使能定时器2
}
USART3_RX_BUF[USART3_RX_STA++] = USART3_NewData;//最新接收数据放入数组
}
else
{
USART3_RX_STA|=0x8000;//强制标记接收完成
}
HAL_UART_Receive_IT(&huart3,(uint8_t *)&USART3_NewData,1); //再开启串口3接收中断
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim ==&htim2)//判断是否是定时器2中断(定时器到时表示一组字符串接收结束)
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符
USART3_RX_STA|=0x8000;//接收标志位最高位置1表示接收完成
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_EVENTSOURCE_UPDATE );//清除TIM2更新中断标志
__HAL_TIM_DISABLE(&htim2);//关闭定时器2
}
}
int fputc(int ch, FILE *f) //串口重定向
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
##不想写了,主要核心代码可以参考正点原子的,大家不懂的可以私信,看到一定回复。文章来源地址https://www.toymoban.com/news/detail-426749.html
到了这里,关于STM32F103C8T6+ESP8266WIFI+DHT11模块连接巴法云的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!