STM32G474对于TIM+DAC+DAM简单使用

11 篇文章 0 订阅

STM32G474的DAC具有4个内部通道以及3个外部通道。
此篇以TIM+DMA + DAC实现3通道转换,且三通道相互独立控制。不需要独立使用则可以节省1TIM+DMA+DAC。
对于三通道独立使用DAC配置如下:


__align(32) volatile uint16_t DAC1_ConvertedValue[40];//转换数组
__align(32) volatile uint16_t DAC2_ConvertedValue[40];
__align(32) volatile uint16_t DAC3_ConvertedValue[40];

void Dac1_Dma_Init(void)
{
	DAC_ChannelConfTypeDef DAC_Config;
	
	DAC1_Handle.Instance = DAC1;
	if (HAL_DAC_Init(&DAC1_Handle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	DAC_Config.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;		//指定DAC输出是否连接到芯片外围
	DAC_Config.DAC_DMADoubleDataMode = DISABLE;					//指定在选择的通道中是否应该启用DMA双数据模式
	DAC_Config.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;//指定频率接口模式
	DAC_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;		//指定DAC通道输出缓冲区是否启用或禁用
	DAC_Config.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;	//指定DAC模式
	DAC_Config.DAC_SignedFormat = DISABLE;				//指定在选择的通道中是否应该使用已签署的格式
	DAC_Config.DAC_Trigger = DAC_TRIGGER_T4_TRGO;		//指定选择的DAC通道的外部触发器TIM4
	DAC_Config.DAC_Trigger2 = DAC_TRIGGER_NONE;			//指定选择的DAC通道的外部二次触发器
	DAC_Config.DAC_UserTrimming = DAC_TRIMMING_FACTORY;//指定平边模式	
	if (HAL_DAC_ConfigChannel(&DAC1_Handle, &DAC_Config, DAC_CHANNEL_1) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}	
	if (HAL_DACEx_SelfCalibrate(&DAC1_Handle, &DAC_Config, DAC_CHANNEL_1) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	DAC_Config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;	//TIM6
	if (HAL_DAC_ConfigChannel(&DAC1_Handle, &DAC_Config, DAC_CHANNEL_2) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	if (HAL_DACEx_SelfCalibrate(&DAC1_Handle, &DAC_Config, DAC_CHANNEL_2) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	if (HAL_DAC_Start_DMA(&DAC1_Handle, DAC_CHANNEL_1, (uint32_t*)DAC1_ConvertedValue, 40, DAC_ALIGN_12B_R) != HAL_OK)//需要转换传输的数有40个
	{
		Error_Handler(__FILE__, __LINE__);
	}
	if (HAL_DAC_Start_DMA(&DAC1_Handle, DAC_CHANNEL_2, (uint32_t*)DAC2_ConvertedValue, 40, DAC_ALIGN_12B_R) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}	
}

void Dac2_Dma_Init(void)
{
	DAC_ChannelConfTypeDef DAC_Config;
	
	DAC2_Handle.Instance = DAC2;
	if (HAL_DAC_Init(&DAC2_Handle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	DAC_Config.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;		
	DAC_Config.DAC_DMADoubleDataMode = DISABLE;					
	DAC_Config.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;
	DAC_Config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;		
	DAC_Config.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;	
	DAC_Config.DAC_SignedFormat = DISABLE;				
	DAC_Config.DAC_Trigger = DAC_TRIGGER_T7_TRGO;	//TIM7	
	DAC_Config.DAC_Trigger2 = DAC_TRIGGER_NONE;			
	DAC_Config.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
	if (HAL_DAC_ConfigChannel(&DAC2_Handle, &DAC_Config, DAC_CHANNEL_1) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	
	if (HAL_DACEx_SelfCalibrate(&DAC2_Handle, &DAC_Config, DAC_CHANNEL_1) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
		
	if (HAL_DAC_Start_DMA(&DAC2_Handle, DAC_CHANNEL_1, (uint32_t*)DAC3_ConvertedValue, 40, DAC_ALIGN_12B_R) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
}

以上为三通道DAC配置。
对于DMA的配置则如下:

void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	__HAL_RCC_DMAMUX1_CLK_ENABLE();
	__HAL_RCC_DMA1_CLK_ENABLE();
	
	if(hdac->Instance == DAC1)
	{
		__HAL_RCC_DAC1_CLK_ENABLE();
		__HAL_RCC_GPIOA_CLK_ENABLE();
		
		GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
		GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
		
		DAC1DMA_Handler.Instance = DMA1_Channel1;
		DAC1DMA_Handler.Init.Request = DMA_REQUEST_DAC1_CHANNEL1;
		DAC1DMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
		DAC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
		DAC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
		DAC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
		DAC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
		DAC1DMA_Handler.Init.Mode = DMA_CIRCULAR;
		DAC1DMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
		if (HAL_DMA_Init(&DAC1DMA_Handler) != HAL_OK)
		{
			Error_Handler(__FILE__, __LINE__);
		}

		DAC2DMA_Handler.Instance = DMA1_Channel2;
		DAC2DMA_Handler.Init.Request = DMA_REQUEST_DAC1_CHANNEL2;
		DAC2DMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
		DAC2DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
		DAC2DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
		DAC2DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
		DAC2DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
		DAC2DMA_Handler.Init.Mode = DMA_CIRCULAR;
		DAC2DMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
		if (HAL_DMA_Init(&DAC2DMA_Handler) != HAL_OK)
		{
			Error_Handler(__FILE__, __LINE__);
		}
		
		__HAL_LINKDMA(hdac,DMA_Handle1,DAC1DMA_Handler);
		__HAL_LINKDMA(hdac,DMA_Handle2,DAC2DMA_Handler);
	}
	else if(hdac->Instance == DAC2)
	{
		__HAL_RCC_DAC2_CLK_ENABLE();
		__HAL_RCC_GPIOA_CLK_ENABLE();
		
		GPIO_InitStruct.Pin = GPIO_PIN_6;
		GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
		
		DAC3DMA_Handler.Instance = DMA1_Channel3;
		DAC3DMA_Handler.Init.Request = DMA_REQUEST_DAC2_CHANNEL1;
		DAC3DMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH;
		DAC3DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;
		DAC3DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;
		DAC3DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
		DAC3DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
		DAC3DMA_Handler.Init.Mode = DMA_CIRCULAR;
		DAC3DMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
		if (HAL_DMA_Init(&DAC3DMA_Handler) != HAL_OK)
		{
			Error_Handler(__FILE__, __LINE__);
		}

		__HAL_LINKDMA(hdac,DMA_Handle1,DAC3DMA_Handler);
	}
}

以下为3个定时器配置,当定时时间到达,DAC将会转换一次。

void Dac_config_Init(uint8_t num)
{
	TIM_ClockConfigTypeDef sClockSourceConfig;
	TIM_MasterConfigTypeDef sMasterConfig;
	
	switch(num)
	{
		case DacTim1:
			TIMx_Handle[num].Instance = TIM4;
			break;
		
		case DacTim2:
			TIMx_Handle[num].Instance = TIM6;
			break;
		
		case DacTim3:
			TIMx_Handle[num].Instance = TIM7;
			break;
	}
	
	TIMx_Handle[num].Init.Prescaler = 1 - 1;
	TIMx_Handle[num].Init.Period = 170 * 5 - 1;//5us
	TIMx_Handle[num].Init.RepetitionCounter = 0;
	TIMx_Handle[num].Init.CounterMode = TIM_COUNTERMODE_UP;
	TIMx_Handle[num].Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	TIMx_Handle[num].Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	if (HAL_TIM_Base_Init(&TIMx_Handle[num]) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
	if (HAL_TIM_ConfigClockSource(&TIMx_Handle[num], &sClockSourceConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
	sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	if (HAL_TIMEx_MasterConfigSynchronization(&TIMx_Handle[num], &sMasterConfig) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}
}

以上为STM32G474对于3个TIM+DAC+DMA的使用,对于双通道同步输出则只需要简单修改即可。以上配置DMA传输数据为每个通道40个。定时器是每5us转换一次,转换时三通道同步转换,转换值由数组中的参数决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值