STM32G474单片机开发入门(十七)DAC详解及输出电压和正弦波实战

文章目录

一.概要

DAC(Digital to analog converter)即数字模拟转换器,它可以将数字信号转换为模拟信号。它的功能与ADC相反,单片机普通I/O口只能输出高或者低,DAC引脚就能输出0~3.3V内任意电压值的电平。

STM32单片机的DAC功能通过内置于芯片内部的数模转换器实现,能够将数字信号转换为模拟信号,这在音频处理和波形生成中发挥着关键作用。

DAC的主要应用场景包括:

‌音频处理‌:STM32的DAC模块支持立体声音频输出,可以应用于各种音频应用,如安全警报系统、蓝牙耳机、发声玩具、答录机、人机接口以及低成本的音乐播放器等。通过配置适当的引脚和外设,STM32能够方便地实现音频信号的生成和播放。

‌波形生成‌:DAC还可以用于生成各种模拟波形,包括正弦波、方波等。例如,通过配置DAC输出正弦波,可以应用于科学实验、教育演示等领域,作为刺激源来测试听觉系统或其他系统的响应。此外,通过数学运算准备数字模式的波形数据,STM32能够生成高质量的正弦波形,用于精确的测量和控制应用。

‌模拟控制‌:除了音频和波形生成,DAC还可用于各种需要模拟信号控制的场景,如电机控制、温度调节、灯光亮度调整等。通过输出不同的模拟电压,可以实现对这些设备的精细控制。

二.STM32G474RET6单片机DAC外设特点

DAC 模块是 12 位电压输出数模转换器。DAC 可以8位或12 位模式进行配置,并且可与DMA 控制器配合使用。

STM32G474RET6的DAC(数模转换器)具有以下特点:

  1. ‌通道配置‌
    提供7个12位DAC通道,其中3个为缓冲外部输出通道,4个为无缓冲内部通道。
    内部通道支持直接连接至片上外设(如运算放大器或比较器),简化电路设计。
  2. ‌性能参数‌
    ‌外部通道‌:最高1MHz输出速率,支持轨到轨输出。
    ‌内部通道‌:最高15MHz输出速率,适合高速信号生成。
    支持单端或差分输出模式,灵活适配不同应用场景。
  3. ‌功能特性‌
    集成硬件加速的DMA传输,实现高效数据流处理。
    支持与定时器同步触发,确保精确时序控制(如PWM波形生成)。
    内置偏移补偿和增益校准功能,提升输出精度。
  4. ‌应用优势‌
    可直接驱动外部负载或配合运算放大器构建模拟电路(如程控放大器)。
    在电机控制、电源管理等场景中,与PWM、ADC协同实现闭环控制。

三.STM32单片机DAC内部结构图

DAC内部结构图如下

DAC相关引脚说明

四.STM32单片机DAC基本操作

DAC 通道使能

将 DAC_CR 寄存器中的相应 ENx 位置 1,即可接通对应 DAC 通道。经过一段启动时间

tWAKEUP 后,DAC 通道被真正使能。

DAC 转换

DAC_DORx 无法直接写入,任何数据都必须通过加载 DAC_DHRx 寄存器(写入

DAC_DHR8Rx、DAC_DHR12Lx、DAC_DHR12Rx、DAC_DHR8RD、DAC_DHR12LD 或DAC_DHR12LD)才能传输到 DAC 通道 x。

DAC 输出电压

经过线性转换后,数字输入会转换为 0 到 VREF+ 之间的输出电压。

各 DAC 通道引脚的模拟输出电压通过以下公式确定:

程序中调用Hal库代码,以下关键语句就能使PA4引脚输出1.65V直流电压值。

c 复制代码
  MX_DAC1_Init();//PA4作为DAC1_OUT1输出引脚
	HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);//DAC引脚输出电压值为2048*3300/4096
	HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);//使能DAC1通道1

DAC 输出正弦波

