stm32中分析UART中IDLE,RXNE,TC,TXE这些标志位的作用

下面将基于 STM32 标准库,结合之前提到的不同应用场景,给出使用 TXETCIDLE 和 RXNE 标志位的代码示例及分析。

1. 连续数据发送(使用 TXE

应用场景

向外部设备连续发送大量数据,如向显示屏发送显示数据、向传感器发送配置指令序列等。

代码示例
#include "stm32f10x.h"void USART1_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 使能 USART1 和 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA9 为复用推挽输出(TX)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART1USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);// 使能 USART1USART_Cmd(USART1, ENABLE);
}void USART1_SendString(const char* str) {while (*str) {// 等待发送数据寄存器为空while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);// 写入新的数据USART_SendData(USART1, (uint8_t)*str++);}
}int main(void) {USART1_Configuration();const char* message = "Hello, World!";USART1_SendString(message);while (1) {// 主循环}
}
代码分析
  • USART1_Configuration 函数:
    • 使能 USART1 和 GPIOA 的时钟。
    • 配置 PA9 为复用推挽输出,用于 USART1 的发送功能。
    • 初始化 USART1,设置波特率为 115200,数据位为 8 位,停止位为 1 位,无校验位,无硬件流控制,仅使能发送模式。
    • 使能 USART1。
  • USART1_SendString 函数:
    • 使用 USART_GetFlagStatus 函数检查 TXE 标志位,当该标志位为 SET 时,表示发送数据寄存器为空。
    • 使用 USART_SendData 函数将字符串中的字符依次发送出去。
  • main 函数:
    • 调用 USART1_Configuration 函数初始化 USART1。
    • 调用 USART1_SendString 函数发送字符串 "Hello, World!"。

2. 数据发送完成确认(使用 TC

应用场景

在对数据完整性要求较高的场景中,确保整个数据帧完整无误地发送到目标设备。

代码示例
#include "stm32f10x.h"void USART1_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 使能 USART1 和 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA9 为复用推挽输出(TX)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART1USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);// 使能 USART1USART_Cmd(USART1, ENABLE);
}void USART1_SendDataAndWaitComplete(uint8_t data) {// 等待发送数据寄存器为空while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);// 写入数据USART_SendData(USART1, data);// 等待发送完成while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}int main(void) {USART1_Configuration();uint8_t command = 0xAA;USART1_SendDataAndWaitComplete(command);while (1) {// 主循环}
}
代码分析
  • USART1_Configuration 函数:与连续数据发送场景中的配置函数相同。
  • USART1_SendDataAndWaitComplete 函数:
    • 先使用 USART_GetFlagStatus 函数检查 TXE 标志位,当该标志位为 SET 时,将数据写入 DR 寄存器。
    • 然后使用 USART_GetFlagStatus 函数检查 TC 标志位,当该标志位为 SET 时,表示整个数据帧发送完成。
  • main 函数:
    • 调用 USART1_Configuration 函数初始化 USART1。
    • 调用 USART1_SendDataAndWaitComplete 函数发送一个字节的命令 0xAA

3. 数据帧边界识别(使用 IDLE

应用场景

接收不定长的数据帧,如从传感器接收实时数据、从其他设备接收通信协议数据等。

代码示例
#include "stm32f10x.h"
#include <stdio.h>#define BUFFER_SIZE 256
uint8_t rx_buffer[BUFFER_SIZE];
uint8_t rx_index = 0;void USART1_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 使能 USART1 和 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA10 为浮空输入(RX)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART1USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx;USART_Init(USART1, &USART_InitStructure);// 使能 USART1 的 IDLE 中断USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);// 配置 NVICNVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 使能 USART1USART_Cmd(USART1, ENABLE);
}void USART1_IRQHandler(void) {if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) {// 清除 IDLE 标志位USART_ClearITPendingBit(USART1, USART_IT_IDLE);uint8_t temp = USART_ReceiveData(USART1); // 读取数据以清除 IDLE 标志// 处理一帧数据接收完成事件// 这里简单打印接收到的数据长度printf("Received %d bytes of data.\n", rx_index);// 清空缓冲区和索引rx_index = 0;} else if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {// 读取接收缓冲区的数据rx_buffer[rx_index++] = USART_ReceiveData(USART1);// 清除 RXNE 标志位USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}int main(void) {USART1_Configuration();while (1) {// 主循环}
}
代码分析
  • USART1_Configuration 函数:
    • 使能 USART1 和 GPIOA 的时钟。
    • 配置 PA10 为浮空输入,用于 USART1 的接收功能。
    • 初始化 USART1,设置波特率为 115200,数据位为 8 位,停止位为 1 位,无校验位,无硬件流控制,仅使能接收模式。
    • 使能 USART1 的 IDLE 中断,并配置 NVIC。
    • 使能 USART1。
  • USART1_IRQHandler 函数:
    • 当 IDLE 中断发生时,使用 USART_ClearITPendingBit 函数清除 IDLE 标志位,读取数据以彻底清除该标志。处理接收到的数据(这里简单打印数据长度),并清空缓冲区和索引。
    • 当 RXNE 中断发生时,将接收到的数据存入缓冲区,并清除 RXNE 标志位。
  • main 函数:
    • 调用 USART1_Configuration 函数初始化 USART1。
    • 进入主循环等待中断。

4. 实时数据接收(使用 RXNE

应用场景

实时处理接收到的数据,如实时监测传感器数据、接收外部设备的控制指令等。

代码示例
#include "stm32f10x.h"void USART1_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 使能 USART1 和 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA10 为浮空输入(RX)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART1USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx;USART_Init(USART1, &USART_InitStructure);// 使能 USART1 的 RXNE 中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 配置 NVICNVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);// 使能 USART1USART_Cmd(USART1, ENABLE);
}void USART1_IRQHandler(void) {if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {uint8_t data = USART_ReceiveData(USART1); // 读取接收缓冲区的数据// 简单处理接收到的数据,这里假设点亮一个 LEDif (data == '1') {GPIO_SetBits(GPIOA, GPIO_Pin_0);  // 点亮 PA0} else if (data == '0') {GPIO_ResetBits(GPIOA, GPIO_Pin_0);  // 熄灭 PA0}// 清除 RXNE 标志位USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}int main(void) {// 使能 GPIOA 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA0 为推挽输出GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART1_Configuration();while (1) {// 主循环}
}
代码分析
  • USART1_Configuration 函数:
    • 使能 USART1 和 GPIOA 的时钟。
    • 配置 PA10 为浮空输入,用于 USART1 的接收功能。
    • 初始化 USART1,设置波特率为 115200,数据位为 8 位,停止位为 1 位,无校验位,无硬件流控制,仅使能接收模式。
    • 使能 USART1 的 RXNE 中断,并配置 NVIC。
    • 使能 USART1。
  • USART1_IRQHandler 函数:
    • 当 RXNE 中断发生时,使用 USART_ReceiveData 函数读取接收缓冲区的数据。
    • 根据接收到的数据内容,控制 PA0 引脚的电平,实现点亮或熄灭 LED 的功能。
    • 使用 USART_ClearITPendingBit 函数清除 RXNE 标志位。
  • main 函数:
    • 使能 GPIOA 时钟,配置 PA0 为推挽输出。
    • 调用 USART1_Configuration 函数初始化 USART1。
    • 进入主循环等待中断。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 题目 解析代码 题目 解析 首先先让所有的f&#xff08;i&#xff09;i&#xff0c;即每个人最开始的祖先都是自己&#xff0c;然后就每一次都让轮到那个数的父亲1&#xff0c;第二次出现的时候就直接用父亲替换掉 并查集适用场景 …

GitHub上传项目

总结&#xff08;有基础的话直接执行这几步&#xff0c;就不需要再往下看了&#xff09;&#xff1a; git init 修改git的config文件&#xff1a;添加:[user]:name你的github用户名 email你注册github的用户名 git branch -m master main git remote add origin 你的URL gi…

关于Windows输入法切换的一些总结

语言和键盘的关系&#xff08;第一层是语言 语言下一层是键盘&#xff09; 如下图&#xff1a;语言就是 中文 英文 阿拉伯文之类的 键盘就是 语言中文下的&#xff1a;XX输入法 语言的切换 和 键盘&#xff08;输入法&#xff09;的切换 &#xff08;用windos空格 可以切换…

C# Unity 唐老狮 No.7 模拟面试题

本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: 全部 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho 如果你发现了文章内特殊的字体格式,…

搜广推校招面经三十九

小红书&#xfe63;图搜 一、两个整数的汉明距离 两个整数之间的汉明距离是指这两个数字对应二进制位相同位置不同的个数。换句话说&#xff0c;它就是将一个整数变成另一个整数所需要改变的二进制位的数量。例如&#xff0c;如果两个整数在它们的二进制表示中有三个位置上的…

conda list <package> 指令输出的build和channel含义

Build&#xff1a;表示当前安装包的 构建版本&#xff0c;即该包的编译、构建、发布的具体版本。通常包含一些额外的标识&#xff0c;帮助你区分同一包的不同版本。 Channel&#xff1a; 表示该包的 来源渠道&#xff0c;即该包是从哪个 Anaconda 仓库&#xff08;频道&#…

Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置

截止 2025/3/9 &#xff0c;版本更新到了 3.29.1 &#xff0c;但是为了防止出现一些奇怪的bug&#xff0c;我安装的还是老一点的&#xff0c;3.19&#xff0c;其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量&#xff08;Windows&#xff09; PUB_H…

Linux系统编程--线程同步

目录 一、前言 二、线程饥饿 三、线程同步 四、条件变量 1、cond 2、条件变量的使用 五、条件变量与互斥锁 一、前言 上篇文章我们讲解了线程互斥的概念&#xff0c;为了防止多个线程同时访问一份临界资源而出问题&#xff0c;我们引入了线程互斥&#xff0c;线程互斥其实…

学习小程序开发--Day1

项目学习开篇 项目架构 项目进程 创建uni-app项目 通过HBuilderX创建 小结 page.json 和 tabBar 目录文件 pages.json的配置

在word下写公式

需求 word的可视化编辑公式是好的&#xff0c;但是很丑&#xff08;见下图&#xff09; 我希望公式是这样的&#xff08;见下图&#xff09; 解决方案 1.先转换为“线性”&#xff08;即Latex格式&#xff09; 2.得到下面这个玩意&#xff0c;把\mathrm去掉&#xff08;功能是…

uniapp,自绘仪表盘组件(基础篇)

文章目录 一、为什么需要自绘仪表盘&#xff1f;二、准备知识三、实现基础仪表盘1. 组件模板结构2. 核心绘制逻辑3. 样式优化 四、使用示例五、核心实现原理六、扩展方向七、常见问题 一、为什么需要自绘仪表盘&#xff1f; 在物联网、数据监控等场景中&#xff0c;仪表盘是常…

导入 Excel 规则批量修改或删除 Excel 表格内容

我们前面介绍过按照规则批量修改 Excel 文档内容的操作&#xff0c;可以对大量的 Excel 文档按照一定的规则进行统一的修改&#xff0c;可以很好的解决我们批量修改 Excel 文档内容的需求。但是某些场景下&#xff0c;我们批量修改 Excel 文档内容的场景比较复杂&#xff0c;比…

Python贝壳网二手小区数据爬取(2025年3月更)

文章目录 一、代码整体架构解析二、各部分代码详解1. main()主函数解析2. 会话初始化&#xff08;伪装浏览器身份&#xff09;3. 动态参数生成&#xff08;反爬虫核心机制&#xff09;4. 列表页抓取&#xff08;获取小区列表&#xff09;5. 列表页解析&#xff08;提取小区信息…

C++的内存管理

1. C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int…

mac本地代理nginx,解决跨域问题

brew install nginxbrew info nginxnginx配置文件 /opt/homebrew/etc/nginx/nginx.conf 如何打开呢&#xff1f; open /opt/homebrew 启动nginx brew services start nginx改配置&#xff1a; server {listen 8080;server_name localhost;#charset koi8-r;#access_…

Clion快捷键、修改字体

文章目录 一、Clion快捷键1.撤销&#xff1a;crtl Z2.重做&#xff1a;crtl shift Z3.删除该行&#xff1a;crtl Y4.多行后退&#xff1a;选中多行 Tab5.多行缩进&#xff1a;选中多行 shift Tab 二、修改注释的斜体 一、Clion快捷键 1.撤销&#xff1a;crtl Z 2.重做…

【漫话机器学习系列】126.多项式回归(Polynomial Regression)

多项式回归&#xff08;Polynomial Regression&#xff09; 1. 什么是多项式回归&#xff1f; 多项式回归&#xff08;Polynomial Regression&#xff09;是一种用于建模非线性关系的回归分析技术。它是线性回归的一种扩展形式&#xff0c;允许模型通过增加自变量的高次项来更…

python网络爬虫开发实战之基本库使用

目录 第二章 基本库的使用 2.1 urllib的使用 1 发送请求 2 处理异常 3 解析链接 4 分析Robots协议 2.2 requests的使用 1 准备工作 2 实例引入 3 GET请求 4 POST请求 5 响应 6 高级用法 2.3 正则表达式 1 实例引入 2 match 3 search 4 findall 5 sub 6 com…

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。

1、在 vscode 终端执行 get-ExecutionPolicy 返回 Restricted 状态是禁止的 返回 RemoteSigned 状态是可正常执行npm命令 2、更改状态 set-ExecutionPolicy RemoteSigned 如果提示需要管理员权限&#xff0c;可加参数运行 Set-ExecutionPolicy -Scope CurrentUser RemoteSi…

数据结构基础之《(19)—矩阵处理》

一、zigzag打印矩阵 Z字形打印矩阵 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 打印顺序&#xff1a;1,2,7,13,8,3,4,9,14... 核心技巧&#xff1a;找到coding上的宏观调度 左上角有A、B两个点&#xff0c;A往右一步一步走&#xff0c;B往下一步一步走 写一个…