我的意愿是将TC4作为一个定时器,该定时器定时值可改变,但预分频不变,一开始就先初始化,什么都设置好了,等要使用定时的时候,我会先将要定时的值设置好,然后启动定时器,然后在溢出中断中设置了一个标志符,中断一到该标志符将置为定时完成标志,在主程序中一直在查询该标志,应该算是查询方式吧。 volatile int8 Timer4_over; void TIM4_IRQHandler(void) { if (TIM4->SR & (1<<0)) { TIM4->SR &= ~(1<<0); // clear UIF flag Timer4_over=is_over; } } // end TIM4_IRQHandler __inline static void TIM4_Init(uint16 Prescale) { RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;//特别注意 TIM4->PSC = Prescale*2; // set prescaler TIM4->CR1 &= ~0x0001; // disable timer TIM4->SR &= ~(1<<0); // clear UIF flag Timer4_over=not_over; TIM4->CR1 = (1<<7)|(1<<4)|(1<<3)|(1<<2); TIM4->CR2 = 0; TIM4->DIER = __TIM4_DIER; // enable interrupt NVIC->ISER[0] |= (1 << (TIM4_IRQChannel & 0x1F)); // enable interrupt
TIM4->ARR = 40000; TIM4->CNT=40000; } void TIM4_Start(uint16 delay) { RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; TIM4->CR1 &= ~0x0001; // disable timer TIM4->SR &= ~(1<<0); // clear UIF flag TIM4->ARR = delay; TIM4->CNT=delay; Timer4_over=not_over; TIM4->CR1 |= TIMX_CR1_CEN; } uint16 TIM4_Stop(void) { if(Timer4_over==is_over) { TIM4->CR1 &= ~0x0001; // disable timer TIM4->SR &= ~(1<<0); // clear UIF flag return is_over; } else return not_over; } void TIM4_Close(void) { TIM4->CR1 &= ~0x0001; // disable timer TIM4->SR &= ~(1<<0); // clear UIF flag }
使用方法为: TIM4_Init(374); TIM4_Start(9600); while(TIM4_Stop()!=is_over); TIM4_Close(); ... TIM4_Start(9600); while(TIM4_Stop()!=is_over); TIM4_Close(); 现在发现一个问题,就是第一次定时的时候,总是时长不正确,偏小,从第二次以后就正常了。 最后我发现ST的官方程序是将RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;提到最前面的,但在看了http://hi.baidu.com/comyboy/blog/item/e5f08e01021a38011d9583e7.html后,他却没有这样做,难道不是开了时钟后才能操作定时器的寄存器吗? 最后我该了下,将“//特别注意”那一行移到结尾,再运行,发现,一下子就正确了。
问题解决了,但是到底是什么原因造成这个了?还有,难道不是开了时钟后才能操作定时器的寄存器吗?因为我记得我有另外个模块,就是因为在操作寄存器前没有开启该时钟而导致过失败。
以上问题请各位能解惑,谢谢1 |