比较器

MM32L0系列MCU内嵌两个通用比较器 COMP1 和 COMP2,为通用的可编程电压比较器,可独立使用(适用所有终端上的 I/O 口),也可与定时器结合使用, 支持两个独立的比较器。它们可用于多种功能,包括:由模拟信号触发低功耗模式唤醒事件调节模拟信号与 DAC 和定时器输出的 PWM 相结合,组成逐周期的电流控制回路。

比较器框图
MM32 定时器捕获比较器输出

COMPx信号宽度需要测量的输入信号连接到 PA0-PA7。参考信号可通过以下方式供电:

● 内部参考电压(VREFINT、 3/4 VREFINT、 1/2 VREFINT 或 1/4 VREFINT)

● PA4\ PA5\ PA0\ PA7的外部引脚(COMP1),PA4\ PA5\ PA2\ PA7的外部引脚(COMP2)COMPx 输出重映射通过COMP1_CSR[13:10],COMP2_CSR[13:10]比较器 x 输出选择位实现。

在 MM32L0系列MCU中,COMP1 \COMP2 输出可以重映射到内置定时器 TIM1 的 BKIN(刹车输入)和IC4上。重映射 COMP21\COMP2 输出时,可以测量具有特定高/低电平的信号宽度或频率(例如,移位信号)。

定时器输入捕获通道应配置为同时在上升沿和下降沿保存定时计数器值。当输入信号高于参考电压时, COMPx 输出处于高电平,此时会在定时器输入捕获上生成一个上升沿。当输入信号低于参考电压时, COMPx输出处于低电平,此时会生成一个下降沿。两个连续事件之间经过的时间(下降沿到上升沿或者上升沿到下降沿)表示脉冲宽度。因此,只需对计数器值做减法即可测量脉冲宽度。

COMPx输出重映射到定时器
MM32 定时器捕获比较器输出

1、将定时器输入捕获通道配置为仅在上升沿或下降沿保存计数器值,即可获得信号频率。

2、参考电压可以使用内部参考电压(0.4v、0.6v、0.9v和1.2v),也可以使用外部 GPIO 接到某一个电压值(0-5v)作为反相输入。

脉冲宽度测量应用:

将 COMPx 输出连接到定时器的输入捕获通道,则可以测量电容值,电容测量过程包括通过电阻对电容进行充电和放电。测量原理基于电阻、电容 (RC) 网络充电时间的测量过程,方法如下:

● 测量充电时间
● 已知充电电阻 (R)
● 可计算未知的电容 (C)

测量电容的电路图
MM32 定时器捕获比较器输出

通过 PWM 模式下配置的定时器输出比较通道 (TIMx OC),可确保 RC 网络周期性的充电和放电过程。

输入电压连接到 COMPx 同相输入,而阈值连接到 COMPx 反相输入。当输入电压超过阈值时, COMPx 输出切换为高电平,同时发生保存计数器值的捕获事件。

MM32 定时器捕获比较器输出

充电函数如下所示:

Input voltage =VDD(1- exp(- t /T))

其中:

● VDD 为正电源电压
● t 为时间
● T 为 RC 常数

根据上述公式可以推算:

C = -t / ( R x In( 1-threshold /(VDD) ))

比较器配置程序:

void Comp_Config(uint32_t COMP_Selection_COMPx)
{
COMP_InitTypeDef COMP_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_COMP, ENABLE);//开比较器时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//开GPIOA的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_7);// 复用AF7,比较器输出

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//内部参考电压1.2v(可以内部基准设置0.4v、0.6v、0.9v和1.2v)
COMP_InitStructure.COMP_InvertingInput = COMP_InvertingInput_VREFINT;
//PA5为正相输入引脚
COMP_InitStructure.COMP_NonInvertingInput = COMP_NonInvertingInput_IO6;
//输出重印射到TIM1的输入捕获通道4
COMP_InitStructure.COMP_Output = COMP_Output_TIM1IC1;
//比较器不上锁
COMP_InitStructure.COMP_BlankingSrce = COMP_BlankingSrce_None;
//比较器输出极性:同相输出
COMP_InitStructure.COMP_OutputPol = COMP_OutputPol_NonInverted;
//比较器迟滞电压:0mV(可设置迟滞电压0-27mV)
COMP_InitStructure.COMP_Hysteresis = COMP_Hysteresis_No;
//比较器模式:中等速率(可设置极低速率、低速率、中等速率、高速率)
COMP_InitStructure.COMP_Mode = COMP_Mode_MediumSpeed; COMP_Init(COMP_Selection_COMPx, &COMP_InitStructure);
//使能比较器
COMP_Cmd(COMP_Selection_COMPx, ENABLE);
}

