有人使用STM32G431芯片做DAC应用,具体来说就是通过DMA将数据从指定内存传送给DAC数据寄存器,并由定时器触发DAC转换。他发现总是没法实现该功能。这里简单介绍下相关实现过程,并做些提醒。这里要演示的基本功能就是让DAM将内存数据周期性传输给DAC数据寄存器,最后输出一路正弦波。
结合STM32G4芯片的特性,这里可以有两种实现方式。
第一种,DMA的请求来自于DAC1的转换事件。第二种,DMA的请求来自于定时器事件,下面用到的是定时器的更新事件。这里就两种实现方式的配置及相关用户代码简单介绍下,以供参考。
我们先看第一种方式,即DMA请求来自DAC转换事件,定时器3触发DAC的转换。
使用CubeMx进行配置
完成配置后生成初始代码,再添加下面代码即可验证测试:
#define Tpai (2*3.14159)
uint32_t PData[200],Dac_data;
uint16_t i;
for (i=0;i《200;i++)
{
PData[i]=
(uint32_t ) (2000*(sin((Tpai/200)*i))+2000);
} //prepare data for DAC
HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t*)&PData[0], 200,DAC_ALIGN_12B_R);
__HAL_TIM_ENABLE(&htim3);
上面配置的DMA传输方向是从内存到外设,目的和源的访问宽度都是32位WORD. 当然也可以是内存访问宽度为16位的半字,外设访问宽度为32位字。即DMA的配置像下面这样也是可以的。
其它配置不动,代码稍微改动和整理下即可。参见下面代码:
Uint16_t PData[200],Dac_data;
#define Tpai (2*3.14159)
uint16_t i;
for (i=0;i《200;i++)
{
PData[i]=
(uint16_t )(2000*(sin((Tpai/200)*i))+2000);
} //prepare data for DAC
SET_BIT(hdac1.Instance-》CR,DAC_CR_DMAEN1);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
HAL_Delay(2);
HAL_DMA_Start_IT(&hdma_dac1_ch1,(uint32_t)&PData[0],(uint32_t)&DAC1-》DHR12R1, 200);
__HAL_TIM_ENABLE(&htim3);
第一种方式就介绍到这里,再来看看第二种实现方式,即TIMER更新事件作为DMA请求源,同时作为DAC转换触发源。
基于CubeMx配置,主要调整下DMA配置,其它配置基本不动。
主要是DMA请求事件变了,其它配置跟第一种模式基本一样。
配置完成后生成初始化代码,再添加下面用户代码:
#define Tpai (2*3.14159)
uint16_t PData[200], Dac_data;
uint16_t i;
for (i=0;i《200;i++)
{
PData[i]=
(uint16_t )(2000*(sin((Tpai/200)*i))+2000);
}
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
HAL_Delay(3);
HAL_DMA_Start(&hdma_tim3_up,(uint32_t)&PData[0],(uint32_t)&DAC1-》DHR12R1, 200);
__HAL_TIM_ENABLE_DMA(&htim3, TIM_DMA_UPDATE);
__HAL_TIM_ENABLE(&htim3);
这里要提醒一点,G4系列的DAC1的数据保持寄存器可以一次放2个通道的数据,在使用DMA传输时,即使只用到1个通道,DMA对它的访问也要遵循WORD对齐,不然你可能会遇到麻烦。
如果说,我们不使用DMA做数据传输,只是手动给DAC喂数据,那如何实现上述效果呢?这时我们可以使用软件触发DAC的传输,手动给DAC的数据保持寄存器赋值,参考配置及实现代码如下:
相关用户代码如下:
#define Tpai (2*3.14159)
uint16_t PData[200],Dac_data;
uint16_t i;
for (i=0;i《200;i++)
{
PData[i]=
(uint16_t)(2000*(sin((Tpai/200)*i))+2000);
}
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
HAL_Delay(3);
while(1)
{
for(i=0;i《200;i++)
{
DAC1-》DHR12R1= PData[i];
SET_BIT(hdac1.Instance-》SWTRIGR,DAC_SWTRIGR_SWTRIG1);
HAL_Delay(5);
Dac_data = DAC1-》DOR1;//for debug
}
}
总之,不论使用哪种方式,都可以实现我们所期望的结果,即输出如下正弦波。