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