HPMicro MCU片上ACMP使用指南
HPMicro MCU片上ACMP使用指南
1. 引言
ACMP(Analog Comparator,模拟比较器)是嵌入式系统中常见的外设之一,主要用于比较两个模拟信号的电压,并根据比较结果输出数字信号。它在电压监测、传感器信号处理、低功耗控制等方面有广泛应用。
2. 特点
- 工作电压范围:3.0~3.6V
- 支持轨到轨输入: 0~VCC
- 可编程迟滞等级
- 支持窗口模式输出
- 支持对输出进行数字滤波
- 支持中断
- 支持DMA
- 内置DAC
3. 功能描述
ACMP(模拟比较器)用来比较PIN和MIN两个模拟输入信号,当PIN的电压高于MIN的电压时,ACMP输出逻辑1;反之,当PIN的电压低于MIN的电压时,ACMP输出逻辑0。
注: HPMicro MCU中的ACMP所有系列中,均支持输入比较和中断功能,以及从trigmux输出ACMP的逻辑输出信号,而部分系列不支持将ACMP的逻辑输出信号输出至PAD,具体请查阅UM
4. ACMP的结构
每一个ACMP实列由一个数字控制块和多个比较器组成, 具体请查阅UM
5. 输入配置
PIN的输入来源:
- INP0, 仅连接到ACMP内置的DAC_OUT
- INP1
- INP2
- INP3
- INP4
- INP5
- INP6
- INP7
MIN的输入来源:
- INN0, 仅连接到ACMP内置的DAC_OUT
- INN1
- INN2
- INN3
- INN4
- INN5
- INN6
- INN7
6. 迟滞等级
HPMICRO的片上MCU的ACMP有4个迟滞等级
- 等级0 (迟滞作用最强)
- 等级1
- 等级2
- 等级3 (无迟滞)
注:迟滞等级0~3,作用逐级递减
7. 输出控制
-
输出取反
-
控制反向输出
-
-
输出滤波
-
旁路模式
- 关闭数字滤波器
-
滤刺模式
- 滤波器输入翻转后,输出也会立即翻转,之后会在一定时间内无视滤波器的输入
-
延时模式
- 滤波器输入翻转后需要保持一定时间,滤波器输出才会翻转
-
滤峰模式
- 滤波器输入置逻辑1后,需要保持一定时间,滤波器输出才会置逻辑1,而滤波器输入置0,滤波器输出会立即置0,从而滤除不够长的输入波峰
-
滤谷模式
- 滤波器输入置逻辑0后,需要保持一定时间,滤波器输出才会置逻辑0,而滤波器输入置1,滤波器输出会立即置1,从而滤除不够长的输入波谷
-
-
窗口控制
-
使能窗口控制信号(WINEN)后,可以通过WIN信号与输出信号相与后输出
-
8. 工作模式
-
高性能模式
-
常规模式
注:两者相比,高性能模式下,ACMP的输出延时更小,但是功耗更高
9. 中断和DMA
-
ACMP可以在输出的上升沿,下降沿,或者双边沿产生中断
-
ACMP可以在输出的上升沿,下降沿,或者双边沿产生DMA请求
10. 如何通过HPM SDK来使用HPMicro MCU片上的ACMP?
-
ACMP管脚初始化
-
设置指定管脚IO PAD的FUNC_CTL寄存器的BIT8(IOC_PAD_FUNC_CTL_ANALOG_MASK),用于隔离指定管脚所复用的数字功能
以HPM6750为例,PE21既有数字功能, 也有模拟功能:
因此对于此管脚(PE21)需要使用模拟功能时,就需要隔离数字功能,程序设置如下:void init_acmp_pins(void) { /* configure to CMP1_INN6 function */ HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; }
注: 若ACMP的PIN和MIN都是从外部管脚输入(不使用内置DAC),则对应两个管脚都需要隔离数字功能
-
设置指定管脚IO PAD的FUNC_CTL寄存器的BIT4~BIT0,用于选择相应的数字功能
以HPM6750为例,选择从COMP_1,即PE25管脚输出ACMP的数字输出信号
因此对于此管脚(PE25)需要使用数字功能时,程序设置如下:
void init_acmp_pins(void) { /* configure to CMP1_INN6 function */ HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* configure to ACMP_COMP_1(ALT16) function */ HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PE25_FUNC_CTL_ACMP_COMP_1; }
注: 数字输出功能并非在所有HPMicro的MCU上都支持,详细请查阅UM
-
-
ACMP时钟初始化
-
时钟来源
- 时钟来源于APB,与AHB同频,无需额外设置
-
设置link group
void board_init_acmp_clock(ACMP_Type *ptr) { (void)ptr; clock_add_to_group(clock_acmp0, BOARD_RUNNING_CORE & 0x1); }
注: HPMicro MCU可以通过SYSCTL来设置link group
-
-
ACMP初始化
-
设置ACMP属性
a) 设置结构体定义
typedef struct acmp_channel_config { uint8_t plus_input; /* 正极输入通道 */ uint8_t minus_input; /* 负极输入通道 */ uint8_t filter_mode; /* 滤波器模式 */ uint8_t hyst_level; /* 迟滞等级 */ bool enable_cmp_output; /* 比较器输出使能 */ bool enable_window_mode; /* 窗口模式使能 */ bool invert_output; /* 反向输出控制 */ bool bypass_filter; /* 滤波器旁路控制 */ bool enable_dac; /* 内置DAC使能 */ bool enable_hpmode; /* 高性能模式使能 */ uint16_t filter_length; /* 滤波长度,以ACMP时钟周期为单位 */ } acmp_channel_config_t;
b) 示例:设置ACMP的的正极通道输入内置DAC的输出,负极通道输入来自输入通道6上对应的管脚信号,并将迟滞等级设置为0(无迟滞)
acmp_channel_config_t acmp_channel_configure; acmp_channel_get_default_config(HPM_ACMP0, &acmp_channel_configure); /* 默认禁用了窗口模式和滤波器 */ acmp_channel_configure.plus_input = ACMP_INPUT_DAC_OUT; acmp_channel_configure.minus_input = ACMP_INPUT_ANALOG_6; acmp_channel_configure.enable_dac = true; acmp_channel_configure.enable_cmp_output = true; acmp_channel_configure.hyst_level = ACMP_HYST_LEVEL_3; acmp_channel_config(HPM_ACMP0, ACMP_CHANNEL_CHN1, &acmp_channel_configure, true);
-
使能ACMP的IRQ及中断
-
IRQ 宏定义命名格式
IRQn_ACMPi_ch, 其中i表示ACMP实例的序号,ch表示ACMP所连接的比较器的序号(ACMP通道号) -
使能IRQ
intc_m_enable_irq_with_priority(IRQn_ACMP0_1 /* ACMP通道所对应的IRQ */, 1);
- 中断事件
#define ACMP_EVENT_RISING_EDGE (1U) /* 输出上升沿 */ #define ACMP_EVENT_FALLING_EDGE (2U) /* 输出下降沿 */
- 使能输出中断
示例:使能ACMP0 通道1的输出上升沿中断
acmp_channel_enable_irq(HPM_ACMP0, ACMP_CHANNEL_CHN1 /* ACMP通道 */, ACMP_EVENT_RISING_EDGE /* 上升沿 */, true);
-
-
功能演示
a) 通过动态设置内置DAC的输出,且在ACMP0 通道1的输出上升沿中断来确定ACMP MIN管脚输入的电压
volatile bool acmp_output_toggle; SDK_DECLARE_EXT_ISR_M(IRQn_ACMP_1, isr_acmp) void isr_acmp(void) { /* 标记输出上升沿标志 */ acmp_output_toggle = true; /* 禁止输出上升沿中断 */ acmp_channel_enable_irq(HPM_ACMP0, ACMP_CHANNEL_CHN1, ACMP_EVENT_RISING_EDGE, false); }
int main(void) { ... ... ... ... ... while (1) { /* 设置内置DAC输出值为0 */ acmp_channel_config_dac(HPM_ACMP0, ACMP_CHANNEL_CHN1, 0); board_delay_ms(1U); /* 清除中断状态位 */ acmp_channel_clear_status(HPM_ACMP0, ACMP_CHANNEL_CHN1, ACMP_EVENT_RISING_EDGE); /* 使能输出上升沿中断 */ acmp_channel_enable_irq(HPM_ACMP0, ACMP_CHANNEL_CHN1, ACMP_EVENT_RISING_EDGE, true); /* 循环遍历DAC输出,从最小值到最大值,产生中断后退出循环 */ for (uint32_t dac_value = 0; dac_value <= ACMP_CHANNEL_DACCFG_DACCFG_MASK; dac_value++) { /* 设置内置DAC输出指定值所对应的电压 */ acmp_channel_config_dac(HPM_ACMP0, ACMP_CHANNEL_CHN1, dac_value); /* 等待输出稳定 */ board_delay_us(100U); /* 判断输出是否产生上升沿 */ if (acmp_output_toggle) { printf("acmp out toggled, the dac set value is 0x%x\n", dac_value); /* 清除上升沿输出中断标记 */ acmp_output_toggle = false; break; } } board_delay_ms(50U); } return 0; }
b) 观察测试log
说明:上述代码在hpm6750evk2上运行,当输入电压为1.1V时(VREFH为3.3V), ACMP输出上升沿中断时,对应的内置DAC数值为0x55, log如下:
acmp example acmp out toggled, the dac set value is 0x55
-