首页 > 其他分享 >STM32:STM32串行通信:STM32串行通信基础理论

STM32:STM32串行通信:STM32串行通信基础理论

时间:2024-09-04 12:51:43浏览次数:7  
标签:HAL USART UART 通信 STM32 huart2 Init 串行

STM32:STM32串行通信:STM32串行通信基础理论

在这里插入图片描述

串行通信概述

串行通信的基本概念

串行通信是一种数据传输方式,其中数据位被逐个按顺序传输,通常通过一条信号线完成。与并行通信相比,串行通信使用较少的线路,因此在长距离通信和减少硬件成本方面具有优势。在串行通信中,数据通常以帧的形式发送,每一帧包含起始位、数据位、停止位,有时还包括校验位,用于检测传输中的错误。

串行通信的类型:同步与异步

异步串行通信

异步串行通信是最常见的串行通信类型,它不需要时钟信号来同步发送和接收数据。每个字符(字节)的传输都是独立的,由起始位和停止位来界定。起始位是一个低电平信号,表示数据传输的开始;数据位随后传输,最后是停止位,通常是一个高电平信号,表示数据传输的结束。异步通信的速率由波特率决定,波特率是指每秒传输的信号变化次数。

示例代码:STM32异步串行通信初始化
// 异步串行通信初始化
void USART_Init(USART_TypeDef* USARTx, uint32_t BaudRate, uint32_t WordLength, uint32_t StopBits, uint32_t Parity, uint32_t Mode, uint32_t HardwareFlowControl, uint32_t OverSampling)
{
    // 设置波特率
    USARTx->BRR = BaudRate;

    // 设置数据位长度
    USARTx->CR1 &= ~USART_CR1_DATA;
    USARTx->CR1 |= WordLength;

    // 设置停止位
    USARTx->CR2 &= ~USART_CR2_STOP;
    USARTx->CR2 |= StopBits;

    // 设置奇偶校验位
    USARTx->CR1 &= ~USART_CR1_PCE;
    USARTx->CR1 |= Parity;

    // 设置通信模式
    USARTx->CR1 &= ~USART_CR1_M0;
    USARTx->CR1 |= Mode;

    // 设置硬件流控制
    USARTx->CR3 &= ~USART_CR3_RTSE;
    USARTx->CR3 |= HardwareFlowControl;

    // 设置过采样
    USARTx->CR1 &= ~USART_CR1_OVER8;
    USARTx->CR1 |= OverSampling;

    // 启用USART
    USARTx->CR1 |= USART_CR1_UE;
}

同步串行通信

同步串行通信需要一个共同的时钟信号来同步数据的发送和接收。发送方和接收方都遵循时钟信号的节奏,这使得数据传输更加精确,尤其是在高速通信中。SPI(Serial Peripheral Interface)和I2C(Inter-Integrated Circuit)是两种常见的同步串行通信协议。

示例代码:STM32 SPI通信初始化
// SPI通信初始化
void SPI_Init(SPI_TypeDef* SPIx, uint32_t SPI_Direction, uint32_t SPI_Mode, uint32_t SPI_DataSize, uint32_t SPI_CPOL, uint32_t SPI_CPHA, uint32_t SPI_NSS, uint32_t SPI_BaudRatePrescaler, uint32_t SPI_FirstBit, uint32_t SPI_CRCPolynomial)
{
    // 设置SPI方向
    SPIx->CR1 &= ~SPI_CR1_BIDIOE;
    SPIx->CR1 |= SPI_Direction;

    // 设置SPI模式
    SPIx->CR1 &= ~SPI_CR1_SSM;
    SPIx->CR1 |= SPI_Mode;

    // 设置数据大小
    SPIx->CR1 &= ~SPI_CR1_DFF;
    SPIx->CR1 |= SPI_DataSize;

    // 设置时钟极性
    SPIx->CR1 &= ~SPI_CR1_CPOL;
    SPIx->CR1 |= SPI_CPOL;

    // 设置时钟相位
    SPIx->CR1 &= ~SPI_CR1_CPHA;
    SPIx->CR1 |= SPI_CPHA;

    // 设置NSS管理
    SPIx->CR1 &= ~SPI_CR1_NSSP;
    SPIx->CR1 |= SPI_NSS;

    // 设置波特率预分频器
    SPIx->CR1 &= ~SPI_CR1_BR;
    SPIx->CR1 |= SPI_BaudRatePrescaler;

    // 设置数据传输的起始位
    SPIx->CR1 &= ~SPI_CR1_LSBFIRST;
    SPIx->CR1 |= SPI_FirstBit;

    // 设置CRC多项式
    SPIx->CR1 &= ~SPI_CR1_CRCEN;
    SPIx->CR1 |= SPI_CRCPolynomial;

    // 启用SPI
    SPIx->CR1 |= SPI_CR1_SPE;
}

