打印
[其他ST产品]

(转载分享篇)基于STM32 DAC+TIMER+DMA经验分享

[复制链接]
622|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2023-7-14 09:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AC, DAC, DM, DMA, ST
本帖最后由 两只袜子 于 2023-7-14 09:17 编辑


现在有如下图所示的这样一个需求,**使用STM32芯片来实现。

横轴表示时间,纵轴表示电压【3.3v为限】,不同时刻的电压输出不一样、持续时间也不尽相同。


使用特权

评论回复
沙发
两只袜子|  楼主 | 2023-7-14 09:16 | 只看该作者
此问题源于某高校STM32学习时的习题,这里拿出来一起交流探讨下。方法不是唯一的,尤其基于不同STM32系列。这里尽量使用通用、常规的方法,算是抛砖引玉。

显然,我们可以考虑使用STM32的DAC加TIMER以及片内其它资源加以实现。

对于这个实现我们可以分两种方式完成,每一种方式同时也体现不同难度。

我们可以考虑下面两种应用情形:

第一种方式:MCU除了做这一件事外,还做点别的,比方做按键响应、ADC采样这些,整体上没有太复杂的功能和要求。【中断方式】

第二种方式:MCU的主要工作是别的而不再是这个输出了,要求该输出自启动后不再需要CPU的参与,即由相应外设自行完成。【DMA方式】

对于第一种实现方式,我们可以用个TIMER作为时基,每到适当的计时点就通过TIMER中断及时修改DAC的输出值而改变输出电压。至于对DAC输出寄存器赋值,可以直接在定时器中断里操作,也可以先在定时器中断里设置标志位后在主循环里实现修改,可以灵活决定。显然,这样操作也不会影响其它按键处理、ADC处理等。该方式的实现就介绍到这里,重点聊聊第二种方式。

对于第二种方式,显然不能使用中断,这里就得DMA出场了。因为人家要求该输出自启动后不再让CPU参与。这里有两个量都是变的,DAC的输出值在变,不同DAC输出所持续的时间也在变。这两个变量都需要DMA帮忙完成,显然DAC的输出需要使用TIMER事件来触发DMA,这里使用更新事件比较合理。那么,TIMER自身的数据更新又如何实现呢?我们可以考虑使用TIMER的比较事件来触发另外的DMA请求以更新自己。

下面我使用STM32F4系列芯片的TIM1及DAC来实现第二种需求。【当然,使用STM32其它系列,比如G4,H5,H7,U5等都可以】

TIM1的更新事件触发DMA,修改DAC的输出寄存器的值以改变输出。另外,选择TIM1通道1的比较事件触发DMA【哪个通道比较事件不重要,能触发DMA即可】,使用TIMER DMA Burst传输同时修改TIM1的ARR,RCR,CCR1三个寄存器的值,此处RCR始终用0值。因为这里要修改CCR1的值,RCR夹在ARR和CCR1寄存器中间,做Burst传输时RCR必须每次被使用。【这里CCR1的值其实也可以固定不变。我是每次取ARR的中间值作为CCR1的值,不是必须的。主要是考虑到有些应用场合可能需要动态修改CCR值,在此特意拓展下TIMER Burst传输的应用介绍。】

使用特权

评论回复
板凳
两只袜子|  楼主 | 2023-7-14 09:17 | 只看该作者
下面是关于TIM1时基参数的初始配置,其中ARR和CCR1值我是随便设定的,算是个过渡值,目的就是产生更新事件和比较事件,之后都会按照代码中预定的数据运行。



下面是有关TIM1的基于更新事件和通道1比较事件的DMA配置。


下面截图是关于DAC的CubeMx配置,比较简单,开启其输出功能即可。


下面截图里的数组DacOutData[10]存放不同时刻DAC输出所对应的数据。数组PulseData3[30]存放10次DMA Burst 传输用到的数据。显然这两个数组数据在使用时间上要匹配,否则输出波形对不了。


下面是具体的用户代码,使用CubeMx进行配置和STM32 HAL库函数,以源码形式放在下面,供有需要的参考、使用。
  • HAL_DMA_Start_IT(&hdma_tim1_up, (uint32_t) DacOutData, \
  • (uint32_t)&hdac.Instance->DHR12R1, 10);
  •   __HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_UPDATE);
  •   __HAL_TIM_CLEAR_FLAG(&htim1,TIM_DMA_CC1);
  •   HAL_TIM_DMABurst_MultiWriteStart(&htim1, TIM_DMABASE_ARR, \
  •   TIM_DMA_CC1,(uint32_t *)PulseData3,   \
  •   TIM_DMABURSTLENGTH_3TRANSFERS,10*3);
  •   __HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
  •   HAL_DAC_Start(&hdac,  DAC_CHANNEL_1);
  • __HAL_TIM_ENABLE(&htim1);

复制代码


下面黑底黄线图是基于上面配置及代码的最终实现截图。跟最初的需求曲线进行比对,不难发现是一致的。




OK,今天的分享就到这里,是些比较基础的东西。只有掌握最基础的,才会有最灵活的发挥。

使用特权

评论回复
地板
帛灿灿| | 2024-2-9 08:27 | 只看该作者

当电路出现异常过压并达到其击穿电压时

使用特权

评论回复
5
Bblythe| | 2024-2-9 09:30 | 只看该作者

例如下图中在SPI信号线上串联电阻就是为了改善匹配情况

使用特权

评论回复
6
周半梅| | 2024-2-9 11:26 | 只看该作者

即原/副边交错通断。

使用特权

评论回复
7
Pulitzer| | 2024-2-9 12:29 | 只看该作者

般只要关注值、精度、额度功率

使用特权

评论回复
8
童雨竹| | 2024-2-9 14:25 | 只看该作者

然后将其用作在PCB组装过程中放置在另一个板上的独立部件。

使用特权

评论回复
9
Wordsworth| | 2024-2-9 15:28 | 只看该作者

ESD静电保护器基本上都是通过静电进行吸收和耗散

使用特权

评论回复
10
Clyde011| | 2024-2-9 16:31 | 只看该作者

这类型灌封胶一般分为A、B双组份在进行1:1的配比后再进行灌封的操作

使用特权

评论回复
11
公羊子丹| | 2024-2-9 17:24 | 只看该作者

然后在专用站中检查每个半孔,

使用特权

评论回复
12
万图| | 2024-2-9 18:27 | 只看该作者

同时把异常高压箝制在一个安全水平之内

使用特权

评论回复
13
万图| | 2024-2-9 18:27 | 只看该作者

同时把异常高压箝制在一个安全水平之内

使用特权

评论回复
14
Uriah| | 2024-2-9 19:30 | 只看该作者

从而抑制电路的振荡。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2033

主题

7323

帖子

10

粉丝