打印
[其他]

AC7811-ACMP模拟比较器

[复制链接]
652|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
coshi|  楼主 | 2023-3-14 13:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
在无感的BLDC方波控制中,AC7811没办法再直接通过PWDT模块检测霍尔信号了。

所以需要先进行ACMP模块的初始化配置,使能ACMP模块正常工作后,ACMP会对输入的三相反电动势与电机中电电压进行轮询模拟,得到各相反电动势过零点,进而模拟霍尔信号通过CTU输出至PWDT采集。

模块简介
ACMP 模块包括 ACMP0 和 ACMP1。

ACMP0 和 ACMP1 都包含一个比较器和一个 6 位数字模拟转换器(DAC)。模拟多路复用器(MUX)提供一个用于从六个通道中选择模拟输入信号的电路。一个通道由 6 位数字模拟转换器(DAC)提供,其他通道由外部输入提供。

ACMP0 的轮询模式和霍尔输出(Hall)功能专为电机应用而设计。ACMP1 没有轮询和霍尔(Hall)输出功能。

功能框图


普通模式
电路
检测引脚:PA8



被测引脚:PB10





软件
IO口配置

/**
* GPIO_Init
*
* @param[in] void
* @return void
*
* @brief GPIO端口初始化
*/
void GPIO_Init(void)
{
        GPIO_SetFunc(GPIO_PA8, 1);//PA8作为功能1 ADC_IN1
        GPIO_SetFunc(GPIO_PB10, 0);//PB10作为功能0,
        GPIO_SetDir(GPIO_PB10,1);//输出
        GPIO_SetPinValue(GPIO_PB10, 0);//输出低电平
}
ACMP初始化

/**
* ACMP_Init
*
* @param[in] void
* @return void
*
* @brief ACMP0模块初始化,
*/
void ACMP0_Normal_Init(void)
{
          ACMP_InitType acmpConfig;
          ACMP_DACType  acmpDACConfig;
          
          acmpConfig.posPin = ACMP_INPUT_EXT1;//正输通道选择
          acmpConfig.negPin = ACMP_INPUT_DAC ;//负输入通道选择
          acmpConfig.pollEn = 0;//不使能轮询模式
          acmpConfig.intEn = ENABLE;//使能中断
          acmpConfig.hyst = ACMP_HYST_20MV;//迟滞挡位选择
          acmpConfig.edgeType = ACMP_INTERRUPT_EDGE_FALLING_RISING;//中断触发模式
          acmpConfig.moduleEnable = ENABLE;//使能ACMP模块
          ACMP_Init(ACMP_CHANNEL0,&acmpConfig);
          NVIC_EnableIRQ(ACMP0_IRQn );
          ACMP_SetCallBack(ACMP_CHANNEL0 , ACMP_CallBack);
         
          acmpDACConfig.val = 63;//dac范围0-63 输出电压值:(val/64)*ref
          acmpDACConfig.ref = ACMP_DAC_REFERENCE_VDDA;//DAC参考源选择
          acmpDACConfig.enable = ENABLE;//DAC输出使能
          ACMP_SetDacValue(ACMP_CHANNEL0, &acmpDACConfig);
}

ACMP0的中断回调

/**
* ACMP_Callback
*
* @param[in]  none
* @return    none
*
* @brief   ACMP0中断回调函数,读出数据输出,并翻转PB10端口
*/        
uint8_t ACMPData =0;
void ACMP_CallBack(void)
{

        if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG)!=0)  //正常模式中断标志
        {
               
                ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG);//清中断标志
                ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG))>>7;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
                printf("data is %d\n",ACMPData );
                GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
               
        }
}

实测
ACMP+:PA8-ACMP_IN1-ADC_IN1

ACMP-:内部的DAC 配置成63 代表5V

也就是说ADC_IN1通道采集到的电压>5V时,则输出为1

ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG))>>7;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
对于为什么要>>7右移7位,和ACMP0的数据寄存器有关,正常模式输出在第7位上,而读到的是整个DR寄存器的值,所以要进行移位。



发现板子引脚不对
历程中引脚和demo板不对应,进行修改

