XL6601系列ACMP模拟比较器使用
模拟比较器(ACMP)
实现一个简单的小功能,掉电检测,使用到了ACMP外设,认为学习东西后总得产出点什么,所以在此简单记录一下。
简介特性
模拟比较器模块(ACMP)提供一个用于比较两个模拟输入电压的电路。此比较器电路适用于在整个供电电压范围内操作(全摆幅操作);
- 可在 2.7 V 至 5.5 V 的整个电源电压范围上操作
- 片上 6 位分辨率 DAC,基准电压源可以选择 VDD 或内部带隙基准
- 可配置迟滞(个人理解是)
- 可在比较器输出上升沿、下降沿或者任何边沿时选择产生中断
- 最多 4 个可选择比较器输入
实现
使用引脚复用外设ACMP0作为比较引脚,对此IO口电压进行比较,当引脚电压低于设定的对比值(DAC值),并在上升沿下降沿触发中断。
结构框图
要想怎么实现的肯定要先理解结构框图了:
- 比较器输入端IN+ 6位DAC选择VDDA为基准与输入端IN- ACM0进行比较;
- 输出一路到外部输出,一路到ACO(返回比较器输出的当前值)寄存器;
- 将编译控制逻辑 ACMPMOD(确定中断触发器的触发模式)进行设置;
- 产生有效边沿后ACF产生中断标志位置位,触发中断;
- ACIE(中断使能)触发中断;
Demo
实例代码,一些理解写在了注释中
void Judge_Status(Return_Status flag)
{ //正常执行就都会返回RET_STATE_OK,否则死循环
if(flag != RET_STATE_OK)
{
while(1);
}
}
/*********** ACMP配置初始化 ***************/
static void ACMP_Config(ACMP_Type *ACMPx)
{
ACMP_InitTypeDef ACMP_Initstructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = (uint32_t)ACMP0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
FUNC_Status = SIM_SCGC_Cmd(SIM_SCGC_ACMP0,ENABLE);
Judge_Status(FUNC_Status);
ACMP_Initstructure.ACMP_HystMode = ACMP_Hyst_20mv; //ACMP选择了20mv的停滞
ACMP_Initstructure.ACMP_IntTrigMode = ACMP_Int_FallorRiseEdge; //上升沿下降沿均可触发中断
ACMP_Initstructure.ACMP_InputP = ACMP_Positive_EXT0; //这里有个注意的,这是比较器输入IN+和IN-是反过来的,即为IN+为ACMP0,IN-为DAC输入
ACMP_Initstructure.ACMP_InputN = ACMP_Negative_DAC;
ACMP_Initstructure.ACMP_InputPin = ACMP_IN0; //以ACMP0为比较口
ACMP_Initstructure.ACMP_DACEN = ENABLE; //使能
ACMP_Initstructure.ACMP_DACRefVoltage = ACMP_DACRef_VDDA; //以VDDA为基准
ACMP_Initstructure.ACMP_DACValue = 0x1F; //DAC电平选择 = Vin/64*(1+0x1f) = 5/64*(1+31) = 2.5(V)
//比较电压,掉电触发下降沿中断,当ACMP复用IO口低于这个电压输出0或者1(设置(IN+,IN-)ACMP_InputN、ACMP_InputP,结构框图对应的比较器输入脚即可决定)
FUNC_Status = ACMP_Init(ACMPx, &ACMP_Initstructure ); //初始化ACMP
Judge_Status(FUNC_Status);
FUNC_Status = ACMP_InterruptEn(ACMPx, ENABLE ); //启用ACMP中断
Judge_Status(FUNC_Status);
FUNC_Status = ACMP_OutputPinEn(ACMPx, ENABLE ); //输出引脚使能
Judge_Status(FUNC_Status);
FUNC_Status = ACMP_EnableCmd(ACMPx, ENABLE); //ACMP模块使能
Judge_Status(FUNC_Status);
}
/*********** 主函数 ***************/
int32_t main (void)
{
SYS_CLK_STATUS clk_state;
clk_state = SystemSetFEI(ICS_IRC_50K, ICS_FLLFACTOR_1920);
if(clk_state != SYS_CLK_OK)
{
while(1);
}
Systick_Init();
ACMP_Config(ACMP0);
FUNC_Status = GPIO_SetPinDir(GPIO_PTH5 ,GPIO_Direction_Output); //LED引脚配置为输出
Judge_Status(FUNC_Status);
for(;;)
{
Delay_ms(1000);
}
}
/*********** ACMP中断调用函数 ***************/
static void ACMPx_IRQ_CallBack(ACMP_Type *ACMPx)
{
uint8_t ACMP_Out = 0;
FUNC_Status = ACMP_GetOutPutLogic(ACMPx, &ACMP_Out); //获取比较器输出值
Judge_Status(FUNC_Status); //根据上面配置信息,IN+电压小于IN-电压即为掉电
if(ACMP_Out) //输出为1,未掉电
{
FUNC_Status = GPIO_ClrPin(GPIO_PTH5);
Judge_Status(FUNC_Status);
}
else //输出为0,确定掉电,因为配置IN-是DAC值
{
// 全局标志位置位,另写函数获取是否掉电,后续调用此函数写掉电后执行的操作
FUNC_Status = GPIO_SetPin(GPIO_PTH5);
Judge_Status(FUNC_Status);
}
FUNC_Status = ACMP_ClearIntFlag(ACMPx); //清除标志位
Judge_Status(FUNC_Status);
}
/*********** ACMP0中断服务函数 ***************/
void ACMP0_IRQHandler(void)
{
ACMPx_IRQ_CallBack(ACMP0);
}
官方解释
相关寄存器的描述已写出,以便更好阅读理解(阅读可更好理解ACMP的工作)。
功能说明
ACMP 模块就功能而言由两部分组成:数模转换器(DAC)和比较器(CMP)。
DAC 包括 64 级 DAC(数模转换器)和相关控制逻辑。通过置位 ACMP_C1[DACREF](DAC基准选择),DAC 可选择 VDDA 或片上带隙基准源这两个基准输入的其中之一作为 DAC 输入 Vin(这边选择的就是VDDA)。DAC 使能后,将ACMP_C1[DACVAL](DAC输入电平)中设置的数据转换为步进式模拟输出,然后馈入 ACMP 作为内部基准输入。输出电压范围为 Vin/64 到 Vin。步进大小为 Vin/64。
正输入与负输入
ACMP 可以实现正输入与负输入的模拟比较,然后提供一个数字输出和相关的中断。ACMP 的正负输入均可从四个通用输入中选择:三个外部基准输入和一个来自 DAC 输出的内部基准输入。
ACMP 的正输入由 ACMP_C0[ACPSEL](正输入选择)选定,其负输入由 ACMP_C0[ACNSEL](负输入选择)(Demo区注释已解释过)选定。可通过使用适当的值配置 ACMPC0 来比较 8 个输入的任何配对。
输出
通过置位 ACMP_CS[ACE](ACMP使能)使能 ACMP 之后,比较结果以数字输出呈现(1、0)。只要 ACMP_CS[ACMOD](中断边沿触发方式)中定义的有效边沿出现,ACMP_CS[ACF](中断标志位)的电平就会变为有效值。
输出标志
ACMP_CS[ACO](ACPC输出,比较后的结果)根据比较结果而改变,因此它可以用作一个跟踪标志,连续指示输入的电压变化。
如果选择芯片外部的基准输入作为 ACMP 的输入,那么必须置位对应的 ACMP_C2[ACIPE](是否允许对应的外部模拟输入,这边是允许DAC输入的,2.5V数字量转2.5V模拟量)位以使能来自焊盘接口的输入。如果需要将ACMP的输出置于外部引脚上(比较后的结果输出到引脚,这边不需要,只需得知是否掉电,其这个功能仅ACMP1支持),那么必须置位ACMP_CS[ACOPE](是否允许ACMP输出置于外部引脚上)位以使能焊盘逻辑的 ACMP 引脚功能。
中断
如果 ACMP_CS[ACMOD](中断边沿触发方式)定义的有效边沿出现时总线时钟可用,那么 ACMP_CS[ACF](中断标志位)的电平就会变为有效值。如果 ACMP_CS[ACIE](使能中断)置位,那么会发生 ACMP 中断事件。 ACMP_CS[ACF](中断标志位)位的电平将一直保持有效值,直到 ACMP 中断被软件清零。将 0 写入 ACMP_CS[ACF](中断标志位)位可清零该中断。
设置与操作
ACMP 两部分( DAC 和 CMP)的设置和操作可以独立进行。但是,如果 DAC 用作 CMP 的输入,那么在使能 ACMP 之前必须对 DAC 进行配置。
由于输入转换会导致 ACMP 输入上出现问题,因此用户应在启用 ACMP 之前完成输入选择,并且不能在启用 ACMP 时更改选择输入以避免意外输出。同样,更改 ACMP_C1[DACVAL](DAC输入电平,即为设置的2.5V)之后,DAC会有一定的设置延迟,因此用户应当在使能 DAC 之前完成 ACMP_C1[DACVAL](DAC输入电平)的设置。