有了DAC输出电压值,通过定时器将预先生成的正弦波数据表,按定时器触发频率逐点写入DAC寄存器,形成连续模拟信号‌,这样就形成了正弦波的波形。

以下关键语句就是使PA4引脚输出正弦波,在定时器中断时间触发DAC输出正弦波数据表格里的电压值。

c 复制代码
//60个点为1个周期,所以如果需要产生1KHZ的正弦波,定时器中断频率就是60KHZ,如果定时器时钟是170MHZ,所以htim2.Init.Period就要改成2832(2833.3-1)
#define TABLE_SIZE 60 // 正弦波表的大小,决定了正弦波的分辨率和频率精度
uint16_t sinewave[TABLE_SIZE] = {
0x07ff,0x08cb,0x0994,0x0a5a,0x0b18,0x0bce,0x0c79,0x0d18,0x0da8,0x0e29,0x0e98,0x0ef4,0x0f3e,0x0f72,0x0f92,0x0f9d,
0x0f92,0x0f72,0x0f3e,0x0ef4,0x0e98,0x0e29,0x0da8,0x0d18,0x0c79,0x0bce,0x0b18,0x0a5a,0x0994,0x08cb,0x07ff,0x0733,
0x066a,0x05a4,0x04e6,0x0430,0x0385,0x02e6,0x0256,0x01d5,0x0166,0x010a,0x00c0,0x008c,0x006c,0x0061,0x006c,0x008c,
0x00c0,0x010a,0x0166,0x01d5,0x0256,0x02e6,0x0385,0x0430,0x04e6,0x05a4,0x066a,0x0733};
//定时器溢出中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) // 定时器中断服务例程
{
	   uint16_t sineValue = sinewave[SineTableIndex]; // 获取当前正弦波值
    if (htim->Instance == TIM2) // 检查是否是TIM2的溢出中断
    {
        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sineValue); // 设置DAC输出值
        SineTableIndex = (SineTableIndex + 1) % TABLE_SIZE; // 更新索引,实现循环更新正弦波值
    }
}

五.CubeMX配置一个DAC输出电压例程

1.硬件准备

STLINK接STM32G474RET6开发板,STLINK接电脑USB口,万用表一个,板子用5V USB线供电。

2.创建CubeMX工程

如下图所示,打开STM32CubeMX软件,新建工程。

如下图所示,Part Number处输入STM32G474RE,再双击就创建新的工程。

如下图所示,配置下载口引脚,PA13为SWD的SWDIO脚,PA14为SWD的SWCLK脚。

如下图所示,配置DAC1,PA4引脚为DAC1通道1。

如下图所示,配置系统主频170Mhz,使用内部16MHZ晶振。

如下图所示,配置工程文件名,保存路径,KEIL5工程输出方式。

如下图所示,生成工程。

如下图所示,增加代码,实现PA4引脚输出1.65V电压。

主要代码如下

c 复制代码
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();//SysTick配置成1ms中断

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();//16M内部晶振,170MHZ系统主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DAC1_Init();//PA4作为DAC1_OUT1输出引脚
  /* USER CODE BEGIN 2 */
	HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);//DAC引脚输出电压值为2048*3300/4096
	HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);//使能DAC1通道1
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

3.实验效果

下载完程序后,用万用表量PA4引脚电压,可以看到电压值1.646V。

六.CubeMX配置一个DAC输出1KHZ正弦波例程

1.硬件准备

STLINK接STM32G474RET6开发板,STLINK接电脑USB口,示波器一台,板子用5V USB线供电。

2.创建CubeMX工程

跟前面的DAC输出电压工程创建方式一样,配置DAC输出,只需要添加一个定时器2中断,以下配置定时器中断频率为60KHZ。

配置定时器2中断使能。

如下图所示,增加代码,添加正弦波数据表。

如下图所示,启动TIM2与DAC输出。

主要代码如下

