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 Sine12bit32 = { 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(PSIZE1:0位),令PSIZE1:0=10,外设数据宽度32bits

hdma_dac1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
//设置DMA_CCRx寄存器bit11:10(MSIZE1:0]位),令MSIZE1: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(PL1:0),令PL1: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中的CKD9: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引脚的波形如下:

相关推荐
Zw-awa8 小时前
八路循迹模块的 DO:先让小车沿着线跑起来
stm32
黑妹天下第一乖10 小时前
第09讲 · 多媒体与音频 SDK:硬件编解码与端侧语音
人工智能·嵌入式硬件·深度学习·机器人·音视频·iot
富唯智能机器人10 小时前
机械加工厂数字化转型|机器人全场景应用解决方案|富唯智能
经验分享
comyccccc10 小时前
LM2596电源PCB布局布线全解析学习笔记
单片机·嵌入式硬件
一隅论数智11 小时前
OWL(Web Ontology Language)介绍与使用举例(二)
大数据·经验分享·笔记·学习·自然语言处理·学习方法·政务
恒锐丰科技林技术员12 小时前
EG2122 半桥栅极驱动芯片原理与工程应用解析
经验分享·嵌入式硬件·硬件工程
qq_4017004112 小时前
FreeRTOS 堆内存管理源码剖析:释放一块内存,空闲块数量反而变少了?
单片机·freertos
新晨单片机设计13 小时前
S017C-基于STM32汽车防酒驾系统(心率、血氧、短信)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·防酒驾报警系统
fly_sunnn14 小时前
STM32-GPIO输出以及按键控制LED&光敏传感器控制蜂鸣器
stm32·单片机·嵌入式硬件
数字新视界14 小时前
U位资产管理系统发布全面数字化监控解决方案
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统