STM32与ESP8266实现串口通信

本文详细介绍了如何在物联网项目中使用STM32控制ESP8266进行数据通信,包括ESP8266端的串口数据接收和输出,以及STM32端的串口数据接收和发送功能的实现,展示了两设备间的双向数据交换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

不少做物联网毕设的同学可能会遇到用STM32做控制ESP8266做联网的设计,但在实现两者的通信方面犯了难。本文针对该问题,提供了数据通信的方案,并成功实现两者间的数据通信。

ESP8266端数据接收与输出

ESP8266端数据接收

该函数实现ESP8266从自定义串口上接收来自STM32的数据并通过ESP8266的硬件串口上输出数据

#include <SoftwareSerial.h>
//自定义串口 (RX, TX)   # D6接TX D7接RX
SoftwareSerial MySerial(D6, D7);

String data1;  // 接受外部数据

String receive1() {   // 接受外部数据
  String data;
  if (MySerial.available()) {
    data = (char)MySerial.read();
    data += receive1();
  }
  return data;
}


void setup() {
  Serial.begin(115200);    //内部串口初始化
  MySerial.begin(115200);  //外部串口初始化
}
void loop() {  
  data1 = receive1();
  if (data1 != "") {
    Serial.println(data1);    //接受的外部数据内部打印
  }    
  MySerial.println("i am fine");
  delay(1000);

}

其中MySerial.println(“i am fine”); 可以实现ESP8266向STM32发送 I am fine

ESP8266端数据输出

ESP8266数据输出非常简单,利用函数

MySerial.println(data1);

即可实现数据传输。

STM32端数据接收与输出

本文采用STM32的硬件串口三实现数据传输

STM32端数据接收

usart3.c文件代码

#include "sys.h"
#include "usart.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"
#include "stdio.h"

u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; 				//接收缓冲,最大USART2_MAX_RECV_LEN个字节.
u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; 			  //发送缓冲,最大USART2_MAX_SEND_LEN字节

u16 USART3_RX_STA;   						//接收数据状态

u8* temp[4];
int i = 0;

void usart3_Init(u32 bound)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	// GPIOA时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //串口3时钟使能

    USART_DeInit(USART3);  //复位串口2
    //USART2_TX   PB10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11

    //USART2_RX	  PB11
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11

    USART_InitStructure.USART_BaudRate = bound;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx ;	//收发模式

    USART_Init(USART3, &USART_InitStructure); //初始化串口2

    USART_Cmd(USART3, ENABLE);                    //使能串口

    //使能接收中断
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断

    //设置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1 ; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    USART3_RX_STA = 0;		//清零

}

void USART3_IRQHandler(void)
{
    u8 res;
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
    {
        res = USART_ReceiveData(USART3);
        if((USART3_RX_STA & 0x8000) == 0) //接收未完成
        {
            if(USART3_RX_STA & 0x4000) //接收到了0x0d
            {
                if(res != 0x0a)USART3_RX_STA = 0; //接收错误,重新开始
                else USART3_RX_STA |= 0x8000;	//接收完成了
            }
            else //还没收到0X0D
            {
                if(res == 0x0d)USART3_RX_STA |= 0x4000;
                else
                {
                    USART3_RX_BUF[USART3_RX_STA & 0X3FFF] = res ;
                    USART3_RX_STA++;
                    if(USART3_RX_STA > (USART3_MAX_RECV_LEN - 1))USART3_RX_STA = 0; //接收数据错误,重新开始接收
                }
            }
        }
    }
    if(USART3_RX_STA & 0x8000)
    {
        //原始串口三数据
        printf("%s\r\n", USART3_RX_BUF);
		USART3_RX_STA = 0;
    }
}

/*****************************************************
* 函数:串口二发送字节
* 参数:byte---要发送的字节
* 功能:
* 备注:
*****************************************************/
void usart3_Send_Byte(uint8_t byte)   //串口发送一个字节
{
    while(USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET); //等待发送完成 检测 USART_FLAG_TC 是否置1
    USART_SendData(USART3, byte);  //通过库函数发送数据
    USART_ClearITPendingBit(USART3, USART_IT_TC);//清除串口3发送完成中断线路挂起位
}

/*****************************************************
* 函数:串口二发送字符串函数
* 参数:string---要发送的字符串  length--要发送字符串的长度
* 功能:
* 备注:
*****************************************************/
void usart3_Send_String(uint8_t* string,  uint8_t length)
{
    uint8_t i;
    for(i = 0; i < length; i++)
        usart3_Send_Byte(*string++);//发送一个字节
}