定时器TIM1配置程序:

void TIM1_PWMINPUT_INIT(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_ICInitTypeDef TIM1_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM1时钟使能
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);GPIOA时钟使能

TIM_TimeBaseStructure.TIM_Period = arr; //设置重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;// TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

NVIC_InitStructure.NVIC_IRQChannel = TIM1_IRQn; //配置中断优先级
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

TIM1_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1映射到TI1 上
TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 上升沿捕获
TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上
TIM1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //不分频
TIM1_ICInitStructure.TIM_ICFilter = 0x0; //不滤波
TIM_PWMIConfig(TIM1, &TIM1_ICInitStructure);

TIM_ITConfig(TIM1, TIM_IT_CC1|TIM_IT_Update, ENABLE); //使能捕获和更新中断
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1|TIM_IT_Update); //清中断
TIM_Cmd(TIM1, ENABLE); //定时器使能
}

定时器TIM1中断服务函数:

void TIM1_CC_IRQHandler (void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
{
period = TIM_GetCapture1(TIM1);
duty = TIM_GetCapture2(TIM1);
CollectFlag = 1;
}
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1|TIM_IT_Update);
}

小结:

1、为保证恶劣环境下比较器设置不能被无效寄存器访问或者程序计数器破坏所改变,比较器控制和状态寄存器可以设为写保护(只读),一旦设置完成, LOCK 位必须设为 1,这导致整个 COMPx_CSR 寄存器变成只读,包括 LOCK 位在内。写保护只能被 MCU 复位所清除。

2、在某些用电池供电的应用中,MCU需要在环境明亮时上电;其它情况下,微控制器必须保持断电状态。对于此类应用,可以使用电阻随光强度变化的光敏电阻 (LDR) 来控制MCU的状态。使用 LDR 传感器时,MCU可根据 LDR 电阻提供的电压切换到低功耗模式或退出低功耗模式。MM32L0系列MCU 的比较器COMP1和COMP2的可在内部将该输出分别连接到 EXTI 线19和20。

转自:灵动微电子

围观 812

前言

STM32H7 集成了运算放大器(COMP),可与模拟信号进行比较来进行电压检测,内置的 COMP 节省了 MCU 外接 COMP 的硬件成本。本文将介绍 STM32H7 的片内 COMP 的不同工作模式,并提供配置 COMP 的例程。

STM32H7 模拟比较器(COMP)特性

以下是 STM32H7 模拟比较器主要特性:

• 两个独立的比较器 COMP1 和 COMP2 可以组合在一起来创建一个窗口比较器
• 可编程的比较器迟滞
• 可编程的速度和功耗
• 可配置的正和负输入
• 多路复用 I/O 引脚,DAC 通道 1 和 2,内部参考电压和三个因数值
• 输出重定向
o 配置 I/Os
o 计时器——打断事件给快速 PWM 关闭,逐周期电流控制,输入捕获给时间测量
o 输出 blanking 源
• 比较两个模拟信号,并提供数字输出指示哪个大
• 有能力从停止模式唤醒 CPU

模拟比较器 COMP 在 STM32H7 上的应用

STM32H7 模拟比较器(COMP)特性工作模式

COMP 窗口模式

模拟比较器 COMP 在 STM32H7 上的应用

窗口比较器的目的是指示,如果模拟电压比阈值电压更低或更高,应用于每一个比较器的反相输入。两个非反相输入端可以在内部连接,通过启用 WINMODE,可以节省一个 IO 口,用作其它的用途。

COMP 打断信号生成

模拟比较器 COMP 在 STM32H7 上的应用

比较器(COMP1/COMP2) 输出值能产生打断输入信号给定时器 (TIM1 & TIM8) 在输入脚 TIMx_BKIN or TIMx_BKIN2 通过配置 GPIO alternate function。

COMP Blanking

模拟比较器 COMP 在 STM32H7 上的应用

防止在 PWM 周期的开始由于短周期电流峰值,电流调节跳闸。掩码 COMP 输出重定向到定时器打断输入。

应用实例

硬件环境

