打印
[应用相关]

STM32实验十五:模拟比较器comp

[复制链接]
9149|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
模拟比较器comp
沙发
東南博士|  楼主 | 2018-2-28 20:56 | 只看该作者
在STM32L011中,硬件模拟比较器有两个,COMP1和COMP2,这不是废话吗?

单用比较器当然是比较电压,如果两个混用,就可以做到类似ADC的模拟看门狗一样的功能.

1.png (123.49 KB )

1.png

使用特权

评论回复
板凳
東南博士|  楼主 | 2018-2-28 20:57 | 只看该作者
如果正相输入端电压高于反相输入端电压,那么输出1,这么很容易理解,就是比如比较PA0和PA1电压,PA1和Vref电压等等.如果是两个COMP一起用呢,那么COMP都输出为1,那么就是电压过高了,既超过COMP1门限也超过COMP2门限,如果都输出为低,那么就是过低了,既低于COMP1也低于COMP2,所以,一个输出高一个输出低,就表明在范围内了,这样是合理的设定.

因为COMP的寄存器,在Keil中没有表示出来,所以还是看看手册描述,来一一对应.也可能因为只有一个寄存器,就懒得写了?好吧,他的初始化方法呢,我总结了一下,手册描述得有点冗长了.

准备工作就是人工计算好CSR寄存器应该填什么内容,只有一个寄存器不是什么麻烦事情.而且几乎长得一样.

使用特权

评论回复
地板
東南博士|  楼主 | 2018-2-28 20:57 | 只看该作者
资料图

2.png (286.93 KB )

2.png

使用特权

评论回复
5
東南博士|  楼主 | 2018-2-28 20:59 | 只看该作者
好了,下面开始看看思路.

如果开了VREF,要打开VREF,相应是SYSCFG->CFGR3,在SYSCFG_CFGR3_ENBUFLP_VREFINT_COMP位.
打开IO配置,打开所需时钟.
写CSR寄存器.
如果需要,写EXTI寄存器.
锁定COMP寄存器,这样COMP的数值就再也改不了,除非复位系统,这一步可以不做.

使用特权

评论回复
6
東南博士|  楼主 | 2018-2-28 21:00 | 只看该作者
另外注意事项,ADC和COMP用的是同一个中断,如果用到了ADC,要分别判断.所用引脚也是差不多.另外引脚分配如下.

PA0 COMP1反相输入端
PA1 COMP1正向输入端
PA6 COMP1输出端
PA2 COMP2反相输入端
PA3 COMP3正向输入端
PA4 COMP2输出端
都集中在PA上,所以要打开PA的时钟就可以.特别注意,输出端不是模拟引脚.COMP的时钟SYSCFG提供的,其他也没什么,完整程序如下.可以自行下载实践.

使用特权

评论回复
7
東南博士|  楼主 | 2018-2-28 21:00 | 只看该作者
#include "stm32l0xx.h"

__IO uint32_t uwTick;

void SysTick_Delay(__IO uint32_t Delay)
{
    uint32_t tickstart = 0U;
    tickstart = uwTick;
    while((uwTick - tickstart) < Delay)
    {
    }
}

void RCC_Init(void)
{
    /* LSE OFF,LSI DEFAULT,MSI OFF,HSI ON,PLL ON,SYSCLK = 32MHz,CK_PWR = FCLK = HCLK = SysTick = APB1 = APB2 = 32MHz.*/
    FLASH->ACR = FLASH_ACR_PRE_READ | FLASH_ACR_PRFTEN;
    MODIFY_REG(PWR->CR, PWR_CR_VOS, (PWR_CR_VOS_0));
    MODIFY_REG(RCC->CR, RCC_CR_HSION | RCC_CR_HSIDIVEN , RCC_CR_HSION);
    while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET);
    MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSITRIM, (uint32_t)(16) << 8U);
    CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
    while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET);
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV | RCC_CFGR_PLLSRC, (uint32_t)((RCC_CFGR_PLLMUL4) | (RCC_CFGR_PLLDIV2) | (RCC_CFGR_PLLSRC_HSI)));
    SET_BIT(RCC->CR, RCC_CR_PLLON);
    while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET);
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(0x01U));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV1);
    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
    while ((uint32_t)(RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV1);
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_CFGR_PPRE1_DIV1) << 3));
    CLEAR_BIT(RCC->CR, RCC_CR_MSION);

    /* SysTick CLK = 4MHz,Reload = 1kHz. */
    SysTick->LOAD  = (uint32_t)0x00000F9FUL;
    NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    SysTick->VAL   = 0UL;
    SysTick->CTRL  = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
    /* SysTick->CTRL  = SysTick_CTRL_TICKINT_Msk; */

}

