如果串口可以用dma,spi可以用dma,adc都可以用dma,那岂不是dac也可以用dma?加上预先存好的数据来模拟任意的电压变化?来模拟一些信号波形,甚至音频?
尝试一下,好像还真可以,在cube下的配置还非常简单(踩坑不算的话)。
基本流程是配置dac,并且使用dma功能,从内存到外设,外设也就是dac的电压输出值,dma由定时器触发,开启一次dma发送,包括多个数据,每个数据的传输则有定时器的定时时间来控制,信号的周期也可以通过定时器的定时时间来修改
1.dac的设置
基础的参数设置很简单,output buffer不影响功能(随意),
触发方式需要选择一个定时器来控制,例如tim6
信号生成模式选择disable,否则就是内置的三角波以及噪声信号。
2.dma的设置
字还是半字需要和数据匹配。
3.tim6的设置
不一定是tim6,而是dac触发方式选择了哪个定时器,就相应配置哪个。
主要是需要选择事件输出,当定时时间到了,会触发一次dac的转换
4.验证正弦波
增加正弦波的信号幅值大小的表数组,网上抄来的,只是为了演示功能。
/*正弦波数据,12bit,1个周期128个点, 0-4095之间变化*/
const uint32_t userWavesin[] =
{
2047, 2147, 2248, 2347, 2446, 2544, 2641, 2737,
2830, 2922, 3012, 3099, 3184, 3266, 3346, 3422,
3494, 3564, 3629, 3691, 3749, 3803, 3852, 3897,
3938, 3974, 4006, 4033, 4055, 4072, 4084, 4092,
4094, 4092, 4084, 4072, 4055, 4033, 4006, 3974,
3938, 3897, 3852, 3803, 3749, 3691, 3629, 3564,
3494, 3422, 3346, 3266, 3184, 3099, 3012, 2922,
2830, 2737, 2641, 2544, 2446, 2347, 2248, 2147,
2047, 1947, 1846, 1747, 1648, 1550, 1453, 1357,
1264, 1172, 1082, 995, 910, 828, 748, 672,
600, 530, 465, 403, 345, 291, 242, 197,
156, 120, 88, 61, 39, 22, 10, 2,
0, 2, 10, 22, 39, 61, 88, 120,
156, 197, 242, 291, 345, 403, 465, 530,
600, 672, 748, 828, 910, 995, 1082, 1172,
1264, 1357, 1453, 1550, 1648, 1747, 1846, 1947
};
开启dma的同时,需要开启定时器。
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)userWavesin, 128, DAC_ALIGN_12B_R);
HAL_TIM_Base_Start(&htim6);
然后在示波器上查看效果
放大一下可以看出正弦的信号是由很多个不同电压的脉冲形成的
并且在配置dma时,设置的circle循环模式,当一个周期执行完后,就会重新开始一次新的传输,所以就是连续的正弦波了。不过这东西为啥在每次输出之后会掉下来变成0还不知道原因,手册也没有说明。
至此,可以输出任意的信号了,或许可以用来直接驱动喇叭来模拟音频,只要解析到音频文件的数据源后再对应给信号到喇叭,就可以驱动喇叭发出原件原本的声音了。
测试例程在关注公众号(芯片家)后发送"正弦波"关键字后就可以获取下载链接了
其中dma的设置有些问题,在设置位宽时与程序中的数据类型不匹配导致电压变0形成了脉冲,重新发了一篇续。