STM32示波器设计

2023-11-17

目录

前言

1、硬件模块

2、示波器基础知识

2.1 当头一棒就是,波形的概念

2 .2 第二就是需要观察的波形参数

2.3 第三就是示波器参数

2.3.1 采样率

2.3.2 带宽

2.3.4 刷新率

3、ADC采集和DAC输出

3.1 ADC 采集实现

3.1.1 配置ADC采集为定时触发DMA采集模式

3.1.2 配置ADC关联的定时器

3.1.3 转换成有效值

3.2 DAC波形输出

3.2.1 选择定时器触发

3.2.2 配置定时器

3.2.3 生成波形数据

4、波形刷新方案

4.1 初始化流程

4.2 生成波形数据

4.3 波形刷新

方案1:消隐一条线,画当前线,而不是消隐完再画线

方案2:特殊处理网格点

方案3:计算像素点,整屏刷新

5、触发模式

6、存储深度


前言

出于产品需求,需要在产品中集成示波器功能,满足显示实时电压的需求。

这篇文章就总结和讨论一下示波器的方案设计(低成本)。

其中,实现方案主要是在3、4章节,1、2是概念部分和环境介绍,不需要的可以跳过。

如下是我设计时的主要参考资料。

参考资料1:二代示波器教程 - 随笔分类 - 硬汉eric2013 - 博客园 (cnblogs.com)

参考资料2:STM32袖珍示波器DS201设计 - 电路城 (cirmall.com)

1、硬件模块

总体而言,能够提供的硬件模块2个:MCU的ADC接口,LCD屏幕,别的就没了;

放大电路、滤波功能统统没有,demo板子直接用MCU的ADC接口采集外部电压,将处理后的数据送到屏幕去刷新。

同时为了模拟测量数据,还使用DAC+定时器来输出正弦波、方波、三角波等波形。

2、示波器基础知识

2.1 当头一棒就是,波形的概念

概念1:波形是指相应物理量在时间和空间上的分布情况的图形抽象。

概念2:正弦波是在时域中定义的,其它任何非正弦波形都可以看作是正弦波的叠加。

2 .2 第二就是需要观察的波形参数

如下图所示。

基本观察参数:最大值、最小值和峰峰值(不是错别字,就是峰峰值,最差);

其它参数还有:顶端值、底端值和幅值,这三者都是在稳定值中计算出来的;

时域参数:上升时间,下降时间,正脉宽,负脉宽,这四者都是测量值,还有频率、占空比,是计算出来的值。

一般我们需要显示的,就是①最大值、最小值和峰峰值,②频率、占空比,③X、Y轴单位大小

2.3 第三就是示波器参数

2.3.1 采样率

采样率是指一秒内能采集到多少个样本值。

理论上说,采样率最大要超过被测信号最大频率的5倍以上,才能较为完整的采集到数据规律。(为什么?被测信号频率除以采样频率,其实就是在被测信号一个周期内能采集到的点数,若小于5个点,则很难具体描绘出数据规律)

STM32单片机的采样率,等于采样时钟除以采样周期,以STM32F4系列芯片为例,ADC最大时钟为36MHz,ADC最小采样周期为3+12个周期,故采样率最大为36/15=2.4MHz。

实际应用中:

1、根据主频时钟,ADC实际分频得到的时钟计算,比如同时使用USB接口时,主频最大168MHz,ADC最大时钟21MHz;

2、可以通过双路或三路ADC同时使用,提高ADC采样率

2.3.2 带宽

带宽的定义:在频幅特性曲线中,当信号衰减至-3db(70.7%)时,此时的频点定义为示波器的带宽。

如何计算?我还没闹明白,留到后面仔细研究。

但是可以明白的是,带宽要大于被测信号的5倍以上(普遍认为的)才能不失真。

采样率低和带宽小对波形带来的的几种影响

 

2.3.4 刷新率

刷新率,即刷新一帧波形图像的速率。

假设刷新一张波形(大约2万个像素点)需要15ms,则刷新率就等于66帧每秒。

刷新率主要受限于MCU主频,以及数据处理效率,和屏幕刷新效率。

数据处理和屏幕刷新的提高有这么几种思路:

1、裸机运行

减少任务切换带来的时间消耗(微秒级)

2、利用缓存

以空间换时间:一种是将函数封装写入存储设备,提高调用效率;一种是开辟缓存(全局变量)存储数据,便于处理波形数据和LCD像素点数据。

3、优化算法

