STM32G474使用TIM2触发DAC输出输出正弦波

STM32G474使用TIM2触发DAC输出,数据从内存到外设就要使用DMA来协助。DAC1每隔1秒输出一个正弦波数据,就会模拟近似得到模拟的正弦波形。用来测试CPU内部的运算放大器,或者用作其它模拟输入信号。

测试程序如下:

#include "DAC.h"
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "delay.h"

/*
STM32G474之DAC输出,使用DMA从内存搬运数据到DAC1外设,使用TIM2触发DAC1输出
*/

void DAC1_CHANNEL_1_Init(void);

const uint16_t Sine12bit[32] = { 511, 611, 707, 796, 873, 937, 984, 1013,

1023, 1013, 984, 937, 873, 796, 707, 611,

511, 412, 315, 227, 149, 86, 38, 9,

0, 9, 38, 86, 149, 227, 315, 412};
//函数功能:DAC1通道1初始化
void DAC1_CHANNEL_1_Init(void)

{

DAC_HandleTypeDef hdac1;
//DAC1句柄,若直接对寄存器DAC1->DHR12R1和DAC1->DHR12R2操作,就可以将其设置为局部变量
//DAC1->DHR12R1为DAC通道1(12位右对齐数据保持寄存器)
//DAC1->DHR12R2为DAC通道2(12位右对齐数据保持寄存器)

GPIO_InitTypeDef GPIO_InitStruct = {0};

DAC_ChannelConfTypeDef sConfig; //DAC通道参数相关结构体

DMA_HandleTypeDef hdma_dac1_ch1;

TIM_HandleTypeDef htim2;

TIM_ClockConfigTypeDef sClockSourceConfig = {0};

TIM_MasterConfigTypeDef sMasterConfig = {0};

__HAL_RCC_DAC1_CLK_ENABLE();
//使能DAC1时钟
//RCC_AHB2ENR寄存器bit18(DAC1EN),令DAC1EN=1使能DAC1时钟

__HAL_RCC_GPIOA_CLK_ENABLE();//GPIOA时钟使能

GPIO_InitStruct.Pin = GPIO_PIN_4; //选择引脚号码为4

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式

GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器,将PA4引脚连接到DAC1通道1

hdac1.Instance = DAC1; //DAC1

HAL_DAC_Init(&hdac1); //初始化DAC

sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;

//DAC时钟选择

sConfig.DAC_DMADoubleDataMode = DISABLE; //双重数据模式(高带宽模式)关闭

sConfig.DAC_SignedFormat = DISABLE; //有符号模式关闭

sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; //关闭采样保持

// sConfig.DAC_Trigger = DAC_TRIGGER_NONE; //不需要外部触发

sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;//使用TIM2触发DAC输出

sConfig.DAC_Trigger2 = DAC_TRIGGER_NONE;

sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; //DAC输出缓冲器打开

sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;//允许内部连接DAC_Channel
// sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; //不允许内部连接DAC_Channel

sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY; //工厂矫正模式

HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1); //初始化

__HAL_RCC_DMA1_CLK_ENABLE(); //DMA1时钟使能

__HAL_RCC_DMAMUX1_CLK_ENABLE();//设置RCC->AHB1ENR寄存器bit2(DMAMUX1EN位),令DMAMUX1EN=1,DMAMUX1时钟使能

hdma_dac1_ch1.Instance = DMA1_Channel1;//使用DMA1的通道1

hdma_dac1_ch1.Init.Request = DMA_REQUEST_DAC1_CHANNEL1;//DMA需求来源DAC1

hdma_dac1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;

//设置DMA_CCRx寄存器bit4(DIR位),令DIR=1,数据传输方向:内存到外设

hdma_dac1_ch1.Init.PeriphInc = DMA_PINC_DISABLE;

//设置DMA_CCRx寄存器bit6(PINC位),令PINC=0,外设地址不增加

hdma_dac1_ch1.Init.MemInc = DMA_MINC_ENABLE;

//设置DMA_CCRx寄存器bit7(MINC位),令MINC=1,内存地址增加

hdma_dac1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
//设置DMA_CCRx寄存器bit9:8(PSIZE[1:0]位),令PSIZE[1:0]=10,外设数据宽度32bits

hdma_dac1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
//设置DMA_CCRx寄存器bit11:10(MSIZE[1:0]]位),令MSIZE[1:0]=01,内存数据宽度16bits

hdma_dac1_ch1.Init.Mode = DMA_CIRCULAR;
//DMA_CIRCULAR:"DAM循环搬运数据"
//DMA_NORMAL;若启动一次DMA,则DMA搬运一次数据
//设置DMA_CCRx寄存器bit5(CIRC位),令CIRC=1,这里设置"DAM循环搬运数据"

hdma_dac1_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH;

//设置DMA_CCRx寄存器bit13:12(PL[1:0]),令PL[1:0]=11b,DMA抢占优先级最高

HAL_DMA_Init(&hdma_dac1_ch1);

__HAL_LINKDMA(&hdac1,DMA_Handle1,hdma_dac1_ch1);
//将DAC1与DMA联系起来
//把hdac1结构体的参数赋给DMA_Handle1

__HAL_RCC_TIM2_CLK_ENABLE();//使能"定时器2"的时钟,Enable TIM2 clock

htim2.Instance = TIM2;

htim2.Init.Period = 9999;

//定时器周期(9999+1)

htim2.Init.Prescaler = 16;

//设置TIM1预分频器为(16+1)

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//设置时钟分频系数,TIM1_CR1中的CKD[9:8]=00b,tDTS=ttim_ker_ck;
//溢出时间为(9999+1)*1*(16+1)/170000000/1=0.01秒

htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

htim2.Init.RepetitionCounter = 0;//重复计数(1-0),产生一次中断

htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;//TIM_AUTORELOAD_PRELOAD_DISABLE;
//这里设置"使能重装载"

HAL_TIM_Base_Init(&htim2);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
//TIM_TRGO_UPDATE是"更新事件用来触发器输出"Update event is used as trigger output (TRGO2)
// sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
//TIM1_TRGO2是adc_ext_trg10,用来触发ADC1/2/3/4/5

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

//Configures the TIM in master mode.

/*
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
//设置NVIC中断分组4:4位抢占优先级,0位响应优先级
//选择中断优先级组4,即抢占优先级为4位,取值为0~15,响应优先级组为0位,取值为0
//DMA1_Channel1_IRQn抢占优先级为5,响应优先级为0
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);//使能DMA1_Channel1_IRQn中断
*/

HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1,(uint32_t*)Sine12bit, 32, DAC_ALIGN_12B_R);

//启动DMA传输

HAL_TIM_Base_Start(&htim2);//启动TIM2

}

测试PA4引脚的波形如下:

相关推荐
良许Linux33 分钟前
32岁入行STM32迟吗?
stm32·单片机·嵌入式硬件
m0_466607701 小时前
【STM32CubeMX】ST官网MCU固件库下载及安装
stm32·单片机·嵌入式硬件
Wallace Zhang5 小时前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭5 小时前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
HX科技10 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Suagrhaha10 天前
驱动入门的进一步深入
linux·嵌入式硬件·驱动
国科安芯10 天前
基于ASP4644多通道降压技术在电力监测系统中集成应用与发展前景
嵌入式硬件·硬件架构·硬件工程