目录
一、参考硬件
二、 建立新工程
1.配置DAC
2.配置DMA
3.配置定时器
4.配置时钟和Debug
三、修改代码
1.初始化定时器和DAC
2.定义波形数据
3.波形数据的产生方法
四、查看结果
一、参考硬件
本项目依赖的软件和硬件工程参考本文作者写的文章: 细说MCU用自带的波形发生器实现DAC输出的方法-CSDN博客 https://blog.csdn.net/wenchm/article/details/140710913https://blog.csdn.net/wenchm/article/details/140710913
因为STM32G474RE可以通过GPIO输出三路模拟信号,DAC1有两个输出通道,DAC2 有一个;所以要输出两路信号,可以使用DAC1的一个通道和DAC2,也可以仅使用DAC1,用它的两个通道。
本文介绍使用DAC1的两个通道产生两路相位不同的正弦信号。
二、 建立新工程
1.配置DAC
在DAC1的模式(Mode)区,将两个通 道的模式(OUT1 mode和OUT2 mode)均选择为连接到外部引脚(Connected to external pin only)。
在DAC1通道的设置区,先将它们的输出缓冲(Output Buffer)禁止 (也可以保持使能),随后分别将它们的Trigger参数选择为Timer3 Trigger Out event。
2.配置DMA
增加一个DAC1_CH 请求(也可以是CH2)。
DMA请求模式选择Circular,让它循环工作;将外设 (Peripheral)和存储器(Memory)的数据宽度均选择为按字(Word)的方式。其余参数保持默认值。
3.配置定时器
选择TIM3,时钟源(Clock Source)选择为内部时钟(Internal Clock)。将预分频因子设置为0,计数器周期设为169,并将触发事件(Trigger Event Selection TRGO)选择为Update Event,其余参数保持默认值。
4.配置时钟和Debug
将高速时钟(HSE)设置为 Crystal/Ceramic Resonator,使用片外时钟晶体作为HSE的时钟源。最后,在SYS中将 Debug设置为Serial Wire。由于没有使用中断,所以不用配置NVIC。
三、修改代码
1.初始化定时器和DAC
由于使用了DAC的DMA功能,并且用TIM3来触发DAC,所以在初始化代码中要加入启动DAC和TIM3的语句。启动TIM3的函数通过调用库函数HAL_TIM_Base_Start()来实现。本例中还采用带DMA功能的DAC,但这次用的是DAC1的两个通道,所以要用专门的库函数来启动该功能,此函数为HAL_DACEx_Dual- Start_DMA()。将这两个函数的调用放到main函数中while(1)前的注释对中:
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim3);
HAL_DACEx_DualStart_DMA(&hdac1,DAC_CHANNEL_1,DualSineWaveData, DAC_BUFFER_SIZE,DAC_ALIGN_12B_R);
/* USER CODE END 2 */
在HAL_DACEx_DualStart_DMA()函数中,第二个参数用的是DAC_CHANNEL_1,是DAC1的通道1,这是因为前面配置DAC1的DMA参数时配置的是DAC1_CH1,如果配置的DAC1_CH2,则此处应使用DAC_CHANNEL_2;第三个参数用的是一个数组,用来存储波形数据,数据的长度为DAC_BUFFER_SIZE,该变量可以定义到main.h中:
/* USER CODE BEGIN Private defines */
#define DAC_BUFFER_SIZE (uint16_t) 50
/* USER CODE END Private defines */
2.定义波形数据
存储波形数据的数组DualSineWaveData在这里这个数组要定义成32位的,每个数据点包含两个16位的数,分别传递给DAC1的CH1和CH2。本例给出一个示例波形数据是两个正弦波,其中一个的幅值是另一个的一半。
/* USER CODE BEGIN PV */
uint32_t DualSineWaveData[DAC_BUFFER_SIZE] = {134155263,150998007,167578591,183569335,
198839168,213060412,226036458,237570700,247466532,255592883,261753148,265947327,268044352,
268044223,265946944,261752515,255592012,247465435,237569395,226034965,213058755,198837375,
183567432,167576608,150995976,134218752,117376008,100795424,84804680,69534847,55313603,
42337557,30803315,20907483,12781132,6620867,2426688,329663,329792,2427071,6621500,12782003,
20908580,30804620,42339050,55315260,69536640,84806583,100797407,117378039};
/* USER CODE END PV */
将上述数组DualSineWaveData定义为全局变量,放到主函数的注释对中。
3.波形数据的产生方法
使用MATLAB软件,在新编辑器窗口,编辑并生成波形数据:
A = 4096/2-1; %信号幅值
N = 50; %一个周期内的数据点数
Ph = 0; %信号1初始相位
Ph2 = pi/2; %信号2初始相位
SineDataPh0 = ceil(A*sin(Ph:2*pi/N:2*pi*(1-1/N)+Ph)+A);
SineDataPh90 = ceil(A/2*sin(Ph2:2*pi/N:2*pi*(1-1/N)+Ph2)+A);
SineData = SineDataPh0*65536+ SineDataPh90;
Fid = fopen('SineData.txt','w');
fprintf(Fid,'%d,',SineData);
fclose(Fid);
四、查看结果
根据TIM3参数的设置,生成的正弦波形频率应该为20 kHz。
DAC1_OUT1对应PA4,DAC1_OUT2对应PA5。PA5通过NUCLEO- G474RE板上CN10的第11引脚或CN5的第6引脚引出(该引脚就是控制板上发光二极管 LD2的引脚)。通过示波器测量PA4、PA5引脚上的电压,将会得到两个正弦波,频率均为 20 kHz。
由示波器波形图可以看到,两路信号的幅值不同,相位也不同,这是由于在32位数组中组组合了两个波形数据。
SineData是两路数据(SineDataPh0和SineDataPh90)合成的结果。SineDataPh90的初始相位为90°(即pi/2),所以在sin()函数的参数里,是从pi/2开始的。在SineData中,低16位对应的是初始相位为90°的数据,并且幅值为A/2。在DMA传递数据时,低 16位会传递给DAC1的通道1。