AC7811-ACMP模拟比较器

文章介绍了在无感BLDC电机控制中,如何利用AC7811的ACMP模块替代霍尔信号检测。通过初始化配置ACMP0模块,设置正负输入通道、轮询模式和中断,以及DAC输出电平,实现对电机反电动势的检测。在轮询模式下,ACMP会按设定顺序和频率检测各通道,通过中断回调处理检测结果,从而模拟霍尔信号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在无感的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
	{}		
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值