串行通信的常见协议

UART/USART

UART(Universal Asynchronous Receiver/Transmitter)和USART(Universal Synchronous/Asynchronous Receiver/Transmitter)是异步串行通信的协议,广泛用于微控制器和计算机之间进行数据传输。STM32微控制器具有多个USART模块,可以配置为异步或同步模式。

SPI

SPI是一种同步串行通信协议,通常用于微控制器与外围设备之间的高速数据交换。SPI通信由主设备控制,使用时钟信号(SCK)和从设备选择信号(NSS)来同步数据传输。

示例代码:STM32 SPI数据发送
// SPI数据发送
void SPI_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
    // 等待发送缓冲区空闲
    while (!(SPIx->SR & SPI_SR_TXE));

    // 发送数据
    SPIx->DR = Data;
}

I2C

I2C是一种两线式同步串行通信协议,用于连接微控制器和多个外围设备。I2C通信由主设备控制,使用串行数据线(SDA)和串行时钟线(SCL)进行通信。

示例代码:STM32 I2C数据发送
// I2C数据发送
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
{
    // 等待发送缓冲区空闲
    while (!(I2Cx->SR1 & I2C_SR1_TXE));

    // 发送数据
    I2Cx->DR = Data;
}

CAN

CAN(Controller Area Network)是一种用于车辆环境的串行通信协议,用于在多个设备之间进行实时通信。CAN协议支持多主模式,允许多个设备同时发送数据。

RS-485

RS-485是一种用于多点系统中的串行通信标准,具有较高的抗干扰能力和长距离传输能力。在RS-485网络中,通常使用差分信号进行通信,以提高信号的稳定性和可靠性。

Bluetooth

蓝牙是一种无线串行通信协议,用于短距离设备之间的数据交换。蓝牙通信基于射频技术,可以实现音频、数据等多种类型的信息传输。

Zigbee

Zigbee是一种基于IEEE 802.15.4标准的无线串行通信协议,适用于低功耗、低数据速率的网络。Zigbee网络可以包含多个设备,形成星型、树型或网状网络结构。

NFC

NFC(Near Field Communication)是一种短距离无线串行通信技术,用于设备之间的数据交换。NFC通信基于电磁感应原理,可以在几厘米的距离内实现数据传输。

RFID

RFID(Radio Frequency Identification)是一种无线串行通信技术,用于识别和跟踪物体。RFID系统通常由阅读器和标签组成,通过射频信号进行通信。

Modbus

Modbus是一种串行通信协议,用于工业自动化设备之间的数据交换。Modbus协议支持多种通信模式,包括串行异步、串行同步和以太网。

Ethernet

以太网是一种基于IEEE 802.3标准的串行通信协议,用于局域网中的数据传输。以太网通信基于双绞线或光纤,可以实现高速数据传输。

USB

USB(Universal Serial Bus)是一种用于连接计算机和外围设备的串行通信协议。USB通信基于差分信号,可以实现高速数据传输和电源供应。

Wi-Fi

Wi-Fi是一种无线串行通信协议,用于局域网中的数据传输。Wi-Fi通信基于射频技术,可以实现高速无线数据传输。

Zigbee

Zigbee是一种基于IEEE 802.15.4标准的无线串行通信协议,适用于低功耗、低数据速率的网络。Zigbee网络可以包含多个设备,形成星型、树型或网状网络结构。

LoRa

LoRa(Long Range)是一种无线串行通信技术,用于低功耗广域网络(LPWAN)。LoRa通信基于扩频技术,可以在远距离内实现数据传输。

Zigbee

(注:Zigbee已列出,此处重复,故不再赘述)

LoRaWAN

LoRaWAN是一种基于LoRa技术的无线串行通信协议,用于构建低功耗广域网络。LoRaWAN协议支持多种网络架构,包括星型、树型和网状网络。

Zigbee

(注:Zigbee已列出,此处重复,故不再赘述)

Zigbee

(注:Zigbee已列出,此处重复,故不再赘述)

通过上述内容,我们了解了串行通信的基本概念、类型以及常见的串行通信协议。在实际应用中,选择合适的串行通信协议和配置参数对于实现高效、可靠的通信至关重要。

STM32串行通信模块

USART模块介绍

STM32微控制器系列中,USART(Universal Synchronous/Asynchronous Receiver/Transmitter)模块是用于实现串行通信的关键组件。它支持全双工通信,即同时发送和接收数据,且能够以同步或异步模式工作。USART模块通常用于与外部设备进行通信,如串行外设接口(SPI)、通用异步收发传输器(UART)等。

