嵌入式MCU面试笔记2
目录
串口通信
概论
原理
配置
HAL库代码
1. 初始化函数
2. 数据发送和接收函数
3. 中断和DMA函数
4. 中断服务函数
串口通信
概论
我们知道,通信桥接了两个设备之间的交流。一个经典的例子就是使用串口通信交换上位机和单片机之间的数据。
比较常见的串口通信协议是下面这两个:
UART(通用异步收发传输器,Universal Asynchronous Receiver/Transmitter):这里可以看到,这样的协议只有Asynchronous,提示你这个协议是异步的。异步通信,需要在传递数据的同时,添加起始位、停止位、校验位等进行帧同步放置进行数据裁剪和区分。
USART(通用同步异步收发传输器)则更进一步,支持了同步的通信方式在同步模式下,USART通过时钟信号与从设备同步数据传输,在异步模式下工作与UART相似。
原理
本质上,就是数据通过数据线移动,从一个设备传递到另一个设备。在串口通信中,这是通过移位寄存器移位实现的。移出去的位被派发到传输线上传递出去,给下一个移进来的比特腾出来位置。对于接受的设备,那就是接受到来的比特,给下一个到来的比特腾出位置。

仔细看,这里的移位寄存器示意图就是在移动将它发送到TX端上从数据线上流出去,另一端如果有来者,则从RX端进入接收移位寄存器进来。
配置
上面的笼统概述没有统一问题:咋个长度?咋个校验?收发速度如何?不讨论这些问题,双方无法保证数据的接受和发送是一一呼应的,极易导致数据接受和发送异常。所以就有了协议,协议约定了两者的动作。
-
波特率,串口通信的速率,一般需要配置波特率寄存器实现。其计算公式是:
-
空闲,一般为高电平
-
起始位,标志一个数据帧的开始,固定为低电平。当数据开始发送时,产生一个下降沿。(空闲–>起始位)
-
数据位,发送数据帧,1为高电平,0为低电平。低位先行。 比如 发送数据帧0x0F 在数据帧里就是低位线性 即 1111 0000
-
校验位,用于数据验证,根据数据位的计算得来。有奇校验,偶校验和无校验。
奇校验(Odd Parity):确保数据帧中1的数量为奇数。 偶校验(Even Parity):确保数据帧中1的数量为偶数。
-
停止位,用于数据的间隔,固定为高电平。数据帧发送完成后,产生一个上升沿。(数据传输–>停止位)
HAL库代码
1. 初始化函数
-
HAL_UART_Init()
这个函数一般如果使用CubeMx配置的话就会给你写好了,它用于初始化UART外设,包括波特率、数据位、停止位、奇偶校验和硬件流控制。通常在程序开始时调用此函数,以配置UART通信的基本参数。
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
参数说明:
-
huart:指向UART句柄的指针,句柄包含了UART的所有配置参数,如波特率、数据位、停止位等。
返回值:
-
HAL_OK:初始化成功。 -
HAL_ERROR:初始化失败。
使用示例:
UART_HandleTypeDef huart1; 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);
-
2. 数据发送和接收函数
-
HAL_UART_Transmit()
用于通过UART发送数据。此函数可以在阻塞模式、非阻塞模式或中断模式下工作。
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向要发送的数据的指针。 -
Size:要发送的数据字节数。 -
Timeout:超时时间,单位为毫秒。
返回值:
-
HAL_OK:数据发送成功。 -
HAL_ERROR:发送失败。
使用示例:
uint8_t msg[] = "Hello UART!"; HAL_UART_Transmit(&huart1, msg, sizeof(msg)-1, 1000);
-
-
HAL_UART_Receive()
用于从UART接收数据。该函数也可以在阻塞模式、非阻塞模式或中断模式下工作。
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向接收数据的缓冲区。 -
Size:要接收的数据字节数。 -
Timeout:超时时间,单位为毫秒。
返回值:
-
HAL_OK:数据接收成功。 -
HAL_ERROR:接收失败。
使用示例:
uint8_t receivedData[10]; HAL_UART_Receive(&huart1, receivedData, 10, 1000);
-
3. 中断和DMA函数
-
HAL_UART_Transmit_IT()
这种方式就是异步的,执行完这个函数只是委托函数开始转发,程序流继续执行。用于通过中断方式发送数据。当数据发送完成时,会触发中断。
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向要发送的数据的指针。 -
Size:要发送的数据字节数。
返回值:
-
HAL_OK:数据发送任务已启动。 -
HAL_ERROR:启动失败。
使用示例:
uint8_t msg[] = "Hello UART!"; HAL_UART_Transmit_IT(&huart1, msg, sizeof(msg)-1);
-
-
HAL_UART_Receive_IT()
用于通过中断方式接收数据。接收的数据将在中断服务程序(ISR)中处理。
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向接收数据的缓冲区。 -
Size:要接收的数据字节数。
返回值:
-
HAL_OK:接收任务已启动。 -
HAL_ERROR:启动失败。
使用示例:
uint8_t receivedData[10]; HAL_UART_Receive_IT(&huart1, receivedData, 10);
-
-
HAL_UART_Transmit_DMA()
用于通过DMA(直接内存访问)发送数据。DMA可以使数据传输不占用CPU,从而提高数据传输效率。
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向要发送的数据的指针。 -
Size:要发送的数据字节数。
返回值:
-
HAL_OK:DMA传输已启动。 -
HAL_ERROR:启动失败。
使用示例:
uint8_t msg[] = "Hello UART!"; HAL_UART_Transmit_DMA(&huart1, msg, sizeof(msg)-1);
-
-
HAL_UART_Receive_DMA()
用于通过DMA接收数据。DMA可以有效地将数据从UART缓冲区传输到内存,而无需CPU干预。
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数说明:
-
huart:指向UART句柄的指针。 -
pData:指向接收数据的缓冲区。 -
Size:要接收的数据字节数。
返回值:
-
HAL_OK:DMA接收已启动。 -
HAL_ERROR:启动失败。
使用示例:
uint8_t receivedData[10]; HAL_UART_Receive_DMA(&huart1, receivedData, 10);
-
4. 中断服务函数
在使用中断模式时,需要实现中断回调函数。这些函数由HAL库调用。我们需要做的就是实现这些函数(有趣的是默认的实现是__weak的,意味着用户的定义隶属于强定义,编译器优先采纳用户实现。)
-
HAL_UART_TxCpltCallback()
当数据发送完成时,这个回调函数会被调用。
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
-
HAL_UART_RxCpltCallback()
当数据接收完成时,这个回调函数会被调用。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
相关文章:
嵌入式MCU面试笔记2
目录 串口通信 概论 原理 配置 HAL库代码 1. 初始化函数 2. 数据发送和接收函数 3. 中断和DMA函数 4. 中断服务函数 串口通信 概论 我们知道,通信桥接了两个设备之间的交流。一个经典的例子就是使用串口通信交换上位机和单片机之间的数据。 比较常见的串…...
云原生时代,如何构建高效分布式监控系统
文章目录 一.监控现状二.Thanos原理分析SidecarQuerierStoreCompactor 三.Sidecar or ReceiverThanos Receiver工作原理 四.分布式运维架构 一.监控现状 Prometheus是CNCF基金会管理的一个开源监控项目,由于其良好的架构设计和完善的生态,迅速成为了监控…...
mysql从全备文件中提取单库或单表进行恢复——筑梦之路
前提条件 与业务确认涉及业务、数据库IP、数据误删除时间点、数据删除涉及的SCHEMA、数据表,确认该数据库为MySQLdump备份方式,备份策略为每日凌晨1点进行数据库全备份,备份保留7天,业务误删除数据时间点为当日10点左右࿰…...
渗透测试技法之口令安全
一、口令安全威胁 口令泄露途径 代码与文件存储不当:在软件开发和系统维护过程中,开发者可能会将口令以明文形式存储在代码文件、配置文件或注释中。例如,在开源代码托管平台 GitHub 上,一些开发者由于疏忽,将包含数据…...
火语言RPA--配置文件读取
🚩【组件功能】:读取配置文件信息以字典类型输出。 配置预览 配置说明 要读取的文件 支持T或# 读取配置文件的路径及名称,绝对路径。 配置文件类型 INI或XML两种选项供选择。 编码 写入配置文件的编码,以列表方式供选择&am…...
电子应用设计方案104:智能家庭AI弹簧床系统设计
智能家庭 AI 弹簧床系统设计 一、引言 智能家庭 AI 弹簧床系统旨在为用户提供更加舒适、个性化的睡眠体验,通过结合人工智能技术和先进的床垫设计,实时监测和调整睡眠环境,以满足不同用户的需求。 二、系统概述 1. 系统目标 - 自动适应用户…...
基于paddleocr的表单关键信息抽取
全流程如下: 数据集 XFUND数据集是微软提出的一个用于KIE任务的多语言数据集,共包含七个数据集,每个数据集包含149张训练集和50张验证集分别为: ZH(中文)、JA(日语)、ES(西班牙)、FR(法语)、IT(意大利)、DE(德语)、PT(葡萄牙)&a…...
爬虫基础之爬取某基金网站+数据分析
声明: 本案例仅供学习参考使用,任何不法的活动均与本作者无关 网站:天天基金网(1234567.com.cn) --首批独立基金销售机构-- 东方财富网旗下基金平台! 本案例所需要的模块: 1.requests 2.re(内置) 3.pandas 4.pyecharts 其他均需要 pip install 模块名 爬取步骤: …...
深入理解动态规划(dp)--(提前要对dfs有了解)
前言:对于动态规划:该算法思维是在dfs基础上演化发展来的,所以我不想讲的是看到一个题怎样直接用动态规划来解决,而是说先用dfs搜索,一步步优化,这个过程叫做动态规划。(该文章教你怎样一步步的…...
(1)STM32 USB设备开发-基础知识
开篇感谢: 【经验分享】STM32 USB相关知识扫盲 - STM32团队 ST意法半导体中文论坛 单片机学习记录_桃成蹊2.0的博客-CSDN博客 USB_不吃鱼的猫丿的博客-CSDN博客 1、USB鼠标_哔哩哔哩_bilibili usb_冰糖葫的博客-CSDN博客 USB_lqonlylove的博客-CSDN博客 USB …...
基于STM32单片机设计的宠物喂食监控系统
1. 项目开发背景 随着宠物数量的增加,尤其是人们对宠物的养护需求日益增多,传统的人工喂养和管理方式难以满足现代养宠生活的需求。人们越来越希望通过智能化手段提高宠物养护的质量和效率,特别是对于宠物喂食、饮水、温湿度控制等方面的智能…...
MATLAB绘图:随机彩色圆点图
这段代码在MATLAB中生成并绘制了500个随机位置和颜色的散点图。通过随机生成的x和y坐标以及颜色,用户可以直观地观察到随机点的分布。这种可视化方式在数据分析、统计学和随机过程的演示中具有广泛的应用。 文章目录 运行结果代码代码讲解 运行结果 代码 clc; clea…...
重定向与缓冲区
4种重定向 我们有如下的代码: #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h>#define FILE_NAME "log.txt"int main() {close(1)…...
【Elasticsearch】index:false
在 Elasticsearch 中,index 参数用于控制是否对某个字段建立索引。当设置 index: false 时,意味着该字段不会被编入倒排索引中,因此不能直接用于搜索查询。然而,这并不意味着该字段完全不可访问或没有其他用途。以下是关于 index:…...
Golang Gin系列-8:单元测试与调试技术
在本章中,我们将探讨如何为Gin应用程序编写单元测试,使用有效的调试技术,以及优化性能。这包括设置测试环境、为处理程序和中间件编写测试、使用日志记录、使用调试工具以及分析应用程序以提高性能。 为Gin应用程序编写单元测试 设置测试环境…...
九、CSS工程化方案
一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址:GitHub - postcss/postcss-cli: CLI for postcss postcss地址:GitHub - postcss/postcss: Transforming styles…...
YOLOv11改进,YOLOv11检测头融合DSConv(动态蛇形卷积),并添加小目标检测层(四头检测),适合目标检测、分割等任务
前言 精确分割拓扑管状结构例如血管和道路,对各个领域至关重要,可确保下游任务的准确性和效率。然而,许多因素使任务变得复杂,包括细小脆弱的局部结构和复杂多变的全局形态。在这项工作中,注意到管状结构的特殊特征,并利用这一知识来引导 DSCNet 在三个阶段同时增强感知…...
大数据治理实战指南:数据质量、合规与治理架构
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 引言 随着企业数字化转型的加速,大数据已成为驱动业务决策的核心资产。然而,数据治理的缺失或不完善&…...
SQL Server 建立每日自动log备份的维护计划
SQLServer数据库可以使用维护计划完成数据库的自动备份,下面以在SQL Server 2012为例说明具体配置方法。 1.启动SQL Server Management Studio,在【对象资源管理器】窗格中选择数据库实例,然后依次选择【管理】→【维护计划】选项࿰…...
three.js+WebGL踩坑经验合集(4.2):为什么不在可视范围内的3D点投影到2D的结果这么不可靠
上一篇,笔者留下了一个问题,three.js内置的THREE.Vector3.project方法算出来的结果对于超出屏幕可见范围的点来说错得相当离谱。 three.jsWebGL踩坑经验合集(4.1):THREE.Line2的射线检测问题(注意本篇说的是Line2,同样也不是阈值…...
window保存好看的桌面壁纸
1、按下【WINR】快捷键调出“运行”窗口,输入以下命令后回车。 %localappdata%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets 2、依次点击【查看】【显示】,勾选【隐藏的项目】,然后按【CtrlA】全部…...
Protobuf序列化协议使用指南
简介 在本篇博客中,将会介绍protobuf的理论及使用方法。该文章仅做分享使用及自我复习使用,使用的图片来自百度,无法找到作者,如若侵权请联系删除。 目录 简介 概述 1.protobuf是什么? 2.序列化/反序列是什么&…...
83,【7】BUUCTF WEB [MRCTF2020]你传你[特殊字符]呢
进入靶场 图片上这个人和另一道题上的人长得好像 54,【4】BUUCTF WEB GYCTF2020Ezsqli-CSDN博客 让我们上传文件 桌面有啥传啥 /var/www/html/upload/344434f245b7ac3a4fae0a6342d1f94a/123.php.jpg 成功后我就去用蚁剑连了,连不上 看了别的wp知需要…...
低代码系统-产品架构案例介绍、轻流(九)
轻流低代码产品定位为零代码产品,试图通过搭建来降低企业成本,提升业务上线效率。 依旧是从下至上,从左至右的顺序 名词概述运维层底层系统运维层,例如上线、部署等基础服务体系内置的系统能力,发消息、组织和权限是必…...
Linux——网络(udp)
文章目录 目录 文章目录 前言 一、upd函数及接口介绍 1. 创建套接字 - socket 函数 2. 绑定地址和端口 - bind 函数 3. 发送数据 - sendto 函数 4. 接收数据 - recvfrom 函数 5. 关闭套接字 - close 函数 二、代码示例 1.服务端 2.客户端 总结 前言 Linux——网络基础…...
Nxopen 直齿轮参数化设计
NXUG1953 Visualstudio 2019 参考论文: A Method for Determining the AGMA Tooth Form Factor from Equations for the Generated Tooth Root Fillet //FullGear// Mandatory UF Includes #include <uf.h> #include <uf_object_types.h>// Internal I…...
初阶数据结构:链表(二)
目录 一、前言 二、带头双向循环链表 1.带头双向循环链表的结构 (1)什么是带头? (2)什么是双向呢? (3)那什么是循环呢? 2.带头双向循环链表的实现 (1)节点结构 (2…...
Rust:高性能与安全并行的编程语言
引言 在现代编程世界里,开发者面临的最大挑战之一就是如何平衡性能与安全性。在许多情况下,C/C这样的系统级编程语言虽然性能强大,但其内存管理的复杂性导致了各种安全漏洞。为了解决这些问题,Rust 作为一种新的系统级编程语言进入…...
使用openwrt搭建ipsec隧道
背景:最近同事遇到了个ipsec问题,做的ipsec特性,ftp下载ipv6性能只有100kb, 正面定位该问题也蛮久了,项目没有用openwrt, 不过用了开源组件strongswan, 加密算法这些也是内核自带的,想着开源的不太可能有问题ÿ…...
网络安全 | F5-Attack Signatures详解
关注:CodingTechWork 关于攻击签名 攻击签名是用于识别 Web 应用程序及其组件上攻击或攻击类型的规则或模式。安全策略将攻击签名中的模式与请求和响应的内容进行比较,以查找潜在的攻击。有些签名旨在保护特定的操作系统、Web 服务器、数据库、框架或应…...
