【STM32】DAC

DAC,数模转换器,用于输出模拟信号的大哥,输出正弦波就靠它了。

大部分图片来源:正点原子HAL库课程

 专栏目录:记录自己的嵌入式学习之路-CSDN博客


目录

1    特性

2    DAC数据格式

3    触发方式

3.1    自动触发

3.2    外部事件触发

3.3    软件触发

4    DMA

5    输出电压计算

6    关于输出缓冲

7    输出电压配置步骤

7.1    相关HAL库函数

7.2    关键结构体

8    输出正弦波

8.1    配置步骤

8.2    波形数值计算

8.3    总体思路

9    PWM DAC

9.1    应用场景

9.2    原理

9.3    分辨率

9.4    RC滤波器的设计示例


1    特性



2    DAC数据格式

  • 其中x代表通道1还是通道2。

3    触发方式

共三种:自动触发(也称禁止触发)、软件触发、外部事件触发。

3.1    自动触发

即不使能触发的情况。

特点:经过1个APB1时钟周期,数据保存寄存器的值输出到数据输出寄存器中。DHRx数据加载到DORx后,模拟输出电压将经过时间VSETTLING后可用,即写入数据输出寄存器后,经过一个建立时间后转成电压输出。

3.2    外部事件触发

包括选择了外部中断线触发或者定时器触发的情况,详见TSEL2寄存器。

特点:经过3个APB1时钟周期,数据保存寄存器的值输出到数据输出寄存器中。DHRx数据加载到DORx后,模拟输出电压将经过时间VSETTLING后可用,即写入数据输出寄存器后,经过一个建立时间后转成电压输出。

  • 外部事件触发支持DMA

3.3    软件触发

写入寄存器进行软件触发后,其寄存器又会自动清零,下次再写入的时候才会进行下一次的软件触发。

特点:经过1个APB1时钟周期,数据保存寄存器的值输出到数据输出寄存器中。DHRx数据加载到DORx后,模拟输出电压将经过时间VSETTLING后可用,即写入数据输出寄存器后,经过一个建立时间后转成电压输出。


4    DMA

每个DAC通道都有DMA功能,两个DMA通道分别用于处理两个DAC通道的DMA请求。如果DMAENx位置1时,如果发生外部触发(而不是软件触发),就会产生一个DMA请求,然后DAC_DHRx寄存器的数据被转移到DAC_NORx寄存器。


5    输出电压计算

这里存疑,有可能是除以4095或者255。


6    关于输出缓冲

使能了DAC的输出缓冲后可以减小输出阻抗,适合直接驱动一些外部负载,但无法输出0V,因此在例程中并不使用。


7    输出电压配置步骤

7.1    相关HAL库函数

  • 注意⚠️:HAL_DAC_SetValue和HAL_DAC_GetValue的数字量都是基于位数决定的,并不是电压值。如12bit就是0-4095,8bit就是0-255,将其与3.3V(即DAC的参考电压)进行线性换算,算出来才是输出的电压。

7.2    关键结构体

  • 注意!DAC_ChannelConfTypeDef的DAC_Trigger成员宏通过文档注释中的@ref是找不到的,需要去stm32f1xx_hal_dac_ex.h文件找DACEx_trigger_selection;

8    输出正弦波

8.1    配置步骤

8.2    波形数值计算

  • 形参取值范围的拟定原因解析:
    • 以一个正弦函数的峰谷之间的范围为例,输出正弦波的前提是这一段范围内所有点都有自己的独立对应的x和y,因此要求(sample/2)<maxval;
  • 相邻采样点的x轴间隔的数值由来:
    • samples在这里就是相当于周期T,而整段的距离(姑且理解为距离吧)根据三角函数的表达式,它就是2π,所以相邻点的间隔就是2π/sample了。
  • 注意⚠️:此处输出的正弦波并不通用,因为这里数值4095就是3.3V,数值0就是0V,是无法像真正的通用正弦一样随意调整幅值、相位、垂直位移的。