功能特性

  • 全双工操作:同时发送和接收数据。
  • 多种通信模式:支持同步和异步模式。
  • 数据格式灵活:可配置数据位长度(8位或9位)、停止位数量(1或2)、奇偶校验位等。
  • 错误检测:包括帧错误、噪声错误、溢出错误和奇偶错误。
  • 中断和DMA支持:提供中断和DMA传输,以减少CPU的负担。

USART寄存器详解

USART模块的配置和操作主要通过其寄存器来实现。以下是一些关键寄存器的介绍:

1. USART_CR1(控制寄存器1)

  • UE:USART使能位,用于使能或禁用USART模块。
  • TE:发送使能位,用于使能或禁用数据发送。
  • RE:接收使能位,用于使能或禁用数据接收。
  • IDLEIE:空闲线中断使能位,用于使能或禁用空闲线中断。

2. USART_CR2(控制寄存器2)

  • LINEN:LIN模式使能位,用于使能或禁用LIN模式。
  • STOP[1:0]:停止位长度选择位,用于配置停止位的长度。
  • CLKEN:时钟使能位,用于使能或禁用USART时钟。

3. USART_SR(状态寄存器)

  • TXE:发送数据寄存器空位,表示发送数据寄存器为空,可以写入数据。
  • RXNE:接收数据寄存器非空位,表示接收数据寄存器中有数据可读。
  • IDLE:空闲线检测位,表示检测到空闲线状态。

4. USART_DR(数据寄存器)

  • 用于读取接收到的数据或写入要发送的数据。

USART初始化配置

初始化USART模块涉及设置其工作模式、波特率、数据格式和中断等。以下是一个使用STM32 HAL库进行USART初始化的示例代码:

// 包含必要的头文件
#include "stm32f1xx_hal.h"

// 定义USART句柄
static UART_HandleTypeDef huart1;

// 初始化USART1
void MX_USART1_UART_Init(void)
{
    // 配置USART1的参数
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    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;

    // 初始化USART1
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        // 初始化失败处理
        Error_Handler();
    }
}

代码解析

  • huart1.Instance:指定要初始化的USART实例。
  • huart1.Init.BaudRate:设置波特率,这里是9600bps。
  • huart1.Init.WordLength:设置数据位长度,这里是8位。
  • huart1.Init.StopBits:设置停止位数量,这里是1位。
  • huart1.Init.Parity:设置奇偶校验,这里禁用了奇偶校验。
  • huart1.Init.Mode:设置工作模式,这里是全双工模式。
  • huart1.Init.HwFlowCtl:设置硬件流控制,这里禁用了硬件流控制。
  • huart1.Init.OverSampling:设置过采样率,这里是16倍过采样。

数据样例

在串行通信中,数据通常以ASCII码或二进制形式传输。例如,发送字符串"Hello, World!":

// 发送字符串
void SendString(void)
{
    char str[] = "Hello, World!";
    HAL_UART_Transmit(&huart1, (uint8_t*)str, sizeof(str)-1, HAL_MAX_DELAY);
}

中断处理

USART模块支持中断,以下是一个接收中断的示例:

void USART1_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
    {
        // 读取接收寄存器中的数据
        uint8_t data = HAL_UART_Receive(&huart1, 1, 1, HAL_MAX_DELAY);
        // 处理接收到的数据
        ProcessReceivedData(data);
    }
}

DMA传输

对于大量数据传输,使用DMA可以提高效率,以下是一个使用DMA发送数据的示例:

// 发送数据
void SendData_DMA(uint8_t* pData, uint16_t Size)
{
    // 配置DMA
    __HAL_LINKDMA(&huart1, hdmatx, DMA1_Channel2);
    HAL_DMA_Init(huart1.hdmatx);

    // 设置DMA传输参数
    __HAL_DMA_SET_PARMS(huart1.hdmatx, (uint32_t)USART1, (uint32_t)pData, Size);

    // 启动DMA传输
    __HAL_DMA_ENABLE(huart1.hdmatx);
}

通过上述代码和数据样例,可以详细了解STM32的USART模块如何进行初始化配置、数据发送和接收,以及如何使用中断和DMA进行高效数据传输。这为开发基于STM32的串行通信应用提供了坚实的基础。

异步串行通信实践

配置USART为异步模式

在STM32微控制器中,异步串行通信主要通过USART(通用同步/异步收发器)模块实现。配置USART为异步模式涉及设置波特率、数据位、停止位、奇偶校验位等参数。以下是一个配置STM32的USART1为异步模式的示例代码:

// 包含必要的头文件
#include "stm32f1xx_hal.h"

