STM32G474使用DAC1和DAC2的输出作为比较器输入,测试模拟比较器,方法如下:
PA1的附加功能为COMP1_INP,无需映射,直接将它配置为模拟功能,就可以使用了。
将COMP1_OUT引脚映射到PA0;
采用DAC2_OUT1输出电压给COMP1_INP引脚,因此在测试时,需要将PA6和PA1短接。
采用DAC1_OUT1输出在内部连接到“比较器反向输入端”;
当DAC2_OUT1输出电压大于“VCC/2”时,开灯;
当DAC2_OUT1输出电压小于或等于“VCC/2”时,关灯;
1、比较器内部连接
如果我们不看表格,而是将DAC2_CH1连接到比较器1的反向输入端,那就大错特错了。
注意:在使用内部连接时,需要参考表“Table 197. COMPx inverting input assignment”。
随便连接,电路工作不正确。
STM32G474有3个DAC通道是带缓冲的外部通道
PA4的附加功能为DAC1_OUT1,无需映射,直接将它配置为模拟功能,就可以使用了。
PA5的附加功能为DAC1_OUT2,无需映射,直接将它配置为模拟功能,就可以使用了。
PA6的附加功能为DAC2_OUT1,无需映射,直接将它配置为模拟功能,就可以使用了。
2、测试程序
COMP_HandleTypeDef hcomp1;
DAC_HandleTypeDef DAC_1_Handler;
//DAC1句柄,若直接对寄存器DAC1->DHR12R1和DAC1->DHR12R2操作,就可以将其设置为局部变量
DAC_HandleTypeDef DAC_2_Handler;
//DAC2句柄,若直接对寄存器DAC2->DHR12R1操作,就可以将其设置为局部变量
void COMP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_SYSCFG_CLK_ENABLE();
//RCC_APB2ENR寄存器bit0(SYSCFGEN),SYSCFGEN=1,使能SYSCFG + COMP + VREFBUF + OPAMP时钟
__HAL_RCC_PWR_CLK_ENABLE();
//RCC_APB1ENR1寄存器bit28(PWREN),PWREN=1,启用电源接口时钟
__HAL_RCC_GPIOA_CLK_ENABLE();//开启GPIOA时钟
GPIO_InitStruct.Pin = GPIO_PIN_1; //选择引脚编号为1
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式
GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; //输出速度设置为5MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器
//配置“比较器同向输入引脚”
GPIO_InitStruct.Pin = GPIO_PIN_0; //选择引脚编号为0
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; //复用推挽模式
GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; //输出速度设置为5MHz
GPIO_InitStruct.Alternate = GPIO_AF8_COMP1; //PA0映射到COMP1_OUT
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器
//配置“比较器输出引脚”
hcomp1.Instance = COMP1;
hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1;
//配置“比较器同向输入信号Vin+”来自PA1引脚
hcomp1.Init.InputMinus = COMP_INPUT_MINUS_DAC2_CH1;
//配置“比较器反向输入信号Vin-”来自“DAC2_CH1通道”
hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED;
//配置比较器输出极性:当“Vin+ > Vin-”,则输出高电平
hcomp1.Init.Hysteresis = COMP_HYSTERESIS_NONE;
//Set comparator hysteresis mode of the input minus
hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE;
hcomp1.Init.TriggerMode = COMP_TRIGGERMODE_NONE;
HAL_COMP_Init(&hcomp1);
__HAL_COMP_ENABLE(&hcomp1);
//使能比较器
//COMP_CxCSR寄存器bit0(EN),EN=1表示使能比较器
HAL_COMP_Start(&hcomp1);//启动COMP1,Start COMP1
DAC1_Init();
DAC2_Init();
}
void DAC1_Init(void)
{
DAC_ChannelConfTypeDef DAC1_CH1; //DAC通道参数相关结构体
GPIO_InitTypeDef GPIO_InitStruct; //IO口参数结构体
__HAL_RCC_DAC1_CLK_ENABLE(); //使能DAC1时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
GPIO_InitStruct.Pin = GPIO_PIN_4; //选择引脚编号为4
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式
GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //输出速度设置为25MHz至50MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器
DAC_1_Handler.Instance = DAC1; //DAC1
HAL_DAC_Init(&DAC_1_Handler); //初始化DAC
DAC1_CH1.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;
//DAC时钟选择
DAC1_CH1.DAC_DMADoubleDataMode = DISABLE; //双重数据模式(高带宽模式)关闭
DAC1_CH1.DAC_SignedFormat = DISABLE; //有符号模式关闭
DAC1_CH1.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; //关闭采样保持
DAC1_CH1.DAC_Trigger = DAC_TRIGGER_NONE; //不需要外部触发
DAC1_CH1.DAC_Trigger2 = DAC_TRIGGER_NONE; //不需要外部触发
DAC1_CH1.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; //DAC输出缓冲器打开
DAC1_CH1.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;//允许内部连接DAC1_CH1
DAC1_CH1.DAC_UserTrimming = DAC_TRIMMING_FACTORY; //工厂矫正模式
HAL_DAC_ConfigChannel(&DAC_1_Handler, &DAC1_CH1, DAC_CHANNEL_1); //初始化
HAL_DACEx_SelfCalibrate(&DAC_1_Handler, &DAC1_CH1, DAC_CHANNEL_1); //矫正
HAL_DAC_Start(&DAC_1_Handler,DAC_CHANNEL_1); //开启DAC1通道1
// HAL_DAC_SetValue(&DAC_1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);
//设置DAC输出电压: 2048*3.3/(0xFFF+1)=1.65V
DAC1->DHR12R1=2048;
//使用寄存器器,直接设置DAC输出电压: 2048*3.3/(0xFFF+1)=1.65V
}
void DAC2_Init(void)
{
DAC_ChannelConfTypeDef DAC2_CH1; //DAC通道参数相关结构体
GPIO_InitTypeDef GPIO_InitStruct; //IO口参数结构体
__HAL_RCC_DAC2_CLK_ENABLE(); //使能DAC2时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
GPIO_InitStruct.Pin = GPIO_PIN_6; //选择引脚编号为6
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; //模拟模式
GPIO_InitStruct.Pull = GPIO_NOPULL; //引脚上拉和下拉都没有被激活
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //输出速度设置为25MHz至50MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//根据GPIO_InitStruct结构变量指定的参数初始化GPIOA的外设寄存器
DAC_2_Handler.Instance = DAC2; //DAC2
HAL_DAC_Init(&DAC_2_Handler); //初始化DAC
DAC2_CH1.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_160MHZ;
//DAC时钟选择
DAC2_CH1.DAC_DMADoubleDataMode = DISABLE; //双重数据模式(高带宽模式)关闭
DAC2_CH1.DAC_SignedFormat = DISABLE; //有符号模式关闭
DAC2_CH1.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; //关闭采样保持
DAC2_CH1.DAC_Trigger = DAC_TRIGGER_NONE; //不需要外部触发
DAC2_CH1.DAC_Trigger2 = DAC_TRIGGER_NONE; //不需要外部触发
DAC2_CH1.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; //DAC输出缓冲器打开
DAC2_CH1.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; //不允许内部连接DAC2_CH1
DAC2_CH1.DAC_UserTrimming = DAC_TRIMMING_FACTORY; //工厂矫正模式
HAL_DAC_ConfigChannel(&DAC_2_Handler, &DAC2_CH1, DAC_CHANNEL_1); //初始化
HAL_DACEx_SelfCalibrate(&DAC_2_Handler, &DAC2_CH1, DAC_CHANNEL_1); //矫正
HAL_DAC_Start(&DAC_2_Handler,DAC_CHANNEL_1); //开启DAC2通道1
HAL_DAC_SetValue(&DAC_2_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);
//设置DAC输出电压: 2048*3.3/(0xFFF+1)=1.65V
// DAC2->DHR12R1=2048;
//使用寄存器器,直接设置DAC输出电压: 2048*3.3/(0xFFF+1)=1.65V
}
void Test_COMP(void)
{
uint32_t dac_steps = 0UL;
uint32_t dac_Value;
while (1)
{
dac_Value=dac_steps*DAC_SAWTOOTH_STEPINC;
printf("dac_Value=0x%X\r\n",dac_Value);
HAL_DAC_SetValue(&DAC_2_Handler, DAC_CHANNEL_1,DAC_ALIGN_12B_R,dac_Value );
HAL_DAC_SetValue(&DAC_1_Handler,DAC_CHANNEL_1,DAC_ALIGN_12B_R,2048);
dac_steps++;
if (dac_steps > DAC_SAWTOOTH_STEPS){ dac_steps = 0; }
HAL_Delay(4);//延时4ms
if (HAL_COMP_GetOutputLevel(&hcomp1) == COMP_OUTPUT_LEVEL_HIGH)
{//COMP_CxCSR寄存器bit30(VALUE),VALUE=1表示比较器输出为高电平
LED1_On();
}
else
{
LED1_Off();
}
}
}
comp.h文件如下:
#ifndef __COMP_H__
#define __COMP_H__
#include "stm32g4xx_hal.h"
//使能int8_t,int16_t,int32_t,int64_t
//使能uint8_t,uint16_t,uint32_t,uint64_t
#define DAC_VALUE_MAX ((uint32_t) 4095) //DAC的最大电压为4095*3.3/4096=3.299V
#define DAC_SAWTOOTH_STEPS ((uint32_t) 45) //DAC的总步数
#define DAC_SAWTOOTH_STEPINC ( (uint32_t) DAC_VALUE_MAX/DAC_SAWTOOTH_STEPS )
//DAC每走1步的增量值
extern void COMP_Init(void);
extern void Test_COMP(void);
#endif /*__ GPIO_H__ */
3、比较器输出波形