gpt4 book ai didi

timer - 如何停止 ATmega328 上的定时器

转载 作者:行者123 更新时间:2023-12-03 09:08:48 31 4
gpt4 key购买 nike

我编写了一些简单的代码,在 Arduino Uno 上使用计时器1。问题是我无法以任何方式停止计时器。

我正在使用这个程序来计算并在显示屏上显示引脚 2 上的外部中断数量,同时测量时间。但是,当我按下按钮 fin 时,我想停止为程序生成中断,该中断会增加名为 cas 的变量时间。请问你能帮忙吗?

我的代码:

#include <OLED_I2C.h>
#define alarm_output 10
#define fin 13

int suma=0;
int alarm=0;
float cas=0;

OLED myOLED(SDA, SCL, 8);
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
extern uint8_t SmallFont[];

void setup(void) {

pinMode(alarm_output,OUTPUT);
digitalWrite(alarm_output,LOW);
pinMode(fin,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);

//interrupt
interrupts();
attachInterrupt(digitalPinToInterrupt(2), displej, CHANGE);

//first screen
myOLED.begin();
myOLED.setFont(SmallFont);
myOLED.print("TIME:", 0, 30);
myOLED.print("INTERRUPT:", 0, 56);
myOLED.print("Laser game", CENTER, 0);
myOLED.setFont(MediumNumbers);
myOLED.printNumF(cas,1,RIGHT,20);
myOLED.setFont(BigNumbers);
myOLED.printNumI(suma, RIGHT, 40);
myOLED.update();

//start loop
up:;
if(digitalRead(9)==1)
goto up;

// TIMER 1 for interrupt frequency 10 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 10 Hz increments
OCR1A = 24999; // = 16000000 / (64 * 10) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 64 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
}

void displej(){
suma++;
alarm=3;
}

ISR(TIMER1_COMPA_vect){
cas=cas+0.1;
if(alarm>0)
alarm--;

}

void loop(void) {
myOLED.setFont(MediumNumbers);
myOLED.printNumF(cas,1,RIGHT,20);
myOLED.setFont(BigNumbers);
myOLED.printNumI(suma, RIGHT, 40);
myOLED.update();

if(digitalRead(fin)==0){
cli();
TCCR1B |= (0 << CS12) | (0 << CS11) | (0 << CS10); //this do now work
detachInterrupt(digitalPinToInterrupt(2));
sei();
}
if(alarm>0)
digitalWrite(alarm_output,HIGH);
else
digitalWrite(alarm_output,LOW);

delay(10);

}

最佳答案

我已经测试了“关闭计时器”的所有三种方法。只需在下面的代码中注释掉您喜欢的代码即可查看演示。这三种方法都可以有效地让 Arduino 的 LED 停止闪烁。

void setup(void) {
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
interrupts();

// TIMER 1 for interrupt frequency 10 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 10 Hz increments
OCR1A = 24999; // 200 millisecond cycle
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 64 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
}

volatile uint8_t count = 0;
volatile uint8_t timer_flip = 0;


ISR(TIMER1_COMPA_vect){
if (timer_flip == 0)
timer_flip = 1;
else
timer_flip = 0;

if (timer_flip == 1)
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);

count++;
}

void loop(void)
{
if (count > 100) // runs for a few seconds
{
//cli(); // One way to disable the timer, and all interrupts

//TCCR1B &= ~(1<< CS12); // turn off the clock altogether
//TCCR1B &= ~(1<< CS11);
//TCCR1B &= ~(1<< CS10);

//TIMSK1 &= ~(1 << OCIE1A); // turn off the timer interrupt
}
}

这个确切的代码现在正在我旁边的 Uno 上运行。我已经测试了上面所有三种“关闭”机制,它们都有效。

为了制作一个最小的、可验证的示例,我去掉了所有 OLED 内容。我将引脚 13 更改为输出,并将其设置为让 LED 闪烁(当它停止时,计时器和/或中断明显被禁用)。

几个学习点:

  • 如果没有额外的电路,您不应该将引脚 13 用于“fin”按钮 - 请参阅 this Arduino official reference .
  • 您应该将在中断服务例程中写入的任何变量声明为 volatile
  • 您选择哪种方法来关闭计时器取决于您的目标。您只需禁用定时器中断、禁用所有中断或干脆关闭时钟源即可。选择权在你。

关于timer - 如何停止 ATmega328 上的定时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44735248/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com