PA8改成了PC4,对应LED2,让其根据ACMP0采集到的信号进行翻转,点亮或者熄灭LED2。



ACMP-,内部DAC参考电压val修改成30,对应30/64*5V=2.34V

这样就可以使用GND和5V进行测试,观察输出的数值。



接5V时,5>2.34 输出为1;

接GND时,GND<2.34输出为0;



小结
普通模式,重点在于:正输入与负输入的选择;DAC输出电平的设置。

轮询模式
和普通模式相比,有以下区别:

ACMP0模块初始化

/**
* ACMP_Init
*
* @param[in] void
* @return void
*
* @brief ACMP0模块初始化,
*/
void ACMP0_Polling_Init(void)
{
          ACMP_InitType     acmpConfig;
          ACMP_DACType      acmpDACConfig;
          ACMP_PollingType  acmpPollingConfig;
         
          acmpConfig.negPin = ACMP_INPUT_DAC ;//负输入通道选择
          acmpConfig.pollEn = 1;//使能轮询模式
          acmpConfig.intEn = ENABLE;//使能中断
          acmpConfig.hyst = ACMP_HYST_20MV;//迟滞挡位选择
          acmpConfig.edgeType = ACMP_INTERRUPT_EDGE_FALLING_RISING;//中断触发模式
          acmpConfig.moduleEnable = ENABLE;//使能ACMP模块
          ACMP_Init(ACMP_CHANNEL0,&acmpConfig);
          NVIC_EnableIRQ(ACMP0_IRQn );
          ACMP_SetCallBack(ACMP_CHANNEL0 , ACMP_CallBack);
         
          acmpDACConfig.val = 63;//dac范围0-63 输出电压值:(val/64)*ref
          acmpDACConfig.ref = ACMP_DAC_REFERENCE_VDDA;//DAC参考源选择
          acmpDACConfig.enable = ENABLE;//DAC输出使能
          ACMP_SetDacValue(ACMP_CHANNEL0, &acmpDACConfig);
          
          acmpPollingConfig.posPollingEnable = ENABLE;//正输入通道轮询模式使能
                acmpPollingConfig.negPollingEnable = DISABLE;//负输入通道轮询模式关闭
                acmpPollingConfig.pollingDiv = ACMP0_POLLING_FREQ_DIVIDER_256;//轮询分频值
                acmpPollingConfig.pollingChannelSeq = 7;//轮询通道序列设置,禁用/使能相应的通道
                acmpPollingConfig.hallOutEn = DISABLE;
                ACMP_PollingModeInit(ACMP_CHANNEL0, &acmpPollingConfig);
}

多了轮询的结构第参数配置:

正输入通道轮询模式使能;负输入通道轮询模式关闭;轮询分频值(就是几个通道之间切换的频率);轮询通道序列设置,禁用7通道;HALL输出禁止。

还有读取ACMP0数据寄存器DR相应位的数值时,所处位置不同要移不同的位数。

/**
* ACMP_Callback
*
* @param[in]  none
* @return    none
*
* @brief   ACMP0中断回调函数,读出数据输出,并翻转PB10端口
*/        
uint8_t ACMPData =0;
void ACMP_CallBack(void)
{
  if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG )!=0)  //轮询模式通道0中断标志
        {
                ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG);//清中断标志
        }
        if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG )!=0)  //轮询模式通道0中断标志
        {
               
                ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG);//清中断标志
                ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG))>>0;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
                printf("data is %d\n",ACMPData );
    GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
               
        }
        else if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG )!=0)  //轮询模式通道1中断标志
        {
                ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG);//清中断标志
                ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG))>>1;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
                printf("data is %d\n",ACMPData );
    GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
        }
        else if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG )!=0)  //轮询模式通道2中断标志
        {
                ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG);//清中断标志
                ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG))>>2;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
                printf("data is %d\n",ACMPData );
    GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
        }
        else
        {}               
}

————————————————
版权声明:本文为CSDN博主「Iron2222」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43824188/article/details/128542048

使用特权

评论回复

相关帖子

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

本版积分规则

95

主题

3301

帖子

4

粉丝