STM32G474CET6 DAC+DMA输出正弦波

转载:

原作者

 

https://www.cnblogs.com/cariohu/p/16152996.html

通过DAC输出正弦波可以直接在while循环中设置DAC的输出值,函数是HAL_DAC_SetValue(&hdac1,DAC1_CHANNEL_1,DAC_ALIGN_12B_R,2000)。但这种方式会导致CPU的负载率太高,刷新频率也不够快。所以,我需要用DMA来帮助CPU把数据快速的写入DAC的值寄存器中。CubeMX中的具体配置步骤如下

第一步,配置总线时钟,按下图配置即可,我们用的一般都是陶瓷晶振。注意是HSE作为时钟输入源,系统时钟选择PLLCLK。

  

        第二步,配置JTAG口,下载和调试程序使用

        第三步,配置TIM6,这个是作为DAC输出更新的触发源,DAC就是按这个TIM6的时间间隔更新输出。其他定时器也可以作为触发源的,具体哪些看对应芯片手册。分频系数为0就是不分配,总线时钟168M,计数值1680-1就是10us更新一次。触发事件要选择update,这个一定要选,不然DAC没有触发源,不会工作的。

         第四步,配置DAC,DAC的配置要选择连接到外部的pin,这样信号就是在pin脚输出了。Trigger触发源要选择TIM6 trigger,如果配置的是其他TIM就对应更改,DAC配置这两个就可以了,其他默认即可。

        第五步,配置DMA,DMA是英文Direct memory access的缩写,就是内存的直接访问,这样的话就不需要CPU来写入了,并且它的速率远高于通过CPU操作的方式。模式选择circular,这样只需启动一次DMA传输即可。数据宽度需要特别注意,外设是选择Word而不是halfword,被这个坑了很久。

问题解决后看到官方手册的如下描述,访问AHB总线的外设不支持byte/half-word传输,这个一定要注意,被坑了很久。

        配置好之后用CubeMX工具生产代码,主要要选择对应的编译器,我用的是KEIL v5。只需要在主函数中加两条指令和一个sin波形数组就可以了。如下是sin波形生产数据,这里只是举例,大家可以有自己的数组。

//正弦波单个周期的点数
#define POINT_NUM 32
uint8_t Idx;
/* 波形数据 ---------------------------------------------------------*/
const uint16_t Sine12bit[POINT_NUM] = {
	2048	, 2460	, 2856	, 3218	, 3532	, 3786	, 3969	, 4072	,
	4093	, 4031	, 3887	, 3668	, 3382	, 3042	,	2661	, 2255	, 
	1841	, 1435	, 1054	, 714		, 428		, 209		, 65		, 3			,
	24		, 127		, 310		, 564		, 878		, 1240	, 1636	, 2048
};


HAL_TIM_Base_Start(&htim7);
HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_1,(uint32_t *)Sine12bit, 32,DAC_ALIGN_12B_R);
HAL_DAC_Start_DMA(&hdac,DAC_CHANNEL_2,(uint32_t *)DualSine12bit, 32,DAC_ALIGN_12B_R);
	

        在初始化这里添加如下函数,第一个函数是启动TIM,这样TIM就会按设定好的时间去触发DAC。当DAC被触发后就会发送DMA请求,DMA收到请求后就会把一个数据传入DAC寄存器,然后等待下一次的请求。流程就是TIM—>DAC—>DMA,DMA把数据传入DAC后,DAC就会释放DMA请求,等带下一次TIM的触发信号。当整个数组传输完成后,又会开始下一轮的传输,因为DMA的模式是circular。

        第二个函数就是启动DAC和DMA,最后一个参数是12bit的右对齐。这个就是这么简单,改变定时器的定时时间也就是改变正弦波的周期,可以根据需要自己调节。正弦波的周期就是  定时时间间隔*数组长度。我试了下TIM6的频率为12Mhz的时候信号输出正常,频率再高的时候DAC输出不变化了,这个12Mhz的更新频率比直接在while循环中赋值的方式至少快了一个数量级。

        接示波器效果如下,唯一遇到是就是DMA配置的坑,其他一次成功。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用DAC DMA输出正弦波,您需要按照以下步骤操作: 1. 打开STM32CubeMX软件,并创建一个新的工程。 2. 在“Pinout”选项卡中,选择您的MCU型号,然后选择DAC输出管脚。 3. 在“Clock Configuration”选项卡中,设置DAC时钟源和时钟分频器。 4. 在“DAC Configuration”选项卡中,启用DAC,并设置DAC输出参数,例如分辨率和数据对齐方式。 5. 在“DMA Configuration”选项卡中,启用DMA,并设置DMA通道参数,例如传输方向和数据宽度。 6. 在“Project Manager”选项卡中,生成代码,并在Keil或者其他编译器中编译和下载代码。 7. 在代码中编写一个生成正弦波的函数,并使用DMA正弦波数据发送到DAC输出寄存器。 8. 在主函数中调用生成正弦波函数,并启动DMA传输。 下面是一个简单的生成正弦波函数的示例代码: ```c #include <math.h> #define PI 3.14159265358979323846 void generate_sine_wave(uint16_t *buffer, uint16_t buffer_size, uint16_t amplitude, uint16_t offset, uint16_t frequency) { for (uint16_t i = 0; i < buffer_size; i++) { float sine_value = sin(2 * PI * frequency * i / buffer_size); uint16_t dac_value = (uint16_t)((sine_value + 1) * amplitude / 2 + offset); buffer[i] = dac_value; } } ``` 在主函数中,您可以按照以下步骤启动DMA传输: ```c // 初始化DAC输出缓冲区 #define BUFFER_SIZE 100 uint16_t dac_buffer[BUFFER_SIZE]; generate_sine_wave(dac_buffer, BUFFER_SIZE, 2048, 2048, 10); // 启动DMA传输 HAL_StatusTypeDef status = HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)dac_buffer, BUFFER_SIZE, DAC_ALIGN_12B_R); if (status != HAL_OK) { // DMA传输启动失败 } ``` 这样,您就可以使用DAC DMA输出正弦波了。您可以通过更改生成正弦波函数中的参数来调整正弦波的幅度、偏移和频率。您还可以通过更改DAC输出参数来调整DAC输出的分辨率和数据对齐方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值