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引脚的波形如下:

相关推荐
三菱-Liu16 分钟前
三菱FX5U CPU实时监视功能GX LogViewer Version
驱动开发·嵌入式硬件·硬件工程·制造
板子小哥1 小时前
Lua语法基础全面剖析(中篇)
开发语言·嵌入式硬件·junit·单元测试·硬件工程·lua·1024程序员节
杜若南星1 小时前
保研考研机试攻略:python笔记(2)
数据结构·经验分享·笔记·python·考研·算法
Industio_触觉智能1 小时前
瑞芯微RK3566/RK3568 Android11下该如何默认屏蔽导航栏/状态栏?看这篇文章就懂了
嵌入式硬件·物联网·rk3568·rk3566·鸿蒙开发板
陌夏微秋2 小时前
00 硬件、嵌入式硬件知识-目录篇
linux·stm32·单片机·嵌入式硬件·mcu·ubuntu
yava_free2 小时前
OpenMV的无人驾驶智能小车模拟系统
c语言·c++·stm32
Whappy0013 小时前
4. STM32之TIM实验--输出比较(PWM输出,电机,四轴飞行器,智能车,机器人)--(实验2:PWM驱动舵机)
stm32·嵌入式硬件·机器人
RIGOL小普3 小时前
如何利用双踪示波器测量两个电压信号的相位差?如何判别波形的超前与滞后?
单片机·嵌入式硬件·fpga开发·硬件工程·射频工程
烧烤大团子3 小时前
记录cuda12.4 ubuntu20.04安装DGL
linux·经验分享
cl°4 小时前
【WPF】如何获取屏幕比例
经验分享·wpf