EFM32片内外设--DAC之Alt output
如果大家有看EFM32的datasheet里面有关DAC输出通道时,是否有时候看的不是很明白? DAC0_OUT0,DAC0_OUT0ALT? 这些是什么概念,以及如何将DAC配置到相应的GPIO口上?这个问题也曾困扰过我,后来弄清楚之后,却一直没来得及写一篇说明。现在就补上吧,希望还不算晚。
首先,需要说明的是,只有内部带OPA功能的EFM32型号,才会遇到DAC Alt Output的问题。型号包括TG(部分),LG,GG,WG等。其他型号的DAC输出,以G840为例,就只有DAC0_OUT0,DAC0_OUT1引脚。
其次,要配置为DAC0_OUT0ALT等引脚输出,需要额外配置OPA的寄存器。
以下我们分三种情况,来分别描述寄存器如何设置。第一种情况,在DAC的DAC0_OUT0引脚上输出一个模拟电压。这是最常用的情况。第二种情况是在DAC0_OUT0ALT引脚上输出一个模拟电压。第三种情况就是同时在DAC0_OUT0和DAC0_OUT0ALT输出模拟电压。这样就能覆盖所有的应用情况了。好了,Let‘s go。 开工吧。
硬件平台:TG STK,MCU:TG840. 通过查询TG840的Datasheet可以得知,DAC0_OUT0是PB11(#0),DAC0_OUT0ALT是PD0(#4).
软件:参考后面的代码。
首先,我们先实现第一种情况,在DAC的DAC0_OUT0引脚上输出一个模拟电压,主要是将DAC的输出模式配置为Output to pin only。即OUTMODE = 1。参考代码如下:
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_dac.h"
/* Function prototypes */
void DAC_setup(void);
void DAC_WriteData(DAC_TypeDef *dac, unsigned int value, unsigned int ch);
/**************************************************************************//**
* @brief Main function
* Setup of dac and calculating output value, enter em1 while dac is working
*****************************************************************************/
int main(void)
{
/* Initialize chip */
CHIP_Init();
uint32_t DAC_Value;
/* Initialise the DAC */
DAC_setup();
/* Enable DAC channel 0, located on pin PB11 */
DAC_Enable(DAC0, 0, true);
/* Calculate output to 0.5 V. */
DAC_Value = (uint32_t)((0.8 * 4096) / 1.25);
/* Write the new value to DAC register */
DAC_WriteData(DAC0, DAC_Value, 0);
while(1);
}
/**************************************************************************//**
* @brief Setup DAC
* Configures and starts the DAC
*****************************************************************************/
void DAC_setup(void)
{
/* Use default settings */
DAC_Init_TypeDef init = DAC_INIT_DEFAULT;
DAC_InitChannel_TypeDef initChannel = DAC_INITCHANNEL_DEFAULT;
/* Enable the DAC clock */
CMU_ClockEnable(cmuClock_DAC0, true);
/* Calculate the DAC clock prescaler value that will result in a DAC clock
* close to 500kHz. Second parameter is zero, if the HFPERCLK value is 0, the
* function will check what the current value actually is. */
init.prescale = DAC_PrescaleCalc(500000, 0);
/* Set DAC's outmode to output to pin */
init.outMode = dacOutputPin;
/* Set reference voltage to 1.25V */
init.reference = dacRef1V25;
/* Initialize the DAC and DAC channel. */
DAC_Init(DAC0, &init);
DAC_InitChannel(DAC0, &initChannel, 0);
}
/**************************************************************************//**
* @brief Write DAC conversion value
*****************************************************************************/
void DAC_WriteData(DAC_TypeDef *dac, unsigned int value, unsigned int ch)
{
/* Write data output value to the correct register. */
if (!ch)
{
dac->CH0DATA = value;
}
else
{
dac->CH1DATA = value;
}
}
此时在STK的PB11引脚上应该能测得一个0.8V左右的模拟电压。接下来,我们看看如何将这个电压切换到PD0上去。修改的步骤如下:
1. 将DAC_CTRL寄存器中的OUTMODE配置为ADC。
2. DAC0通道0对应的OPA是OPA0,因此需要操作DACn_OPA0MUX寄存器。并且将该寄存器中的OUTPEN为OUT4。为何选择OUT4,是因为这里的OUT4,相当于选择Location4。可不是因为PD4的端口编号是4,才选择OUT4的哦。^_^
3. 配置DACn_OPA0MUX寄存器中OUTMODE。由于我现在仅想在PD4上输出,因此在这里配置为ALT。
配置部分的代码,请参考如下:
void DAC_setup(void)
{
/* Use default settings */
DAC_Init_TypeDef init = DAC_INIT_DEFAULT;
DAC_InitChannel_TypeDef initChannel = DAC_INITCHANNEL_DEFAULT;
/* Enable the DAC clock */
CMU_ClockEnable(cmuClock_DAC0, true);
/* Calculate the DAC clock prescaler value that will result in a DAC clock
* close to 500kHz. Second parameter is zero, if the HFPERCLK value is 0, the
* function will check what the current value actually is. */
init.prescale = DAC_PrescaleCalc(500000, 0);
/* Set DAC's outmode to output to ADC */
init.outMode = dacOutputADC;
/* Set reference voltage to 1.25V */
init.reference = dacRef1V25;
/* Initialize the DAC and DAC channel. */
DAC_Init(DAC0, &init);
DAC0->OPA0MUX &= ~ (_DAC_OPA0MUX_OUTMODE_MASK | _DAC_OPA0MUX_OUTPEN_MASK);
DAC0->OPA0MUX |= DAC_OPA0MUX_OUTMODE_ALT | DAC_OPA0MUX_OUTPEN_OUT4;
DAC_InitChannel(DAC0, &initChannel, 0);
}
经过以上的修改,应该可以在PD4上观察到0.8V的模拟电压了,而PB11上的0.8V则消失了。接下来我们看看如何在PD4和PB11上同时输出。需要修改的地方,如下所示:
1. 将DAC_CTRL寄存器中的OUTMODE配置为PINADC。代码如下:
void DAC_setup(void)
{
/* Use default settings */
DAC_Init_TypeDef init = DAC_INIT_DEFAULT;
DAC_InitChannel_TypeDef initChannel = DAC_INITCHANNEL_DEFAULT;
/* Enable the DAC clock */
CMU_ClockEnable(cmuClock_DAC0, true);
/* Calculate the DAC clock prescaler value that will result in a DAC clock
* close to 500kHz. Second parameter is zero, if the HFPERCLK value is 0, the
* function will check what the current value actually is. */
init.prescale = DAC_PrescaleCalc(500000, 0);
/* Set DAC's outmode to output to PINADC */
init.outMode = dacOutputPinADC;
/* Set reference voltage to 1.25V */
init.reference = dacRef1V25;
/* Initialize the DAC and DAC channel. */
DAC_Init(DAC0, &init);
DAC0->OPA0MUX &= ~ (_DAC_OPA0MUX_OUTMODE_MASK | _DAC_OPA0MUX_OUTPEN_MASK);
DAC0->OPA0MUX |= DAC_OPA0MUX_OUTMODE_ALT | DAC_OPA0MUX_OUTPEN_OUT4;
DAC_InitChannel(DAC0, &initChannel, 0);
}
这里主要是讲明了如何配置,才能达到DAC在Alt引脚上输入的效果。呵呵。刚开始的时候,DAC和OPA的关系有时候确实会让人绕,但是只要理清关系之后,程序思路也就会变得清晰。