在无感的BLDC方波控制中,AC7811没办法再直接通过PWDT模块检测霍尔信号了。 所以需要先进行ACMP模块的初始化配置,使能ACMP模块正常工作后,ACMP会对输入的三相反电动势与电机中电电压进行轮询模拟,得到各相反电动势过零点,进而模拟霍尔信号通过CTU输出至PWDT采集。
模块简介
ACMP 模块包括 ACMP0 和 ACMP1。
ACMP0 和 ACMP1 都包含一个比较器和一个 6 位数字模拟转换器(DAC)。模拟多路复用器(MUX)提供一个用于从六个通道中选择模拟输入信号的电路。一个通道由 6 位数字模拟转换器(DAC)提供,其他通道由外部输入提供。
ACMP0 的轮询模式和霍尔输出(Hall)功能专为电机应用而设计。ACMP1 没有轮询和霍尔(Hall)输出功能。
功能框图
普通模式
电路
软件
IO口配置
/*** GPIO_Init** @param[in] void* @return void** @brief GPIO端口初始化*/void GPIO_Init(void){GPIO_SetFunc(GPIO_PA8, 1);//PA8作为功能1 ADC_IN1GPIO_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)*refacmpDACConfig.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,正输入小于负输入,输出1printf("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)*refacmpDACConfig.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,正输入小于负输入,输出1printf("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,正输入小于负输入,输出1printf("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,正输入小于负输入,输出1printf("data is %d\n",ACMPData );GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平}else{}}


