首页
📁归档
⏳时光机
📫留言
🚩友链
💰资助名单
推荐
🎧音乐
🏜️ 壁纸
❤ 捐助
Search
1
【NPN/PNP三极管】放大电路饱和失真和截止失真的区别
19,410 阅读
2
论文写作中如何把word里面所有数字和字母替换为新罗马字体
10,256 阅读
3
【高数】形心计算公式讲解大全
8,816 阅读
4
【概论】一阶矩、二阶矩原点矩,中心矩区别与概念
7,530 阅读
5
Vivado-FPGA Verilog烧写固化教程
7,014 阅读
🪶微语&随笔
励志美文
我的随笔
写作办公
📡电子&通信
嵌入式&系统
通信&信息处理
编程&脚本笔记
⌨️IC&系统
FPGA&ASIC
VLSI&IC验证
EDA&虚拟机
💻电子&计算机
IP&SOC设计
机器学习
软硬件算法
登录
18(共101篇)
找到
101
篇与
18
相关的结果
- 第 5 页
2022-04-07
西北大学模拟电子技术个人考研笔记
西北大学843、849历年真题 下载地址:https://wwek.lanzoue.com/ip1gv2m1mg3c 提取码: 警告 若个人或辅导机构 擅自复制本文直接或间接盈利 、请向我举报,举报方式见下面,本人以 著作权法 追查到底!同时核查该机构/个人 是否有非法出书情况 、是否有 出版权与书号 , 一并交于公安机关追查 ! 本站域名由sciarm.com更变为ee.ac.cn 和下文页面中信息不冲突 举报方式-请携带证据举报 1.邮箱hyliu@ee.ac.cn 2.点击博客中留言或私聊都可
嵌入式&系统
我的随笔
# 电子线路
刘航宇
4年前
0
1,870
32
UltraSE: Single-Channel Speech Enhancement Using Ultrasound阅读感悟
目录 一、论文基本信息 二、论文主要内容2.1 研究的背景 2.2 研究的目标 2.4 困难与拟解决对策, 2.5 技术优势 2.6 研究技术简述 2.6.1 ULTRASE DNN 模型概述2.6.2 基于 CGAN 的跨模态训练 2.6.3 ULTRASE 实现 2.7 研究验证2.7.1 微基准比较 2.7.2 消融研究 2.7.3 系统效率 2.8 文章结论 三、阅读理解与心得 参考文献 一、论文基本信息 作者 :孙科(加州大学圣地亚哥分校); 张新宇(加州大学圣地亚哥分校) 出版源 :第27届移动计算和网络国际会议论文集2021年10月第160-173页 摘要 :鲁棒语音增强被认为是音频处理的圣杯,也是人机交互的关键要求。用单通道、纯音频方法解决这个任务仍然是一项艰巨的挑战,尤其是在涉及相互竞争的扬声器和背景噪声混合的实际场景中。在本文中,我们提出了UltraSE,它使用超声波传感作为一种补充模式,将所需说话者的声音从干扰和噪声中分离出来。UltraSE使用商用移动设备(例如智能手机)发射超声波并捕捉说话者发音手势的反射。 它引入了一种多模态、多领域的深度学习框架来融合超声多普勒特征和可听语音频谱图。此外,它还利用一个基于跨模态相似性测量网络的经过对抗性训练的鉴别器来学习两种异质特征模式之间的相关性。我们实验验证了UltraSE同时提高了语音清晰度和质量,并且大大优于最先进的解决方案。 二、论文主要内容 2.1 研究的背景 人类听觉系统非常有能力在干扰扬声器和噪音的混合中挑选出语音源,这仍然是机器听觉的基本挑战。在当今人机交互和人机交互的数字通信系统的激增下,但这个问题仍然存在。示例:移动VoIP、语音命令、现场语音的后期制作等。语音分离与增强(SSE)的相关研究问题通常被认为是音频处理的圣杯。经典解决方案需要依赖先验知识(即每个扬声器的特征工程)或[1] 定向麦克风阵列来将所需的源与环境声音隔离开来。在过去的几年里,深度学习技术已经激增并显着推进了该领域,实现了单麦克风扬声器独立SSE。在分离2个净语音的混合物时,最先进的解决方案已证明平均音频质量提高了约 10 dB。然而,超过2个扬声器与背景噪声混合的具有挑战性的情况很少受到关注。最近的一个初步测试表明,现有的深度学习模型在这种情况下通常表现不佳,因为非结构化背景噪声损害了它们识别语音流中可分离结构的能力。此外,现有的纯音频方法无法解决标签排列问题,即将模型输出与所需的说话者相关联。视听算法利用说话者面部的视频记录来同时解决SSE和排列问题。然而,在特定视角和可调节照明条件下对相机的需求限制了它们的实际可用性[2]。 2.2 研究的目标 利用超声传感作为一种补充方式,将所需的说话者语音与噪声和干扰分开。 这种方法称为 UltraSE,适用于配备单个麦克风和扬声器的商品移动设备(例如智能手机)。 图1说明了该文的基本思想。在录音过程中,UltraSE 不断发出听不见的超声波,该超声波由靠近智能手机的说话者的发音(嘴唇运动)调制。 因此,麦克风记录的信号既包含可听见的声音,也包含听不见的反射。如图1 所示,虽然可听声音(“绿色”)混合了目标清晰的语音(“黑色”)和其他干扰以及背景噪声(“蓝色”),但听不见的反射(“橙色”)仅捕捉目标用户与清晰语音相关的发音手势动作。UltraSE采用DNN框架捕捉这种相关性,并对可听声音进行去噪 图片 图1:UltraSE 针对用户手持智能手机在嘈杂环境中录制语音的场景。UltraSE 使用超声波传感作为一种补充方式,将所需说话者的声音与干扰分开。 2.4 困难与拟解决对策, 问题一:尽管存在干扰,如何通过超声波描述发音姿势?捕捉精细的发音手势是一项挑战,因为它们速度快(80厘米/秒),位移小(小于5厘米)。此外,由于谐波和硬件伪影,语音和超声波之间存在相互干扰 解决对策:充分利用了超声波的优势,即高采样率和与时间域中清晰语音的完美对齐。作者设计了发射超声波形来捕获短期高分辨率多普勒频谱图,并采用一次性发射体积校准来减少跨模态干扰。 问题二:如何设计一个 DNN 模型来融合这两种模态并表示它们的相关性?没有现有方法能够解决作为 UltraSE 基础的跨模态降噪问题,即使用一种模态(超声波)来重建受噪声/干扰污染的另一种模态(语音)。 解决对策:由于两种模态的物理特征特征不同,我们设计了一个双流 DNN 架构来处理每个模态,并设计一个自注意力机制来融合它们。 此外,作者提出了一种基于条件 GAN (cGAN) 的训练模型,该模型具有新颖的跨模态相似性测量网络,以实现这种能力。 问题三:如何提高增强语音的清晰度和质量? 解决对策:时频 (T-F) 频谱图的幅度对于语音清晰度至关重要,而相位决定了语音质量。作者将 UltraSE 扩展为两阶段多域 DNN 架构,该架构优先优化 T-F 域中的清晰度,然后在T域中重构相位以提高语音质量。根据经验观察,我们将多模态融合网络置于 T-F 域内,即发音手势与语音清晰度更相关。 2.5 技术优势 纯音频语音增强:利用T-F 域方法、T域方法和多领域方法对非语音噪声表现出可接受的性能,但它们仍然无法处理涉及多个干扰。为了解决此类语音分离问题,Deep clustering 为每个源训练语音嵌入,然后使用聚类算法将它们分离。PIT在训练过程中迭代地改变源的排列,以训练一个排列不变的语音分离模型。这些方法仍然需要先验地知道说话人的数量,并且不适用于超过3个说话人加上噪声的情况。此外,标签排列问题仍然存在——它们可以分离多个语音源,但不能自动识别哪个来自目标说话者,这可能会阻碍某些机器操作的后端任务(例如,智能手机上的语音助手)。UltraSE克服了所有这些缺陷。 多模态语音增强为了解决排列问题:视听(AV)方法使用对象面部的视频记录作为音频的提示,有许多缺点。例如除了麦克风之外,他们还需要一个额外的摄像头,在良好的光照条件下指向拍摄对象的脸部,这在许多典型用例中是不方便的,甚至是不可行的。此外,相机在许多对隐私敏感的地方无法使用。前人探索了使用超声作为增强语音的补充方式的想法。然而,这些作品都需要特殊的超声波硬件。相比之下,UltraSE 只需要智能手机上的单个音频通道,并克服了模态之间的相互干扰等实际挑战。此外,他们使用传统的方法,即非负矩阵分解和非线性回归,只显示了对环境噪声的语音增强性能,而不是语音干扰。UltraSE 通过设计多模态多域 DNN 框架进一步突破了这一想法的极限,以实现与视听方法类似的语音分离和增强性能。 无需设备的超声波传感:无设备超声波传感技术可以利用商品移动设备上的扬声器和麦克风来跟踪附近物体的距离/方向变化。最先进的超声波手势跟踪方案可以达到毫米级的精度。 除了位置和手势跟踪,最近的研究还尝试使用超声波传感进行唇读[41]。 然而,由于空间分辨率不足,它们只适合粗略的传感应用,相比之下,UltraSE 率先展示了超声波传感可以作为一种补充方式来解决鸡尾酒会问题并将语音增强提升到一个新的水平。 2.6 研究技术简述 UltraSE 代表了首个使 SSE 性能接近多通道解决方案的纯音频方法,同时克服了标签排列问题。下面简述出三个重要技术贡献: • 作者设计了一个多模态多域 DNN 框架,用于单通道语音增强,融合了超声和语音特征,同时提高了语音清晰度和质量。 2.6.1 ULTRASE DNN 模型概述 第一步是从原始信号创建 DNN 输入特征。然后,我们设计一个两阶段、多模态、多域的 DNN 模型,该模型包括三个关键模块,简述如下。 T-F 域多模态振幅网络模块通过使用语音和超声波作为输入来生成幅度理想比率掩码 (aIRM),即净和噪声频谱图的幅度之间的比率。它由两个子网组成。 子网 (i) 双流特征嵌入:我们的模型首先使用嘈杂语音的 T-F 频谱图和并发超声多普勒频谱图作为输入。然后,我们设计了一个双流特征嵌入架构,将不同的模态转换到相同的特征空间,同时保持它们的时域对齐。 子网 (ii) 语音和超声融合网络:然后,我们在频率维度上连接每个流的特征。进一步应用自我注意机制来融合级联特征图,让多模态信息相互“串扰”。融合的特征随后被送入 BiLSTM 层,然后是三个 FC 层。结果输出是一个幅度掩模,它与原始噪声幅度谱图相乘以生成幅度增强的T-F 谱图。 图片 图2:UltraSE的多模态多域 DNN 设计概览。卷积层表示法:Channels@Kernel size 如图3说明了DNN 输入特征的预处理步骤工作流程。 l1ev5znd.png图片 图3:DNN 输入特征设计 l1ev76fq.png图片 图4:UltraSE基于cGAN的跨模态训练概览 基于cGAN 的跨模式训练,如图 4 所示,我们设计了一种基于 cGAN 的训练方法,以进一步去噪幅度增强的T-F频谱图。在我们的cGAN 模型中,生成器就是上面的 T-F 域多模态幅度网络;鉴别器被设计成鉴别增强的频谱图是否对应于超声传感特征。T 域相位网络。我们使用iSTFT(一个固定的 1D 卷积层)将幅度增强的 T-F 频谱图转换为T域波形。为了微调增强信号的相位,我们设计了一个编码器-解码器架构来重建相位以接近 T 域中的净语音。 • 作者设计了一个基于cGAN 的跨模态训练模型,该模型有效地捕捉了超声和语音之间的相关性以进行多模态去噪。 2.6.2 基于 CGAN 的跨模态训练 UltraSE 的基本问题是多模态降噪,即使用一种模态(超声波)来恢复被噪声/干扰污染的另一种模态(语音)。前者感知分辨率低,但无干扰,与后者相关。尽管我们有意保持两者之间的时间对齐,但很难强制多模态融合网络“理解”这种多模态相关性,因为传统的损失函数(例如MSE)只能训练网络来清理端到端的TF频谱。 因此,我们提出了一种基于 cGAN 的训练方法,该方法隐含地将跨模态相关性的最大化本身作为训练目标。 任何GAN设计中的一个关键要素是定义鉴别器使用的相似度度量。与在相同类型特征之间进行比较的传统 GAN 应用程序(例如图像生成)不同,我们的跨模态 cGAN 需要区分增强的 TF 语音频谱图是否与超声多普勒频谱图匹配(即,它们是“真实的”还是“假”对)。 我们提出了一个跨模式的 Siemese 神经网络来应对这一挑战。Siamese 神经网络使用共享权重和模型架构,同时在两个不同的输入向量上协同工作以计算可比较的输出向量。它传统上用于测量来自相同模态的两个输入之间的相似性,例如,两个图像。为了启用跨模态连体神经网络,我们创建了两个独立的子网络(图7),旨在分别表征语音和超声的时频域特征之间的对应关系。基本架构下,这两个输入是一个 CNN-LSTM 模型。 由于人类语音在 F 域中包含谐波和空间关系,因此语音 CNN 子网络使用扩张卷积进行频域上下聚合。超声传感的多普勒频移主要包含局部特征。因此,超声 CNN 子网络仅包含传统的卷积层。在卷积之后,使用 Bi-LSTM 层来学习两种模式的长期时域信息。 最后,引入三个全连接(FC)层来分别学习两个可比较的输出向量。 我们强调,这种跨模态设计不共享架构和参数,这与传统的 Siamese 网络不同。 l1ev87c1.png图片 图5:跨模态相似性测量网络的输出 PDF 图5显示了输出的概率密度函数 (PDF),其中较小的值表示较高的相似性。很明显他输出的真对和假对的PDF完美分离,这意味着我们的相似性测量网络可以有效地区分一对语音和超声输入是否由相同的发音姿势生成。 • 我们收集了一个新的语音数据集——UltraSpeech,并与最先进的解决方案相比验证了 UltraSE 的性能。 2.6.3 ULTRASE 实现 传统的语音数据集只包含原始语音,没有超声波传感信号。为了评估 UltraSE,我们创建了一个名为 UltraSpeech 的新数据集,其中包含两者。 数据收集:我们招募了20名流利的英语人士(4名女性,16 名男性,平均年龄 25 岁)来收集 UltraSpeech 数据集。每个参与者被要求在安静的环境中使用 2 种典型的电话持有方式(“电话”模式和“走向麦克风”模式,如图8(b)所示)在 TIMIT 语音语料库[3]中说出至少300个句子。同时,我们使用定制的 Android 应用程序 UltraRecord,通过智能手机底部的扬声器和麦克风以 96 kHz 的采样率发出超声波信号并捕获音频片段。 请注意,我们不限制用户将智能手机与嘴巴保持特定距离。总的来说,我们为每种握持方式收集了8k 5秒净的语音片段。我们遵循现有的 SSE 工作,合成混合生成嘈杂的语音数据集。干扰语音来自 TIMIT 数据集,其中包含 6300 个不同的英语句子,由 630 位说话者生成,总共持续 3.5 小时。环境噪声数据集来自 AudioSet,其中包含来自现实生活的526种噪声类型的超过170万个10秒片段,包括广泛的人类和动物声音、乐器和流派以及日常生活中常见的噪声。此外,我们生成了一个训练集,其中干扰语音和净语音来自同一个说话者。 这被广泛认为是 SSE [4] 最具挑战性的案例,因为干扰具有与所需语音无法区分的相同听觉模式。 我们将其添加到训练数据集中,以强制模型利用除了听觉特征之外的超声特征。我们的训练数据集包含由三星 Galaxy S8 智能手机收集的 15 名参与者的净语音。每个参与者的净语音都混合了 20 种不同的噪音设置。 对于每个噪声设置,干扰扬声器的数量 ? 均匀分布在 [0,4]中,SNR 均匀分布在 [−9, 6] dB(平均为 -1.5 dB)中。训练数据总共包含 120k 5 秒的嘈杂语音片段(300 小时)。 l1evaw7s.png图片 l1evbffv.png图片 我们在 Pytorch 中实现了 UltraSE DNN模型。特征图的维度和每一层的参数如图 2、6、7 和表 1、2、3所示。除了最后一层应用了sigmoid 之外,ReLU 激活跟随所有层。对于训练,我们使用 Adam 优化器,初始学习率为 1? − 04,每 5 个 epoch 下降25%,总共 20 个 epoch。UltraSE有15.5M和3.1M参数用于第一阶段和第二阶段 DNN。 2.7 研究验证 2.7.1 微基准比较 在本节中,我们的默认测试数据集包括另外 5 名参与者在“Towards mic”模式下的净语音,使用三星 S8 收集。我们的测试环境包括 6 种不同的干扰加噪声设置:1? +?、2? +?、3? +?、> 3? +?、2?(“s”和“a”表示干扰扬声器和环境噪声)和最难的情况 >= 2 个同说话者干扰加上噪声 (>= 2?? + ?)。 噪声语音信号的 SNR 水平均匀分布在 [−9, 6] dB 中。 UltraSE 的所有结果都来自从训练数据集生成的单个模型。我们将 UltraSE 与 4 种最先进的 SSE 方法进行比较,PHASEN [5](TF 域方法)、SEGAN(T 域方法)、AVSPEECH (视听方法)、Conv-TasNet(语音分离法)。为了公平比较,我们重新实现了 PHASEN、SEGAN 和 Conv-TasNet,并在 UltraSpeech 数据集上训练和测试它们。PHASEN 和 SEGAN 只使用 1? + ? 训练集,因为它们是为语音增强而不是分离而设计的。PHASEN 和 SEGAN 在 1? + ?(见表 4)下的结果与原始工作相似,这表明了我们实现的正确性。对于语音分离方法,即 Conv-TasNet,我们首先在“2?”环境中对其进行训练和评估,以检查我们实现的正确性。 然后,我们使用“2? + ?”数据集以 2 位说话者的净语音作为基本事实来训练模型,并在表 4 中比较其他环境中的结果。对于AVSPEECH,由于我们的数据集没有录像,我们直接使用[6]中的结果作为基线。 l1evc762.png图片 与最先进的语音增强方法相比,UltraSE 显着提高了嘈杂和多说话人环境中的语音质量和清晰度。表4显示了在 [−9, 6] dB 范围内均匀分布的所有输入 SNR 水平下的测试结果。UltraSE 在所有4个指标上均优于 PHASEN 和 SEGAN。在 1? + ? 环境中,UltraSE 实现了平均 17.25 SiSNR (18.75 ΔSiSNR) 和 3.50 PESQ。在具有多扬声器干扰的其他环境中,超声传感模式的作用更为突出,在2个基线上分别平均提高了 6.04 dB 和 9.77 dB 的 SiSNR。即使对于最困难的情况 >= 2?? + ?,UltraSE 仍可实现 8.97 dB SiSNR 和 2.52 PESQ。 此外,UltraSE 的性能略高于AVSPEECH,这可能是因为超声波特征的采样时间粒度比视频帧更精细,并且可以更好地与语音信号对齐。 大多数现有的语音分离方法只能在有限数量的干扰说话者(2∼3)和没有环境噪声的情况下工作[29,30,73,76]。 如表4所示,当使用“2? + ?”数据集训练 Conv-TasNet 时,Conv-TasNet 在“2? + ?”和“2?”设置中取得了良好的性能,但在其他复杂的设置中表现不佳 环境。 相比之下,在 > 3? + ? 设置下,UltraSE 优于 Conv-TasNet 约 6 dB 的 SDR 或 SiSNR,STOI 为 10%,PESQ 为 24%。 l1evcov7.png图片 图8中的散点图显示了测试数据集中每个句子的输入和输出 SiSNR,其中包括所有 6 个环境。UltraSE 在不同环境和句子中始终如一地实现高性能,平均 14.75 dB SiSNR 增益。 即使在 -9 dB 输入的最坏情况下,增强型语音平均达到 8.86 dB SiSNR。 2.7.2 消融研究 我们进行了消融研究,以更好地了解 UltraSE 中不同设计组件的性能。 这里的测试数据集包括除了“>= 2?? + ?”之外的所有环境,这在实践中并不常见。 表 5 总结了结果。 l1evdhei.png图片 “No T domain”表示没有“T do-main波形语音增强”的DNN模型。 结果表明,该模块几乎不影响 STOI,这是一种语音清晰度指标。 但它有助于分别获得 0.46 dB SDR、0.58 dB SiSNR、0.12 PESQ,这证明它可以进一步提高 T-F 域多模态网络,生成语音的感知质量。 “No cGAN”表示没有“基于 cGAN 的跨模态模型训练”的模型。 应用 cGAN 时,所有指标都显着提高,因为我们的 cGAN 设计迫使网络学习超声和语音之间的相关性,这是 UltraSE 设计背后的关键原则。 “No Fusion Network”是指超声和语音信号的特征图在时频域中直接拼接,没有融合块。 性能略有下降,因为融合块有助于多模态特征相互“串扰”。 “No Ultrasound”表示网络开头没有超声流的网络。 结果变得接近于没有超声传感的传统语音增强方法,例如,PHASEN。 2.7.3 系统效率 时间消耗:我们评估 UltraSE 在 3 个平台上的运行时处理延迟,包括 NVIDIA GTX 2020 (GPU)、Intel i9-9980 3.00GHz (CPU) 和配备 Qual comm Snapdragon 835 CPU 的三星 Galaxy S8 (手机)。前两个对应于 UltraSE 被卸载到受信任的云或边缘服务器的情况。 表6总结了结果。GPU 服务器仅经历 14.85 毫秒的延迟,这对于 VoIP 应用程序来说是可以接受的(最多 150 毫秒 [7])。 智能手机外壳是使用三星 Galaxy S8 上的 Pytorch Mobile [8] 测量的。请注意,最新版本的 Pytorch Mobile [8] 仅支持单 CPU 处理,没有任何 GPU/NPU 支持。 因此,延迟相对较高(处理 5 秒语音需要 25.08 秒),这仅适用于离线处理应用程序,例如音频消息和录音。有大量关于提高智能手机 DNN 效率的文献 [9],表明使用移动 GPU/NPU 可以减少 50 倍以上的延迟。 我们将为我们未来的工作探索这些解决方案。 另请注意,由于使用了 Bi-LSTM 块,UltraSE 需要以 5 秒为单位处理输入。 这意味着它的 SSE 在 5 秒的初始引导期后开始生效。 l1eve81q.png图片 能耗:我们的实验表明,典型的智能手机(Samsung S8)可以连续使用 UltraSE 录制语音,同时发射超声波信号 60.57 小时(不显示)。 我们使用 Android Profiler [80] 进行的测量显示 UltraSE 的 CPU 负载平均为 48.7%,功耗为在 0 到 3 之间的“1”级别。当卸载到服务器时,计算能量消耗变得可以忽略不计。 唯一的开销是 UltraSE 需要将原始的 48/96 kHz 采样率的音频流上传到服务器,然后从服务器下载增强的语音。我们的实验表明,三星 S8 可以在卸载模式下连续运行 UltraSE 并通过 WiFi 上传/下载音频流 10.82 小时。服务器卸载可能会引发其他问题,例如安全性,但这超出了我们当前工作的范围。 2.7.4 泛化采样频率 通过 96 kHz 采样率数据集训练的 UltraSE 模型可直接用于增强以 48 kHz 采样率记录的测试语音。只要超声传感特征的 FFT 窗口长度和跳跃长度分别保持 85 ms 和 10 ms,48 kHz 采样率的特征分辨率与 96 kHz 采样率的情况相同。表5 显示在 96 kHz 采样率训练模型上测试 48/ 96 kHz 采样率数据集时性能下降可忽略不计。 l1evf1bn.png图片 图8:发音手势的 SNR。 握持方式:在“电话通话”模式下(图 8(a)),用户的面部部分遮挡了超声波信号,因此我们训练了一个与“朝向麦克风”模式不同的模型(图 8(c))。 UltraSE 可以使用智能手机内置的基于 IMU 的握持方式检测算法自动选择模型 [81]。 我们的实验表明,在 -1.5 dB 平均输入 SNR 下,由于遮挡,“电话呼叫”(12.47 dB SiSNR)的性能略低于“Towards mic”(13.12 dB SiSNR)。 我们进一步评估了每个模型在不同嘴到麦克风距离下的灵敏度。 图8(b) 和图 8(d) 显示了超声的平均 SNR (SNR?) 与增强语音的 SiSNR。 对于两种握持方式,???? 远远超过 10 dB,语音 SiSNR 在 20 cm 距离内保持在 12 dB 左右。 实验表明,只要嘴到麦克风的距离保持在 20 厘米以内,UltraSE 模型的性能就会始终如一。 运动干扰:我们测量来自 3 种主要运动伪影的干扰影响,即呼吸、手势和行走。 在“朝向麦克风”和“打电话”模式下,分别在嘴巴距离麦克风 15 厘米和 2 厘米时进行了实验。(i) 呼吸频率 (~30 bpm) 远小于关节运动 (> 10 Hz),因此它对 UltraSE 的影响可以忽略不计。(ii) 手势引入与关节运动相似的多普勒效应 [36, 40, 51],这可能造成不可忽视的干扰。我们在推动手势干扰下测量关节手势的 SNR?。 SNR? 在 0° 到 90° 的 7 个不同角度每 2 cm 处进行采样,步长为 15°,靠近用户的嘴。 图 13 显示了“朝向麦克风”模式下 SNR? 的空间分布 [82]。 只要手势距离嘴巴 > 25 厘米(这在日常使用场景中很常见),SNR? 就会保持在 10 dB 以上,这对于 UltraSE 来说已经足够了(图 8)。 麦克风阵列可用于聚焦用户的嘴部区域以进一步减轻干扰 [40],但这超出了 UltraSE 的范围。我们省略了“电话通话”模式,因为麦克风离嘴更近,并且感应 SNR? 保持较高。(iii) 当其他人走近(0.8 m 远)时,我们发现 SNR? 几乎没有受到影响,因为超声音量相对较低,并且用户的嘴更近。 总体而言,发音手势的 SNR? 足够高(> 10 dB),并且 UltraSE 模型在日常使用场景中不受运动伪影的影响。 智能手机的概括:不同的智能手机可能有不同的扬声器麦克风布局。 例如,三星 S8、LG G8S ThinQ 和 VIVO X20 的底部麦克风和扬声器之间的距离分别为 5 毫米、25 毫米和 25 毫米。扬声器和麦克风的高频响应也可能因手机型号而异[83]。 将三星 S8 数据集训练的 DNN 模型直接应用到 LG G8S ThinQ 和 VIVO X20 时,增强语音的 SiSNR 分别变为 9.21 dB 和 9.53 dB。低于同款手机壳13.21 dB),但仍高于无超声传感的 SiSNR(7.68 dB)。 为了保持最佳性能,一种直接的方法是为每个电话模型执行一次训练数据收集。 或者,我们可以使用涵盖典型硬件配置的各种智能手机来丰富 UltraSpeech 数据集。 这留给我们以后的工作。 l1evfc20.png图片 真实环境使用实验:我们要求用户在 4 个不同的真实世界环境中使用 UltraSE,即 1) 带有排气扇和流水噪音的浴室环境(平均 75 dBA); 2)有电视噪音的客厅环境(平均55分贝); 3) 有谈话噪音的室内会议环境(平均 60 dBA); 4) 有车辆噪音的室外路边环境(平均 60 dBA)。 与合成嘈杂语音不同,我们无法在这些场景中捕获真实净的语音并评估 SDR、SiSNR、STOI 和 PESQ 等指标。 因此,为了评估 UltraSE 在实际使用中的性能,我们使用 ASR 单词错误率???=(?+?+?)/? 作为指标,其中?、?、?和?是替换、删除的数量 ,插入,目标用户的口语总数。 具体来说,我们要求用户在 TIMIT 语音语料库中跨不同环境说出至少 50 个句子。 图 9 显示了在不同环境中使用和不使用 UltraSE 的WER。 在非语音噪声环境下,即浴室和路边,UltraSE 略微提高了 ASR 语音识别率,因为 ASR 本身具有减轻背景环境噪声干扰的能力。 在语音嘈杂的环境中,即客厅和会议室,WER 高于 100%,因为非目标用户的语音引入了许多词插入和替换。UltraSE 在这种情况下取得了显着的改进,因为它能够通过使用超声波感应将所需的说话者语音与噪声分开。 2.8 文章结论 超声波传感可以作为解决鸡尾酒会问题的补充方式。UltraSE系统引入了通用DNN机制来实现这些功能,例如,多模态多域融合网络和基于新型跨模态连体网络的基于cGAN的训练模型。UltraSE指向了一个新的方向,它融合了无线传感能力,将机器感知提升到一个新的水平。 三、阅读理解与心得 作者提出了UltraSE,它使用超声波传感作为一种补充模式,将所需说话者的声音从干扰和噪声中分离出来。UltraSE使用商用移动设备发射超声波并捕捉说话者发音手势的反射。它引入了一种多模态、多领域的深度学习框架来融合超声多普勒特征和可听语音频谱图。并且利用一个基于跨模态相似性测量网络的经过对抗性训练的鉴别器来学习两种异质特征模式之间的相关性。最后实验验证了UltraSE同时提高了语音清晰度和质量,并且优于当下先进的解决方案。 作者在第一二节分别介绍了该技术的背景与优势,中间章节介绍技术路线,最后就微观基准比较、消融研究、系统效率与泛化采样频率四个方面对实验进行评估得出超声波传感可以作为解决鸡尾酒会问题的补充方式。UltraSE 系统引入了通用 DNN 机制来实现此类功能,融合了无线传感功能,将机器感知提升到一个新的水平。但是在实验分析中不乏存在一个小问题,在系统延时上UltraSE 需要以 5 s 的片段处理输入,这意味着其SSE在5秒的初始引导期后开始生效,如果设备不支持GPU / NPU话,延迟将会很高大于可接受的范围了,基于此这将是进一步研究的对象。 通过本次阅读,使我对电子与通信技术了解了不少,让我懂得专业基本素养及其重要,一方面是专业知识的积累,另一方是英语水平的训练。今后要养成不断阅读文献的习惯,将输入更好的转化为输出,同时在阅读文献方面要做到四知,一、“知事”,了解所读论文的研究内容和研究结果,即英文中的“What had been done? What was the result”。通过阅读摘要(Abstract)或概要(Summary),可以知道研究结果,即知道“What”;而参读全文则可以知道实验方法和策略,即知道“How”。二、“知人”,学会了解研究人员以及他或他们所在研究机构等背景资料。三、“知因”,阅读一篇文章时,有三个问题需要我们思考。一是,为什么研究者能够想到做这个研究。一是,研究者为什么这样设计实验。另一个就是,如果让我们来做,我们会怎样设计我们的研究。四、“知短”,不是所有的研究论文是完美的,许多实验设计可以改进。至于所引出的未解决的问题,更是无穷尽,“真理不是绝对的”。 参考文献 [1] Quan Wang, Hannah Muckenhirn, Kevin Wilson, Prashant Sridhar, Zelin Wu, John Hershey, Rif A Saurous, Ron J Weiss, Ye Jia, and Ignacio Lopez Moreno. Voice filter: Targeted voice separation by speaker-conditioned spectrogram masking. In Proceedings of Interspeech, 2019. [2] Triantafyllos Afouras, Joon Son Chung, and Andrew Zisserman. My lips are concealed: Audio-visual speech enhancement through obstructions. In Proceedings of Interspeech, 2019. [3] John S Garofolo et al. Darpa timit acoustic-phonetic speech database. National Institute of Standards and Technology (NIST), 1988. [4] Aviv Gabbay, Asaph Shamir, and Shmuel Peleg. Visual speech enhancement. In Proceedings of Interspeech, 2018. [5] Dacheng Yin, Chong Luo, Zhiwei Xiong, and Wenjun Zeng. Phasen: A phaseand-harmonics-aware speech enhancement network. In Proceedings of AAAI, 2020. [6] Ariel Ephrat, Inbar Mosseri, Oran Lang, Tali Dekel, Kevin Wilson, Avinatan Hassidim, William T Freeman, and Michael Rubinstein. Looking to listen at the cocktail party: A speaker-independent audio-visual model for speech separation. In Proceedings of ACM SIGGRAPH, 2018. [7] Chris Lewis and Steve Pickavance. Implementing quality of service over cisco mpls vpns. Selecting MPLS VPN Services, 2006 [8] Pytorch Mobile, 2020. https://pytorch.org/mobile/home/. [9] Siqi Wang, Anuj Pathania, and Tulika Mitra. Neural network inference on mobile socs. IEEE Design & Test, 2020.
刘航宇
4年前
1
1,096
1
2022-03-30
西北大学843&849备考小经验
目录 843&849历年真题 下载地址:https://wwu.lanzoub.com/i3si90ai9k3g 提取码: 正文 本人22考研已经上岸西北大学电子科学与技术专业 图片 本文不会长篇大论,节省彼此时间,不建议天天看经验贴,有这时间建议做个题跑个步比啥都好。 英语和政治篇 英语和政治篇不多叙述、我相信这个难不倒大家,过线肯定能过,多年国家线分数线尚未超过40,精简回答政治7、8月起每天1-2小时,英语前期单词后期真题,真题建议做到2刷。 数学篇 本人数学这次没发挥好105分,,本人正式备考在7月份开始考研,时间短,那么这么短时间如何提高数学与专业课呢?答案就是不断做题,看视频是次要的本人由于起步晚,直接不看视频就做题,不会就翻书查答案,再不行就看对应知识点,一下节省了好几个月时间。咳咳,不建议大家学我。数学前期建议选任何一本考研书都可,1800不建议因为答案非最简答案,很多同学看不懂原因是这个思路有问题,不是最简思路,并非见到极限我就用泰勒!9月前完成强化,强化方式1.强化卷、2.题目少的习题册(张、汤、李都有)选一个精做,别欺骗自己只求数量、不求质量那是害人!9月-10月先做各机构的模拟题,先不要做真题,模拟题做多少是多少!10月-12月中旬做真题,数一必须后期真题,真题每年有好多以前考过的类型你在二刷时候就能发现22年、21年、20年、19年等等都有很多和19xx年、200x年很类似题目,千万别后期光刷模拟题质量不是一个层次哦!第一个月2天1张卷子第一天做完第二天改错吃透,第二个月1天1份,最后半月二刷1天2份根据程度只刷错题也行一定一定要吃透!历年真题。。我们偶数年吃透考个100+不是问题,奇数年吃透110+不是问题。数学就是题海战术和反复吃透,真题很重要有可能就从1987年起刷2次,真题错题能做到我遇到必会就是一个反反复复克服定势思维的过程。 专业篇 不要迷信押题卷,我们这一届843、849也没几个报班、还有有些微博网上讲题的老师水平,emmm我不评价!? ,我考研期间都 免费 给别人讲了一些题,我相信学弟学妹应该也需要学习那么就挂出来吧,如下所示 集成运放深度理解讲解 专业课如何学? 1.前期(7、8月左右)看上海交大模电视频、认真做笔记,有空课后题 2.数电呢?数电再模电之后学、数电可以看书自学23456章很重要,课后题必做,比如逻辑代数,编码、译码器,寄存器,计数器,加法器这些等等 视频课后题9月中旬前建议完成 3.后期9月中旬后,建议好好研究真题?学长可以免费提供我的个人笔记 4.真题建议做到二刷、吃透,最后1个月看自己笔记和书本和做过的习题即可,基本没有什么大问题的 迷茫指导 结语 西北大学很好,老师也很强,希望各位学弟学妹都能上岸,加油!考研过程最忌讳形式主义、自我感动,合理规划,适合自己是最总要的,我的仅仅是个提示,不要老是看这些,7月前有时间多多锻炼一下身体,西北大学目前843、849在211考研中难度不是很大,既然选择了认真对待肯定没问题!学长希望大家都能上岸,一战成硕! 免费笔记入口 模拟电子技术 数字电子技术
我的随笔
刘航宇
4年前
0
1,197
15
2022-03-13
数字电路基础-最大项与最小项
目录 1.定义 2.性质 3.关系 1.定义 最小项:n个变量的逻辑乘,即与形式,每个变量以原变量或者反变量的形式出现一次。n个变量共有2n个最小项。用m表示,如ABC,表示为m0。 最大项:n个变量的逻辑和,即或形式,每个变量以原变量或者反变量的形式出现一次。n个变量共有2n个最大项。用M表示,如A+B+C,表示为M0。 如下为三变量最小项和最大项的表示方法: 图片 2.性质 对于n个变量来说,若给定这些变量确定的值,那么2n个最小项中仅有一组值为1,其余全为0;2n个最大项中仅有一组值为0,其余全为1. 全部最小项之和恒等于1;全部最大项之积恒等于0。(可由第一条性质中看出) 任意两个最小项之积等于0;任意两个最大项之和等于1。(可由第一条性质中看出) 若干个最小项的和等于其余最小项和的反。简单可以记做为卡诺图上分成两部分,他们之间为反关系。 3.关系 最小项的反是最大项,最大项的反是最小项。 图片
嵌入式&系统
刘航宇
4年前
0
1,970
6
SIM900A发送与接受短信
目录 一.SMS简介 二.短信的控制模式与编码1.Text Mode 2.PDU Mode 3.GSM编码 4.UCS2编码 三.收发英文短信1.AT+CPMS查询短信数量 2.AT+CNMI设置新消息提示类型 3.AT+CMGF选择短信模式 4.AT+CSCS设置编码 5.AT+CSMP设置短信文本模式 6.AT+CMGS发送消息到指定手机号 四.收发中文短信 一.SMS简介 SMS(Short Messaging Service)中文名称短信服务,短信是当下每一部手机上必备的功能之一,顾名思义,它是在手机之间发送文字信息或从个人计算机或手持设备向手机发送信息的一种方式,其文本信息的最大发送量为160个字符(字母、数字或者拉丁字母中的字符),对于中文一般最大发送量为70个字符。 这里我想用SIM900A模块实现短信的收发。 图片 二.短信的控制模式与编码 先说一下:我采用的是Text Mode下使用GSM编码收发英文短信、使用UCS2编码收发中文短信 对于短信的控制一共有三种模式:Block Mode、基于AT指令的Text Mode、基于AT指令的PDU Mode 。目前手机中默认使用PDU Mode,通过PDU编码的短信可以是文字、声音或者图像。Text Mode只能用于发送ANSI范围的字符,发送方式比较简单。 SIM900A模块只提供Text Mode 和PDU Mode。 中文短信中,所有汉字和字符都是采用UNICODE编码。 1.Text Mode Text Mode下,发送及接收到的数据均以ASCII码的显示来表示,可以发送指令"AT+CMGF=1",将GSM短信发送方式更改为文本模式。文本模式下接收的数据会自动解码,比如你收到一条短信息,GSM会返回:+CMGR: “REC UNREAD”,"+8613806XXXXXX",“11/10/21,13:22:13+32” hello (短信内容会自动换行) 不需要自己解码,便可得到短信的发送者、发送时间和短信内容,比较容易操作。 理论上Text Mode下,是只能够收发英文短信,但是SIM900A模块可以在Text Mode下使用UCS2编码,从而可以发送接收中文短信。 2.PDU Mode PDU相当于一个数据包,它由SMS的信息组成,作为一种数据单元,必须包含源地址、目的地址、有效时间、数据格式、协议类型、正文、正文长度(可达140字节),这些信息都以十六进制表示。 PUD Mode被所有手机支持,可以使用任何字符集,其编码方式分为:7bit、8bit、UCS2。 7-bit编码用于发送普通的ASCII字符,它将一串7-bit的字符(最高位为0)编码成8-bit的数据,每8个字符可“压缩”成7个;8-bit编码通常用于发送数据消息,比如图片和铃声等;而UCS2编码用于发送Unicode字符。在这三种编码方式下,PDU串的用户信息(TP-UD)段最大容量(可以发送的短消息的最大字符数)分别是160、140和70。这里,将一个英文字母、一个汉字和一个数据字节都视为一个字符。 理论上发送中文短信需要使用PDU Mode的UCS2编码,上面也说了,SIM900A模块可以使用Text Mode发送UCS2编码,而且PDU Mode比Text Mode更加复杂,所以我采用了Text Mode收发中英文短信。 PDU Mode的详细讲解可以借鉴此博客:点击链接跳转 3.GSM编码 在GSM编码模式下,收发消息的内容和电话号码,都是以ASCII字符的形式显示的,发送英文短信时使用十分方便。 所以我使用GSM编码来收发英文短信。 4.UCS2编码 谈到UCS2编码就不得不说UNICODE,UNICODE又叫统一码、万国码,是计算机科学领域里的一项行业标准,包括字符集、编码方案等。UNICODE 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。简单来说,UNICODE编码可以表示世界上任意一种语言(有点夸张),自然也可以表示中文。 而UCS2编码是UNICODE的一种,UCS2中每个字符都占俩个字节。 使用UCS2编码后,发送短信的手机号码、短信内容都要经过UCS2编码转换才可以,但UCS2编码发送的消息在手机上可以直接显示为中文。 所以,需要UCS2与中文的转换软件,如下,可以实现中文和UCS2的双向转换 图片 三.收发英文短信 1.AT+CPMS查询短信数量 图片 2.AT+CNMI设置新消息提示类型 图片 3.AT+CMGF选择短信模式 图片 4.AT+CSCS设置编码 图片 图片 5.AT+CSMP设置短信文本模式 使用Text Mode的GSM编码时,短信文本模式设置为: AT+CSMP=17,167,0,240(消息显示在终端) AT+CSMP=17,167,0,241(消息存储在SIM卡中) 图片 6.AT+CMGS发送消息到指定手机号 使用Text Mode的GSM编码时,直接AT+CMGS="手机号"即可,然后,在>后输入要发送的内容(不要勾选发送新行),最后发送HEX(十六进制)的:1A 即可。 如图,我使用本机向本机发送了一条短信,而且,本机收到短信后在终端中显示出来了。 图片 这是SIM公司给出的例子: 图片 CTRL-Z 代表十六进制:1A 使用SIM900A向本机发送一条英文短信的完整步骤如下: 图片 四.收发中文短信 收发中文短信利用的是Text Mode下的UCS2编码。 相比于收发英文短信,收发中文短信需要修改的地方有: 修改编码:AT+CSCS=“UCS2” 修改短信文本模式:AT+CSMP=17,167,0,24(短消息显示在终端,25:存储在SIM中) 手机号码要用UNICODE码 发送的消息要用UNICODE码(有专门的转换软件) 这是SIM公司给出的例子: 图片 我要发送信息:可爱的小白鼠,女朋友收到后回复消息,用软件将UNICODE码转换为中文,串口操作界面如示: 图片 发消息如示: 图片 收消息如示: 图片 这是我的SIM900A 图片
嵌入式&系统
刘航宇
4年前
0
1,171
2
HAL_STM32_DS18B20开发
1.设置一个如PA0作为DS18B20模块接口 2.添加下面2个文件,注意程序已经集成us延时 ds18b20.c #include "ds18b20.h" static inline void delay_ms(uint32_t delay) { HAL_Delay(delay); } #define CPU_FREQUENCY_MHZ 72 // CPU主频,根据实际进行修改 static void delay_us(uint32_t delay) { int last, curr, val; int temp; while (delay != 0) { temp = delay > 900 ? 900 : delay; last = SysTick->VAL; curr = last - CPU_FREQUENCY_MHZ * temp; if (curr >= 0) { do { val = SysTick->VAL; } while ((val < last) && (val >= curr)); } else { curr += CPU_FREQUENCY_MHZ * 1000; do { val = SysTick->VAL; } while ((val <= last) || (val > curr)); } delay -= temp; } } //复位DS18B20 void DS18B20_Rst(void) { DS18B20_IO_OUT(); //SET PA0 OUTPUT DS18B20_DQ_OUT=0; //拉低DQ delay_us(750); //拉低750us DS18B20_DQ_OUT=1; //DQ=1 delay_us(15); //15US } //等待DS18B20的回应 //返回1:未检测到DS18B20的存在 //返回0:存在 uint8_t DS18B20_Check(void) { uint8_t retry=0; DS18B20_IO_IN();//SET PA0 INPUT while (DS18B20_DQ_IN&&retry<200) { retry++; delay_us(1); }; if(retry>=200)return 1; else retry=0; while (!DS18B20_DQ_IN&&retry<240) { retry++; delay_us(1); }; if(retry>=240)return 1; return 0; } //从DS18B20读取一个位 //返回值:1/0 uint8_t DS18B20_Read_Bit(void) // read one bit { uint8_t data; DS18B20_IO_OUT();//SET PA0 OUTPUT DS18B20_DQ_OUT=0; delay_us(2); DS18B20_DQ_OUT=1; DS18B20_IO_IN();//SET PA0 INPUT delay_us(12); if(DS18B20_DQ_IN)data=1; else data=0; delay_us(50); return data; } //从DS18B20读取一个字节 //返回值:读到的数据 uint8_t DS18B20_Read_Byte(void) // read one byte { uint8_t i,j,dat; dat=0; for (i=1;i<=8;i++) { j=DS18B20_Read_Bit(); dat=(j<<7)|(dat>>1); } return dat; } //写一个字节到DS18B20 //dat:要写入的字节 void DS18B20_Write_Byte(uint8_t dat) { uint8_t j; uint8_t testb; DS18B20_IO_OUT();//SET PA0 OUTPUT; for (j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if (testb) { DS18B20_DQ_OUT=0;// Write 1 delay_us(2); DS18B20_DQ_OUT=1; delay_us(60); } else { DS18B20_DQ_OUT=0;// Write 0 delay_us(60); DS18B20_DQ_OUT=1; delay_us(2); } } } //开始温度转换 void DS18B20_Start(void)// ds1820 start convert { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0x44);// convert } //初始化DS18B20的IO口 DQ 同时检测DS的存在 //返回1:不存在 //返回0:存在 uint8_t DS18B20_Init(void) { DS18B20_Rst(); return DS18B20_Check(); } //从ds18b20得到温度值 //精度:0.1C //返回值:温度值 (-550~1250) short DS18B20_Get_Temp(void) { uint8_t temp; uint8_t TL,TH; short tem; DS18B20_Start (); // ds1820 start convert DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0xbe);// convert TL=DS18B20_Read_Byte(); // LSB TH=DS18B20_Read_Byte(); // MSB if(TH>7) { TH=~TH; TL=~TL; temp=0;//温度为负 }else temp=1;//温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL;//获得底八位 tem=(float)tem*0.625;//转换 if(temp)return tem; //返回温度值 else return -tem; } ds18b20.h #ifndef __DS18B20_H #define __DS18B20_H #include "main.h" #include "stm32f1xx_hal.h" //#include "delay.h" #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) #define GPIOA_ODR_Addr (GPIOA_BASE+12) #define GPIOB_ODR_Addr (GPIOB_BASE+12) #define GPIOC_ODR_Addr (GPIOC_BASE+12) #define GPIOD_ODR_Addr (GPIOD_BASE+12) #define GPIOE_ODR_Addr (GPIOE_BASE+12) #define GPIOF_ODR_Addr (GPIOF_BASE+12) #define GPIOG_ODR_Addr (GPIOG_BASE+12) #define GPIOA_IDR_Addr (GPIOA_BASE+8) #define GPIOB_IDR_Addr (GPIOB_BASE+8) #define GPIOC_IDR_Addr (GPIOC_BASE+8) #define GPIOD_IDR_Addr (GPIOD_BASE+8) #define GPIOE_IDR_Addr (GPIOE_BASE+8) #define GPIOF_IDR_Addr (GPIOF_BASE+8) #define GPIOG_IDR_Addr (GPIOG_BASE+8) #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //IO方向设置 #define DS18B20_IO_IN() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;} #define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;} //IO操作函数 #define DS18B20_DQ_OUT PAout(0) //数据端口 PA0 #define DS18B20_DQ_IN PAin(0) //数据端口 PA0 uint8_t DS18B20_Init(void); //初始化DS18B20 short DS18B20_Get_Temp(void); //获取温度 void DS18B20_Start(void); //开始温度转换 void DS18B20_Write_Byte(uint8_t dat);//写入一个字节 uint8_t DS18B20_Read_Byte(void); //读出一个字节 uint8_t DS18B20_Read_Bit(void); //读出一个位 uint8_t DS18B20_Check(void); //检测是否存在DS18B20 void DS18B20_Rst(void); //复位DS18B20 #endif程序进行调用 使用温度=DS18B20_Get_Temp();进行调用数值,可见精度达到要求了 图片 图片
嵌入式&系统
刘航宇
4年前
4
1,465
11
2022-01-31
【10】基于STM32CubeMX-STM32ADC与OLED开发
目录 实训案例:ADC与OLED综合训练 实训案例:ADC与OLED综合训练 在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能: 【1】 上电开机后,首选在OLED上显示“强国图志”图片,然后让LED1与LED2依次点亮,然后熄灭,进行灯光检测。灯光检测结束后,OLED切换至数据显示界面,分3行: 第1行显示:“ sciarm.com ” 第2行显示:“采样值:” 第3行显示:“电压值:” 【2】在主程序中,采用查询的方式,每隔0.3秒对ADC_IN0通道的光敏传感器进行一次电压数据采集,并将采样到的12位数据换算成对应的实际电压值。LED1作为A/D采样指示灯,每采样一次闪烁一下。 【3】每进行完一次光敏传感器的数据采样和电压换算后,将其结果更新到OLED显示屏中相应的位置。如果光敏传感器的电压值小于1.3V,则将LED2灯点亮,反之,将LED2灯关闭。 图片 //首先需要进行OLED的底层驱动函数移植,生成相应的文字和图片数据 /* USER CODE BEGIN Includes */ //====引入OLED底层驱动的头文件======== #include "XMF_OLED_STM32Cube.h" #include "stdio.h" /* USER CODE END Includes */extern unsigned char BMP1[]; #define LED1_ON() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_SET) #define LED2_ON() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_RESET) #define LED2_OFF() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8,GPIO_PIN_RESET) uint16_t ADC0_Value = 0; uint16_t ADC_Volt = 0; uint8_t str_buff[64];//LED灯流水点亮检测 void LED_Check() { LED1_ON(); HAL_Delay(500); LED2_ON(); HAL_Delay(500); LED1_OFF(); HAL_Delay(500); LED2_OFF(); HAL_Delay(500); }//显示开机LOGO图片 void OLED_display_pic() { OLED_Clear(); OLED_DrawBMP(0,0,128,8,BMP1); }//显示数据显示界面 void OLED_display_info() { OLED_Clear(); OLED_ShowString(6,0,(uint8_t *)"sciarm.com"); HAL_Delay(200); OLED_ShowCHinese(0,3,24); OLED_ShowCHinese(18,3,25); OLED_ShowCHinese(36,3,26); OLED_ShowString(54,3,(uint8_t *)":"); HAL_Delay(200); OLED_ShowCHinese(0,6,16); OLED_ShowCHinese(18,6,17); OLED_ShowCHinese(36,6,26); OLED_ShowString(54,6,(uint8_t *)":"); HAL_Delay(200); }//更新ADC采样数据与换算结果 void OLED_display_dat() { sprintf((char*)str_buff, "%4d", ADC0_Value); OLED_ShowString(64,3,(uint8_t *)str_buff); sprintf((char*)str_buff, "%d.%d%dV", ADC_Volt/100, (ADC_Volt%100/10), ADC_Volt%10); OLED_ShowString(64,6,(uint8_t *)str_buff); }//ADC采样过程与灯光自动控制 void Get_ADC0_Value() { HAL_ADC_Start(&hadc1); if(HAL_OK == HAL_ADC_PollForConversion(&hadc1, 30)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); ADC_Volt = ADC0_Value * 330 / 4096; if(ADC_Volt < 130) { LED2_ON(); } else { LED2_OFF(); } } HAL_ADC_Stop(&hadc1); }/* USER CODE BEGIN 2 */ OLED_Init(); //初始化OLED OLED_display_pic(); //显示开机LOGO图片 LED_Check(); //灯光检测 OLED_display_info(); //显示数据界面 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { LED1_ON(); //ADC采样指示灯点亮 Get_ADC0_Value(); //进行一次ADC采样及逻辑处理 OLED_display_dat(); //更新OLED中的采样数据 HAL_Delay(200); //延时0.2秒 LED1_OFF(); //ADC采样指示灯关闭 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
嵌入式&系统
# 嵌入式
刘航宇
4年前
0
1,072
13
2022-01-29
【9】基于STM32CubeMX-STM32OLED开发
目录 必备文件 关于OLED的概述 OLED开发相关资源下载 基于STM32CubeMX的OLED底层驱动函数移植 OLED驱动库中常用的函数 实训案例:STM32控制OLED显示 必备文件 OLED文件-SPI版 下载地址:https://wwu.lanzoub.com/iCqK302ybokh 提取码: OLED I2C版4脚 下载地址:https://wwi.lanzouw.com/ilMr9zjrhsb 提取码: 关于OLED的概述 OLED:Organic Light-Emitting Display,有机发光显示。 OLED具备自发光、厚度薄、视角广、功耗低、对比度高、响应速度快、可用于挠曲性面板、使用温度范围广、构造及其制作过程较简单等优异特性,并认为是一种比液晶显示更为先进的新一代平板显示技术。以目前的技术,OLED的尺寸还难以大型化,但是分辨率却可以做得很高。 基于STM32的OLED应用,要做那些事情: 【1】移植OLED的底层驱动函数库。 【2】准备需要的中文字符和图片等数据。 【3】调用OLED驱动库中的底层函数进行应用开发。 图片 OLED开发相关资源下载 基于STM32CubeMX的OLED屏驱动程序库(内含4个文件) 【1】XMF_OLED_STM32Cube.c:驱动程序的源文件。 【2】XMF_OLED_STM32Cube.h:驱动程序的头文件。 【3】XMF_OLED_Font.h:字库数据文件。 【4】XMF_OLED_BMP.h:图片数据文件。 基于STM32CubeMX的OLED底层驱动函数移植 【1】将4个驱动文件拷贝到工程文件中,和main.c放在同一目录,并将XMF_OLED_STM32Cube.c添加到工程代码文件中,并在main.c中引入头文件XMF_OLED_STM32Cube.h。 【2】根据所选用的芯片型号,修改XMF_OLED_STM32Cube.h头文件中所以用的芯片头文件。 【3】根据硬件电路原理图中,修改XMF_OLED_STM32Cube.h中OLED的引脚定义。 【4】查看OLED_Init(void)初始化函数的源码,根据电路接口和应用需要进行修改。 图片 OLED驱动库中常用的函数 void OLED_Init(void); //OLED初始化函数 void OLED_Clear(void); //OLED清屏函数//显示英文字符串函数 void OLED_ShowString(unsigned char x,unsigned char y,unsigned char *p); 参数1:x,起点列坐标,0~127 参数2:y,起点行坐标,0~7 参数3:*p,字符串指针 返回值:void,无。//显示中文字符函数 void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no); 参数1:x,起点列坐标,0~127 参数2:y,起点行坐标,0~7 参数3:no,待显示中文字符在数组Hzk[][32]中的位置。 返回值:void,无。//显示图片函数 void OLED_DrawBMP( unsigned char x0, unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]); 参数1:x0,起点列坐标,0~127 参数2:y0,起点行坐标,0~7 参数3:x1,图片的列范围,1~128 参数4:y1,图片的行范围,1~8 参数5:BMP[],待显示图片数据的数组。 返回值:void,无。实训案例:STM32控制OLED显示 要点 图片 字库软件中行前后缀不需要括号 在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能: 【1】用取字模软件生产一张图片数据,作为开机界面在OLED上显示。 【2】0.5秒后进入信息界面, 第1行显示网址“sciarm.com”, 第2行显示中文“小蜜蜂笔记”,第3行显示日期“2022-02-18”。 图片 //用取字模软件生成开机LOGO图片数据,并拷贝到XMF_OLED_BMP.h的数组中。 const unsigned char BMP1[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //此处省略64×62个字节元素 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };//用取字模软件生成所需中文字符数据,保持到XMF_OLED_Font.h中的Hzk[]数组。 const unsigned char Hzk[][32]={ {0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x20,0x40,0x80,0x00,0x00}, {0x08,0x04,0x03,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x01,0x0E,0x00},/*"小",0*/ /* (16 X 16 , 宋体 )*/ {0x10,0x4C,0x24,0x04,0xF4,0x84,0x8D,0x56,0x44,0x24,0x14,0xC4,0x24,0x54,0x0C,0x00}, {0x00,0x41,0x5D,0x55,0x54,0x55,0x55,0x7F,0x55,0x55,0x55,0x55,0x7C,0xC0,0x00,0x00},/*"蜜",1*/ /* (16 X 16 , 宋体 )*/ {0x00,0xF8,0x08,0xFF,0x08,0xF8,0x80,0x90,0x4C,0x57,0xA4,0x54,0x4C,0x84,0x80,0x00}, {0x20,0x63,0x21,0x1F,0x11,0x39,0x10,0x10,0x15,0x15,0xFF,0x15,0x15,0x10,0x10,0x00},/*"蜂",2*/ /* (16 X 16 , 宋体 )*/ {0x10,0x08,0x44,0x47,0x4C,0x54,0x44,0xD4,0x28,0x27,0x24,0x2C,0x34,0x04,0x04,0x00}, {0x00,0x10,0x12,0x12,0x12,0x12,0x12,0x7F,0x89,0x89,0x89,0x89,0x89,0x88,0xF0,0x00},/*"笔",3*/ /* (16 X 16 , 宋体 )*/ {0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x84,0x84,0x84,0x84,0x84,0xFC,0x00,0x00,0x00}, {0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x3F,0x40,0x40,0x40,0x40,0x41,0x40,0x70,0x00},/*"记",4*/ /* (16 X 16 , 宋体 )*/ };extern unsigned char BMP1[]; void OLED_display_pic() { OLED_Clear(); OLED_DrawBMP(0,0,128,8,BMP1); }void OLED_display_info() { OLED_Clear(); OLED_ShowString(6,0,(uint8_t *)"sciarm.com"); OLED_ShowCHinese(10,3,0); //小 OLED_ShowCHinese(28,3,1); //蜜 OLED_ShowCHinese(46,3,2); //蜂 OLED_ShowCHinese(64,3,3); //笔 OLED_ShowCHinese(82,3,4); //记 OLED_ShowString(24,6,(uint8_t *)"2022-02-18"); }//在mian()函数中添加下面的代码: /* USER CODE BEGIN 2 */ OLED_Init(); //OLED初始化 OLED_display_pic(); //显示图片 HAL_Delay(500); //延时0.5秒 OLED_display_info(); //显示信息 /* USER CODE END 2 */
嵌入式&系统
# 嵌入式
刘航宇
4年前
17
2,041
14
2022-01-26
【8】基于STM32CubeMX-STM32ADC开发基础
目录 STM32的ADC资源概述 ADC启动与停止相关的HAL库函数 ADC转换结果读取的HAL库函数 查询方式,阻塞式A/D转换HAL库函数 中断方式,非阻塞式A/D转换HAL库函数 实训案例:ADC单次数据采样与电压换算用查询,阻塞的方式来实现 用中断,非阻塞的方式来实现 STM32的ADC资源概述 STM32F103ZE芯片(144脚)中有ADC1、ADC2、ADC3共3个12位逐次逼近型模数转换器,具有18个测量通道,可测量16个外部和2个内部信号源(内部温度和内部参考电压)。这2个内部信号源只能连接到ADC1。 ADC的各个通道的A/D转换可以单次、连续、扫描或间断模式执行。 A/D转换结果以左对齐或右对齐的方式,存储在16位规则组或者注入组数据寄存器中。 按照A/D转换的组织形式来划分,ADC的模拟输入通道分为规则组和注入组两种。 ADC可以对一组最多16个通道按照指定的顺序逐个进行转换,这组指定的通道称为规则组。 在实际应用中,可能需要中断规则组的转换,临时对某些通道进行转换,好像这些通道注入了原来的规则组,故称注入组,最多由4个通道组成。 ADC启动与停止相关的HAL库函数 //查询,阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc); //查询,阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);ADC转换结果读取的HAL库函数 uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc); 参数1:hadc,ADC实例指针。 返回值:uint32_t,ADC转换结果。查询方式,阻塞式A/D转换HAL库函数 HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout); 参数1:hadc,ADC实例指针。 参数2:Timeout,超时时间。 返回值:HAL_StatusTypeDef,函数执行状态。应用实例:用查询的方式,进行一次A/D采样并将结果读出。 uint16_t ADC_Value = 0; //以查询的方式启动ADC HAL_ADC_Start(&hadc); //等待一次规则组的ADC转换完成,并将结果读出 if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); }中断方式,非阻塞式A/D转换HAL库函数 应用实例:用中断的方式,进行一次A/D采样并将结果读出。 uint16_t ADC_Value = 0; //以中断的方式启动ADC HAL_ADC_Start_IT(&hadc); //重写ADC转换完成中断回调函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { ADC0_Value = HAL_ADC_GetValue(&hadc1); }实训案例:ADC单次数据采样与电压换算 在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能: 【1】将ADC_IN0设置为12位ADC,右对齐,启用中断。 【2】分别用查询和中断这2种方式,每隔0.5秒采样一次ADC的数据。 【3】将每次读取到的ADC采样值转换为对应电压值,发送到上位机。 【4】LED1作为采样指示灯,在ADC转换过程中点亮,其余时间熄灭。 图片 要点配置 图片 图片 串口 图片 没有接收中断,不需要对NVIC进行使能 #include "stdio.h" #define LED1_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET) uint16_t ADC0_Value = 0, ADC0_Volt = 0; uint8_t str_buff[64];void UR1_Send_Info() { sprintf((char *)str_buff,"采样值:%d,电压值:%d.%d%dV\r\n",ADC0_Value,ADC0_Volt/100,(ADC0_Volt%100)/10,ADC0_Volt%10); HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000); }用查询,阻塞的方式来实现 void Get_ADC_Value() { HAL_ADC_Start(&hadc1); LED1_ON(); if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); ADC0_Volt = ADC0_Value * 330 / 4096; } UR1_Send_Info(); LED1_OFF(); HAL_ADC_Stop(&hadc1); }//在mian()函数中添加以下代码: /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { Get_ADC_Value(); //启动一个阻塞式的ADC转换并读取数据 // UR1_Send_Info(); //向上位机发生采样值和电压值 HAL_Delay(500); //延时0.5秒,再进行下一次ADC采样 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */用中断,非阻塞的方式来实现 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { ADC0_Value = HAL_ADC_GetValue(&hadc1); //读取ADC转换结果 ADC0_Volt = ADC0_Value * 330 / 4096; //将采样值换算成电压值 UR1_Send_Info(); //向上位机发生ADC采样信息 LED1_OFF(); //关闭LED1采样指示灯 } }//在mian()函数中添加以下代码: /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_ADC_Start_IT(&hadc1); //启动一个非阻塞式的ADC转换并读取数据 LED1_ON(); //点亮LED1采样指示灯 HAL_Delay(500); //延时0.5秒,再进行下一次ADC采样 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
嵌入式&系统
# 嵌入式
刘航宇
4年前
1
1,505
11
【4】基于STM32CubeMX-STM32定时器开发
目录 定时器的基本概述 STM32通用定时器的重要知识点 实训案例:外部中断信号控制LED灯开关 定时器的基本概述 通过滴漏和漏沙瓶这两个例子简单讲述定时器的基本工作原理。 STM32的常见的定时器资源: 系统嘀嗒定时器SysTick、看门狗定时器WatchDog、实时时钟RTC、基本定时器、通用定时器、高级定时器。 系统嘀嗒定时器SysTick :这是一个集成在Cortex M3内核当中的定时器,它并不属于芯片厂商的外设,也就是说使用ARM内核的不同厂商,都拥有基本结构相同的系统定时器。主要目的是给RTOS提供时钟节拍做时间基准。 基本定时器:TIM6、TIM7。 通用定时器:TIM2、TIM3、TIM4、TIM5。在基本定时器的基础上,实现输出比较、输入捕获、PWM生成、单脉冲模式输出等功能。这类定时器最具代表性,使用也最广泛。 高级定时器:TIM1、TIM8。 STM32通用定时器的重要知识点 通用定时器的基本结构组成: STM32的通用定时器,是一个通过可编程预分频器(Prescaler)驱动的16位自动重装主计数器(Counter Period)构成。可以对内部时钟或触发源以及外部时钟或触发源进行计数。 通用定时器的基本工作原理: 首先,定时器时钟信号送入16位可编程预分配器(Prescaler),该预分配器系数为0~65535之间的任意数值。预分配器溢出后,会向16位的主计数器(Counter Period)发出一个脉冲信号。 预分频器,本质上是一个加法计数器,预分频系数实际上就是加计数的溢出值。 定时器发生中断时间的计算方法: 定时时间 = (Prescaler+1 ) X (Counter Period+1) X 1/ 定时器时钟频率 时钟信号1KHz,Prescaler为9,Counter Period为999,定时时间? 图片 计算案例 图片 实训案例:外部中断信号控制LED灯开关 配置要点 图片 图片 图片 图片 图片 图片 图片 图片 在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能: 【1】利用TIM2实现间隔定时,每隔0.2秒将LED1的开关状态翻转。 【2】利用TIM3实现间隔定时,每隔1秒将LED2的开关状态翻转。 【3】修改TIM2的初始化代码,改为每隔0.5秒将LED1的开关状态翻转。 图片 /* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) //处理TIM2间隔定时中断 { AL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); } if(htim->Instance == TIM3) //处理TIM3间隔定时中断 { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); } } /* USER CODE END 0 *//* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim2); //启动定时器TIM2 HAL_TIM_Base_Start_IT(&htim3); //启动定时器TIM3 //有IT的代表使能时钟中断 /* USER CODE END 2 */
嵌入式&系统
# 嵌入式
刘航宇
4年前
2
1,370
26
2022-01-17
【3】基于STM32CubeMX-STM32中断系统
目录 中断什么意思 STM32的中断系统 STM32的外部中断 外部中断的程序设计思路 外部中断初始化函数剖析 外部中断服务函数的编写 实训案例:外部中断信号控制LED灯开关 中断什么意思 你打开火,烧上一壶水。然后去洗衣服,在洗衣服的过程中,突然听到水壶发出水开的报警声,这时,你停止洗衣服动作,立即去关掉火,然后将开水灌入暖水瓶中,灌完开水后,你又回去继续洗衣服。这个过程中实际上就发生了一次中断。 如图: 图片 图片 STM32的中断系统 理解中断、中断源、中断向量、中断优先级、中断服务函数…等基础概念。 ARM Cortex M3内核支持256个中断,包括16个内核中断和240个外设中断,拥有256个中断优先级别。 STM32的中断通道可能会由多个中断源共用。这就意味着,某一个中断服务函数也可能被多个中断源所共用。所以,在中断服务函数的入口处,需要有一个判断机制,用以辨别是那个中断触发了中断。 STM32微处理器的内核中有一个NVIC(嵌套向量中断控制器)的设备,它对中断进行统一的协调和控制,其中最主要的工作就是控制中断通道的使能和确定中断的优先级。 STM32中有2个优先级的概念:抢占优先级和响应优先级,每个中断都需要指定这两种优先级。 如果两个抢占优先级相同的中断同时到达,NVIC会根据他们的响应优先级高低来决定先处理哪一个。如果两个同时到达的中断的抢占优先级和响应优先级都相等,则根据中断的自然排位顺序来决定响应哪一个。 STM32的外部中断 外部中断EXTI是STM32微处理器实时处理外部事件的一种机制,由于中断请求主要来自GPIO端口的引脚,所以称为外部中断。 STM32F013微处理器有19个能产生事件/中断请求的边沿检测器,每个输入线可以独立地配置成输入类型(脉冲或挂起)和对应的触发事件(上升沿、下降沿或双边沿触发),也可以独立地屏蔽。 EXTI0~EXTI15:GPIO端口引脚。 EXTI16:PVD输出,可编程电压监测。 EXTI17:RTC闹钟。 EXTI18:USB唤醒。 外部中断的程序设计思路 传统STM32外部中断设计步骤 : 【1】将GPIO初始化为输入端口。 【2】配置相关I/O引脚与中断线的映射关系。 【3】设置该I/O引脚对应的中断触发条件。 【4】配置NVIC,并使能中断。 【5】编写中断服务函数。 配置要点提示 引脚设外部中断,上升沿,上拉 图片 使能NVIC 图片 基于STM32CubeMX的外部中断设计步骤: 【1】在STM32CubeMX中指定引脚,配置中断初始化参数。 选择GPIO引脚的功能,设置中断信号触发条件,使能NVIC对应的中断通道。 【2】重写该I/O引脚对应的中断回调函数。 外部中断初始化函数剖析 //外部中断初始化相关的操作在gpio.c文件中的MX_GPIO_Init()函数完成。 void MX_GPIO_Init(void) { /*===================== 此处省略无关代码。 ======================*/ /* EXTI interrupt init 外部中断初始化*/ HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0); //设置EXIT9~EXIT5中断的优先级 HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); //使能EXIT9~EXIT5中断通道 HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); }外部中断服务函数的编写 图片 实训案例:外部中断信号控制LED灯开关 在XMF07A或XMF07C开发板上, 利用STM32CubeMX和Keil5协同开发, 完成以下的功能: 【1】将KEY2,即PC13设置为外部中断输入,下降沿触发。在中断服务函数中,切换LED1的开关状态。 【2】将KEY4,即PB5设置为外部中断输入,上升沿触发。在中断服务函 数中,切换LED2的开关状态。 图片 //外部中断的初始化函数由STM32CubeMX辅助生成,用户只需要重写中断回调函数。 /* USER CODE BEGIN 0 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_13) { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); } if(GPIO_Pin == GPIO_PIN_5) { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); } } /* USER CODE END 0 */
嵌入式&系统
# 嵌入式
刘航宇
4年前
0
1,172
15
2022-01-16
【1】基于STM32CubeMX-STM32GPIO端口开发
目录 STM32CubeMX的声明 protuesSTM32仿真开发板下载 STM32的GPIO端口知识要点 GPIO电平输出HAL库函数 GPIO电平翻转HAL库函数 GPIO初始化函数源码剖析 实训案例:基于STM32CubeMX的跑马灯 仿真开发实例 STM32CubeMX的声明 【1】STM32CubeMX 是一个代码辅助生成工具,在生成工程代码的同时,根据你的功能选择和配置帮你做了必要的初始化,这也就意味着你不再需要对底层的特殊功能寄存器进行初 始化配置,但是不代表你就可以不去学习 STM32 的基本知识和各个外设的工作原理与参数 特性等。 【2】虽然不再要求你去了解 STM32 底层寄存器的定义,但却要求你要了解由 STM32CubeMX生产的代码内在的逻辑联系以及 HAL 库中的常用函数原型与使用。 【3】STM32CubeMX 的最大好处就是,使开发流程、文件结构、库函数等标准化 protuesSTM32仿真开发板下载 protues STM32C8开发板 下载地址:https://wwu.lanzoub.com/ixmmx04hidud 提取码: STM32的GPIO端口知识要点 GPIO:General Purpose Input & Output STM32芯片最拥有GPIOA、GPIOB…GPIOG等7组端口,每组端口最多拥有Pin0、Pin1…Pin15共16个引脚。 STM32的每个I/O端口都可以自由编程,但I/O端口寄存器必须按32位字被访问。STM32的每个I/O端口都由7个寄存器来控制。 STM32的GPIO端口可以由软件配置成8种模式: 推挽输出、开漏输出、推挽式复用功能、开漏式复用功能; 模拟输入、浮空输入、下拉输入、上拉输入。 GPIO电平输出HAL库函数 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState); 参数1:GPIOx,端口号,如:GPIOB,GPIOF。 参数2:GPIO_Pin,引脚号,如:GPIO_PIN_9,GPIO_PIN_12。 参数3:PinState,引脚输出状态。高电平----GPIO_PIN_SET;低电平----GPIO_PIN_RESET。 返回值:void,空。 应用举例:向PB8引脚输出高电平。 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);GPIO电平翻转HAL库函数 void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 参数1:GPIOx,端口号,如:GPIOB,GPIOF。 参数2:GPIO_Pin,引脚号,如:GPIO_PIN_9,GPIO_PIN_12。 返回值:void,空。 应用举例:将PA3引脚输出电平翻转。 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);GPIO初始化函数源码剖析 void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO端口时钟使能 */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*配置GPIO端口引脚的初始化输出电平 */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_RESET); /*配置GPIO端口输入引脚 : PC13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; //GPIO端口的引脚号是:13 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //GPIO的模式是:输入 GPIO_InitStruct.Pull = GPIO_NOPULL; //没有上拉 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); //将参数结构设置到GPIOC端口 /*配置GPIO端口输出引脚 : PB8 PB9 */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; //GPIO端口的引脚号是:8和9 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //GPIO的模式是:输出 GPIO_InitStruct.Pull = GPIO_NOPULL; //没有上拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; //GPIO的输出速度是:非常低速 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //将参数结构设置到GPIOB端口 }实训案例:基于STM32CubeMX的跑马灯 在XMF07A或XMF07C开发板上,利用STM32CubeMX对STM32芯片的LED控制引脚进行配置并快速生产项目,在Keil5中进行代码编写,实现跑马灯功能,即:LED1灯亮,过一会,LED2灯亮,过一会,LED1灯熄灭,过一会,LED2灯熄灭….如此循环。 XMF07C开发板:STM32L151C8T6 (电路功能兼容物联网国赛设备) XMF07A开发板:STM32F103C8T6 图片 /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //向PB9输出高电平,点亮LED1灯 HAL_Delay(500); //延时500ms HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //向PB9输出低电平,熄灭LED1灯 HAL_Delay(500); //延时500ms HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); //用翻转电平的方式,实现LED1灯的点亮与熄灭 HAL_Delay(500); //延时500ms HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); //用翻转电平的方式,实现LED2灯的点亮与熄灭 HAL_Delay(500); //延时500ms /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */仿真开发实例 原理图: 图片 1.新建CubeMX工程 选择对应的MCU,在proteus8中支持STM32F103的几款muc,这里我们选择STM32R6 图片 设置下载方式 图片 配置LED灯的GPIO l1p0om1l.png图片 配置时钟树 l1p0ownv.png图片 选择keil5工程(或者其他工程) l1p0pb0l.png图片 勾选此处可以使得每个初始化的外设有独立的.c和.h l1p0ptxo.png图片 生成MDK工程 l1p0ro0x.png图片 添加LED闪烁的代码,并编译生成.hex文件 HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5); HAL_Delay(0XFF)l1p0sq2c.png图片 将hex文件下载到proteus8中去 l1p0t26z.png图片 此时仿真会报错,原因是电源为接入,只需要将电源接入即可 l1p0tjr9.png图片 此处VDDA,VSSA分别加入到电网VCC与GND中,详细可以百度 l1p0tpli.png图片 最后,就可以看到有一个LED灯反复交替闪烁! l1p0u3mg.png图片
嵌入式&系统
# 嵌入式
刘航宇
4年前
8
6,899
118
上一页
1
...
4
5
6
...
9
下一页