// 定义USART配置结构体
static UART_HandleTypeDef huart1;

// 初始化USART1
void USART1_Init(void)
{
    // 配置GPIO
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
    __HAL_RCC_USART1_CLK_ENABLE(); // 使能USART1时钟

    GPIO_InitStruct.Pin = GPIO_PIN_9; // TX
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10; // RX
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 配置USART
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    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;
    HAL_UART_Init(&huart1);
}

代码解释

  1. 时钟使能:通过__HAL_RCC_GPIOA_CLK_ENABLE()__HAL_RCC_USART1_CLK_ENABLE()使能GPIOA和USART1的时钟。
  2. GPIO配置:设置GPIOA的9号引脚为推挽输出模式,用于发送数据;10号引脚为输入模式,用于接收数据。
  3. USART配置:设置USART1的波特率为9600,数据位为8位,停止位为1位,无奇偶校验,工作模式为发送和接收。

实现简单的数据发送与接收

在配置好USART后,可以使用HAL库函数来发送和接收数据。以下是一个发送和接收单个字符的示例:

// 发送单个字符
void SendChar(char c)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)&c, 1, 1000);
}

// 接收单个字符
char ReceiveChar(void)
{
    uint8_t c;
    HAL_UART_Receive(&huart1, &c, 1, 1000);
    return c;
}

代码解释

  1. 发送函数SendChar函数使用HAL_UART_Transmit发送一个字符。参数&c是指向字符的指针,1表示发送1个字节,1000是等待时间(单位:毫秒)。
  2. 接收函数ReceiveChar函数使用HAL_UART_Receive接收一个字符。&c用于存储接收到的字符,1表示接收1个字节,1000是等待时间。

异步通信中断处理

在异步通信中,中断处理是关键,它允许在数据到达时立即处理,而无需轮询。以下是一个配置USART1中断并处理接收数据的示例:

// 定义接收缓冲区
uint8_t RxBuffer[10];
uint8_t RxIndex = 0;

// USART中断服务例程
void USART1_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
    {
        // 读取接收到的数据
        RxBuffer[RxIndex] = HAL_UART_Receive_IT(&huart1);
        RxIndex++;

        // 检查缓冲区是否已满
        if (RxIndex >= 10)
        {
            RxIndex = 0; // 重置索引
            // 在这里处理接收到的数据
            ProcessReceivedData(RxBuffer);
        }
    }
}

// 处理接收到的数据
void ProcessReceivedData(uint8_t* data)
{
    // 打印接收到的数据
    for (int i = 0; i < 10; i++)
    {
        if (data[i] != 0)
        {
            printf("%c", data[i]);
        }
    }
}

代码解释

  1. 接收缓冲区:定义一个10字节的接收缓冲区RxBuffer和一个索引RxIndex来跟踪接收到的数据。
  2. 中断服务例程USART1_IRQHandler在接收到数据时被调用。使用__HAL_UART_GET_FLAG检查接收数据寄存器是否非空,然后使用HAL_UART_Receive_IT读取数据并存储到缓冲区中。
  3. 数据处理:当缓冲区满时,调用ProcessReceivedData函数处理接收到的数据。在这个例子中,数据被打印到串行监视器。

通过以上步骤,STM32可以有效地配置为异步串行通信模式,并能够发送、接收和处理数据。这为开发基于STM32的串行通信应用提供了坚实的基础。

同步串行通信实践

配置USART为同步模式

在STM32中,USART(通用同步/异步收发传输器)模块可以配置为同步串行通信模式。同步模式下,数据的发送和接收由外部时钟信号控制,这通常用于与外部设备进行通信,如ADC、DAC或其它微控制器,其中数据传输的时序需要严格控制。

配置步骤

  1. 时钟使能:首先,需要使能USART和GPIO的时钟。
  2. GPIO配置:配置USART的TX和RX引脚为复用推挽输出和输入模式。
  3. USART初始化:设置USART的工作模式为同步,配置波特率、数据位、停止位等。
  4. 使能同步时钟:通过设置USART_CR1寄存器中的UE位和M位,使能USART并进入同步模式。
  5. 配置同步时钟源:通过USART_BRR寄存器设置外部时钟源的频率。

示例代码

