本期测评我来完成一下我测评计划中提到的用DAC输出一个正选波形。DAC波形输出效果请看二楼。我这里给大家总结了两种输出正弦波形的方法,查表法和公式法。
准备工作
首先我们先翻阅一下datasheet,看一下dac的引脚是什么。
这里翻阅之后我们需要在msp.c文件中进行引脚的初始化。msp.c文件一般是使能相应的硬件和做引脚初始化的。
下面这段代码主要进行初始化dac以及dac两个通道的引脚,并且还使能了dma中断。
void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
{
if(hdac->Instance==DAC)
{
/* Enable DAC clock */
__HAL_RCC_DAC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStructure;
/* Initialization GPIO */
/**DAC1 GPIO Configuration
PA4 ------> DAC_OUT1
PA5 ------> DAC_OUT2
*/
GPIO_InitStructure.Pin = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStructure.Pull=GPIO_NOPULL;
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
printfS("DAC Channel-1:PA4\r\n");
printfS("DAC Channel-2:PA5\r\n");
/* Enable the DAC DMA underrun interrupt */
hdac->Instance->CR |= DAC_CR_DMAUDIE1 | DAC_CR_DMAUDIE2;
NVIC_ClearPendingIRQ(DAC_IRQn);
NVIC_SetPriority(DAC_IRQn, 5);
NVIC_EnableIRQ(DAC_IRQn);
}
}
这里完成之后我们需要在新建一个dac.c文件,用于存放我们的dac相关的代码。我们知道dac是属于数模转换,用12位或其他位数字转换成对应的电压值。下面是dac转换逻辑图,方便大家理解dac。
1.查表法
查表法就是将正弦波的数据存在一个数组中,然后依次遍历这个数组将其存入dac转换器。这种方法的缺点是cpu占用率较高,不利于多任务的运行。
我们先定义一个数组,用于存放我们的dac的数值。到时候我们可以直接将这些数字写进dac转换寄存器当中就可以实现转换了。
这里我打算用用定时器来定义每两个数值之间的转换时间,定义一个变量volatile uint32_t gtimer_Update_Flag标志位来确定是否可以进行转换了,并且在定时器中断中将他置1。这里我用的是TIM7,定时器初始化代码如下
我们在更新中断里把这个标志位置1,如下图所示
此时我们就可以编写dac输出正弦波的应用代码了,只需要在判断标志位为1时利用函数HAL_DACEx_DualSetValue将数组的数值写进到寄存器当中就可以了,如下图所示
这里我们就完成了全部的代码编写,我这里创建一个任务来运行。
2.公式法
公式法简而言之就是利用数学公式进行计算,我把这一步骤设计在定时器中断中,可以减少cpu的占有率,有利于多任务的运行。
我们这一方法相比上方的查表法,只需要修改函数DAC_OutPut_Sinx中的应用代码。其只需要进行初始化。
而这个方法的重头戏就在定时器中断中,我们在定时器中断中进行计算。
大家看到我上面的公式,看一看出我的正选波的振幅是多大吗?
我的振幅A=(1240/4096)*3.3 约等于1V,有兴趣的小伙伴可以看看我的定时器,算算我的正弦波的频率为多大。
创建任务代码和查表法是一样的,不需要改动。
总结:这次测评我用了两种方法来输出正弦波,分别为查表法和公式法。但是我更推荐用公式法,因为是在定时器中断中完成的,减少了cpu的占用率,方便多任务的运行。两种方法我都在我的工程实现了,大家可以去验证一下。
本帖最后由 qiao--- 于 2024-1-22 22:59 编辑
DAC两种方法输出正弦波形
而这个方法的重头戏就在定时器中断中,我们在定时器中断中进行计算。
更正一下楼主的提法,应该是在定时器“回调函数”中完成。
我也很粗心呀,经常出错漏。
我现在给你用示波器演示一下。
楼主,您也可以尝试一下 DMA + DAC + Timer 的组合方式,即DMA用来传输DAC的输出值,Timer用来定期触发DMA开始传输。
引用: lugl4313820 发表于 2024-1-20 09:02 而这个方法的重头戏就在定时器中断中,我们在定时器中断中进行计算。 更正一下楼主的提法,应该是在定时 ...
所言极是,感谢更正
引用: lugl4313820 发表于 2024-1-20 08:59 我直接输出电压值,但是用ADC测试,那的电压是不稳定的,如果我想一直输出电压值 需要怎么操作呀
你的意思是用DAC输出电压,用ADC再测DAC输出的电压吗
引用: jobszheng5 发表于 2024-1-20 09:24 楼主,您也可以尝试一下 DMA + DAC + Timer 的组合方式,即DMA用来传输DAC的输出值,Timer用来定期触发DMA ...
确实,这样也可以减少cpu 的使用率,直接用DMA传输表中的数了,感谢珍贵意见
引用: qiao--- 发表于 2024-1-20 12:38 整么样,有没有波形,没有我改一下代码
好象没有出波形,测出来的是电源的干扰波形。还有用中断的方式,你要加入延迟,要不LED任务就不运行了。
我在前面也用DAC弄了一下,但是好象输出的电压不是稳定的。
引用: lugl4313820 发表于 2024-1-20 12:45 好象没有出波形,测出来的是电源的干扰波形。还有用中断的方式,你要加入延迟,要不LED任务就不运行了。 ...
懂了,用第一种方法需要改一下那个定时器回调函数,需要把那个置1这个你改没,如果没改可能是因为这个才没有波形,就是第二种方法有波形但是led任务没有正常运行这样对吗
引用: lugl4313820 发表于 2024-1-20 12:46 我在前面也用DAC弄了一下,但是好象输出的电压不是稳定的。
不稳定,DAC好像有一个矫正功能,你可以试一下,用之前矫正一下看看
引用: littleshrimp 发表于 2024-1-20 12:43 定时器中断里做这样的运算 应该花很长时间才能退出中断吧?
中断要快进快出,我这个运算很快的,之前在一本书上看到这样写的
引用: qiao--- 发表于 2024-1-20 12:49 懂了,用第一种方法需要改一下那个定时器回调函数,需要把那个置1这个你改没,如果没改可能是因为这个才 ...
第二种好象也没有,第一种也是一样的。
引用: qiao--- 发表于 2024-1-20 12:50 不稳定,DAC好像有一个矫正功能,你可以试一下,用之前矫正一下看看
其实这个CPU频率非常高,用你多任务系统,对CPU来说没什么问题。可以采用DMA配合中断来实现。