一是优化代码,二是提高编译器优化等级。


对于前期的开发工作,都可以先抛开,先上RTOS,再实现基本的波形实时输出功能,并先在功能上进行优化。优化完毕之后,再在刷新时间上进行尝试优化(可以逐步降级,但不能逐步升级)。

3、ADC采集和DAC输出

前提        {

        芯片平台:STM32F429ZGT6

        ADC:PA3

        DAC:PA4

}

3.1 ADC 采集实现

3.1.1 配置ADC采集为定时触发DMA采集模式

如下以PA3为例,①选择定时器3触发,②选择最小采样周期三,③选择DMA循环模式或Normal模式(半字大小)

3.1.2 配置ADC关联的定时器

如下,选择定时器触发事件为更新事件。

由此我们就用两种手段判断ADC数据转换是否结束:

1、读取ADC的DMAbuf的count值

注意ADC的DMA Count读取函数,读取到的数目,而不是实际长度;比如BUF长度为300,每个单元2byte大小,当DMA满时读取到的数值时300(而不是像串口中断那样,读到的是0)。

2、在DMA完成中断的回调函数中判断

触发完成中断时,肯定意味着1次转换结束,可以直接处理,也可以只关闭不处理(等待线程去处理)。

3.1.3 转换成有效值

ADC数据的第一层处理,就是要根据自己的硬件电路设计,将ADC数值转换成真实电压值。

我这里是MCU直连,所以转换关系就是 vol = adc_value * 3300 / 4096 .

参考资料中,DS201中硬件电路使用了输入放大器和挡位切换电路,需要由硬件工程师计算电阻分压和放大关系,最终得到计算公式。

有了这一层数据,才方便后续进行算法消抖、归一化处理等等。

3.2 DAC波形输出

由于测量内部电压的波形基本是条直线,外部环境输入电压又容易超过3.3V导致MCU烧坏。

所以利用内部DAC输出,用ADC测量DAC,还少了跟地线。

或者更巧妙一点,就只用一个IO,DAC输出的同时用ADC进行测量。

血的教训!

单片机ADC采集的基准电压与芯片供电电压都是3.3V,又没有分压电阻,

所以最大只能测量3.3V。

但是,我接入外部输入时,没控制好,怼了一个12V过去,正点原子380块的STM32H743 MCU直接烧了。


这里DAC的配置,采用的是DMA+DMA+定时器。

3.2.1 选择定时器触发

记得配置为DMA循环模式

3.2.2 配置定时器

还是定时器“更新事件”

3.2.3 生成波形数据

根据自己的测试需求,生成正弦波和方波数据。其本质就是一个uint16_t类型的数组,其中的数据按照一定的周期进行演进。

配置好之后,启动定时器并配置DMAbuf进行输出。

HAL_TIM_Base_Start(&htim6);
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, pData, Length, DAC_ALIGN_12B_R);

4、波形刷新方案

前提        {

        屏幕尺寸:320*240

        波形窗口:300*200

        LCD API函数(初始化、清屏、画点、画线、显示字符串)

}

4.1 初始化流程

1)初始化DAC模块,启动DAC模块数据传输

2)初始化ADC模块,开始采集ADC数据

3)while(1)循环进行如下判断:死等ADC采集完成,完成之后先处理数据,处理之后,先启动下一次ADC传输,再在ADC传输没有结束之前刷新、刷完波形。

4.2 生成波形数据

在”ADC+DMA中断接收“,我们已经收到了真实电压数据集。

假如此时垂直扫描电压为5V(即Y轴最大电压为5V,最小电压为0V),那么y轴又只有200个像素点,每一个点的数值单元为5000/200=25,所以还要对数据集除以25得到对应的Y轴坐标点。

这里有几个问题:

1、能否直接除以25?

假如数据除以25之后,出现与真实值+1、-1的锯齿特性时,会导致波形有毛刺。

这时就需要设计优化算法,比如最简单的四舍五入。

2、X轴坐标点如何确定?

我目前的处理方式时,按照当前水平扫描时钟(时基挡位)扫描1次,比如当前时基为200us,那就200us扫描一次,扫描够300个坐标点结束,开始处理-刷新。

这里也有很多优化方式:比如扫描次数设置为300的倍数,时基缩小对应的倍数或不变,从中筛选若干个范围并取平均得到300个点。


不论如何,最终送给屏幕刷新的就是一个长度为300的数组,对应300个坐标值。这300个坐标值,就叫做波形数据。

4.3 波形刷新

