TMR定时器捕捉(Capture)
前言:
在CH579官方例程中,已经有了通过定时器翻转IO口、定时器产生PWM输出、定时器产生CAP捕捉(DMA通道)、定时器产生计数器的相关例程。本篇博客主要是通过定时器1产生CAP捕获功能并作讲解。
一、操作
使用CH579芯片进行定时器的CAP捕捉,首先需要注意的是引脚功能,PA10是作为低频振荡器的输入端。使用该引脚进行捕捉,需要释放该引脚原先的功能,所以第一步是启用芯片内部32K,同时程序中关闭外部低频晶振引脚功能。
PWR_UnitModCfg( DISABLE, UNIT_SYS_LSE ); // 注意此引脚是LSE晶振引脚,要保证关闭才能使用其他功能
CH579的定时器是26位,所以最大超时为3FFFFFF。在捕捉时我们可以自由设置超时时间。如下图,设置超时为FFFF,则在打印时我们将红框里的数据全部相加,然后将所得值除以主频,便得到了捕获的值((0x0000ffff×6 + 1a84) / 40M ,结果如下图可见)。如果,设置超时时间为默认值即3FFFFFF,则会打印为00061a7e,将得到的值除以40M,结果是一样的(0x00061a7e / 40M)。详细讲解见CH579的芯片手册。
二、程序
/*程序:(使用40M的时钟进行CAP捕捉。需注意开启PLL电源控制位)*/
UINT32 capbuf[200];
UINT16 caplen = 0;
void DebugInit(void) //配置串口1打印
{
GPIOA_SetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
UART1_DefInit();
}
int main()
{
SetSysClock(CLK_SOURCE_PLL_40MHz); //R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON; //打开PLL电源控制位
DebugInit(); //配置串口调试
#if 1 /* 定时器3,PWM输出 */ //此为被捕捉的方波,由定时器产生
GPIOA_ResetBits( GPIO_Pin_2 ); // 配置PWM口 PA2
GPIOA_ModeCfg( GPIO_Pin_2, GPIO_ModeOut_PP_5mA );
TMR3_PWMInit( High_Level, PWM_Times_1 );
TMR3_PWMCycleCfg( 400000 ); // 周期 10ms
TMR3_Disable();
TMR3_PWMActDataWidth( 200000 ); // 占空比设置 , 修改占空比必须暂时关闭定时器
TMR3_Enable();
while(1);
#endif
#if 1
PWR_UnitModCfg( DISABLE, UNIT_SYS_LSE ); // 注意此引脚是LSE晶振引脚,要保证关闭才能使用其他功能
GPIOA_ResetBits( GPIO_Pin_10 ); // 配置PWM口 PA10
GPIOA_ModeCfg( GPIO_Pin_10, GPIO_ModeIN_PU );
TMR1_CapInit( FallEdge_To_FallEdge ); //下降沿到下降沿 & 计数下降沿
TMR1_CAPTimeoutCfg( 0xFFFF ); // 设置捕捉超时时间,最大为3FFFFFF(定时器为26位)
TMR1_ITCfg(ENABLE,RB_TMR_IE_DATA_ACT|RB_TMR_IE_CYC_END); //配置中断使能寄存器
NVIC_EnableIRQ( TMR1_IRQn ); //开启定时器1中断
mDelaymS(3);
while(1) //中断中产生的数据在这里打印出来
{
if(caplen > 200) //一次打印200个,可根据需求增减
{
NVIC_DisableIRQ( TMR1_IRQn ); //打印时关闭中断,防止继续捕获
TMR1_ITCfg(DISABLE,RB_TMR_IE_DATA_ACT|RB_TMR_IE_CYC_END); //打印时关闭中断,防止继续捕获
for(caplen = 0; caplen < 200; caplen++)
{
printf( "capbuf = %08lx\n", capbuf[caplen]); //打印CAP捕捉值
}
}
}
#endif
}
void TMR1_IRQHandler( void ) // TMR1 定时中断
{
UINT16 i ;
if( TMR1_GetITFlag(RB_TMR_IF_DATA_ACT) ) //进入普通捕捉(普通与超时:有且仅有二选一)
{
capbuf[caplen] = R32_TMR1_FIFO; //采集的值放在FIFO寄存器中
caplen++; //设置捕捉次数,本次为200(可增减)
TMR1_ClearITFlag( RB_TMR_IF_DATA_ACT ); // 清除中断标志
}
if( TMR1_GetITFlag( RB_TMR_IF_CYC_END ) ) //进入超时捕捉(普通与超时:有且仅有二选一)
{
capbuf[caplen] = R32_TMR1_CNT_END; //计数终值寄存器,即设置捕捉超时的时间
caplen++;
TMR1_ClearITFlag( RB_TMR_IF_CYC_END ); // 清除中断标志
}
}
CH592捕捉:
CH592捕获定时器产生PWM波形
#include "CH59x_common.h"
__attribute__((aligned(4))) uint32_t CapBuf[200];
volatile UINT32 capbuf[200];
volatile UINT16 caplen = 0;
volatile uint8_t capFlag = 0;;
void DebugInit(void){
GPIOB_SetBits(GPIO_Pin_7);
GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA);
UART0_DefInit();
}
int main(){
SetSysClock(CLK_SOURCE_PLL_60MHz);
DebugInit();
UART0_BaudRateCfg(1500000);
PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);
/* 定时器3,PWM输出 */
GPIOB_ResetBits(GPIO_Pin_22); // 配置PWM口 PB22
GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_5mA);
TMR3_PWMInit(High_Level, PWM_Times_1);
TMR3_PWMCycleCfg(60 * 10); // 周期 100us 最大67108864
TMR3_PWMActDataWidth(30 * 10); // 占空比 50%, 修改占空比必须暂时关闭定时器
TMR3_PWMEnable();
TMR3_Enable();
//xxx 捕获
mDelaymS(3000);
PWR_UnitModCfg(DISABLE, UNIT_SYS_LSE); // 注意此引脚是LSE晶振引脚,要保证关闭才能使用其他功能
GPIOA_ResetBits(GPIO_Pin_10); // 配置PWM口 PA10
GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeIN_PU);
TMR1_CapInit(Edge_To_Edge);
TMR1_CAPTimeoutCfg(0xFFF); // 设置捕捉超时时间
TMR1_DMACfg(ENABLE, (uint16_t)(uint32_t)&CapBuf[0], (uint16_t)(uint32_t)&CapBuf[100], Mode_Single);
TMR1_ITCfg(ENABLE, TMR1_2_IT_DMA_END); // 开启DMA完成中断
PFIC_EnableIRQ(TMR1_IRQn);
while(1){
if(capFlag == 1){
capFlag = 0;
for(uint8_t i = 0; i < 100; i++)
{
PRINT("%08lx\n", CapBuf[i]& 0x3ffffff); // 26bit, 最高位表示 高电平还是低电平
}printf("\n");
}
}
while(1);
}
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void TMR1_IRQHandler(void) // TMR0 定时中断
{
printf("IRQ\n");
if(TMR1_GetITFlag(TMR1_2_IT_DMA_END))
{
TMR1_ITCfg(DISABLE, TMR1_2_IT_DMA_END);//使用单次DMA功能+中断,注意完成后关闭此中断使能,否则会一直上报中断。
TMR1_ClearITFlag(TMR1_2_IT_DMA_END); // 清除中断标志
capFlag = 1;
}
}
26bit为高代表捕捉到高电平,为低代表低电平。
0x12c是波形长度,为300,与PWM边沿吻合。