在无感的BLDC方波控制中,AC7811没办法再直接通过PWDT模块检测霍尔信号了。 所以需要先进行ACMP模块的初始化配置,使能ACMP模块正常工作后,ACMP会对输入的三相反电动势与电机中电电压进行轮询模拟,得到各相反电动势过零点,进而模拟霍尔信号通过CTU输出至PWDT采集。

模块简介

ACMP 模块包括 ACMP0 和 ACMP1。
ACMP0 和 ACMP1 都包含一个比较器和一个 6 位数字模拟转换器(DAC)。模拟多路复用器(MUX)提供一个用于从六个通道中选择模拟输入信号的电路。一个通道由 6 位数字模拟转换器(DAC)提供,其他通道由外部输入提供。
ACMP0 的轮询模式和霍尔输出(Hall)功能专为电机应用而设计。ACMP1 没有轮询和霍尔(Hall)输出功能。

功能框图

image.png

普通模式

电路

检测引脚:PA8
image.png
被测引脚:PB10
image.png
image.png

软件

IO口配置

  1. /**
  2. * GPIO_Init
  3. *
  4. * @param[in] void
  5. * @return void
  6. *
  7. * @brief GPIO端口初始化
  8. */
  9. void GPIO_Init(void)
  10. {
  11. GPIO_SetFunc(GPIO_PA8, 1);//PA8作为功能1 ADC_IN1
  12. GPIO_SetFunc(GPIO_PB10, 0);//PB10作为功能0,
  13. GPIO_SetDir(GPIO_PB10,1);//输出
  14. GPIO_SetPinValue(GPIO_PB10, 0);//输出低电平
  15. }

ACMP初始化

  1. /**
  2. * ACMP_Init
  3. *
  4. * @param[in] void
  5. * @return void
  6. *
  7. * @brief ACMP0模块初始化,
  8. */
  9. void ACMP0_Normal_Init(void)
  10. {
  11. ACMP_InitType acmpConfig;
  12. ACMP_DACType acmpDACConfig;
  13. acmpConfig.posPin = ACMP_INPUT_EXT1;//正输通道选择
  14. acmpConfig.negPin = ACMP_INPUT_DAC ;//负输入通道选择
  15. acmpConfig.pollEn = 0;//不使能轮询模式
  16. acmpConfig.intEn = ENABLE;//使能中断
  17. acmpConfig.hyst = ACMP_HYST_20MV;//迟滞挡位选择
  18. acmpConfig.edgeType = ACMP_INTERRUPT_EDGE_FALLING_RISING;//中断触发模式
  19. acmpConfig.moduleEnable = ENABLE;//使能ACMP模块
  20. ACMP_Init(ACMP_CHANNEL0,&acmpConfig);
  21. NVIC_EnableIRQ(ACMP0_IRQn );
  22. ACMP_SetCallBack(ACMP_CHANNEL0 , ACMP_CallBack);
  23. acmpDACConfig.val = 63;//dac范围0-63 输出电压值:(val/64)*ref
  24. acmpDACConfig.ref = ACMP_DAC_REFERENCE_VDDA;//DAC参考源选择
  25. acmpDACConfig.enable = ENABLE;//DAC输出使能
  26. ACMP_SetDacValue(ACMP_CHANNEL0, &acmpDACConfig);
  27. }

ACMP0的中断回调

  1. /**
  2. * ACMP_Callback
  3. *
  4. * @param[in] none
  5. * @return none
  6. *
  7. * @brief ACMP0中断回调函数,读出数据输出,并翻转PB10端口
  8. */
  9. uint8_t ACMPData =0;
  10. void ACMP_CallBack(void)
  11. {
  12. if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG)!=0) //正常模式中断标志
  13. {
  14. ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG);//清中断标志
  15. ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG))>>7;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
  16. printf("data is %d\n",ACMPData );
  17. GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
  18. }
  19. }

实测

ACMP+:PA8-ACMP_IN1-ADC_IN1
ACMP-:内部的DAC 配置成63 代表5V
也就是说ADC_IN1通道采集到的电压>5V时,则输出为1

  1. ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG))>>7;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1

对于为什么要>>7右移7位,和ACMP0的数据寄存器有关,正常模式输出在第7位上,而读到的是整个DR寄存器的值,所以要进行移位。
image.png

发现板子引脚不对