// 配置USART2为同步模式
void USART2_Init(void)
{
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 9600;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.Init.FIFOMode = UART_FIFOMODE_DISABLE;
  huart2.Init.RxQueueSize = 0;
  huart2.Init.TxFifoThreshold = UART_TXFIFO_THRESHOLD_1_8;
  huart2.Init.RxFifoThreshold = UART_RXFIFO_THRESHOLD_1_8;
  huart2.Init.RxQueueSize = 0;
  huart2.Init.DMAable = UART_DMAABLE_DISABLE;
  huart2.Init.UARTClockSource = UART_CLOCKSOURCE_PCLK;
  huart2.Init.SyncWordLength = UART_SYNCWORDLENGTH_8BIT;
  huart2.Init.SyncMode = UART_SYNCMODE_ENABLE;
  huart2.Init.SyncPrescaler = UART_SYNCPRESCALER_DIV1;
  huart2.Init.SyncPolarity = UART_SYNCPOLARITY_RISING;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
}

同步通信的数据发送与接收

在同步模式下,数据的发送和接收是同步进行的,这意味着发送数据的同时也在接收数据。STM32的USART模块提供了硬件支持,使得数据的同步传输更加高效和准确。

发送数据

数据发送通过USART的发送寄存器进行,当数据被写入发送寄存器时,硬件会自动开始发送过程。

接收数据

数据接收通过USART的接收寄存器完成,当数据到达时,硬件会自动将数据存入接收寄存器。

示例代码

// 发送数据
void SendData(uint8_t data)
{
  // 等待发送寄存器为空
  while (!(USART2->ISR & USART_ISR_TXE));
  // 写入数据到发送寄存器
  USART2->TDR = data;
}

// 接收数据
uint8_t ReceiveData(void)
{
  // 等待接收寄存器非空
  while (!(USART2->ISR & USART_ISR_RXNE));
  // 从接收寄存器读取数据
  return USART2->RDR;
}

同步通信的时钟同步

在同步串行通信中,时钟同步是关键。STM32的USART模块可以通过外部时钟信号进行同步,这通常由另一个设备提供,如SPI主机。时钟同步确保了数据的正确发送和接收,避免了数据位的错位。

配置时钟同步

配置时钟同步涉及到USART_CR1寄存器中的M位和UE位。M位用于选择同步或异步模式,而UE位用于使能USART。

示例代码

// 配置时钟同步
void ConfigureClockSync(void)
{
  // 使能USART2时钟
  __HAL_RCC_USART2_CLK_ENABLE();
  
  // 配置USART2为同步模式
  USART2->CR1 |= USART_CR1_UE | USART_CR1_M;
  
  // 设置外部时钟源的频率
  // 假设外部时钟源频率为1MHz
  USART2->BRR = ((SystemCoreClock / 1000000) * 16) + 1;
}

在上述代码中,SystemCoreClock是STM32的系统时钟频率,通常在stm32f1xx_hal.h头文件中定义。通过调整BRR寄存器的值,可以设置外部时钟源的频率,从而确保数据的同步传输。

通过以上步骤,STM32的USART模块可以被配置为同步串行通信模式,实现与外部设备的高效数据交换。在实际应用中,根据具体需求调整配置参数,可以优化通信性能,满足不同的通信要求。

高级串行通信特性

DMA在串行通信中的应用

原理

DMA (Direct Memory Access) 直接内存访问是一种硬件技术,允许数据在内存和外设之间直接传输,而无需CPU的干预。在STM32中,DMA可以显著提高数据传输的效率,特别是在处理大量数据或需要高速传输的场景下,如串行通信中的数据收发。

内容

在STM32的USART (Universal Synchronous/Asynchronous Receiver/Transmitter) 模块中,DMA可以用于数据的发送和接收。当配置了DMA,USART模块会自动将数据从内存中读取或写入,从而释放CPU去执行其他任务。

示例代码
// 配置USART2 DMA
void USART2_DMA_Config(void)
{
    // 使能USART2 DMA时钟
    __HAL_RCC_DMA1_CLK_ENABLE();
    __HAL_RCC_USART2_CLK_ENABLE();

    // 配置USART2的DMA TX通道
    hdmatx.Instance = DMA1_Channel2;
    hdmatx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdmatx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdmatx.Init.MemInc = DMA_MINC_ENABLE;
    hdmatx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdmatx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdmatx.Init.Mode = DMA_NORMAL;
    hdmatx.Init.Priority = DMA_PRIORITY_LOW;
    hdmatx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdmatx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    HAL_DMA_Init(&hdmatx);

    // 配置USART2的DMA RX通道
    hdmarx.Instance = DMA1_Channel3;
    hdmarx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdmarx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdmarx.Init.MemInc = DMA_MINC_ENABLE;
    hdmarx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdmarx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdmarx.Init.Mode = DMA_NORMAL;
    hdmarx.Init.Priority = DMA_PRIORITY_LOW;
    hdmarx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdmarx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    HAL_DMA_Init(&hdmarx);

    // 配置USART2
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 9600;
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_NONE;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    huart2.Init.DMAEnableTx = UART_DMAENABLER_TX_ENABLE;
    huart2.Init.DMAEnableRx = UART_DMAENABLER_RX_ENABLE;
    HAL_UART_Init(&huart2);
}

