【问题标题】:atmega 328p interrupt and timer setup [C/C++]atmega 328p 中断和定时器设置 [C/C++]
【发布时间】:2017-09-03 10:08:01
【问题描述】:

我正在尝试设置一个中断和一个计数器/定时器。中断是外部的,从引脚读取低逻辑。计时器应每 100 us 递增一次,并加起来为 count 变量。 我已经设置了中断,它工作正常,但是在设置定时器之后,中断和定时器都不起作用。代码是这样的:

volatile boolean allowCount = false, timerFlag = false;
volatile unsigned int counter;
boolean pulseLow = false;


void setup(){

Serial.begin(9600);

// initialize external pin interrupt.
PCICR =  0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10);    // set wanted flags (low logic level causes interrupt)
PCMSK1 = 0b00010000; // Enable Pin Change Interrupt for  A4


// TODO Interrupt settings not working together


// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
OCR1A = 0x18;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 64 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS11);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);


}

void loop(){
    if (allowCount == true)
    {   timer100_uS();

        if (counter > 50 && pulseLow == false){
            DDRC |= (1 << DDC3 ); // sets bit DDC3 to 1 within register DDRC        
            //set pin 3(A3) ouput as sourcing Vcc(HIGH)
            PORTC |= (1 << PORTC3);
            timerReset();
            pulseLow = true;
        }
        if (pulseLow == true){
            timer100_uS();
            if (counter >= 500){
                //set pin3 of port C to LOW (A3);
                PORTC &= ~(1 << PORTC3); 
                pulseLow = false
                timerReset();
        }

    }
// external pin interrupt
ISR(PCINT1_vect){
    if (allowCount == false)
    allowCount = true;
}
// timer/counter interrupt
ISR (TIMER1_COMPA_vect)
{
    if (timerFlag == true){
        counter++;
    }
}

void timer_100uS(void){
    timerFlag = true;
    cli();
}

void timerReset(void){
    sei();
    timerFlag = false;
    counter = 0;
}

使用预分频器 64 和 16 MHz 处理器根据以下公式计算 OCR0A 的值为 24 (0x18):

OCRn =  [ (clock_speed / Prescaler_value) * Desired_time_in_Seconds ] - 1

如何设置不同的中断,使它们不会相互重叠? 或者更好的是,是否可以设置定时器使其不使用中断? 感谢阅读!

【问题讨论】:

  • 只是不要在定时器控制寄存器中设置中断使能是吗?然后轮询状态寄存器以查看计时器是否完成了您等待它执行的操作。
  • 你可以单独使用它们只做一件事或另一件事,但不能同时使用它们,中断是否适用于每种情况?您的外部中断的来源是什么(按钮或来自其他设备的信号)?如果是一个按钮,你如何处理弹跳?
  • @old_timer 从状态寄存器读取定时器/计数器值会怎样?计数器值 = SREG ?外部中断读取过零模拟信号,每次都有效。
  • 看手册几秒钟,有一个 tc0 和 tc1 的中断标志寄存器,您只需阅读它们,手册中的描述确定何时设置。并且手册暗示您可以简单地将它们写清楚。通常对此类寄存器使用写一清除,但每个供应商/设计者是不同的。
  • 看起来外部中断也有一个中断标志寄存器。现在我还没有挖出一个 avr 来尝试所有这一切,这是你的工作。有时有状态寄存器只反映已启用的中断,这很常见,但有些处理器没有另一个启用层,并且一个级别会导致处理器中的中断。有时不是,取决于芯片供应商、设计等。理想情况下,还有另一层,在内核中或更靠近它的是另一层,您可以在不实际中断的情况下轮询和清除。但是你必须为这个芯片解决这个问题。

标签: embedded avr atmega


【解决方案1】:

如我所见,您正在使用 ATMega328 和 Arduino 库。您的问题是 Arduino 库内部使用 Timer 1 用于其内部目的。因此,如果您为 Timer 1 添加自己的中断处理程序,则会覆盖 Arduino 的 Timer 1 中断处理程序,这会破坏库。

如果您想继续使用 Arduino 库,也可以使用该库来控制计时器:Arduino Timer1

【讨论】:

  • * 由于某种原因,格式化无法按预期工作,因此您可以改为阅读此回复。是的,我使用的是 Arduino pro mini 16 MHz,我认为定时器 0 和定时器 2 不能计数到 10 uS,因为它们是 8 位定时器,允许预分频器到 256。所以是的,定时器 1 似乎是唯一的选择。如何检查所有寄存器?如果太复杂,我宁愿将代码直接编程到 arduino 芯片上的 avr 中。
  • 在检查 Arduino source code 之后,似乎 Arduino 库试图配置和使用所有计时器,唯一的“官方”方法是使用它们的库函数。因此,我根据这个事实改变了我的答案。从评论中回答您的问题:要检查处理器寄存器,只需将其内容像普通变量一样写入串行 :)
【解决方案2】:

感谢@old_timer、@klasyc 的回答。 很晚了,但我通过在设置中使用 timer0 而不是 timer1 解决了这个问题:

// initialize external pin interrupt.
PCICR =  0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10);    // set wanted flags (falling edge causes interrupt)
PCMSK1 = 0b00001000; // Enable Pin Change Interrupt for A3

TCCR0B = 0;
TCCR0A = 0;
//set CTC mode
TCCR0A = ( 1 << WGM01 );

// set OCR0A value for 1 us counter (OCRxn = (freq/prescaler)*desired_value)-1
OCR0A = 15;

// set compare match counter
TIMSK0 |= (1 << OCIE0A);


//set prescaler
TCCR0B |= ( 1 << CS00);

在循环之外:

ISR(TIMER0_COMPA_vect){
  counter++;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 2020-05-09
    • 1970-01-01
    相关资源
    最近更新 更多