目录
- 1. 特性
- 1.1 框图
- 1.2 比较器输入信号SEL
- 1.3 比较器滞回选择HYST
- 1.4 比较器的输出
- 1.5 LOCK机制
- 2. 编程
- 2.1 初始化步骤
- 2.2 举例
STM内部的比较器是模拟量的比较器,其与APB2时钟同步,在RCC时钟控制器中没有COMx时钟使能标志位,其时钟的使能与复位与SYSCLK同步。
1. 特性
1.1 框图
1.2 比较器输入信号SEL
比较器的输入端有正负极信号,正极INP通过INPSEL选择输入信号,负极通过INMSEL选择输入信号,其SEL引脚定义如下图表所示。
1.3 比较器滞回选择HYST
滞回英文 Hysteresis ,可以理解为施密特触发器,通过在CSR寄存器中配置HYST来选择滞回电压。
1.4 比较器的输出
根据框图可以看到,比较器的输出信号为VALUE。VALUE直接连接到 HRTIM(高分辨率定时器)外设;VALUE还通过POLARITY(CSR寄存器的POL配置)的极性选择(是否取反)连接到 COMPx_OUT(GPIO)、EXTI总线 和 TIMx定时器。
1.5 LOCK机制
一旦将CSR寄存器的LOCK标志位置位,就不能清除LOCK标志位了,只有重新复位MCU才可清除。并且LOCK置位后,CSR寄存器变为只读,不能重新配置。
2. 编程
2.1 初始化步骤
- 使能SYSCLK时钟
- 初始化GPIO,将要使用到的comp引脚定义为模拟量模式(MODER=3)
- 配置CSR寄存器;使能比较器;锁定寄存器
- 配置中断
2.2 举例
下面以COMP1进行举例,分别使用PB1和PA4作为比较器输入的正负极,上下沿都产生中断。
测试代码如下。(已经提前打开GPIO、SYSCLK时钟)
#define MODER_IN (0x00UL) //输入
#define MODER_OUT (0x01UL) //输出
#define MODER_FUNC (0x02UL) //功能
#define MODER_ANA (0x03UL) //模拟
#define MODER_BIT (0x03UL) //
#define PUPDR_NO (0x00UL) //无上下拉
#define PUPDR_PU (0x01UL) //上拉
#define PUPDR_PD (0x02UL) //下拉
#define PUPDR_BIT (0x03UL) //
#define COMP_COMPx COMP1
#define COMP_INP_GPIO GPIOB
#define COMP_INP_PORT 1
#define COMP_INP_SEL 1 //<根据本文1.2的查表,PB1选择1
#define COMP_INM_GPIO GPIOA
#define COMP_INM_PORT 4
#define COMP_INM_SEL 6 //<根据本文1.2的查表,PA4选择6
void COMP1_Init(void)
{
//步骤2:初始化GPIO,IO模式为模拟量
COMP_INP_GPIO->MODER &= ~(MODER_BIT << (COMP_INP_PORT << 1));
COMP_INP_GPIO->MODER |= (MODER_ANA << (COMP_INP_PORT << 1));
COMP_INP_GPIO->PUPDR &= ~(PUPDR_BIT << (COMP_INP_PORT << 1));
COMP_INP_GPIO->PUPDR |= (PUPDR_NO << (COMP_INP_PORT << 1));
COMP_INM_GPIO->MODER &= ~(MODER_BIT << (COMP_INM_PORT << 1));
COMP_INM_GPIO->MODER |= (MODER_ANA << (COMP_INM_PORT << 1));
COMP_INM_GPIO->PUPDR &= ~(PUPDR_BIT << (COMP_INM_PORT << 1));
COMP_INM_GPIO->PUPDR |= (PUPDR_NO << (COMP_INM_PORT << 1));
//步骤3:配置CSR寄存器;使能比较器;锁定寄存器
COMP1->CSR = 0
|COMP_CSR_LOCK // 【1:寄存器只读】
// COMP_CSR_VALUE // 【只读,不经过机型选择器的value】
// |COMP_CSR_SCALEN // 【1:VREFINT分段使能(VREFINT/1/2/3有效)】
// |COMP_CSR_BRGEN // 【1:电阻桥使能】
|(0 << COMP_CSR_BLANKING_Pos) // 消隐信号选择 <暂时不用
|(3 << COMP_CSR_HYST_Pos) // 滞回电压选择
// 0: No hysteresis
// 1: 10mV hysteresis
// 2: 20mv hysteresis
// 3: 30mV hysteresis <当前选择
// 4: 40mV hysteresis
// 5: 50mV hysteresis
// 6: 60mV hysteresis
// 7: 70mV hysteresis
// |COMP_CSR_POLARITY // 【1:极性反转】
|(COMP_INP_SEL << COMP_CSR_INPSEL_Pos) // 正极输入选择 <根据本文1.2的查表,PB1选择1
|(COMP_INM_SEL << COMP_CSR_INMSEL_Pos) // 负极输入选择 <根据本文1.2的查表,PA4选择6
|COMP_CSR_EN // 比较器使能
;
//步骤4:配置中断
EXTI->IMR1 |= BIT21;//COMP1 Output 中断屏蔽失效
EXTI->RTSR1 |= BIT21;//COMP1 Output 上升沿触发
EXTI->FTSR1 |= BIT21;//COMP1 Output 下降沿触发
}
上述配置中断部分的 BIT21,是通过手册查表 Table 98: EXTI lines connections 来的(手册Page449)。
根据上图可以看到,line21就是COMP1output总线。
EXTI的 RTSR1 、FTSR1 寄存器分别是上升沿使能、下降沿使能寄存器。
配置完毕初始化后,就可以在中断函数中等待比较中断了。中断内部举例代码如下。
void COMP1_2_3_IRQHandler(void)
{
EXTI->PR1 |= BIT21;//清除中断挂起标志位
if(COMP1->CSR & COMP_CSR_VALUE)
GPIOC->BSRR |= BIT13;//LED点亮(测试使用)
else
GPIOC->BSRR |= (BIT13 << 16);//LED关闭(测试使用)
}
当正极大于负极(算上滞回电压),VALUE为0,即比较器输出0;(我测试是这个结果)
当正极小于负极(算上滞回电压),VALUE为1,即比较器输出1。
VALUE值可以在 COMPx->CSR寄存器中读取。