void ADC1_COMP_IRQHandler(void)
{
    if(READ_BIT(EXTI->PR, EXTI_IMR_IM21) != RESET)
    {

        /* COMP1的比较器输出翻转了. */
        WRITE_REG(EXTI->PR, EXTI_IMR_IM21);
    }
    if(READ_BIT(EXTI->PR, EXTI_IMR_IM22) != RESET)
    {

        /* COMP2的比较器输出翻转了. */
        WRITE_REG(EXTI->PR, EXTI_IMR_IM22);
    }

}

void Comp_Init(void)
{

    /* 初始化时钟 */
    SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN);
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); /* COMP共享这个时钟 */

    /* 上电没配置过,默认除了JTAG外引脚都是模拟引脚,所以懒得配置了. */

    /* PA6/PA4 COMP OUT */
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE6 | GPIO_MODER_MODE4, GPIO_MODER_MODE6_1 | GPIO_MODER_MODE4_1);
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFRL6, (0x07 << GPIO_AFRL_AFRL6_Pos) );
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFRL4, (0x07 << GPIO_AFRL_AFRL4_Pos) );
    /* PA0 = INM,PA1 = INP */
    COMP1->CSR = 0x00000011;
    /* PA2 = INM,PA3 = INP */
    COMP2->CSR = 0x00000019;

    /* COMP1占用21线中断,COMP2占用22线中断. */

    /* 上降沿中断 */
    SET_BIT(EXTI->RTSR, EXTI_IMR_IM21 | EXTI_IMR_IM22);
    /* 下降沿中断 */
    SET_BIT(EXTI->FTSR, EXTI_IMR_IM21 | EXTI_IMR_IM22);
    /* 清中断标志 */
    WRITE_REG(EXTI->PR, EXTI_IMR_IM21 | EXTI_IMR_IM22);
    /* 开中断模式 */
    SET_BIT(EXTI->IMR, EXTI_IMR_IM21 | EXTI_IMR_IM22);

    NVIC_SetPriority(ADC1_COMP_IRQn, 0);
    NVIC_EnableIRQ(ADC1_COMP_IRQn);

}

int main(void)
{
    RCC_Init();
    Comp_Init();
    while (1)
    {
        SysTick_Delay(1000);
    }
}

使用特权

评论回复
8
東南博士|  楼主 | 2018-2-28 21:01 | 只看该作者
INM > INP,输出结果 = 0,INM < INP,输出结果 = 1,INM ≈ INP,输出震荡.

使用特权

评论回复
9
捉虫天师| | 2018-2-28 22:45 | 只看该作者
相当于差分逻辑信号

使用特权

评论回复
10
dongnanxibei| | 2018-2-28 23:22 | 只看该作者
这个应该算是模拟应用吧。输出的是逻辑

使用特权

评论回复
11
東南博士|  楼主 | 2018-3-4 12:50 | 只看该作者
是的!是这个意思!

使用特权

评论回复
12
小明的同学| | 2018-3-5 22:39 | 只看该作者
这个做各种检测时候经常用。

使用特权

评论回复
13
lshlin| | 2019-1-31 16:26 | 只看该作者
東南博士 发表于 2018-2-28 21:00
另外注意事项,ADC和COMP用的是同一个中断,如果用到了ADC,要分别判断.所用引脚也是差不多.另外引脚分配如下. ...

模拟比较器的输入阻抗只有400k吗?这是不是有点低啊?

使用特权

评论回复
14
lvyunhua| | 2019-7-9 17:04 | 只看该作者
请问下  STM32F030内部有模拟比较器吗。

使用特权

评论回复
15
wq_net| | 2019-9-20 22:41 | 只看该作者
本帖最后由 wq_net 于 2019-9-20 22:43 编辑
lvyunhua 发表于 2019-7-9 17:04
请问下  STM32F030内部有模拟比较器吗。

没有,STM32F030的模拟相关电路只有一个ADC。
有比较器的最低型号是STM32F051.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

367

主题

6048

帖子

34

粉丝