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);
}
代码解释
- 时钟使能:通过
__HAL_RCC_GPIOA_CLK_ENABLE()
和__HAL_RCC_USART1_CLK_ENABLE()
使能GPIOA和USART1的时钟。 - GPIO配置:设置GPIOA的9号引脚为推挽输出模式,用于发送数据;10号引脚为输入模式,用于接收数据。
- 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;
}
代码解释
- 发送函数:
SendChar
函数使用HAL_UART_Transmit
发送一个字符。参数&c
是指向字符的指针,1
表示发送1个字节,1000
是等待时间(单位:毫秒)。 - 接收函数:
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]);
}
}
}
代码解释
- 接收缓冲区:定义一个10字节的接收缓冲区
RxBuffer
和一个索引RxIndex
来跟踪接收到的数据。 - 中断服务例程:
USART1_IRQHandler
在接收到数据时被调用。使用__HAL_UART_GET_FLAG
检查接收数据寄存器是否非空,然后使用HAL_UART_Receive_IT
读取数据并存储到缓冲区中。 - 数据处理:当缓冲区满时,调用
ProcessReceivedData
函数处理接收到的数据。在这个例子中,数据被打印到串行监视器。
通过以上步骤,STM32可以有效地配置为异步串行通信模式,并能够发送、接收和处理数据。这为开发基于STM32的串行通信应用提供了坚实的基础。
同步串行通信实践
配置USART为同步模式
在STM32中,USART(通用同步/异步收发传输器)模块可以配置为同步串行通信模式。同步模式下,数据的发送和接收由外部时钟信号控制,这通常用于与外部设备进行通信,如ADC、DAC或其它微控制器,其中数据传输的时序需要严格控制。
配置步骤
- 时钟使能:首先,需要使能USART和GPIO的时钟。
- GPIO配置:配置USART的TX和RX引脚为复用推挽输出和输入模式。
- USART初始化:设置USART的工作模式为同步,配置波特率、数据位、停止位等。
- 使能同步时钟:通过设置USART_CR1寄存器中的UE位和M位,使能USART并进入同步模式。
- 配置同步时钟源:通过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_Send
和USART2_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的高级选项。通过设置WordLength
、StopBits
、Parity
和HwFlowCtl
参数,可以调整数据位长度、停止位长度、校验位类型和硬件流控制方式。这些配置可以根据具体的应用需求进行调整,以优化通信性能或满足特定的通信协议要求。
串行通信实例与调试
实现一个完整的串行通信实例
在STM32微控制器中,实现串行通信通常涉及到使用USART(通用同步/异步收发器)模块。下面,我们将通过一个具体的实例来展示如何在STM32上设置并使用USART进行串行通信。
硬件准备
- 确保STM32开发板上具有USART接口。
- 准备一个串口转USB适配器,用于连接STM32和PC。
- 连接TX和RX引脚:STM32的TX引脚连接到适配器的RX引脚,STM32的RX引脚连接到适配器的TX引脚。
软件配置
-
使用STM32CubeMX进行配置
打开STM32CubeMX,选择你的STM32芯片型号,然后在“Pinout & Configuration”窗口中,配置USART引脚和波特率。例如,选择USART2,设置波特率为9600。
-
生成代码
在STM32CubeMX中完成配置后,生成初始化代码。这将包括必要的头文件和初始化函数。
-
编写串行通信代码
// 包含必要的头文件 #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微控制器的初始化和配置。它简化了配置过程,允许用户通过直观的界面选择和配置外设。
步骤
-
选择STM32芯片
在STM32CubeMX的“Device Selection”窗口中,选择你的STM32芯片型号。
-
配置引脚
在“Pinout & Configuration”窗口中,选择USART2,然后配置其TX和RX引脚。通常,TX引脚是PA2,RX引脚是PA3。
-
设置USART参数
在“MCU Configuration”窗口中,设置USART的波特率、数据位、停止位、校验位等参数。
-
生成代码
完成配置后,点击“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