// 发送数据
void USART2_DMA_Send(uint8_t *pData, uint16_t Size)
{
    HAL_UART_Transmit_DMA(&huart2, pData, Size);
}

// 接收数据
void USART2_DMA_Receive(uint8_t *pData, uint16_t Size)
{
    HAL_UART_Receive_DMA(&huart2, pData, Size);
}

描述

上述代码示例展示了如何在STM32上配置USART2模块使用DMA进行数据的发送和接收。首先,通过USART2_DMA_Config函数初始化DMA和USART2,设置数据传输的参数,如字长、停止位、校验位等。然后,通过USART2_DMA_SendUSART2_DMA_Receive函数,可以使用DMA发送和接收数据,其中pData是指向数据缓冲区的指针,Size是传输的数据量。

USART的错误检测与处理

原理

USART模块在数据传输过程中可能会遇到各种错误,如帧错误、噪声错误、溢出错误和奇偶校验错误。STM32提供了错误检测机制,可以在发生错误时生成中断,以便应用程序可以及时处理这些错误。

内容

在STM32的USART配置中,可以启用错误中断,当检测到错误时,相应的错误标志会被设置,同时触发中断。在中断服务程序中,可以通过读取USART的状态寄存器来确定错误类型,并采取相应的措施,如重发数据或记录错误。

示例代码
// 配置USART2错误中断
void USART2_Error_Config(void)
{
    huart2.Instance->CR3 |= USART_CR3_EIE; // 启用错误中断
}

// USART2错误中断服务程序
void USART2_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_ORE) != RESET) // 检查溢出错误
    {
        __HAL_UART_CLEAR_OREFLAG(&huart2); // 清除溢出错误标志
        // 处理溢出错误,例如记录错误或重发数据
    }
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_NE) != RESET) // 检查噪声错误
    {
        __HAL_UART_CLEAR_NEFLAG(&huart2); // 清除噪声错误标志
        // 处理噪声错误
    }
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_FE) != RESET) // 检查帧错误
    {
        __HAL_UART_CLEAR_FEFALG(&huart2); // 清除帧错误标志
        // 处理帧错误
    }
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_PE) != RESET) // 检查奇偶校验错误
    {
        __HAL_UART_CLEAR_PEFALG(&huart2); // 清除奇偶校验错误标志
        // 处理奇偶校验错误
    }
}

描述

在示例代码中,USART2_Error_Config函数用于配置USART2的错误中断。通过设置CR3寄存器的EIE位,使能错误中断。在USART2_IRQHandler中断服务程序中,通过检查USART的状态标志来检测错误类型,并清除相应的错误标志,防止错误标志被重复读取。根据不同的错误类型,应用程序可以采取相应的错误处理措施,如记录错误或重发数据。

USART的高级配置选项

原理

STM32的USART模块提供了多种高级配置选项,包括自适应校验控制、数据位长度、停止位长度、硬件流控制等,这些选项可以满足不同通信协议和应用的需求。

内容

自适应校验控制

自适应校验控制允许USART模块根据接收到的数据自动调整校验位。如果接收到的数据包含奇偶校验位,USART会自动检测并使用奇偶校验;如果没有,USART会忽略校验位。

数据位长度

USART支持7位或8位的数据位长度,这可以通过配置WordLength参数来实现。

停止位长度

USART支持1位、1.5位或2位的停止位长度,这可以通过配置StopBits参数来实现。

硬件流控制

硬件流控制(RTS/CTS)可以用于控制数据的发送,防止数据溢出。在STM32中,可以通过配置HwFlowCtl参数来启用硬件流控制。

示例代码
// 配置USART2高级选项
void USART2_Advanced_Config(void)
{
    huart2.Init.WordLength = UART_WORDLENGTH_7B; // 配置7位数据长度
    huart2.Init.StopBits = UART_STOPBITS_2; // 配置2位停止位
    huart2.Init.Parity = UART_PARITY_EVEN; // 配置偶校验
    huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS; // 启用RTS硬件流控制
    HAL_UART_Init(&huart2);
}

描述

在示例代码中,USART2_Advanced_Config函数展示了如何配置USART2的高级选项。通过设置WordLengthStopBitsParityHwFlowCtl参数,可以调整数据位长度、停止位长度、校验位类型和硬件流控制方式。这些配置可以根据具体的应用需求进行调整,以优化通信性能或满足特定的通信协议要求。

串行通信实例与调试

实现一个完整的串行通信实例