比较简单的方法是,画线+缓存上一次波形数据并消隐;

画线:顾名思义,就是对300个坐标点,每两个点之间画线;

1、先对上一次的波形数据消隐,消隐即将线的颜色化成背景色(擦除上一帧波形);

2、再绘制当前波形数据的波形;

3、缓存当前波形数据。

//绘制波形
//1\擦除原有波形再绘制新波形
//2\输入数组长度为OSC_WIDTH:300
//X0\X1\Y0\Y1分别波形窗口的角落坐标值
void OscDrawWave(uint8_t WaveBuf[])
{
	static uint16_t X = {0};
	static uint8_t WaveBufPre[OSC_WIDTH] = {0};
	
	if(WaveBufPre[0])
	{
		LCD_SetColor(List_c[OSC_M_WAVE].Back, List_c[OSC_M_WAVE].Back);
		for(X = 0; X < X1 - X0 - 1; X++)
		{
			LCD_DrawLine(
				X0 + X, Y1 - WaveBufPre[X], 
				X0 + X + 1, Y1 - WaveBufPre[X+1]
			);
		}
	}
	
	LCD_SetColor(List_c[OSC_M_WAVE].Point, List_c[OSC_M_WAVE].Back);
	for(X = 0; X < X1 - X0 - 1; X++)
	{
		LCD_DrawLine(
			X0 + X, Y1 - WaveBuf[X], 
			X0 + X+ 1, Y1 - WaveBuf[X+1]
		);
	}
	
	for(X = 0; X < X1 - X0; X++){
		WaveBufPre[X] = WaveBuf[X];
	}
}

 这样做的好处就是能减少闪烁频度。

进一步的,从显示原理上,还可以通过以下几种方法提高刷新速度:

方案1:消隐一条线,画当前线,而不是消隐完再画线

如上代码中,即使是做了消隐也会出现闪烁,改成擦除一条线再画一条线,感官上就能好很多。

