STM32F407 的 DAC(Digital-to-analog converters,数模转换器)功能。我们通过学习 DAC,分别是
DAC 输出``、DAC 输出三角波
和 DAC 输出正弦波。
DAC 简介
STM32F407 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的 DAC。DAC 可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。DAC 工作在 12 位模式时,数据可以设置成左对齐或右对齐。DAC 模块有 2 个输出通道,每个通道都有单独的转换器。在双 DAC 模式下,2 个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2个通道的输出。DAC 可以通过引脚输入参考电压 Vref+以获得更精确的转换结果。
STM32 的 DAC 模块主要特点:
- 两个 DAC 转换器:各对应一个输出通道
- 12 位模式下数据采用左对齐或右对齐
- 同步更新功能
- DMA 下溢错误检测
- 噪声\三角波形生成
- DAC 双通道单独或同时转换
- 每个通道都有 DMA 功能
DAC 通道框图
VDDA 和 VSSA 为 DAC 模块模拟部分的供电,而 Vref+则是 DAC 模块的参考电压输入引脚。DAC_OUTx 就是 DAC 的两个输出通道了(对应 PA4 或者 PA5 引脚)。
DAC的这些输入/输出引脚信息
- DAC 输出是受 DORx(x=1/2,下同)寄存器直接控制的,但是我们不能直接往 DORx 寄存器写入数据,而是通过 DHRx 间接的传给 DORx 寄存器,实现对DAC 输出的控制。
- STM32F407 的 DAC 支持 8/12 位模式,8 位模式的时候是固定的右对齐的,而 12 位模式又可以设置左对齐/右对齐。DAC 单通道模式下的数据寄存器对齐方式,总共有 3 种情况:
- 8 位数据右对齐:用户将数据写入 DAC_DHR8Rx[7:0]位(实际存入 DHRx[11:4]位)。
- 12 位数据左对齐:用户将数据写入 DAC_DHR12Lx[15:4]位(实际存入 DHRx[11:0]位)。
- 12 位数据右对齐:用户将数据写入 DAC_DHR12Rx[11:0]位(实际存入 DHRx[11:0]位)。
使用单通道模式下的 DAC 通道 1,采用 12 位右对齐格式,所以采用第③种情况。另外 DAC 还具有双通道转换功能。
对于 DAC 双通道(可用时),也有三种可能的方式,如下图所示:
- 8 位数据右对齐:用户将 DAC 通道 1 的数据写入 DAC_DHR8RD[7:0]位(实际存入DHR1 [11:4]位),将 DAC 通道 2 的数据写入 DAC_DHR8RD[15:8]位(实际存入 DHR2 [11:4]位)。
- 12 位数据左对齐:用户将 DAC 通道 1 的数据写入 DAC_DHR12LD [15:4]位(实际存入DHR1[11:0]位),将DAC通道2的数据写入DAC_DHR12LD [31:20]位(实际存入DHR2[11:0]位)。
- 12 位数据右对齐:用户将 DAC 通道 1 的数据写入 DAC_DHR12RD [11:0]位(实际存入DHR1[11:0]位),将DAC通道2的数据写入DAC_DHR12RD [27:16]位(实际存入DHR2[11:0]位)。
DAC 可以通过软件或者硬件触发转换,通过配置 TENx 控制位来决定。如果没有选中硬件触发(寄存器 DAC_CR1 的 TENx 位置 0),存入寄存器 DAC_DHRx 的数据会在 1 个 APB1时钟周期后自动传至寄存器 DAC_DORx。如果选中硬件触发(寄存器 DAC_CR1 的 TENx 位置 1),数据传输在触发发生以后 3 个 APB1 时钟周期后完成。一旦数据从 DAC_DHRx 寄存器装入 DAC_DORx 寄存器,在经过时间 tSETTLING 之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。
当 DAC 的参考电压为 VREF+的时候,DAC 的输出电压是线性的从 0~VREF+,12 位模式下 DAC 输出电压与 VREF +以及 DORx 的计算公式:
如果使用硬件触发(TEN=1),可通过外部事件(定时计数器、外部中断线)触发 DAC 转换。由 TSELx[2:0]控制位来决定选择 8 个触发事件中的一个来触发转换。这 8 个触发事件如下表所示:
DAC 寄存器
==DACx 控制寄存器(DACx_CR)==
DAC_CR
的低 16 位用于控制通道 1,而高 16 位用于控制通道 2,我们这里仅列出本实验需要设置的一些位:EN1 位
:用于 DAC 通道 1 的使能,我们要用到 DAC 通道 1 的输出,该位必须设置为 1。BOFF1 位
:用于 DAC 输出缓存控制,本教程的三个 DAC 实验我们都不使用输出缓存,即该位设置为 1。TEN1 位
:用于 DAC 通道 1 的触发使能,我们设置该位为 0,不使用触发。写入 DHR1的值会在 1 个 APB1 周期后传送到 DOR1,然后输出到 PA4 口上。TSEL1[2:0]位
,用于选择 DAC 通道 1 的触发方式,这里我们没有用到外部触发,所以这几位设置为 0 即可。WAVE1[1:0]位
,用于控制 DAC 通道 1 的噪声/波形输出功能,我们这里没用到波形发生器,所以默认设置为 00,不使能噪声/波形输出。MAMP[3:0]位
,是屏蔽/幅值选择器,用来在噪声生成模式下选择屏蔽位,在三角波生成模式下选择波形的幅值。本实验没有用到波形发生器,所以设置为 0 即可。DMAEN1 位
,用于 DAC 通道 1 的 DMA 使能,本实验没有用到 DMA 功能,所以设置为0。
==DACx 通道 1 12 位右对齐数据保持寄存器(DACx_DHR12R1)==
DAC 输出
DAC 的 HAL 库驱动
DAC 在 HAL 库中的驱动代码在 stm32f4xx_hal_dac.c 和 stm32f4xx_hal_dac_ex.c 文件(及其头文件)中。
==HAL_DAC_Init 函数==
HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac);
- 形参 1 是 DAC_HandleTypeDef 结构体类型指针变量
typedef struct
{
DAC_TypeDef *Instance; /* DAC 寄存器基地址 */
__IO HAL_DAC_StateTypeDef State; /* DAC 工作状态 */
HAL_LockTypeDef Lock; /* DAC 锁定对象 */
DMA_HandleTypeDef *DMA_Handle1; /* 通道 1 的 DMA 处理句柄指针 */
DMA_HandleTypeDef *DMA_Handle2; /* 通道 2 的 DMA 处理句柄指针 */
__IO uint32_t ErrorCode; /* DAC 错误代码 */
} DAC_HandleTypeDef;
==HAL_DAC_ConfigChannel 函数==
HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel);
- 形参 1 是DAC_HandleTypeDef 结构体类型指针变量。
- 形参 2 是 DAC_ChannelConfTypeDef 结构体类型指针变量,其定义如下:
typedef struct
{
uint32_t DAC_Trigger; /* DAC 触发源的选择 */
uint32_t DAC_OutputBuffer; /* 输出缓冲*/
} DAC_ChannelConfTypeDef;
==HAL_DAC_Start 函数==
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel);
- 形参1 是 DAC_HandleTypeDef 结构体类型指针变量。
- 形参 2 用于选择要启动的通道,可选择 DAC_CHANNEL_1 或者 DAC_CHANNEL_2。
==HAL_DAC_SetValue==
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data);
- 形参 1 是 DAC_HandleTypeDef 结构体类型指针变量。
- 形参 2 用于选择要输出的通道,可选择 DAC_CHANNEL_1 或者 DAC_CHANNEL_2。
- 形参 3 用于指定数据对齐方式。
- 形参 4 设置要加载到选定数据保存寄存器中的数据。
DAC 输出配置步骤
开启DAC 和输出通道的 GPIO 时钟,配置该 IO 口的模拟输出功能
首先开启 DAC 和 GPIO 的时钟,然后配置 GPIO 为模拟模式。
IO 口模拟输出功能是通过函数 HAL_GPIO_Init 来配置的。
__HAL_RCC_DAC_CLK_ENABLE (); /* 使能 DAC1 时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 开启 GPIOA 时钟 */
初始化 DAC
通过 HAL_DAC_Init 函数来设置需要初始化的 DAC。该函数并没有设置任何 DAC 相关寄存器,也就是说没有对 DAC 进行任何配置,它只是 HAL 库提供用来在软件上初始化 DAC。
配置 DAC 通道并启动 DA 转换器
在 HAL 库中,通过 HAL_DAC_ConfigChannel 函数来设置配置 DAC 的通道,根据需求设置触发类型以及输出缓冲。配置好 DAC 通道之后,通过 HAL_DAC_Start 函数启动 DA 转换器。
设置_DAC 的输出值*_
通过 HAL_DAC_SetValue 函数设置 DAC 的输出值。
/**
* @brief DAC 初始化函数
* @param outx: 要初始化的通道. 1,通道 1; 2,通道 2
* @retval 无
*/
void dac_init(uint8_t outx)
{
GPIO_InitTypeDef gpio_init_struct;
DAC_ChannelConfTypeDef dac_ch_conf;
__HAL_RCC_DAC_CLK_ENABLE(); /* 使能 DAC1 的时钟 */
/* 使能 DAC OUT1/2 的 IO 口时钟(都在 PA 口,PA4/PA5) */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* STM32 单片机, 总是 PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
g_dac_handle.Instance = DAC;
HAL_DAC_Init(&g_dac_handle); /* 初始化 DAC */
dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE; /* 不使用触发功能 */
dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; /* 关闭输出缓冲 */
switch(outx)
{
case 1: /* DAC 通道 1 配置 */
HAL_DAC_ConfigChannel(&g_dac_handle,&dac_ch_conf,DAC_CHANNEL_1);
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_1); /* 开启 DAC 通道 1 */
break;
case 2: /* DAC 通道 2 配置 */
HAL_DAC_ConfigChannel(&g_dac_handle,&dac_ch_conf,DAC_CHANNEL_2);
HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_2); /* 开启 DAC 通道 2 */
break;
default:break;
}
}
该函数主要调用 HAL_DAC_Init 和 HAL_DAC_ConfigChannel 函数初始化 DAC,并调用HAL_DAC_Start 函数使能 DAC 通道。HAL_DAC_Init 函数会调用 HAL_DAC_MspInit 回调函数,该函数用于存放 DAC 和对应通道的 IO 时钟使能和初始化 IO 等代码。
==dac_init 函数==
/**
* @brief 设置通道 1/2 输出电压
* @param outx: 1,通道 1; 2,通道 2
* @param vol : 0~3300,代表 0~3.3V
* @retval 无
*/
void dac_set_voltage(uint8_t outx, uint16_t vol)
{
double temp = vol;
temp /= 1000;
temp = temp * 4096 / 3.3;
if (temp >= 4096)temp = 4095; /* 如果值大于等于 4096, 则取 4095 */
if (outx == 1) /* 通道 1 */
{
/* 12 位右对齐数据格式设置 DAC 值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp);
}
else /* 通道 2 */
{
/* 12 位右对齐数据格式设置 DAC 值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_2,DAC_ALIGN_12B_R,temp);
}
}
DAC 输出三角波配置步骤
开启 DACx 和输出通道的 GPIO 时钟,配置该 IO 口的模拟输出功能
首先开启 DACx 和 GPIO 的时钟,然后配置 GPIO 为模拟模式。
__HAL_RCC_DAC_CLK_ENABLE (); /* 使能 DAC1 时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 开启 GPIOA 时钟 */
IO 口模拟输出功能是通过函数 HAL_GPIO_Init 来配置的。
初始化 DACx
通过 HAL_DAC_Init 函数来设置需要初始化的 DAC。该函数并没有设置任何 DAC 相关寄存器,也就是说没有对 DAC 进行任何配置,它只是 HAL 库提供用来在软件上初始化 DAC。
配置 DAC 通道并启动 DA 转换器
在 HAL 库中,通过 HAL_DAC_ConfigChannel 函数来设置配置 DAC 的通道,根据需求设置触发类型以及输出缓冲。
配置好 DAC 通道之后,通过 HAL_DAC_Start 函数启动 DA 转换器。
设置 DAC 的输出值
通过 HAL_DAC_SetValue 函数设置 DAC 的输出值。这里我们根据三角波的特性,创建了dac_triangular_wave 函数用于控制输出三角波。
DAC 驱动源码包括两个文件:dac.c 和 dac.h。
/**
* @brief 设置 DAC_OUT1 输出三角波
* @note 输出频率 ≈ 1000 / (dt * samples) Khz, 不过在 dt 较小的时候,比如小于 5us
时, 由于 delay_us 本身就不准了(调用函数,计算等都需要时间,延时很小的时候,这些
时间会影响到延时), 频率会偏小.
*
* @param maxval : 最大值(0 < maxval < 4096), (maxval + 1)必须大于等于
samples/2
* @param dt : 每个采样点的延时时间(单位: us)
* @param samples: 采样点的个数, samples 必须小于等于(maxval + 1) * 2 ,
且 maxval 不能等于 0
* @param n : 输出波形个数,0~65535
*
* @retval 无
*/
void dac_triangular_wave(uint16_t maxval, uint16_t dt, uint16_t samples,uint16_t n)
{
uint16_t i, j;
float incval; /* 递增量 */
float Curval; /* 当前值 */
if(samples > ((maxval + 1) * 2))return ; /* 数据不合法 */
incval = (maxval + 1) / (samples / 2); /* 计算递增量 */
for(j = 0; j < n; j++)
{
Curval = 0; /* 先输出 0 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,Curval);
for(i = 0; i < (samples / 2); i++) /* 输出上升沿 */
{
Curval += incval; /* 新的输出值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,
Curval);
delay_us(dt);
}
for(i = 0; i < (samples / 2); i++) /* 输出下降沿 */
{
Curval -= incval; /* 新的输出值 */
HAL_DAC_SetValue(&g_dac_handle,DAC_CHANNEL_1,DAC_ALIGN_12B_R,
Curval);
delay_us(dt);
}
}
}
该函数用于设置 DAC 通道 1 输出三角波,输出频率 ≈ 1000 / (dt * samples) Khz,使用 HAL_DAC_SetValue 函数来设置 DAC 的输
出值,这样得到的三角波在示波器上可以看到。如果有跳动现象(不平稳),是正常的。
DAC 输出正弦波实验
让 DAC 输出正弦波。实验将用定时器 2 的更新事件来触发DAC 进行转换,输出正弦波,并以 DMA 的方式传输数据。
DAC 的 HAL 库驱动
下面将介绍本用到且没有介绍过的 HAL 库 API 函数。
==HAL_DAC_Start_DMA==
启动 DAC 使用 DMA 方式传输函数
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length, uint32_t Alignment);
- 形参 DAC_HandleTypeDef 结构体类型指针变量。
- 形参 用于选择要启动的通道,可选择 DAC_CHANNEL_1 或者 DAC_CHANNEL_2。
- 形参3是使用 DAC 输出数据缓冲区的指针。
- 形参 4是 DAC 输出数据的长度。
- 形参 5 是指定 DAC 通道的数据对齐方式,有:DAC_ALIGN_8B_R(8 位右对齐)、DAC_ALIGN_12B_L(12 位左对齐)和 DAC_ALIGN_12B_R(12 位右对齐)三种方式。
==HAL_TIMEx_MasterConfigSynchronization==
- 形参 1 是 TIM_HandleTypeDef 结构体类型指针变量。
- 形参 2 是 TIM_MasterConfigTypeDef 结构体类型指针变量,用于配置定时器工作在主/从模式,以及触发输出(TRGO 和 TRGO2)的选择。
DAC 输出正弦波配置步骤
开启 DACx、DMA 和输出通道的 GPIO 时钟,配置该 IO 口的模拟输出功能
首先开启 DACx、DMA 和 GPIO 的时钟,然后配置 GPIO 为模拟模式。
IO 口模拟输出功能是通过函数 HAL_GPIO_Init 来配置的。
__HAL_RCC_DAC_CLK_ENABLE (); /* 使能 DAC 时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 开启 GPIOA 时钟 */
__HAL_RCC_DMA1_CLK_ENABLE (); /* 开启 DMA1 时钟 */
配置 DMA 并关联 DAC
- 通过 HAL_DMA_Init 函数初始化 DMA,包括配置通道,外设地址,存储器地址,传输数据量等。
- HAL 库为了处理各类外设的 DMA 请求,在调用相关函数之前,需要调用一个宏定义标识符,来连接 DMA 和外设句柄。这个宏定义为__HAL_LINKDMA。
初始化 DACx
通过 HAL_DAC_Init 函数来设置需要初始化的 DAC。该函数并没有设置任何 DAC 相关寄存器,也就是说没有对 DAC 进行任何配置,它只是 HAL 库提供用来在软件上初始化 DAC。
配置定时器控制触发 DAC
- 通过 HAL_TIM_Base_Init 函数设置定时器溢出频率。
- 通过 HAL_TIMEx_MasterConfigSynchronization 函数配置定时器溢出事件用做触发器。
- 通过 HAL_TIM_Base_Start 函数启动计数。
产生正弦波序列
通过 dac_creat_sin_buf 函数产生一组正弦波序列,其本质上就是正弦波曲线上的点。
配置 DAC 通道并开启 DMA 传输
通过 HAL_DAC_ConfigChannel 函数来设置配置 DAC 的通道,根据需求设置触发类型以及输出缓冲等。
再通过 HAL_DAC_Start_DMA 函数启动 DMA 传输以及 DAC 输出。
DAC 驱动源码包括两个文件:dac.c 和 dac.h。
uint16_t g_dac_sin_buf[4096]; /* 正弦波序列数据缓冲区 */
/**
* @brief 产生正弦波函序列
* @note 需保证: maxval > samples/2
*
* @param maxval : 峰值(0 < maxval < 2048)
* @param samples: 采样点的个数
*
* @retval 无
*/
void dac_creat_sin_buf(uint16_t maxval, uint16_t samples)
{
uint8_t i;
float outdata = 0;
if( maxval <= (samples/2) )return ; /* 数据不合法 */
/*
* 正弦波最小正周期为 2π,约等于 2 * 3.1415926
* 曲线上相邻的两个点在 x 轴上的间隔 = 2 * 3.1415926 / 采样点数量
* DAC 无法输出负电压,所以需要将曲线向上偏移一个峰值的量,让整个曲线都落在正数区域
*/
float inc = (2 * 3.1415926) / samples; /* 计算相邻两个点的 x 轴间隔 */
for (i = 0; i < samples; i++) /* 连续打 samples 个点 */
{
/*
* 正弦波函数解析式:y = Asin(wx + φ)+ b
* 计算每个点的 y 值,将峰值放大 maxval 倍,并将曲线向上偏移 maxval 到正数区域
*/
outdata = maxval * sin(inc * i) + maxval;
if (outdata > 4095)
{
outdata = 4095; /* y 值上限限定 */
}
g_dac_sin_buf[i] = outdata;
}
}
该函数用于产生正弦波序列,即正弦波曲线上的各个采样点,各个点最终控制的是DAC_DHR12R1 寄存器的值。在 DAC 输出频率固定、波形周期一定的情况下,采样点越多,实际的曲线越接近于正弦波,但是波形的频率也会越小。
==DAC DMA 初始化函数==
/**
* @brief DAC DMA 初始化函数
* @param outx: 要初始化的通道.1,通道 1; 2,通道 2
* @param cndtr: DMA 通道单次传输数据量(采样点数量)
* @retval 无
*/
void dac_init(uint8_t outx,uint16_t cndtr)
{
GPIO_InitTypeDef gpio_init_struct;
DAC_ChannelConfTypeDef DACCH1_Config;
__HAL_RCC_DAC_CLK_ENABLE(); /* 使能 DAC 的时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能 DAC OUT1/2 的 IO 口时钟 */
__HAL_RCC_DMA1_CLK_ENABLE();
/* STM32 单片机, 总是 PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
g_dma_dac_handle.Instance = DMA1_Stream5; /* DMA1 数据流 5 */
g_dma_dac_handle.Init.Channel = DMA_CHANNEL_7; /* 通道 7 */
g_dma_dac_handle.Init.Direction = DMA_MEMORY_TO_PERIPH;/* 从存储器到外设 */
g_dma_dac_handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
g_dma_dac_handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
/* 外设数据长度:16 位 */
g_dma_dac_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
/* 存储器数据长度:16 位 */
g_dma_dac_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
g_dma_dac_handle.Init.Mode = DMA_CIRCULAR; /* 循环模式 */
g_dma_dac_handle.Init.Priority = DMA_PRIORITY_LOW; /* 中等优先级 */
g_dma_dac_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* 不开启 FIFO */
HAL_DMA_Init(&g_dma_dac_handle); /* 初始化 DMA */
/* 把 DAC 和 DMA 关联 */
__HAL_LINKDMA(&g_dac_dma_handle,DMA_Handle1,g_dma_dac_handle);
g_dac_dma_handle.Instance = DAC;
HAL_DAC_Init(&g_dac_dma_handle); /* 初始化 DAC */
/* 使用定时器 2 的 TRGO 事件触发 DAC 转换 */
DACCH1_Config.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
/* DAC1 输出缓冲关闭 */
DACCH1_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
dac_creat_sin_buf(2048,cndtr); /* 产生正弦波序列,即画点 */
switch(outx)
{
case 1:
HAL_DAC_ConfigChannel(&g_dac_dma_handle,&DACCH1_Config,
DAC_CHANNEL_1); /* DAC 通道 1 配置 */
HAL_DAC_Start_DMA(&g_dac_dma_handle,DAC_CHANNEL_1,
(uint32_t *)g_dac_sin_buf,cndtr,DAC_ALIGN_12B_R); /* 开启 DAC 通道 1 */
break;
case 2:
HAL_DAC_ConfigChannel(&g_dac_dma_handle,&DACCH1_Config
DAC_CHANNEL_2); /* DAC 通道 2 配置 */
HAL_DAC_Start_DMA(&g_dac_dma_handle,DAC_CHANNEL_2,
(uint32_t *)g_dac_sin_buf,cndtr,DAC_ALIGN_12B_R); /* 开启 DAC 通道 2 */
break;
default:break;
}
}
该函数用于初始化 DAC 用 DMA 的方式输出正弦波,我们采用定时器 2 触发 DAC 进行转换输出。这里调用了 dac_creat_sin_buf 函数来产生正弦波序列,采样点的个数通过入口参数 cndtr 传进来。
==定时器相关的 gtim.c 文件==
/**
* @brief 通用定时器 TIMX 初始化函数
* @param arr: 自动重装值。
* @param psc: 时钟预分频数
* @retval 无
*/
void gtim_timx_int_init(uint16_t arr, uint16_t psc)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
GTIM_TIMX_INT_CLK_ENABLE(); /* 使能 TIMx 时钟 */
g_timx_handle.Instance = GTIM_TIMX_INT; /* 通用定时器 x */
g_timx_handle.Init.Prescaler = psc; /* 预分频系数 */
g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
g_timx_handle.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_timx_handle);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; /* 更新事件用于触发 */
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&g_timx_handle, &sMasterConfig);
HAL_TIM_Base_Start(&g_timx_handle); /* 使能定时器 x */
}
评论(0)
您还未登录,请登录后发表或查看评论