在STM32微控制器中,实现串行通信通常涉及到使用USART(通用同步/异步收发器)模块。下面,我们将通过一个具体的实例来展示如何在STM32上设置并使用USART进行串行通信。

硬件准备

  • 确保STM32开发板上具有USART接口。
  • 准备一个串口转USB适配器,用于连接STM32和PC。
  • 连接TX和RX引脚:STM32的TX引脚连接到适配器的RX引脚,STM32的RX引脚连接到适配器的TX引脚。

软件配置

  1. 使用STM32CubeMX进行配置

    打开STM32CubeMX,选择你的STM32芯片型号,然后在“Pinout & Configuration”窗口中,配置USART引脚和波特率。例如,选择USART2,设置波特率为9600。

  2. 生成代码

    在STM32CubeMX中完成配置后,生成初始化代码。这将包括必要的头文件和初始化函数。

  3. 编写串行通信代码

    // 包含必要的头文件
    #include "stm32f1xx_hal.h"
    
    // 定义串口句柄
    UART_HandleTypeDef huart2;
    
    // 初始化USART2
    void MX_USART2_UART_Init(void)
    {
        huart2.Instance = USART2;
        huart2.Init.BaudRate = 9600;
        huart2.Init.WordLength = UART_WORDLENGTH_8B;
        huart2.Init.StopBits = UART_STOPBITS_1;
        huart2.Init.Parity = UART_PARITY_NONE;
        huart2.Init.Mode = UART_MODE_TX_RX;
        huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        huart2.Init.OverSampling = UART_OVERSAMPLING_16;
        HAL_UART_Init(&huart2);
    }
    
    // 发送数据函数
    void SendData(uint8_t *pData, uint16_t Size)
    {
        HAL_UART_Transmit(&huart2, pData, Size, HAL_MAX_DELAY);
    }
    
    // 主函数
    int main(void)
    {
        // 初始化HAL库
        HAL_Init();
    
        // 配置时钟系统
        __HAL_RCC_USART2_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
    
        // GPIO配置
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        // USART配置
        MX_USART2_UART_Init();
    
        // 发送数据
        uint8_t data[] = "Hello, STM32!";
        SendData(data, sizeof(data));
    
        // 无限循环
        while (1)
        {
            // 添加任何其他代码或功能
        }
    }
    

    在这个例子中,我们配置了USART2,并定义了一个发送数据的函数SendData。我们使用HAL库的HAL_UART_Transmit函数来发送数据。

串行通信的调试技巧与工具

  • 使用串口调试助手

    在PC端安装一个串口调试助手,如“CoolTerm”或“Tera Term”。这将帮助你接收和查看STM32发送的数据。

  • 检查波特率设置

    确保STM32和串口调试助手的波特率设置一致。不一致的波特率会导致数据无法正确接收。

  • 使用HAL库的错误处理

    利用HAL库提供的错误处理函数,如HAL_UART_GetError,来检查USART操作中可能发生的错误。

  • 添加日志记录

    在代码中添加日志记录,如使用printf函数,可以帮助你跟踪程序的执行流程和状态。

使用STM32CubeMX进行配置

STM32CubeMX是一个图形化工具,用于STM32微控制器的初始化和配置。它简化了配置过程,允许用户通过直观的界面选择和配置外设。

步骤

  1. 选择STM32芯片

    在STM32CubeMX的“Device Selection”窗口中,选择你的STM32芯片型号。

  2. 配置引脚

    在“Pinout & Configuration”窗口中,选择USART2,然后配置其TX和RX引脚。通常,TX引脚是PA2,RX引脚是PA3。

  3. 设置USART参数

    在“MCU Configuration”窗口中,设置USART的波特率、数据位、停止位、校验位等参数。

  4. 生成代码

    完成配置后,点击“Generate Code”按钮,STM32CubeMX将生成初始化代码和必要的HAL库文件。

注意事项

  • 确保在生成代码前,所有的配置选项都已正确设置。
  • 在生成代码后,检查生成的代码是否符合你的需求,必要时进行修改。

通过以上步骤,你可以使用STM32CubeMX轻松地配置STM32的USART模块,为串行通信做好准备。

串行通信的调试技巧与工具

调试串行通信时,确保数据正确发送和接收是关键。以下是一些调试技巧和工具:

技巧

  • 检查硬件连接

    确保STM32的TX和RX引脚正确连接到串口转USB适配器的RX和TX引脚。

  • 使用串口调试助手

    在PC端使用串口调试助手接收STM32发送的数据,检查数据是否正确。

  • 检查代码逻辑

    确保发送和接收数据的代码逻辑正确,没有遗漏或错误。