c 复制代码
//60个点为1个周期,所以如果需要产生1KHZ的正弦波,定时器中断频率就是60KHZ,如果定时器时钟是170MHZ,所以htim2.Init.Period就要改成2832(2833.3-1)
#define TABLE_SIZE 60 // 正弦波表的大小,决定了正弦波的分辨率和频率精度
uint16_t sinewave[TABLE_SIZE] = {
0x07ff,0x08cb,0x0994,0x0a5a,0x0b18,0x0bce,0x0c79,0x0d18,0x0da8,0x0e29,0x0e98,0x0ef4,0x0f3e,0x0f72,0x0f92,0x0f9d,
0x0f92,0x0f72,0x0f3e,0x0ef4,0x0e98,0x0e29,0x0da8,0x0d18,0x0c79,0x0bce,0x0b18,0x0a5a,0x0994,0x08cb,0x07ff,0x0733,
0x066a,0x05a4,0x04e6,0x0430,0x0385,0x02e6,0x0256,0x01d5,0x0166,0x010a,0x00c0,0x008c,0x006c,0x0061,0x006c,0x008c,
0x00c0,0x010a,0x0166,0x01d5,0x0256,0x02e6,0x0385,0x0430,0x04e6,0x05a4,0x066a,0x0733};


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

uint16_t SineTableIndex = 0; // 正弦波表的索引,用于循环更新正弦波值

//定时器溢出中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) // 定时器中断服务例程
{
	   uint16_t sineValue = sinewave[SineTableIndex]; // 获取当前正弦波值
    if (htim->Instance == TIM2) // 检查是否是TIM2的溢出中断
    {
        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sineValue); // 设置DAC输出值
        SineTableIndex = (SineTableIndex + 1) % TABLE_SIZE; // 更新索引,实现循环更新正弦波值
    }
}

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();//16M内部晶振,170M系统主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DAC1_Init();//DAC1初始化,PA4:DAC1_OUT1
  MX_TIM2_Init();//定时器2初始化,中断频率为60KHZ
  /* USER CODE BEGIN 2 */

  if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)//启动定时器2,并使能溢出中断
  {
    /* Counter enable error */
    Error_Handler();
  }
	HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);//使能DAC1通道1

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

3.实验效果

下载完程序后,用示波器测量PA4引脚波形,可以看到1KHZ的正弦波。

七.小结

DAC外设是STM32单片机开发中的基本操作,学会了DAC,单片机就可以在波形输出,音频驱动,模拟控制‌等场合发挥作用。

相关推荐
DIY机器人工房3 小时前
【嵌入式面试题】STM32F103C8T6 完整元器件解析 + 面试问题答案
stm32·单片机·面试·嵌入式·面试题·diy机器人工房
日更嵌入式的打工仔3 小时前
嵌入式入门:APP+BSP+HAL 三层分级架构浅析
笔记·单片机·嵌入式硬件·学习
优信电子5 小时前
基于STM32F103驱动AS5600读取磁体旋转的模拟量/角度数据
stm32·单片机·嵌入式硬件·as5600·磁编码器·磁角度传感器
homelook6 小时前
【mqtt参数上云和小程序开发】【第5期】hcsr04超声波测距模块调试完成
嵌入式硬件
点灯小铭6 小时前
基于单片机的PWM三基色LED灯控制器设计与无线调色系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
Vae_Mars14 小时前
单片机中的TVS管
单片机·嵌入式硬件
hazy1k16 小时前
51单片机基础-直流电机控制
stm32·单片机·嵌入式硬件·51单片机
小莞尔18 小时前
【51单片机】【protues仿真】基于51单片机智能窗帘系统
c语言·stm32·单片机·嵌入式硬件·物联网·51单片机
我先去打把游戏先20 小时前
ESP32学习笔记(基于IDF):IOT应用——WIFI连接
笔记·单片机·嵌入式硬件·mcu·物联网·学习·esp32