每次我启用计时器时,它都会立即激活中断。无论我如何尝试对其进行预缩放。只有ARR似乎可以工作,但是16位的0.5MHz时钟给了我约160ms的机动性。
#define SYSCLK_FREQ 524288
void timer_init(uint16_t detonation_delay_ms);
int main(void){
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
TIM22->PSC = (SYSCLK_FREQ/1000)-1;
NVIC_EnableIRQ(TIM22_IRQn);
NVIC_SetPriority(TIM22_IRQn,4);
}
/* calling function */
timer_init(65535);
/* calling function */
void timer_init(uint16_t detonation_delay_ms){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
TIM22->ARR = detonation_delay_ms;
TIM22->CR1 |= TIM_CR1_CEN;
TIM22->SR = 0;
}
void TIM22_IRQHandler(void){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
我希望调用函数能够使计时器计时直到毫秒内被调用的值。但是无论我如何设置,它最终都没有定标计时器,并且在调用它后不会立即中断。
正确的方法吗?
TIM22->DIER = TIM_DIER_UIE;
TIM22->ARR = 65535-detonation_delay_ms;
TIM22->EGR = TIM_EGR_UG;
TIM22->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN;
TIM22->SR=0;
答案 0 :(得分:3)
请勿延迟中断
您启用计时器,然后设置错误的ARR-首先设置ARR和预分频器,然后使用EGR寄存器生成UG事件,然后启用计时器。
答案 1 :(得分:0)
像魅力一样工作。仅仅因为我在这里得到了帮助,才会为将来的有兴趣的人提供帮助。
使中断工作于定时器的方法是“手动”生成一次中断。这样做是可行的,因为您可以通过单个“ if”控制中断期间发生的事情。
/* TIMER Enable */
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
我对上面的声明有疑问,不知道为什么,但是在声明了更多的模块之后它不起作用。不得不把它放在更高的位置。手册没有说为什么会发生。
/* Configure TIM22 interrupt */
TIM22->PSC = (SYSCLK_FREQ/1000)-1; /* Prescaler TIMERA 22 */
TIM22->DIER = TIM_DIER_UIE;
TIM22->CNT = 0;
TIM22->EGR = TIM_EGR_UG;
NVIC_EnableIRQ(TIM22_IRQn); /* Zalaczenie przerwania od TIMER'a */
NVIC_SetPriority(TIM22_IRQn,4); /* Ustawienie priorytetu przerwania od TIMER'a */
该预分频比为1ms,因此我将524288的核心速度除了。然后启用中断,将计数器复位以确保其从0开始,然后手动生成中断。而且它只执行一次中断“循环”,但是只有一个“ if”和变量,我可以控制它的作用。
所以我在做什么,我正在调用一个设置时钟并在另一个函数中启用计数的函数enable = 1; timer_init(ms);
然后是函数调用
void timer_init(uint16_t ms)
{
TIM22->CNT = 65535-ms;
TIM22->CR1 |= TIM_CR1_CEN;
}
void TIM22_IRQHandler(void)
/* Up-Counter milisec */
{
if(TIM22->CR1 & TIM_CR1_CEN) {TIM22->CR1 &= ~TIM_CR1_CEN;}
if(TIM22->SR & TIM_SR_UIF) {
if(enable == 1){
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
}
TIM22->SR=0;
}
和中断。 非常感谢!与寄存器玩得开心!