本文硬件环境基于 STM32H743I_EVAL。CN6 的第 29 引脚(PB0)作为 COMP1 模拟电压的输入引脚。

软件配置

虽然 STM32H7 系列中的 ADC 可用作模拟看门狗,看门狗的阈值上限和下限均可编程,但是由于 ADC 在停机模式下会断电,因此 MCU 必须保持在运行模式下才能监视输入端的模拟电压。对于 STM32H743xx 器件,可将 COMP1,此看门狗可在 MCU 处于停机模式下时保持通电状态。这样既可降低功耗,又可实现节能。在模拟看门狗应用中, COMP1 通过外部中断线配置,以在模拟输入电压超过 VREFINT 时使 MCU 退出停机模式。若在整个过程中,模拟电压都处于定义的阈值范围内,MCU 将一直处于停机模式,从而降低功耗。当模拟电压超过定义的阈值时,可通过切换至运行模式来降低平均功耗。

以下是通过 STM32CubeMX 来配置工程实例:

1.选择 STM32H743XI,打开 HSE,PF10 设置为 GPIO 输出,PB0 设置为 COMP 输入。

模拟比较器 COMP 在 STM32H7 上的应用

2. 配置系统时钟为 400MHz 系统时钟以及其它总线时钟。
模拟比较器 COMP 在 STM32H7 上的应用

3. 配置 COMP1 中断为上升沿触发。
模拟比较器 COMP 在 STM32H7 上的应用

CubeMX 中已经配置了一个简单的 COMP1 模拟看门狗的例子,使用 STM32CubeMX 工具 STM32H743XI 生成工程代码,并在 main.c 中添加如下红色的部分代码来开启 COMP1、使能 COMP1 中断,以及添加应用代码。

int main(void)
{
…
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 /* LED1 Off */
 HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);

 MX_COMP1_Init();
 /* Start COMP1 */
 if(HAL_COMP_Start_IT(&hcomp1) != HAL_OK)
 {
 /* Initialization Error */
 Error_Handler();
 }
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* Insert 5 second delay */
 HAL_Delay(5000);
 /* LED1 Off */
 HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);

 /* Enter STOP mode */
 HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
 /* ... STOP mode ... */

 /* at that point, MCU has been awoken */
 /* Re-configure the system clock */
 SystemClock_Config();
 /* LED1 On */
 HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_RESET);
 }
 /* USER CODE END 3 */
}

Startup_stm32h743xx.s 中定义的 COMP1 全局中断服务函数名是 COMP1_IRQHandler,而通过 STM32CubeMX 生成的COMP1 全局中断服务函数名是 COMP_IRQHandler。

DCD COMP1_IRQHandler ; COMP1 global Interrupt 

对 stm32h7xx_it.c 进行修改,如下所示:

/**
* @brief This function handles COMP1 and COMP2 interrupts through EXTI lines 20 and 21.
*/
void COMP_IRQHandler(void)
{
 /* USER CODE BEGIN COMP_IRQn 0 */
 /* USER CODE END COMP_IRQn 0 */
 HAL_COMP_IRQHandler(&hcomp1);
 /* USER CODE BEGIN COMP_IRQn 1 */
 /* USER CODE END COMP_IRQn 1 */
}

改为

/**
* @brief This function handles COMP1 and COMP2 interrupts through EXTI lines 20 and 21.
*/
void COMP1_IRQHandler(void)
{
 /* USER CODE BEGIN COMP_IRQn 0 */
 /* USER CODE END COMP_IRQn 0 */
 HAL_COMP_IRQHandler(&hcomp1);
 /* USER CODE BEGIN COMP_IRQn 1 */
 /

至此,完成的工程已经建立。运行软件后,LED1 默认熄灭并进入待机模式。加 1.22V 或者高于 1.22V 的外部电压到PB0 引脚将触发 COMP1 中断,MCU 被唤醒并点亮 LED1。延时大约 5 秒后,LED1 熄灭并再次进入待机模式,等待 PB0 引脚外部模拟信号触发中断。

总结

片内的 COMP 可对模拟信号进行比较处理,配合片内的 DAC 和定时器等外设联合工作,可满足各种不同的应用需求。本文提供了 STM32LH7 COMP 的一个简单易用的例子,更多详细的应用请参考 STM32H7x3 用户手册及相关资料。

来源: http://www.stmcu.com.cn

围观 4642
订阅 RSS - 比较器