历程中引脚和demo板不对应,进行修改
PA8改成了PC4,对应LED2,让其根据ACMP0采集到的信号进行翻转,点亮或者熄灭LED2。
image.png
ACMP-,内部DAC参考电压val修改成30,对应30/64*5V=2.34V
这样就可以使用GND和5V进行测试,观察输出的数值。
b251470bfafe9c2917c9d94f58df249.jpg
接5V时,5>2.34 输出为1;
接GND时,GND<2.34输出为0;
image.png

小结

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

轮询模式

和普通模式相比,有以下区别:
ACMP0模块初始化

  1. /**
  2. * ACMP_Init
  3. *
  4. * @param[in] void
  5. * @return void
  6. *
  7. * @brief ACMP0模块初始化,
  8. */
  9. void ACMP0_Polling_Init(void)
  10. {
  11. ACMP_InitType acmpConfig;
  12. ACMP_DACType acmpDACConfig;
  13. ACMP_PollingType acmpPollingConfig;
  14. acmpConfig.negPin = ACMP_INPUT_DAC ;//负输入通道选择
  15. acmpConfig.pollEn = 1;//使能轮询模式
  16. acmpConfig.intEn = ENABLE;//使能中断
  17. acmpConfig.hyst = ACMP_HYST_20MV;//迟滞挡位选择
  18. acmpConfig.edgeType = ACMP_INTERRUPT_EDGE_FALLING_RISING;//中断触发模式
  19. acmpConfig.moduleEnable = ENABLE;//使能ACMP模块
  20. ACMP_Init(ACMP_CHANNEL0,&acmpConfig);
  21. NVIC_EnableIRQ(ACMP0_IRQn );
  22. ACMP_SetCallBack(ACMP_CHANNEL0 , ACMP_CallBack);
  23. acmpDACConfig.val = 63;//dac范围0-63 输出电压值:(val/64)*ref
  24. acmpDACConfig.ref = ACMP_DAC_REFERENCE_VDDA;//DAC参考源选择
  25. acmpDACConfig.enable = ENABLE;//DAC输出使能
  26. ACMP_SetDacValue(ACMP_CHANNEL0, &acmpDACConfig);
  27. acmpPollingConfig.posPollingEnable = ENABLE;//正输入通道轮询模式使能
  28. acmpPollingConfig.negPollingEnable = DISABLE;//负输入通道轮询模式关闭
  29. acmpPollingConfig.pollingDiv = ACMP0_POLLING_FREQ_DIVIDER_256;//轮询分频值
  30. acmpPollingConfig.pollingChannelSeq = 7;//轮询通道序列设置,禁用/使能相应的通道
  31. acmpPollingConfig.hallOutEn = DISABLE;
  32. ACMP_PollingModeInit(ACMP_CHANNEL0, &acmpPollingConfig);
  33. }

多了轮询的结构第参数配置:
正输入通道轮询模式使能;负输入通道轮询模式关闭;轮询分频值(就是几个通道之间切换的频率);轮询通道序列设置,禁用7通道;HALL输出禁止。
还有读取ACMP0数据寄存器DR相应位的数值时,所处位置不同要移不同的位数。

  1. /**
  2. * ACMP_Callback
  3. *
  4. * @param[in] none
  5. * @return none
  6. *
  7. * @brief ACMP0中断回调函数,读出数据输出,并翻转PB10端口
  8. */
  9. uint8_t ACMPData =0;
  10. void ACMP_CallBack(void)
  11. {
  12. if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG )!=0) //轮询模式通道0中断标志
  13. {
  14. ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_OUTPUT_FLAG);//清中断标志
  15. }
  16. if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG )!=0) //轮询模式通道0中断标志
  17. {
  18. ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG);//清中断标志
  19. ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL0_FLAG))>>0;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
  20. printf("data is %d\n",ACMPData );
  21. GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
  22. }
  23. else if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG )!=0) //轮询模式通道1中断标志
  24. {
  25. ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG);//清中断标志
  26. ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL1_FLAG))>>1;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
  27. printf("data is %d\n",ACMPData );
  28. GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
  29. }
  30. else if(ACMP_GetFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG )!=0) //轮询模式通道2中断标志
  31. {
  32. ACMP_ClrFlag(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG);//清中断标志
  33. ACMPData = (ACMP_GetOutputValue(ACMP_CHANNEL0, ACMP0_POLLING_OUTPUT_CHANNEL2_FLAG))>>2;//读出ACMP0正常模式的输出值,正输入大于负输入,输出1,正输入小于负输入,输出1
  34. printf("data is %d\n",ACMPData );
  35. GPIO_SetPinValue(GPIO_PB10, ACMPData);//修改PB10输出电平
  36. }
  37. else
  38. {}
  39. }