STM32F1串口通信详解:从配置到实战

STM32F1串口通信详解:从配置到实战

一、串口通信基础

串口(UART)是一种异步全双工通信协议,广泛应用于嵌入式设备调试、传感器数据交互等场景。STM32F1系列微控制器内置多个USART外设(如USART1-USART3),支持以下关键特性:

  • 波特率可调(1200bps~4.5Mbps)
  • 可配置数据位(8/9位)、停止位(1/1.5/2位)
  • 硬件流控制(CTS/RTS)
  • 中断/DMA传输模式

二、硬件连接

USART1为例(PA9-TX, PA10-RX):

  1. 使用USB转TTL模块(如CH340G)连接开发板
  2. 交叉连接TX-RX线(STM32_TX → TTL_RX,STM32_RX → TTL_TX)
  3. 共地连接(GND ↔ GND)

三、代码实现(详细注释版)

  1. 初始化配置函数解析
void USART1_Init(uint32_t baudrate) {
    // 定义GPIO和USART初始化结构体
    GPIO_InitTypeDef GPIO_InitStruct;  // GPIO配置容器
    USART_InitTypeDef USART_InitStruct; // 串口参数容器

    /* 时钟使能(关键步骤!) */
    // 启用USART1和GPIOA的时钟(APB2总线)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

    /* TX引脚(PA9)配置 */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;        // 选择引脚9
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出模式
    /* 为什么用推挽输出?
       保证TX引脚能主动输出高/低电平,提供稳定的驱动能力 */
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 最大输出速率
    GPIO_Init(GPIOA, &GPIO_InitStruct); // 应用配置到GPIOA
   /* RX引脚(PA10)配置 */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式
    /* 浮空输入特点:
       不内部上拉/下拉,依赖外部信号电平,适合接收可变信号 */
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART参数配置 */
    USART_InitStruct.USART_BaudRate = baudrate; // 设置波特率(如9600)
    USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 8位数据位
    USART_InitStruct.USART_StopBits = USART_StopBits_1;     // 1位停止位
    USART_InitStruct.USART_Parity = USART_Parity_No;         // 无校验位
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 启用收发
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
    USART_Init(USART1, &USART_InitStruct); // 应用配置到USART1

    USART_Cmd(USART1, ENABLE); // 最后使能USART外设
}
2. 数据收发函数解析
// 阻塞式发送单字节函数
void USART1_SendByte(uint8_t data) {
    USART_SendData(USART1, data); // 写入数据到发送寄存器
    
    /* 等待发送完成:
       TXE标志位=1表示数据已转移到移位寄存器(非完全发送完成)
       实际使用时建议检查TC标志(传输完成标志)更可靠 */
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

// 中断接收初始化
void USART1_IT_Init(void) {
    // 使能RXNE(接收寄存器非空)中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    
    /* 配置NVIC(嵌套向量中断控制器):
       USART1_IRQn表示中断号,优先级使用默认值 */
    NVIC_EnableIRQ(USART1_IRQn); // 使能USART1全局中断
}

// 中断服务函数(每次接收触发)
void USART1_IRQHandler(void) {
    // 检查是否是RXNE中断触发
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        // 读取接收到的数据(自动清除RXNE标志)
        uint8_t data = USART_ReceiveData(USART1);
        
        /* 示例处理:回传数据
           实际项目建议将数据存入环形缓冲区 */
        USART1_SendByte(data);
        
        // 必须手动清除中断标志
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}

关键代码原理说明

1. 时钟使能
RCC_APB2PeriphClockCmd()
是开启外设的"电源开关",未使能时钟时配置无效
STM32F1的USART1挂载在APB2总线,其他USART在APB1
2. GPIO模式选择
TX引脚:复用推挽输出(GPIO_Mode_AF_PP)
复用功能由USART硬件控制输出时序
推挽结构确保强驱动能力
RX引脚:浮空输入(GPIO_Mode_IN_FLOATING)
高阻抗状态避免影响输入信号
3. 中断流程
接收数据时硬件自动置位RXNE标志
触发中断后跳转到
USART1_IRQHandler
USART_GetITStatus
检查特定中断源
读取数据寄存器会自动清除RXNE标志
必须调用
USART_ClearITPendingBit
清除中断挂起标志
4. 阻塞发送 vs 中断发送
当前示例使用简单阻塞发送,实际项目中:
高频率发送建议使用DMA或带缓冲区的中断发送
阻塞发送在低波特率时可能导致CPU资源浪费
常见疑问解答
Q1: 为什么使能时钟要放在最前面?
A1: STM32的外设配置必须在其时钟开启后进行,否则寄存器访问可能无效或导致硬件错误。

Q2: 如何修改为115200波特率?
A2: 调用
USART1_Init(115200)
即可,但需确保硬件支持(如晶振频率足够)

Q3: 中断函数里为什么要回传数据?
A3: 这是简单的回环测试示例,实际应用应根据协议处理数据,建议添加软件缓冲区。

四、调试技巧

常见问题排查

  1. 无数据收发

    • 检查波特率是否匹配(建议从9600开始)
    • 确认TX/RX线是否反接
    • 测量TX引脚电压(正常应有3.3V高电平)
  2. 数据乱码

    • 检查双方数据位/停止位配置
    • 确认时钟源配置正确(HSI/PLL)
    • 降低波特率测试信号质量
  3. 中断不触发

    • 检查NVIC优先级配置
    • 确认USART_ITConfig使能接收中断

五、实验结果

使用串口助手发送"Hello"时,设备返回:

发送: Hello
接收: Hello

(成功实现数据回环测试)


六、进阶应用

  1. DMA传输:减少CPU占用,适合高速通信
  2. Modbus协议:实现工业标准通信
  3. JSON数据解析:构建IoT应用

推荐工具

  • 串口调试助手:SSCOM/XCOM
  • 协议分析:Wireshark+USB转接器

通过这篇博客,读者可以快速上手STM32F1的串口开发。实际应用中需根据具体需求调整硬件流控制、错误检测等参数。欢迎在评论区交流调试心得! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FightingLod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值