CW32系列MCU的GTIM、ATIM的每个定时器都带有至少4路独立的捕获 / 比较通道,输入捕获功能可以测量输入信号的脉冲宽度或者频率。当捕获比较通道 CHy 上信号发生跳变(上升沿或下降沿)时,硬件自动将当前计数寄存器 GTIMx_CNT 的值存放到对应通道的比较捕获寄存器 GTIMx_CCRy 中,完成一次捕获。通过连续几次捕获即可完成信号脉冲宽度或者频率的测量。 功能框图如下图所示: 各个通道上触发捕获的条件由比较捕获控制寄存器 GTIMx_CMMR 决定。 当发生一次捕获时,通道 CHy 比较捕获中断标志 GTIMx_ISR.CCy 被硬件置位,如果允许中断 ( 设置中断使能寄 存器 GTIMx_IER.CCy 为 1),CPU 将响应中断服务程序。退出中断服务程序之前,应设置中断标志清除寄存器 GTIMx_ICR.CCy 为 0 以清除该标志。 输入捕获来源 GTIM 的输入捕获来源可以是外部 GTIMx_CHy 引脚,也可以是片内其它外设,通过通用定时器输入捕获来源配置寄存器 SYSCTRL_GTIMxCAP 进行配置。当 SYSCTRL_GTIMxCAP.CHy 为 0x00 时,输入捕获信号的外部输入端口由 GPIO 复用功能寄存器 (GPIOx_AFRH 和 GPIOx_AFRL) 进行配置。当 SYSCTRL_GTIMxCAP.CHy 为 0x01 ~ 0x07 时,输入捕获信号来自片内其它外设,如下表所示:
这种配置下,可以在芯片内部实现外部输入的互联,例如将 UART 的 RXD 信号作为输入捕获来源,可以实现对 UART 波特率的自动检测。
实例演示
利用GTIM的输入捕获功能,测量PWM信号的周期和脉宽 1.初始化系统时钟 void RCC_Configuration(void) { __RCC_GTIM1_CLK_ENABLE(); __RCC_GPIOA_CLK_ENABLE(); RCC_HSI_Enable(RCC_HSIOSC_DIV6); // 系统时钟设置为HSI,6分频,8MHz, PCLK、HCLK不分频, PCLK=HCLK=SysClk=8MHz }
2.初始化GPIO void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.IT = GPIO_IT_NONE; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pins = GPIO_PIN_6 | GPIO_PIN_7; GPIO_Init(CW_GPIOA, &GPIO_InitStruct); PA06_AFx_GTIM1CH1();//设置PA06复用为GTIM1_CH1, 上升沿触发捕获 PA07_AFx_GTIM1CH2();//设置PA07复用为GTIM1_CH2,下降沿触发捕获。 } 3.配置中断服务程序 void NVIC_Configuration(void) { __disable_irq(); NVIC_EnableIRQ(GTIM1_IRQn); __enable_irq(); }
4.GTIM1中断服务程序:通道1的输入捕获中断获取计数值VALUE1,通道2的输入捕获中断获取计数值VALUE2,通道1的第2次输入捕获中断获取计数值VALUE3。则信号脉宽=VALUE2-VALUE1,信号周期=VALUE3-VALUE1。注意如果待测量信号的脉宽和周期较长,在计算时需要考虑定时器的溢出问题,详见定时器溢出中断处理内容。 void GTIM1_IRQHandler(void) { GTIM1_IRQHandlerCallBack(); } void GTIM1_IRQHandlerCallBack(void) { static uint8_t stage = 0; static uint32_t cnt = 0; if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV)) { GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV); if (stage == 1) { cnt++; } } if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_CC1)) { if (stage == 0) { PWMPeriod = GTIM_GetCapture1(CW_GTIM1); stage = 1; } else if (stage == 1) { PWMPeriod = GTIM_GetCapture1(CW_GTIM1) + cnt * 65536 - PWMPeriod; stage = 0; cnt = 0; } GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_CC1); } if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_CC2)) { if (stage == 1) { PWMWidth = GTIM_GetCapture2(CW_GTIM1) + cnt * 65536 - PWMPeriod; } GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_CC2); } }
5.主程序:使用GTIM1的CH1和CH2两个通道对PWM输入信号进行测量,在捕获中断服务程序中完成信号的周期和脉宽计算。 static uint32_t PWMPeriod = 0; static uint32_t PWMWidth = 0; int32_t main(void) { RCC_Configuration();//System Clocks Configuration GPIO_Configuration();//GPIO Configuration NVIC_Configuration();//NVIC Configuration GTIM_InitTypeDef GTIM_InitStruct = {0}; GTIM_ICInitTypeDef GTIM_ICInitStruct = {0}; GTIM_InitStruct.Mode = GTIM_MODE_TIME; /*!< GTIM的模式选择。*/ GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE; /*!< GTIM的单次/连续计数模式选择。*/ GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV1; /*!< GTIM的预分频系数。*/ GTIM_InitStruct.ReloadValue = 0xFFFF; /*!< GTIM的重载值。*/ GTIM_InitStruct.ToggleOutState = DISABLE; GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct); //GTIM的基础参数初始化
GTIM_ICInitStruct.CHx = GTIM_CHANNEL1;// GTIM 输入捕获的配置参数 GTIM_ICInitStruct.ICFilter = GTIM_CHx_FILTER_NONE; GTIM_ICInitStruct.ICInvert = GTIM_CHx_INVERT_ON; GTIM_ICInitStruct.ICPolarity = GTIM_ICPolarity_Rising; GTIM_ICInit(CW_GTIM1, >IM_ICInitStruct);//输入捕获功能初始化
GTIM_ICInitStruct.CHx = GTIM_CHANNEL2; GTIM_ICInitStruct.ICPolarity = GTIM_ICPolarity_Falling; GTIM_ICInit(CW_GTIM1, >IM_ICInitStruct);
GTIM_ITConfig(CW_GTIM1, GTIM_IT_CC1 | GTIM_IT_CC2 | GTIM_IT_OV, ENABLE); GTIM_Cmd(CW_GTIM1, ENABLE); while (1) { } }
|