使用UART和USART在STM32上进行双向通信

在本文中,我们将深入了解如何在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/218208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

01_W5500简介

目录 W5500简介: 芯片特点: 全硬件TCPIP协议栈: 引脚分布: W5500简介: W5500是一款高性价比的以太网芯片,其全球独一无二的全硬件TCPIP协议栈专利技术,解决了嵌入式以太网的接入问题,简单易用&#xff…

redis 安装在liunx安装和常用文件配置

文章目录 安装配置文件设置测试启动服务连接服务 安装 1.官网下载压缩包: https://redis.io/download/ 2.将压缩包上传到Linux环境中 解压: tar -xvf redis-xxxxx 3.liunx 需要c的环境 yum -y install gcc-c4.进入redis文件夹 make && make install5.推荐不是必须…

CPP-SCNUOJ-Problem P24. [算法课贪心] 跳跃游戏

Problem P24. [算法课贪心] 跳跃游戏 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标。 输入 输入一行数组nums 输出 输出true/fasle 样例 标准输入 2 3 1 …

spring cloud 整合Feign经行远程调用

文章目录 Feign远程调用Feign替代RestTemplate1)引入依赖2)添加注解3)编写Feign的客户端4)测试5)总结 自定义配置配置文件方式Java代码方式 Feign使用优化 Feign远程调用 先来看我们以前利用RestTemplate发起远程调用…

GORM 多对多many2many 自定义连接表

文章目录 多对多 many2many表结构搭建多对多添加多对多查询多对多的删除、更新 自定义连接表生成表结构操作案例添加文章并添加标签,并自动关联添加文章,关联已有标签给已有文章关联标签替换已有文章的标签查询文章列表,显示标签 自定义连接…

陀螺仪LSM6DSV16X与AI集成(2)----姿态解算

陀螺仪LSM6DSV16X与AI集成.2--姿态解算 概述视频教学样品申请完整代码下载欧拉角万向节死锁四元数法姿态解算双环PI控制器偏航角陀螺仪解析代码上位机通讯加速度演示陀螺仪工作方式主程序演示 概述 LSM6DSV16X包含三轴陀螺仪与三轴加速度计。 姿态有多种数学表示方式&#xff…

TCL - 库编译过程和官方手册

文章目录 TCL - 库编译过程和官方手册概述笔记编译步骤TCL官方手册END TCL - 库编译过程和官方手册 概述 想看看sqlite3的官方demo工程, 没看到. 想编译一下sqlite3源码, 看看编译后有没有example 工程. 看了sqlite3的官方说明, 他们工程使用tcl来编译的. 一听tcl, 咋这么耳熟…

Ribbon 负载均衡

1、负载均衡整体流程 2、负载均衡流程逐级跟踪运行 (1) LoadBlanced 注解可以使LoadBalancerInterceptor拦截到; (2)LoadBalancerInterceptor 实现了ClientHttpRequestInterceptor接口; (3)ClientHttpRequestInterceptor接口释义如下; (4)int…

k8s引用环境变量

一 定义环境变量 ① 如何在k8s中定义环境变量 env、configmap、secret补充: k8s 创建Service自带的环境变量 ② 从pod属性中获取 kubectl explain deploy.spec.template.spec.containers.env.valueFrom关注: configMapKeyRef、fieldRef 和 resour…

zxjy003- Spring Cloud后端工程搭建

一、创建父工程 1、创建 sprigboot 工程 guli-parent groupId : com.atguigu artifactId : guli-parent

RK3568平台开发系列讲解(Linux系统篇)device_node 转换成 platform_device

🚀返回专栏总目录 文章目录 一、DTB转换规则二、转换源码分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍通过设备树 device_node 转换成 platform_device 一、DTB转换规则 device 部分是用 platform_device 结构体来描述硬件资源的, 所以内核最终会将…

【设计模式-3.1】结构型——外观模式

说明:本文介绍设计模式中结构型设计模式中的,外观模式; 亲手下厨还是点外卖? 外观模式属于结构型的设计模式,关注类或对象的组合,所呈现出来的结构。以吃饭为例,在介绍外观模式之前&#xff0…

蓝桥杯网络安全组竞赛

竞赛规则及说明 选拔赛时长:4h 决赛时长:4h 竞赛形式:线上比赛: 个人赛:一人一机,全程机考 大赛制定竞赛系统,在时间内提交答案到比赛系统,超时无法提交 机器环境: 电脑…

matplotlib多子图

matplotlib画图中一个轴占据多个子图 - 知乎 import matplotlib.pyplot as plt fig plt.figure() gs fig.add_gridspec(2,4) ax1 fig.add_subplot(gs[0, 0:2]) ax2 fig.add_subplot(gs[0, 2:]) axa fig.add_subplot(gs[1, 1]) axb fig.add_subplot(gs[1, 2]) axc fig.add…

编写Java应用程序,输出满足1+2+3+……+n<8888的最大正整数n。

源代码: public class Main { public static void main(String[] args) { int i 1; int sum 0; for(i 1;;i){ sum i; if (sum >8888) break; } System.out.println(i-1); } } 实验运行截图:

隐写术和人工智能

在一项新的研究中,人工智能对齐研究实验室 Redwood Research 揭示了大型语言模型 (LLM) 可以掌握“编码推理”,这是一种隐写术形式。 这种有趣的现象使得大型语言模型能够以人类读者无法理解的方式巧妙地将中间推理步骤嵌入到生成的文本中。 大型语言…

【滤波第二期】中值滤波的原理和C代码

中值滤波是一种非线性数字滤波技术,主要应用于信号处理和图像处理领域,用于减小信号中的噪声和离群值。中值滤波的核心思想是通过计算一组数据点的中间值,以抑制脉冲噪声等离群值的影响,从而实现信号的平滑处理。 1,中…

SaToken利用Redis做持久化

官网解释 官网解释 教程 引入依赖 <!-- 提供Redis连接池 --> <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId> </dependency><!-- Sa-Token 整合 Redis &#xff08;使用 jdk 默认序…

QT使用SQLite(打开db数据库以及对数据库进行增删改查)

QTSQLite 在QT中使用sqlite数据库&#xff0c;有多种使用方法&#xff0c;在这里我只提供几种简单&#xff0c;代码简短的方法&#xff0c;包括一些特殊字符处理。 用SQlite建立一个简单学生管理数据库 数据库中有两个表一个是class和student。 class表结构 student表结果…

GitHub Copilot试用指南

GitHub Copilot试用指南 首先读这个文档&#xff0c;按照步骤开启30天的试用&#xff1a;管理个人帐户的 GitHub Copilot 订阅 然后读这个文档&#xff1a;使用 IDE 中的 GitHub Copilot 聊天 &#xff0c;在你习惯使用的IDE中配置copilot&#xff0c;暂时好像只支持jetbrai…
最新文章