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

相关推荐
枯无穷肉1 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
星河梦瑾1 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
不过四级不改名6771 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普1 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣2 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室2 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费2 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
长潇若雪3 小时前
《类和对象:基础原理全解析(上篇)》
开发语言·c++·经验分享·类和对象
qq_397562314 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo20174 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范