在本文中,我们将深入了解如何在STM32上使用UART(通用异步收发传输器)和USART(通用同步异步收发传输器)实现双向通信。UART和USART是常见的串口通信协议,通常用于与其他设备进行数据传输。我们将重点介绍如何配置UART和USART外设,以及如何在STM32中实现双向通信。
首先,我们需要选择适当的引脚,并在STM32的引脚配置中进行设置。假设我们选择了UART1和USART1,并将它们连接到两个不同的外部设备。下面是配置引脚的代码示例:
```c
// 引脚配置
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置UART引脚
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置USART引脚
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_UART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
```
在上述代码中,我们启用了GPIOA的时钟,并将引脚9和引脚10设置为UART1的引脚。我们将引脚2和引脚3设置为USART1的引脚。这些引脚配置具体取决于你所选择的UART和USART外设以及引脚的可用性。
接下来,我们需要配置UART和USART外设,以使它们可以进行数据传输。我们分别配置UART1和USART1的示例代码如下:
```c
// UART配置
UART_HandleTypeDef huart1 = {0};
// 使能UART时钟
__HAL_RCC_USART1_CLK_ENABLE();
// 配置UART
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;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
// 初始化错误处理
Error_Handler();
}
// USART配置
USART_HandleTypeDef husart1 = {0};
// 使能USART时钟
__HAL_RCC_USART1_CLK_ENABLE();
// 配置USART
husart1.Instance = USART1;
husart1.Init.BaudRate = 115200;
husart1.Init.WordLength = USART_WORDLENGTH_8B;
husart1.Init.StopBits = USART_STOPBITS_1;
husart1.Init.Parity = USART_PARITY_NONE;
husart1.Init.Mode = USART_MODE_TX_RX;
husart1.Init.CLKPolarity = USART_POLARITY_LOW;
husart1.Init.CLKPhase = USART_PHASE_1EDGE;
husart1.Init.CLKLastBit = USART_LASTBIT_DISABLE;
if (HAL_USART_Init(&husart1) != HAL_OK)
{
// 初始化错误处理
Error_Handler();
}
```
在上述代码中,我们先分别启用了UART1和USART1的时钟。然后,我们对它们进行了相应的配置。对于UART1,我们设置了波特率为9600,字长为8位,停止位为1,无奇偶校验。我们使能了发送和接收模式,同时禁用了硬件流控制。对于USART1,我们设置了波特率为115200,字长为8位,停止位为1,无奇偶校验。我们使能了发送和接收模式,设置了时钟极性和时钟相位,同时禁用了最后一位时钟。
现在,我们已经成功配置了UART和USART的引脚和外设参数。我们可以使用HAL库提供的函数来发送和接收数据。下面是通过UART和USART进行数据传输的代码示例:
```c
// UART发送数据
uint8_t uart_data_to_send[10] = "Hello UART!";
HAL_UART_Transmit(&huart1, uart_data_to_send, 11, HAL_MAX_DELAY);
// UART接收数据
uint8_t uart_data_received[10];
HAL_UART_Receive(&huart1, uart_data_received, 10, HAL_MAX_DELAY);
// USART发送数据
uint8_t usart_data_to_send[10] = "Hello USART!";
HAL_USART_Transmit(&husart1, usart_data_to_send, 12, HAL_MAX_DELAY);
// USART接收数据
uint8_t usart_data_received[10];
HAL_USART_Receive(&husart1, usart_data_received, 10, HAL_MAX_DELAY);
```
在以上代码中,我们通过HAL_UART_Transmit和HAL_UART_Receive函数分别对UART进行发送和接收数据。通过HAL_USART_Transmit和HAL_USART_Receive函数分别对USART进行发送和接收数据。我们通过传递发送缓冲区的指针、数据长度以及最大延迟时间来实现数据的发送和接收。
最后,我们需要处理可能发生的错误。例如,如果在发送或接收期间发生了错误,我们可以使用回调函数来处理它们(与前面的文章中提到的错误回调函数类似)。
以上是使用UART和USART在STM32上进行双向通信的一个简单示例。通过适当的引脚配置和外设参数设置,我们可以轻松实现双向通信,并进行数据的发送和接收。
【代码】:
完整的代码示例如下:
```c
#include "stm32f4xx_hal.h"
// 错误处理函数
void Error_Handler(void)
{
while (1)
{
// 错误处理
}
}
// UART错误回调函数
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
// 处理UART错误
Error_Handler();
}
}
// USART错误回调函数
void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart)
{
if (husart->Instance == USART1)
{
// 处理USART错误
Error_Handler();
}
}
int main(void)
{
// 引脚配置
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置UART引脚
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置USART引脚
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_UART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// UART配置
UART_HandleTypeDef huart1 = {0};
// 使能UART时钟
__HAL_RCC_USART1_CLK_ENABLE();
// 配置UART
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;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
// 初始化错误处理
Error_Handler();
}
// USART配置
USART_HandleTypeDef husart1 = {0};
// 使能USART时钟
__HAL_RCC_USART1_CLK_ENABLE();
// 配置USART
husart1.Instance = USART1;
husart1.Init.BaudRate = 115200;
husart1.Init.WordLength = USART_WORDLENGTH_8B;
husart1.Init.StopBits = USART_STOPBITS_1;
husart1.Init.Parity = USART_PARITY_NONE;
husart1.Init.Mode = USART_MODE_TX_RX;
husart1.Init.CLKPolarity = USART_POLARITY_LOW;
husart1.Init.CLKPhase = USART_PHASE_1EDGE;
husart1.Init.CLKLastBit = USART_LASTBIT_DISABLE;
if (HAL_USART_Init(&husart1) != HAL_OK)
{
// 初始化错误处理
Error_Handler();
}
// UART发送数据
uint8_t uart_data_to_send[15] = "Hello UART!";
HAL_UART_Transmit(&huart1, uart_data_to_send, strlen(uart_data_to_send), HAL_MAX_DELAY);
// UART接收数据
uint8_t uart_data_received[15];
HAL_UART_Receive(&huart1, uart_data_received, 14, HAL_MAX_DELAY);
// USART发送数据
uint8_t usart_data_to_send[15] = "Hello USART!";
HAL_USART_Transmit(&husart1, usart_data_to_send, strlen(usart_data_to_send), HAL_MAX_DELAY);
// USART接收数据
uint8_t usart_data_received[15];
HAL_USART_Receive(&husart1, usart_data_received, 14, HAL_MAX_DELAY);
while (1)
{
// 主循环
}
}
```
以上是一个简单的例子,介绍了如何使用UART和USART在STM32上进行双向通信。你可以根据实际需求进行修改和扩展。
嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击这里,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦。
点击链接扫码进入嵌入式交流群 https://fss.mpay8.cn/article/dmrjinh2C6fjejm