8.3    总体思路

  • 创建一个数组,用于存放正弦函数的离散点,并使用上述公式计算离散点并对离散点进行合法性校验,如最大值不超过4095、(sample/2)<maxval等;
  • 将DAC的触发设置为定时器触发信号触发;
  • 初始化DMA用于传输数据,将数组作为源地址,将DAC1->DHR12R1寄存器作为目标地址;
  • 调用HAL_TIMEx_MasterConfigSynchronization函数配置定时器的更新事件作为触发输出(TRGO);
  • 按以上方法配置后,每发生一次定时器更新事件,DMA就会在数组中取出一个数据点写入至DAC1的DHR12R1寄存器中;
  • 最终呈现的正弦波的频率为:
  • 频率 = 定时器频率 ÷ 每个正弦波的离散点数目

9    PWM DAC

9.1    应用场景

STM32的DAC只有两路输出通道,有些应用可能需要多路DAC,外扩DAC成本会高不少。在精度要求不高的场合,可以用一种廉价的解决方案实现DAC输出:PWM + RC滤波器。

9.2    原理


9.3    分辨率

9.4    RC滤波器的设计示例


### STM32 DAC 使用教程及示例代码 #### 一、STM32 DAC 模块概述 STM32系列微控制器中的DAC模块具备多种特性,能够满足不同应用场景的需求。该模块拥有两个独立的DAC转换器,支持8位或12位分辨率的数据输出,并提供数据对齐方式的选择——左对齐或是右对齐[^3]。 #### 二、硬件连接说明 对于具体的型号如STM32L151xxxx和STM32L152xxxx而言,它们均内置了DAC组件。当涉及到外部设备接口时,则需注意特定引脚定义;例如,在某些情况下,DAC_OUT1被映射到PA4而DAC_OUT2则位于PA5上[^1]。 #### 三、软件编程指南 为了实现对外部模拟信号的有效控制,下面给出一段用于设置并启动单通道DAC输出的基础C语言程序片段: ```c #include "stm32f1xx_hal.h" void DAC_Config(void){ __HAL_RCC_DAC_CLK_ENABLE(); //使能DAC时钟 DAC_ChannelConfTypeDef sConfig = {0}; hDac.Instance=DAC; hDac.Init.Trigger=DAC_TRIGGER_NONE;//不使用触发源 hDac.Init.Mode=DAC_MODE_NORMAL; //正常工作模式 HAL_DAC_Init(&hDac); sConfig.DAC_Trigger = DAC_TRIGGER_NONE; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; HAL_DAC_ConfigChannel(&hDac, &sConfig,DAC_CHANNEL_1); } int main(){ /* 初始化 */ HAL_Init(); SystemClock_Config(); DAC_Config(); while (1){ uint32_t value = 2047 ;// 中间电压值 HAL_DAC_SetValue(&hDac, DAC_CHANNEL_1 , DAC_ALIGN_12B_R,value); HAL_Delay(1000); } } ``` 上述代码展示了如何初始化DAC外设以及设定其参数来完成一次简单的数值写入操作。这里采用的是轮询的方式来进行持续性的电平调整演示。 另外还有一份针对TLV5618芯片通过SPI协议进行通信的例子,此部分适用于更复杂的多路DAC应用场合: ```c void TLV5618_Write_B(uint16_t dac_value) { uint16_t data = (0x4000) | (dac_value & 0x0FFF); DAC_CS_L; delay_ms(1); DAC_SCK_H; for(int i = 15; i >= 0; i--) { if(data & (1<<i)){//如果是'1' DAC_SO_H; }else{//如果是'0' DAC_SO_L; } DAC_SCK_L; delay_ms(1); DAC_SCK_H; } DAC_SCK_L; delay_ms(1); DAC_CS_H; } ``` 这段函数实现了向指定地址发送命令字节序列的功能,从而可以精确地改变目标器件上的输出状态[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值