一、DAC简介 DAC(Digital-to-Analog Converter),即数字/模拟转换模块,故名思议,其功能是将输入的数字编码转换为相应的模拟电压输出,其功能及 ADC 相反。在常见的数字信号系统中,大多数传感器信号化为电压信号 ADC 将电压模拟信号转换为易于计算机存储和处理的数字编码,然后由计算机处理 DAC 输出电压模拟信号,通常用于驱动某些执行器件,使人类容易感知。例如,音频信号的收集和恢复就是这样一个过程。
STM32 具有片上 DAC 外设的分辨率可以分配为 8 位或 12 位数字输入信号有两个 DAC 这两个通道不相互影响,每个通道都可以使用 DMA 功能,都具有出错检测能力,可外部触发。
二、DAC通道选择 在 STM32 中具有 2 个这样的 DAC 部件,每个 DAC 有 1 将相应的输出通道连接到特定的引脚,即:PA4-通道 1,PA5-通道 2.使用以避免干扰 DAC 功能时,DAC 通道引脚需要配置成模拟输入功能(AIN)。
三、新建工程 1.
2. 选择 MCU 和封装
3. 配置时钟 RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)
选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz 修改 HCLK 的值为 72 输入回车后,软件会自动修改所有配置
4. 调试模式的配置 一个非常重要的步骤,否则第一个烧录程序将无法识别调试器 SYS 设置,选择 Debug 为 Serial Wire
四、DAC1 4.1 参数配置 在 Analog 中选择 DAC 设置,选择 OUT1 Configuration 通道1
或者找到右边的图片 PA4 引脚,选择 DAC_OUT1
具体配置参数如下。
OUT1/2 Configuration: 对应两个输出通道。 External Trigger: 外部中断EXTI9 触发 使用外部中断触发DAC。 Output Buffer: 使能DAC输出缓存。 DAC 集成了 2 输出缓存可用于减少输出阻抗,直接驱动外部负载,无需外部运输。 DAC 可通过设置通道输出缓存 DAC_CR 寄存器的 BOFFx 使能或关闭位置。如果负载能力不好,将在后面连接一个电压跟随器。选择运输时,必须选择电流大的型号。 输出缓冲后,DAC 最小输出电压为 0.2V,最大电压为 VREF±0.2.未能输出缓冲,输出可达0V。
Trigger: 选择DAC的触发方式 Timer 2/4/5/6/7/8 Trigger Out event 定时器触发,这样可以输出特定的波形。这里我们选择定时器2。 Software trigger 在这种模式下,软件触发 DAC_SWTRIGR 将寄存器写入配置,以触发信号进行转换。 Wave generation mode:Disable(不使用波形发生器)。
4.2 配置DMA
点击 DMA Settings 添加 DAC_CH1 对应 的通道3。DMA模式选择循环模式,方向选择内存到外设。
Priority: 当发生多个 DMA 当通道要求时,这意味着有一个顺序问题,由仲裁器管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 设置在寄存器中,有 4 高、高、中、低四个优先级。第二阶段属于硬件阶段,如果两个或两个以上 DMA 通道请求设置的优先级相同,其优先级取决于通道 道号越低,优先权越高,如通道号 0 高于通道 1。在大容量产品和互联产品中,DMA1 高于控制器 DMA2 控制器的优先级。 Mode: Normal 表示单次传输,传输一次后终止传输。 Circular 表示循环传输,传输完成后继续传输,不断循环永不停止。 Increment Address: Peripheral 表示外设地址自增。 Memory 表示内存地址自增。 Data Width: Byte 一个字节。 Half Word 半字,等于两字节。 Word 一个字,等于四字节。 五、TIM2通用定时器 5.1 参数配置
在 Timers 中选择 TIM2 设置,时钟源 Clock Source 选择内部时钟 Internal Clock
在 Parameter Settings 配置具体参数。
Prescaler(时钟预分频) 驱动计数器的时钟 CK_CNT = CK_INT(即72MHz)/(0 1) = 72MHz 即不分频 Counter Mode(计数模式):Up(向上计数模式) Counter Period(自动重装载值):20-1 auto-reload-preload(自动重装载):Disable(不使能) TRGO Parameters(触发输出):Update Event(更新) 当定时器到达时,输出信号(例如:定时器更新产生TRGO信号来触发ADC同步转换)
5.2TIM2中断使能
5.3 生成代码 输入项目名和项目路径
选择应用的 IDE 开发环境 MDK-ARM V5
每个外设生成独立的 ’.c/.h’ 文件 不勾:所有初始化代码都生成 main.c 在相应的外设文件中生成初始化代码。 如 GPIO 生成初始代码 gpio.c 中。
点击 GENERATE CODE 生成代码
六、生成正弦波数据表 输出正弦波的本质是控制 DAC 以 v=sin(t)正弦函数关系输出电压 v 输出电压,t 为时间。 由于模拟信号连续,数字信号离散,因此使用 DAC 当产生正弦波时,只能在一定时间间隔内输出正弦曲线上的点,并在此期间输出相同的电压值。如果缩短时间间隔,提高单个周期内的输出点,可以获得接近连续正弦波的图形,见下图 37-3,如果在外部电路上加入适当的电容滤波,可以得到更完美的图形。
由于正弦曲线是一个周期函数,因此只需要在单个周期内获得数据并按周期重复,而单个周期内取样输出的点数有限,因此为了获得呈现 v=sin(t)函数关系电压值的数据通常不是实时计算获得的,而是在函数单个周期内提前计算电压数据表,并转换为 DAC 寄存器所表示的值。 如 sin 函数值的范围为[-1: 1],而 STM32 的 DAC 输出电压范围为[0~3.3]V,按 12 位 DAC 分辨率表示的方法,可写入寄存器的最大值为 212 = 4096,即范围为[0:4096]。因此,在实际输出时,将进行以下处理:
抬升 sin 函数输出为正值:v = sin(t) 1 ,此时,v 输出范围为[0:2]; 扩展输出至 DAC 全电压范围: v = 3.3*(sin(t) 1)/2 ,此时,v 输出范围为[0:3.3], 正是 DAC 可充分利用扩展到全电压范围的电压输出范围 DAC 的分辨率; 把电压值以 DAC 寄存器的形式表示:Reg_val = 212/3.3 * v = 211*(sin(t) 1)此时,存储 DAC 寄存器的值范围为[0:4096]; 实践证明,在 sin(t)在单个周期内,取 32 电压输出可以更好地恢复正弦波形,因此在 t∈[0:2π]根据上述范间内的等间距 Reg_val 获得公式运算 32 正弦波表可以通过寄存器值获得; 控制 DAC 输出时,每隔一段相同的时间从上述正弦波表中取出一个新数据进行输出,即可输出正弦波。改变间隔时间的单位长度,可以改变正弦波曲线的周期。 正弦波数据表:
[2048, 2460, 2856, 3218, 3532, 3786, 3969, 4072, 4093, 4031, 3887, 3668, 3382, 3042, 2661, 2255, 1841, 1435, 1054, 714, 428, 209, 65, 3, 24, 127, 310, 564, 878, 1240, 1636, 2048]
七、修改main函数 添加正弦波数据表
uint16_t Sine12bit[32] = { 2048 , 2460 , 2856 , 3218 , 3532 , 3786 , 3969 , 4072 , 4093 , 4031 , 3887 , 3668 , 3382 , 3042 ,2661 , 2255 , 1841 , 1435 , 1054 , 714 , 428 , 209 &nsp;, 65 , 3 , 24 , 127 , 310 , 564 , 878 , 1240 , 1636 , 2048 }; 添加 HAL_TIM_Base_Start() 函数,启动定时器。 添加 HAL_DAC_Start_DMA()函数,启动 DAC 的 DMA 输出。
uint16_t Sine12bit[32] = { 2048 , 2460 , 2856 , 3218 , 3532 , 3786 , 3969 , 4072 , 4093 , 4031 , 3887 , 3668 , 3382 , 3042 ,2661 , 2255 , 1841 , 1435 , 1054 , 714 , 428 , 209 , 65 , 3 , 24 , 127 , 310 , 564 , 878 , 1240 , 1636 , 2048 };
/** * @brief The application entry point. * @retval int */ 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();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */ MX_DAC_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start(&htim2); HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)Sine12bit, 32, DAC_ALIGN_12B_R); /* USER CODE END 2 */
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */
/* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
———————————————— 八、试验波形