STM32串口与ESP8266通信时发送0xFF - 问题分析和解决办法

BUG:在USART初始化过程中,USART的TX引脚莫名输出一个0xFF;

  1. 可能原因:GPIO口和USARTD的初始化顺序有问题,GPIO时钟 - GPIO - USART时钟 - USART
  2. 解决办法:调换GPIO和USART时钟的初始化顺序:GPIO时钟 - USART时钟 - GPIO - USART;
  3. 现象:
    1. 按照GPIO - USART时钟的顺序初始化时,发现在执行到开启USART时钟时,ESP8266会回发一个0xFF,推测是ESP8266认为STM32向其发送了0xFF(笔者通过串口向ESP8266发送0xFF时,其会回发0xFF); image-20241018141745123
    2. 怀疑ESP8266将电平波动误判为数据,在初始化USART时钟前加一个延时(等待TX引脚电平稳定):GPIO时钟 - GPIO - 延时 - USART时钟 - USART,发现串口输出数据变为0x00
    3. 通过单步调试发现,当初始化TX的GPIO口开启USART时钟之间没有延时的时候,USART输出0xFF,这两行之间有一定延时的时候,USART输出会变为0x00;怀疑这两次初始化之间的电平波动会使得ESP8266误判数据;
      image-20241018145710544 4. 将初始化顺序改成:GPIO时钟 - USART时钟 - GPIO - USART;串口在初始化过程中不再输出任何数据; image-20241018142921367
  4. 具体原因分析
    1. 只要供电正常,ESP8266模块的RX口就处于时刻准备接收的状态;
    2. 如果在初始化GPIO为复用推挽输出模式(将GPIO_Pin的控制权交给外设)时还未初始化USART时钟,则会导致GPIO_Pin的电平处于不确定状态
    3. GPIO初始化(GPIO_Init())和USART时钟初始化(AT_USARTx_APBxCLOCKCMD())的过程中,都会产生电平波动;此时TX引脚上的电平波动就有可能让ESP8266误认为有数据传输;电平时序如图所示
      image-20241018162435209
    4. 如果先初始化USART时钟再初始化GPIO外设为复用推挽输出模式,则GPIO_Pin的电平被USART确定(高/低),不会处于不确定的波动状态;
如果使用标准库实现,可以使用USART串口通信来实现STM32ESP8266通信。以下是示例代码: ``` #include "stm32f10x.h" void USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } void USART1_Write(uint16_t data) { while (!(USART1->SR & USART_SR_TC)); USART1->DR = (data & 0xFF); } uint16_t USART1_Read(void) { while (!(USART1->SR & USART_SR_RXNE)); return (USART1->DR & 0xFF); } int main(void) { USART1_Init(); while (1) { USART1_Write('A'); // 发送数据 uint16_t data = USART1_Read(); // 接收数据 } } ``` 在此基础上,可以使用AT指令来控制ESP8266进行WiFi连接等操作。具体的AT指令可以参考ESP8266的官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值