有人使用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
}
}
总之,不论使用哪种方式,都可以实现我们所期望的结果,即输出如下正弦波。
好,关于stm32g4的dac应用就简单介绍到这里,stm32g4系列的模拟外设丰富而强大,此处算是抛砖引玉。这里做些分享也是为了让其他有需要的人少走弯路,加速开发进程。【文中代码都很简短、直观,就没做注释说明了。还有个客观原因就是在微信公众号里排版也很费劲,字符不太好对齐。若有需要交流的可以后台留言。】
Imagination推出专为低功耗应用而设计的第二代IEEE 802.11n Wi-Fi硅知识产权(IP)产品
iW3662和iW3688加持,Dialog在照明领域再上新台阶
发烧耳机基础知识
微型断路器的原理说明
吴恩达:模拟人脑,未来AI执行精神层面任务有望快过人类!
基于STM32G4芯片的DAC应用示例分享
STM32中IO口模拟串口输出的乱码现象
某电磁炉热敏电阻测温原理图
魅族将于8月28日正式发布魅族16s Pro手机和全新配件品牌lifeme
工业互联网总体网络架构国家标准正式发布
腾讯与信通院共建联合实验室 解决人工智能产业难题
实现自动驾驶宏图需着眼于当前机遇
焊接机械手在焊接作业中的优势是什么
Realme将在印度尼西亚推出Realme 7i和Realme 7智能手机
电容串联和并联的区别
中国移动OneNET击穿智能家电成本底线
基于分裂式ADC的LMS算法实现数字后台校正
电动车常见问题和处理
智慧公安是智慧城市建设的突破口
Zytronic Displays 在深圳数字广告牌会议展示其独有投射电容式技术