void OscDrawWave(uint8_t WaveBuf[])
{
	static uint16_t X = {0};
	static uint8_t WaveBufPre[OSC_WIDTH] = {0};
	
	for(X = 0; X < X1 - X0 - 1; X++)
	{
		LCD_SetColor(List_c[OSC_M_WAVE].Back, List_c[OSC_M_WAVE].Back);
		LCD_DrawLine(
			X0 + X, Y1 - WaveBufPre[X], 
			X0 + X + 1, Y1 - WaveBufPre[X+1]
		);
		LCD_SetColor(List_c[OSC_M_WAVE].Point, List_c[OSC_M_WAVE].Back);
		LCD_DrawLine(
		X0 + X, Y1 - WaveBuf[X], 
		X0 + X+ 1, Y1 - WaveBuf[X+1]
	);

	for(X = 0; X < X1 - X0; X++){
		WaveBufPre[X] = WaveBuf[X];
	}
}

方案2:特殊处理网格点

对于示波器要刷新的不知有波形,还有网格线,与波形参数。

波形参数一般要变动的是字符串类型的数值,优化空间不大(像素点大小固定)。

而且波形中,往往有大部分像素点是与网格点重合的。

所以对于网格点,就有三种状态,两种判断:

1、消隐时,网格点要绘画成网格颜色,不能是背景色;

2、绘制时,网格点要绘画成波形颜色,不能是网格颜色;

如果不小心将网格点搞成背景色,就会导致波形刷着刷着,网格没了……

方案3:计算像素点,整屏刷新

这种方案是想,计算所有需要变更状态的像素点,送到屏幕进行一次性刷新,或者退后一步逐个刷新像素点。前者“一次性刷新”可以想办法利用类似DMA2D的方式提高刷新速度,后者则可以减少像素点重复刷新次数,进而提高速度。

目前还没有做出来很好的实现方法,后面再研究并分享一下。

5、触发模式

以上讨论的都是,无触发模式的波形处理。

我们当然知道,示波器还有触发功能:自动触发、单次触发,其中触发方式最常用的就是边沿触发,我们假定为垂直扫描电压值的一半+上升沿作为触发条件。

这种条件的实现方式,想到的有一下几种:

1、硬件触发

由硬件决定将数据送进来,第一个信号就是满足条件的起始信号。(我们不用)

2、软件触发

扩大数据采样的样本数量

2.1、软件判断数据的第一个上升沿位置;

2.2、利用外部中断EXTI,选择上升沿触发,触发时记录样本位置;

找到触发位置时,将其后的300个样本值作为坐标点数据

如果没有找到触发位置,则取最后面的300个坐标点强制显示。

6、存储深度

以波形窗口宽度300为例,假设时基最小单位是200us,最大为200ms,相差1000倍,如果想在暂停时极限放大信号状态,就需要3000个坐标点,若还需要能够前后移动一般大小,则总共需要6000个样本点,即6K大小。

存储深度如何实现,略……

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32示波器设计 的相关文章

  • Flutter与Android iOS 的双向通信

    本文章中的完整代码在这里 GitHub zhaolongs Flutter Android iOS Flutter 与 Android iOs 的双向通信 demo demo运行注意 1 Json数据解析异常 org json JSONEx
  • 443.压缩字符串

    443 压缩字符串 给你一个字符数组 chars 请使用下述算法压缩 从一个空字符串 s 开始 对于 chars 中的每组 连续重复字符 如果这一组长度为 1 则将字符追加到 s 中 否则 需要向 s 追加字符 后跟这一组的长度 压缩后得到
  • String内部一次性替换多个字符串

    问题 String进行字符串的替换的时候 可以使用 s replace 但是只能替换一个字符 所以说 当需要多个字符串进行替换是 会有些麻烦 解决 使用StrUtil removeAll 引入hutool包 使用 StrUtil remov
  • 电感相关知识总结

    一 定义及原理 电感就是将导线绕制成线圈形状 当电流流过时 在线圈 电感 两端就会形成较强的磁场 由于电磁感应的作用 会对电流的变化起阻碍作用 因此 电感对直流呈现很小的电阻 近似于短路 对交流呈现的阻抗较高 其阻值的大小与所通过交流信号的
  • 一、深度学习框架究竟是什么?

    1 引言 一直在说深度学习框架 最近也在使用tensorflow进行了简单的实验 但是对其中关系的理解还是不够到位 他们里面究竟是怎样的一个运行机制呢 2 说明 深度学习框架也就像Caffe tensorflow这些是深度学习的工具 简单来
  • k8s从入门到放弃-第九章安全认证

    文章目录 9 1访问控制概述 9 2认证管理 9 3授权管理 9 4准入控制 本章节主要介绍Kubernetes的安全认证机制 9 1访问控制概述 Kubernetes作为一个分布式集群的管理工具 保证集群的安全性是其一个重要的任务 所谓的
  • Java基础语法-标识符

    标识数据的符号称为标识符 变量名称就是标识符 标识符主要用于起名 String name zhangsan 标识符的命名规则 1 英文拉丁字母 String name zhangsan 2 符号 标识符只能采用下划线 和美元 符号其他符号不

随机推荐

  • 关于tomcat繁忙线程数获取

    在某些情况下 我们需要对tomcat的繁忙线程数进行监控以满足我们队应用服务器状态信息的把控 那么我们该如何通过我们自定义的接口来获得tomcat的繁忙线程数 首先 我们应该想到tomcat本身是否为我们提供了类似的方法 博主在实际开发中拜
  • 图床搭建快速入门(PICGO + 腾讯云)

    写在前面 本文参考文章 总结补充有手就行 搭建图床 PicGo 腾讯云 贤蛋大眼萌的博客 CSDN博客 一 安装PICGO 去PICGO官网安装 官网地址 但是需要去Github去下载安装包 下载发行版 更稳定 PicGo PicGo 图片
  • 微信小程序 background-image 报错

    开发过程中使用background设置背景图片在小程序上运行报错如下 报错原因 微信小程序通过background image设置背景 只支持线上图片和base64图片 不支持本地图片 解决 1 图片放到服务器上 使用线上图片 2 base
  • 代码质量与安全

    在任何新的软件开发项目开始时 您就应该考虑软件安全 开始一个新项目或许会令人望而生畏 因为有许多的决定要做 有许多想法必须考虑清楚 通常来说 这些决定和想法包括了定义项目需求 选择正确的流程 选择正确的工具以及确保软件安全 为此 Perfo
  • 【Kettle】【使用Kettle存储数据】【csv_to_MySQL】【xlsx_to_MySQL】

    1 csv to MySQL csv xlsx表格内容如下 需要通过kettle导入MySQL中 在MySQL中创建相同与csv文件相同结构的表 kettle gt book 1 1CSV表输入设置 1 2表输出设置 注意这里如果预览数据
  • 基本增删改查(jquery Datatables+java)

    此例子展示基于Datatables的最新版1 10 5的服务器处理的增删改查 弹窗效果 结合Bootstrap显示表格 局部刷新数据 还应用了dom 自定义按钮 使表格和按钮看起来是一个整体 这个例子中还是用模板引擎 目的是为了掩饰在使用r
  • Linux编程语言glob函数,Linux中glob的用法

    bash中用于实现文件名 通配 通配符 1 任意长度的任意字符 a b aab ab a123b 可以 abc 不可以 2 任意单个字符 a b aab 可以 ab a12b abc 不可以 3 匹配指定范围内的任意单个字符 0 9 a z
  • AD altium designer 按照板子外形覆铜

    AD全是自学 遇到问题baidu 关于覆铜 之前一直看的视频 全都是选了覆铜自己画线 费劲还画不准确 尤其是异型板子还要直线曲线切来切去 其实大部分时候都是板子所有部分都要覆铜 今天终于找到如何不画线直接按照板子外形覆铜了 依次点选菜单栏的
  • Pycharm一个文件多次运行-allow parallel run

    在平时使用Pycharm的时候难免遇到同一个程序运行后 修改参数多次运行 我在平时使用的时候编写RabbitMQ的消费者程序 需要模拟多个消费者进行消费 因此一个程序需要运行数十个副本 在Pycharm里设置如下 View Appearan
  • Java 诊断神器 Arthas

    关于 Arthas Arthas 是一款开源在线 Java 诊断工具 采用命令行交互模式 支持 web 端在线诊断 同时提供丰富的 Tab 自动补全功能 进一步方便进行问题的定位和诊断 得益于 Arthas 强大且丰富的功能 让 Artha
  • mac charles4.0.2免费破解版安装

    mac charles4 0 2免费破解版安装 按相关步骤即可成功安装并使用 1 下载安装charles https www jianshu com p 4f0573f3c5db 2 安装成功之后相关配置 https www jianshu
  • python数据分页pandas,Python数据分析[3] - Pandas包

    Series Series是一个一维的向量 每个值都会有对应标签 该标签我们称之为Index Obj Series 4 5 7 8 Obj Out 5 0 4 1 5 2 7 3 8 dtype int64 Obj2 Series 4 5
  • 范数(norm) 几种范数的简单介绍

    转自 https blog csdn net a493823882 article details 80569888 https www zhihu com question 20473040 什么是范数 我们知道距离的定义是一个宽泛的概念
  • 华为OD机试 Python 观看表演

    题目 题目描述 小明爱看公园里的表演 为了庆祝一个特殊的节日 公园里会有很多并列的表演 但小明只能选择一个看 看完一场后 他需要至少15分钟才能跑到另一个地方看下一场 请帮他算一下 他最多能看几场表演 输入 第一行是一个数字 告诉你总共有多
  • MongoDB 核心技术详解

    一 NoSQL 概述 1 NoSQL 简介 NoSQL 全称是 Not Only Sql 指的是非关系型的数据库 这类数据库主要有这些特点 非关系型的 分布式的 开源的 水平可扩展的 原始的目的是为了大规模 web 应用 这场全新的数据库革
  • The breakpoint will not currently be hit. No symbols have been loaded for this document visual studi...

    问题1 环境设置问题 1 确认是在debug模式下运行 2 确认正确的项目设置 链接器 gt 调试 gt 生成调试信息 是 C gt 常规 gt 调试信息格式 Zi or Z7 问题2 当前代码与当前执行的程序不匹配 1 确认运行的是最新生
  • 2023美赛C题-Wordle预测思路及matlab代码

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 更多Matlab仿真内容点击 智能优化算法 神经网络预测 雷达通信
  • CSS中的弹性布局:flex

    1 flex布局 Flexible Box 1 1 任何一个容器都可以指定为flex布局 可以应用于 块级 元素 也可以用于行内元素 1 2 当父设置flex布局后 子元素的float clear vertical align属性将失效 2
  • 使用pnpm搭建workspace

    前言 上一节中我们使用vite lib打包了组件库 但发现对component调试时很不理想 而pnpm的workspace就是解决这种问题的 开始工作 在core view之上的根目录 建立pnpm workspace yaml 内容如下
  • STM32示波器设计

    目录 前言 1 硬件模块 2 示波器基础知识 2 1 当头一棒就是 波形的概念 2 2 第二就是需要观察的波形参数 2 3 第三就是示波器参数 2 3 1 采样率 2 3 2 带宽 2 3 4 刷新率 3 ADC采集和DAC输出 3 1 A