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

相关推荐
Yesheldon7 小时前
Cadence 高速系统设计流程及工具使用三
嵌入式硬件·fpga开发·硬件架构·硬件工程·智能硬件
inputA8 小时前
【LwIP源码学习6】UDP部分源码分析
c语言·stm32·单片机·嵌入式硬件·网络协议·学习·udp
思考的味道8 小时前
SVM在医疗设备故障维修服务决策中的应用:策略、技术与实践
嵌入式硬件
真的想上岸啊9 小时前
学习51单片机01(安装开发环境)
嵌入式硬件·学习·51单片机
7yewh10 小时前
MCU程序加密保护(二)ID 验证法 加密与解密
单片机·嵌入式硬件·安全
YOYO--小天10 小时前
RS485和RS232 通信配置
linux·嵌入式硬件
小_楠_天_问10 小时前
第二课:ESP32 使用 PWM 渐变控制——实现模拟呼吸灯或音调变化
c语言·嵌入式硬件·mcu·esp32·arduino·pwm·esp32-s3
欢乐熊嵌入式编程11 小时前
智能手表项目风险评估与应对计划书
嵌入式硬件·物联网·目标跟踪·智能手表
JANYI201811 小时前
TTL、RS-232、RS-485电平转换详解
单片机·嵌入式硬件
平凡灵感码头12 小时前
基于智能家居项目 解析DHT11温湿度传感器
单片机·智能家居