usart3.h文件代码

#ifndef __USART3_H
#define __USART3_H
#include "stdio.h"	
#include "sys.h" 

#define USART3_MAX_RECV_LEN		400					//最大接收缓存字节数
#define USART3_MAX_SEND_LEN		400					//最大发送缓存字节数
#define USART3_RX_EN 			1					//0,不接收;1,接收.

extern u8  USART3_RX_BUF[USART3_MAX_RECV_LEN]; 		//接收缓冲,最大USART2_MAX_RECV_LEN字节
extern u8  USART3_TX_BUF[USART3_MAX_SEND_LEN]; 		//发送缓冲,最大USART2_MAX_SEND_LEN字节
extern u16 USART3_RX_STA;   						//接收数据状态

void usart3_Init(u32 bound);
void usart3_Send_Byte(uint8_t byte);
void usart3_Send_String(uint8_t *string,  uint8_t length);
#endif

其中接收来自ESP8266串口数据的代码在usart3.husart3的中断里

printf("%s\r\n", USART3_RX_BUF);

STM32端数据输出

STM32串口3输出通过

void usart3_Send_String(uint8_t *string,  uint8_t length);

函数实现。其中string为幺传输的字符串,length为输出的字符串长度。
其中main函数可以写成

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	
    delay_init();    //延时初始化
	
		uart_init(115200);   //串口1初始化,发送日志信息    
	
		usart3_Init(115200);   //串口3初始化,用来与ESP8266通信
	
	    LED_Init();    //内置LED初始化
                                                                                                                                                           
		printf("stm32 is ok\r\n");    while(1)
    {				
			usart3_Send_String("hello_word",  10);                   
			delay_ms(1000);			
    }
}

可以实现STM32向ESP8266发送hello_world

实现结果

在这里插入图片描述
其中hello_world为STM32向ESP32发送的数据,I am fine 为ESP8266向STM32发送的数据

个人广告
可接单片机类型毕业设计,功能齐全,价格优惠。

### STM32ESP8266之间通过串口通信使用HAL库 为了实现STM32ESP8266之间的串口通信,可以采用ST官方提供的硬件抽象层(HAL)库来简化开发过程。下面是一个简单的例子说明如何配置并初始化USART外设以便于两个设备间的数据交换。 #### 初始化USART接口 首先,在`main.c`文件中的适当位置定义全局句柄结构体用于保存UART的状态信息: ```c UART_HandleTypeDef huart1; ``` 接着是在`MX_USART1_UART_Init()`函数里完成具体的参数设定工作,这部分通常由CubeMx自动生成,但这里给出一个典型的设置方式作为参考[^1]: ```c static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK){ Error_Handler(); } } ``` 上述代码片段设置了波特率为115200bps,无校验位以及单停止位等基本属性,并调用了`HAL_UART_Init()`来进行最终的初始化操作。 #### 数据发送接收处理 对于数据传输部分,则可以通过如下两种方法之一来实现:中断模式或者轮询模式。以下是基于轮询的方式向ESP8266模块发送命令字符串的一个实例: ```c char command[]="AT+CIPSTART=\"TCP\",\"api.openweathermap.org\",80\r\n"; if(HAL_UART_Transmit(&huart1,(uint8_t*)command,strlen(command),HAL_MAX_DELAY)!= HAL_OK){ /* Transfer error in transmission process */ Error_Handler(); } else { //等待一段时间让ESP8266响应 HAL_Delay(100); } // 接收来自ESP8266的消息 uint8_t rx_buffer[64]; memset(rx_buffer, '\0', sizeof(rx_buffer)); if(HAL_UART_Receive(&huart1,rx_buffer,sizeof(rx_buffer)-1,HAL_MAX_DELAY)== HAL_OK){ printf("Received:%s",rx_buffer); }else{ Error_Handler(); } ``` 这段程序先构建了一个指向字符数组的指针变量存储要发出的信息;之后利用`HAL_UART_Transmit()`执行实际的数据传送动作;最后尝试读取对方返回的结果并通过控制台打印出来。 以上就是关于STM32ESP8266之间建立串行连接的大致流程介绍。需要注意的是这只是一个非常基础的例子,具体应用时可能还需要考虑更多细节比如错误检测机制、超时管理等功能增强稳定性。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值