我有旧的可编程定时器/计数器(PD71054 - 计数率设置为3Mhz),现在我想在STM32(STM32F103RET6)中编程一个定时器来代替PD71054。我需要测量方波的持续时间(PA0引脚),我发现有关定时器功能的信息 - 捕获,但我不知道如何使用它。不幸的是,我没有找到如何使用它的好例子(SPL库)。我试图检查信号的边缘。如果检测到上升沿,则TIM5将启动,如果检测到下降沿,则TIM5将停止并且将保存计数值。但我不知道这个解决方案是否合适以及如何为信号的两个边设置中断,并且有两个不同的函数来处理每个斜率。 signal example
int main(void)
{
TIM5_Config();
NVIC_Config ();
//IWDG_ReloadCounter();
RCC_Config();
RCC_APB1PeriphClockCmd(RCC_APB1PeriphClockCmd, ENABLE);
while(1){
}
}
RCC_Config()
{
BKP_DeInit();
// Reset RCC
RCC_DeInit ();
// HSI ON
RCC_HSICmd(ENABLE);
// Wait for HSI
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
void IWDG_Config (void) {
// watchdoga IWGD
IWDG_WriteAccessCmd (IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_4); // 40kHz/4 = 10kHz
IWDG_SetReload(0x28A); // 65ms
IWDG_Enable(); // Start IWDG oraz LSI
}
void TIM5_IRQHandler(void)
{
TIM_Cmd(TIM5, ENABLE);
}
void TIM5_Config (void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
// Ustawienia podstawy czasu TIM5
TIM_TimeBaseStructure.TIM_Period= 0xFFFF; //65535
TIM_TimeBaseStructure.TIM_Prescaler = 23; // fclk = 72MHz/24 =okolo 3MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
// Zrodlo przerwania kanal 1
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM5,ENABLE);
// TIM5_CH1, Rising edge, no filter
TIM_TIxExternalClockConfig(TIM5, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0x00);
TIM5_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM5_ICInitStructure.TIM_ICFilter=0;
TIM5_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
}
void NVIC_Config (void)
{
NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
答案 0 :(得分:-1)
抱歉,我没有时间详细了解TIMER捕获方法。我可以提供更简单的方法来做到这一点,至少你可以试试。在上升沿,下降沿将PA0引脚设置为EXTI。因此IRQ将在上升沿和下降沿产生。同时设置TIM1或TIM2,基本上是32位定时器,具有所需的精度,只需启动定时器及其计数器。因此,在上升沿,您可以轻松地重置定时器TIM1-> CNT = 0,这将是SIGNAL上升时的开始时间。然后当下降沿出现时取得TIM-> CNT。就这样。只是不要忘记控制额外的标志(自己创建的变量),这将有助于分离上升和下降沿。你甚至可以在那些事件中计算那些脉冲,但它不可靠。
这只是一个抽象的摘要,它应该有助于理解一个想法。
void enable_timer(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 48;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0xFFFFFFFF; //32 bit timer , precision 1us
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1, &timerInitStructure);
TIM_Cmd(TIM1, ENABLE);
}
EXTI处理程序:
void EXTI0_1_IRQHandler (void)
{
if (EXTI_GetITStatus(EXTI_LINE0) != RESET){
EXTI_ClearITPendingBit(EXTI_LINE0); //clear the irq flag
if(rising_edge)
TIM1->CNT = 0;
if(falling_edge)
fetcher = TIM1->CNT; // here you get your pulse duration time in us
}
}