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

news2024/11/16 8:20:49

在本文中,我们将深入了解如何在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.coloradmin.cn/o/1284684.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

抓取Chrome所有版本密码

谷歌浏览器存储密码的方式 在使用谷歌浏览器时,如果我们输入某个网站的账号密码,他会自动问我们是否要保存密码,以便下次登录的时候自动填写账号和密码 在设置中可以找到登录账户和密码 也可以直接看密码,不过需要凭证 这其实是windows的DPAPI机制 DPAPI Data Protection Ap…

ESP32 freeRTOS笔记 参数传递、任务优先级

一、四种参数传递方式 1.1 整数传递 使用 (void *) 任何类型传递参数&#xff0c;通过地址传递给任务。 #include <stdio.h> #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h"void myTask(void *pvP…

leetcode算法之栈

目录 1.删除字符串中的所有相邻重复项2.比较含退格的字符串3.基本计算器II4.字符串解码5.验证栈序列 1.删除字符串中的所有相邻重复项 删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {string ret;//使用数组模拟栈操作for(auto …

element的el-date-picker时间控件,限制选择范围区间天数并且当前之后的日期不可选

element的el-date-picker时间控件&#xff0c;限制选择范围区间天数并且当前之后的日期不可选 HTML部分代码 <el-date-pickerv-model"dateRange"type"datetimerange"value-format"yyyy-MM-dd HH:mm:ss"range-separator"至"start-p…

Python小案例:打印10以内的素数

解析 1、利用循环控制范围&#xff08;1,100&#xff09; 2、通过循环判断素数 3、利用标记法进行打印素数 代码 #求1——100之间的素数 for i in range(2,101):is_primeNum Truefor j in range(2,i):if i%j 0:# print(f"{i}不是素数")is_primeNum Falseif is_…

3D Web可视化平台助力Aras开发PLM系统:提供数据访问、可视化和发布功能

HOOPS中文网慧都科技是HOOPS全套产品中国地区指定授权经销商&#xff0c;提供3D软件开发工具HOOPS售卖、试用、中文试用指导服务、中文技术支持。http://techsoft3d.evget.com/ Aras是一个面向数字化工业应用的开放性平台&#xff0c;帮助世界领先的复杂互联产品制造商转变其产…

文字处理工具Word mac软件特点

Microsoft Word mac是一款文字处理软件。它是 Microsoft office 套件的一部分&#xff0c;已广泛用于创建、编辑和格式化文本文档。 Word mac软件特点 改进的协作工具&#xff1a;使用 Microsoft Word 2021&#xff0c;多个用户可以同时处理一个文档&#xff0c;从而更轻松地与…

(华为)网络工程师教程笔记(网工教程)网工入门——3、静态路由路由表的配置

参考文章&#xff1a;【全236集】网络工程师从基础入门到进阶必学教程&#xff01;通俗易懂&#xff0c;2023最新版&#xff0c;学完即可就业&#xff01;网工入门_华为认证_HCIA_HCIP_数据通信_网工学习路线 文章目录 13. 网工入门10-静态路由&#xff08;路由表的配置&#x…

STM32通用定时器

本文实践&#xff1a;实现通过TIM14_CH1输出PWM&#xff0c;外部显示为呼吸灯。 通用定时器简介 拥有TIM2~TIM5、TIM9~TIM14 一共10个定时器&#xff0c;具有4路独立通道&#xff0c;可用于输入捕获、输出比 较&#xff0c;同时包含了基本定时去的所有功能。 通用定时器的结…

Educational Codeforces Round 159 (Rated for Div. 2)(B 二分贪心 Cgcd D二分+前缀和 E字典树)

A - Binary Imbalance 有只要在01之间插入就能制造无限个0&#xff0c;没有0就统计0 1个数即可 #include<bits/stdc.h> using namespace std; const int N 110010,mod998244353; #define int long long typedef long long LL; typedef pair<int, int> PII; const…

java学习part34collect和map

153-集合框架-数组的特点、弊端与集合框架体系介绍_哔哩哔哩_bilibili 1.以前的数组 2.常用 3.Collection add只能加object&#xff0c;如果有基本类型会装箱 3.2集合和数组转换 3.3往集合添加对象的注意事项 4.迭代器 容易越界 一般不用 常用好用 5.for each 类似c的for( …

vue3 vue-router编程式导航(二)

文章目录 一、跳转到指定路径1. query传参2. Params传参 二、前进/后退三、替换当前页 Vue Router提供了强大且灵活的编程式导航功能&#xff0c;能够通过代码来控制路由的切换和跳转。本篇博客将介绍如何在Vue 3应用程序中使用Vue Router进行编程式导航。 一、跳转到指定路径…

Proteus仿真--基于51单片机的DS18B20温度采集及报警

本文介绍基于DS18B20温度采集及报警的仿真设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 其中温度传感器选用DS18B20器件&#xff0c;主要用于获取温度数据并上传&#xff0c;温度显示选用数码管&#xff0c;报警模块选用蜂鸣器 仿真运行视频 Pr…

pip命令详解

pip命令介绍 pip是由Ian Bicking在2008年提出的&#xff0c;他将pyinstall重命名为pip。名称pip是首字母缩写词&#xff0c;全称为“Package Installer for Python”。自Python3的3.4版本以及Python2的2.7.9版本开始&#xff0c;pip被直接包括在Python的安装包内&#xff0c;成…

SpringBoot系列之使用Redis ZSet实现排序分页

软件环境&#xff1a; JDK 1.8 SpringBoot 2.2.1 Maven 3.2 Mysql 8.0.26 spring-boot-starter-data-redis 2.2.1 jedis3.1.0 开发工具 IntelliJ IDEA smartGit 实现思路 相对于set来说&#xff0c;sorted set是一种有序的set&#xff0c;排序是根据每个元素的score…

云原生之深入解析如何限制Kubernetes集群中文件描述符与线程数量

一、背景 linux 中为了防止进程恶意使用资源&#xff0c;系统使用 ulimit 来限制进程的资源使用情况&#xff08;包括文件描述符&#xff0c;线程数&#xff0c;内存大小等&#xff09;。同样地在容器化场景中&#xff0c;需要限制其系统资源的使用量。ulimit: docker 默认支持…

【Vue】使用 Vue CLI 脚手架创建 Vue 项目(使用命令行创建)

前言 在开始使用Vue进行开发之前&#xff0c;我们需要先创建一个Vue项目。Vue CLI&#xff08;Command Line Interface&#xff09;是一个官方提供的脚手架工具&#xff0c;可以帮助我们快速创建Vue项目。 步骤 打开终端或命令行工具&#xff0c;运行以下命令&#xff1a; vu…

传输层可靠传输的原理

目录 1.停止等待协议 2.连续ARQ协议 3.TCP报文段的首部格式 4.TCP的滑动窗口机制 &#xff08;1&#xff09;发送窗口 &#xff08;2&#xff09;接收窗口 &#xff08;3&#xff09;发送缓存 5.超时重传时间的选择 6.选择确认SACK(Selective ACK) 7.使用滑动窗口实现…

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

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

基于Docker构建Python开发环境

1. Dockerfile dockerfile所在目录结构 FROM python:3.8 WORKDIR /leo RUN apt-get install -y wget RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai >/etc/timezone # ssh免密登录 COPY id_rsa.pub /leo RUN mkdir ~/.s…