Arduino Uno Timer1 似乎自行启动
Arduino Uno Timer1 seemingly starts itself
虽然(忙);循环被立即跳过。但是唯一可以将 busy 设置为 0 的地方是在 Timer1 ISR 中。但是定时器 1 已停止并且仅在引脚更改 ISR 中才启动。
从 UART 输出我可以看出定时器 1 ISR 发生了,而 Pin Change ISR 从不发生。这应该是不可能的吧?
我错过了什么?
在我的主要功能中:
...
uint32_t temp = 0;
busy = 1;
mode = 1;
// Timer Interrupt Init
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0)); // Makeing sure timer is not running
TIMSK1 |= (1 << TOIE1); // Timer 1 overflow interrupt enable
TCNT1 = 0; // Makeing sure Timer is on 0
// Pin Change Interrupt Init
PCICR |= (1<<2); // Activating PCMSK2
PCMSK2 |= (1<<6); // PCMSK2 -> PCINT23.. 16 seem to correspond to physical pins D 0-7
UartSendstring("1");
// Scanning (see ISR)
sei();
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0));
while(busy);
cli();
...
定时器 1 中断服务程序:
ISR(TIMER1_OVF_vect)
{
UartSendstring("3");
busy = 0;
}
引脚更改 ISR:
ISR(PCINT2_vect)
{
UartSendstring("2");
//todo make first values not empty
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0));// CS12 - CS10 are set to 0 to stop the timer
data[addr] |= TCNT1L;
data[addr] |= (TCNT1H << 8); // High and low byte are saved to data
TCNT1 = 0; // Timer is reset
TCCR1B |= ((1<<1) | (1<<0)); // CS12 is set to 1 to restart the timer with prescaler 64 -> tick time = 4us
// Signal period duration is 1s / 38 000 = 26us
// -> at least on timer tick in one signal period
addr++; // Prepares to write to the next address with next edge
}
Uart 输出为:
13
编辑
我尝试将 TIMSK1 |= (1 << TOIE1);
移动到 Pin Change ISR。现在它至少像我想要的那样进入那里一次,但是一旦我启用中断,它就会再次触发 ISR 并结束。
由于 Arduino 内核默认启动所有定时器(因为 PWM),中断标志可能已经设置并且一旦您启用相应的中断它们就会触发。所以你必须在重新启用中断之前清除它们。但是有一个小小的障碍:通过将逻辑 1 写入相应位来清除中断标志。因此你必须使用这样的东西 TIFR1 = _BV(ICF1) | _BV(OCF1B) | _BV(OCF1A) | _BV(TOV1);
(但是因为你不使用任何其他 Timer1 中断,你只能清除 TOV1 标志)。
虽然(忙);循环被立即跳过。但是唯一可以将 busy 设置为 0 的地方是在 Timer1 ISR 中。但是定时器 1 已停止并且仅在引脚更改 ISR 中才启动。
从 UART 输出我可以看出定时器 1 ISR 发生了,而 Pin Change ISR 从不发生。这应该是不可能的吧?
我错过了什么?
在我的主要功能中:
...
uint32_t temp = 0;
busy = 1;
mode = 1;
// Timer Interrupt Init
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0)); // Makeing sure timer is not running
TIMSK1 |= (1 << TOIE1); // Timer 1 overflow interrupt enable
TCNT1 = 0; // Makeing sure Timer is on 0
// Pin Change Interrupt Init
PCICR |= (1<<2); // Activating PCMSK2
PCMSK2 |= (1<<6); // PCMSK2 -> PCINT23.. 16 seem to correspond to physical pins D 0-7
UartSendstring("1");
// Scanning (see ISR)
sei();
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0));
while(busy);
cli();
...
定时器 1 中断服务程序:
ISR(TIMER1_OVF_vect)
{
UartSendstring("3");
busy = 0;
}
引脚更改 ISR:
ISR(PCINT2_vect)
{
UartSendstring("2");
//todo make first values not empty
TCCR1B &= ~((1<<2) | (1<<1) | (1<<0));// CS12 - CS10 are set to 0 to stop the timer
data[addr] |= TCNT1L;
data[addr] |= (TCNT1H << 8); // High and low byte are saved to data
TCNT1 = 0; // Timer is reset
TCCR1B |= ((1<<1) | (1<<0)); // CS12 is set to 1 to restart the timer with prescaler 64 -> tick time = 4us
// Signal period duration is 1s / 38 000 = 26us
// -> at least on timer tick in one signal period
addr++; // Prepares to write to the next address with next edge
}
Uart 输出为:
13
编辑
我尝试将 TIMSK1 |= (1 << TOIE1);
移动到 Pin Change ISR。现在它至少像我想要的那样进入那里一次,但是一旦我启用中断,它就会再次触发 ISR 并结束。
由于 Arduino 内核默认启动所有定时器(因为 PWM),中断标志可能已经设置并且一旦您启用相应的中断它们就会触发。所以你必须在重新启用中断之前清除它们。但是有一个小小的障碍:通过将逻辑 1 写入相应位来清除中断标志。因此你必须使用这样的东西 TIFR1 = _BV(ICF1) | _BV(OCF1B) | _BV(OCF1A) | _BV(TOV1);
(但是因为你不使用任何其他 Timer1 中断,你只能清除 TOV1 标志)。