工具

  • 串口调试助手

    如“CoolTerm”或“Tera Term”,用于接收和显示STM32发送的数据。

  • 逻辑分析仪

    如果可用,逻辑分析仪可以帮助你检查STM32的TX和RX引脚上的信号。

  • STM32CubeMonitor-Serial

    这是STM32Cube生态系统的一部分,专门用于STM32的串行通信调试。

通过结合使用这些技巧和工具,你可以有效地调试STM32的串行通信,确保数据的正确传输。

标签:HAL,USART,UART,通信,STM32,huart2,Init,串行
From: https://blog.csdn.net/weixin_42749425/article/details/141877179

相关文章

  • STM32低功耗设计:STM32低功耗通信接口设计
    STM32低功耗设计:STM32低功耗通信接口设计STM32低功耗设计概述低功耗设计的重要性在当今的电子设备设计中,低功耗设计变得日益重要,尤其是在移动设备、可穿戴设备、物联网(IoT)设备以及任何需要长时间运行而无需频繁充电或更换电池的应用中。低功耗设计不仅可以延长设备的......
  • STM32:STM32低功耗设计:低功耗设计的未来趋势与STM32新特性
    STM32:STM32低功耗设计:低功耗设计的未来趋势与STM32新特性STM32低功耗设计基础低功耗设计的重要性在当今的电子设备中,低功耗设计变得日益重要,尤其是在移动设备、物联网(IoT)设备和可穿戴技术中。低功耗设计不仅能够延长设备的电池寿命,减少充电频率,提高用户体验,还能降低设......
  • 字符串行转列 regexp_split_to_table
    在Greenplum数据库中,regexp_split_to_table是一个非常有用的函数,它允许你根据正则表达式将字符串分割成多个部分,并将这些部分作为表中的行返回。这个函数在处理文本数据时特别有用,尤其是当你需要将一个字段中的复合数据分解为独立的元素时。语法regexp_split_to_table(str......
  • Vue3组件通信详解
    Vue3中的组件通讯是Vue应用开发中非常重要的一环,它允许组件之间传递数据和方法,从而实现数据的共享和功能的调用。下面将分别介绍父子组件、孙子组件(祖孙组件)、兄弟组件之间的通讯方式,并给出示例代码和总结表格。一、父子组件通讯1.父传子(props)父组件通过props向子组......
  • 【信息论基础】信息路基础绪论——信息的概念,信息量和信息熵,数字通信系统模型
    1.、信息的定义:事物运动状态或存在方式的不确定状态(fromShannon)2、信息是有大小之分的。3、信息量(自信息)的计算如下:4、我们使用信息熵(informationentropy)这一概念来描述 信息的平均不确定度:(1)例1:对于一个信源的输出有x1~x8,对应的码字输出分别为000,001,010,011,100,10......
  • 进程间通信——消息队列(通俗易懂)
    消息队列概念消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺陷。消息队列包括POSIX消息队列和SystemV消息队列。消息队列是UNIX下不同进程之间实现共享资源的一种机制,UNIX......
  • MQTT揭秘:为什么它是物联网首选的通信协议
    MQTT协议简介概览MQTT是一种基于发布/订阅模式的轻量级消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用而设计,可以用极少的代码为联网设备提供实时可靠的消息服务。MQTT协议广泛应用于物联网、移动互联网、智能硬件、车联网、智慧城市、远程医疗、电力、石油与能源等领......
  • 局域网通信时,解决在一些设备上NsdManager发现服务失败的问题
    1.背景:Google提供了NsdManagerApi以支持局域网发现服务,但是在实际中,一些个别型号手机设备上,NsdManager发现服务失败,mdns解析失败,找不到对应的服务名称,进而无法解析出本地网络内的host和端口。可能存在的问题原因:1.1设备兼容性问题硬件限制:一些低端或较老的设备可......
  • 【北京迅为】《stm32mp157开发板嵌入式linux开发指南》第五章 Ubuntu使用apt-get下载
         iTOP-STM32MP157开发板是基于意法半导体STARM双Cortex-A7核加单Cortex-M4核的一款多核异构处理器。Cortex-A7内核提供对开源操作系统Linux的支持,借助Linux系统庞大而丰富的软件组件处理复杂应用。M4内核上运行对于实时性要求严格的应用。         开......
  • 进程间通信(信号灯集、消息队列)
    1.信号灯集线程:全局变量,同步通过信号量初始化:sem_init(&sem,0,0);申请资源:sem_wait(&sem);P操作,-1释放资源:sem_post(&sem);V操作,+11.1特点信号灯(semaphore),也叫信号量,信号灯集是一个信号灯的集合。它是不同进程间或一个给定进程内部不同线程间同步的机制;而Posi......