2017-09-03 15 views
0

하나의 인터럽트와 하나의 카운터/타이머를 설정하려고합니다. 인터럽트는 외부에서 발생하며 핀에서 로우 로직을 읽습니다. 타이머는 매 100 us마다 증가하고 count 변수까지 추가해야합니다. 타이머를 설정 한 후 인터럽트를 설정했지만 인터럽트 나 타이머가 작동하지 않습니다. 코드 등이다 OCR0A의atmega 328p 인터럽트 및 타이머 설정 [C/C++]

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 프로세서 24 (0x18)를 인 것으로 계산된다 :

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

다른 인터럽트를 설정하는 방법 있도록 그들은 서로 겹치지 않아? 또는 더 나은 방법은 인터럽트를 사용하지 않도록 타이머를 설정할 수 있습니까? 읽어 주셔서 감사합니다.

+0

는 타이머가 예 제어 레지스터의 활성화 인터럽트 설정 해달라고 ? 그런 다음 상태 레지스터를 폴링하여 타이머가 수행 한 작업을 기다리고있는 모든 작업을 완료했는지 확인하십시오. –

+0

개별적으로 하나만 사용하거나 둘 다를 수행 할 수 있습니까? 각 상황에 대해 인터럽트가 작동합니까? 외부 인터럽트의 소스 (버튼 또는 다른 장치의 신호)는 무엇입니까? 버튼이 있다면 바운스를 어떻게 다루고 있습니까? –

+0

@old_timer 상태 레지스터에서 타이머/카운터 값을 읽는 것이 어떻게 보입니까? counterValue = SREG? 외부 인터럽트는 제로 크로싱 아날로그 신호를 읽으며 매번 작동합니다. – flowian

답변

0

Arduino Timer1이 @old_timer 답변 @klasyc 주셔서 감사합니다 :

당신은 아두 이노 라이브러리를 유지하려면

는 타이머를 제어하기 위해 또한 라이브러리를 사용합니다. 는 아주 늦게, 그러나 나는 설정에서 다음과 같은 설정으로 타이머 1 대신 Timer0와를 사용하여 그것을 해결 :

// 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++; 
} 
0

알다시피, ATMdu328을 Arduino 라이브러리와 함께 사용하고 있습니다. 문제는 Arduino 라이브러리가 내부적으로 Timer 1을 내부적으로 사용한다는 것입니다. 따라서 타이머 1에 대한 자체 인터럽트 처리기를 추가하면 라이브러리를 손상시키는 타이머 1에 대한 Arduino의 인터럽트 처리기가 무시됩니다.

+0

* formating은 의도 한대로 작동하지 않으므로 대신이 회신을 읽을 수 있습니다. 네, 16 MHz의 아두 이노 프로 미니를 사용하고 나는 그들이 8 개 비트 타이머는 256 에 프리스케일러를 허용하는 때문에이 타이머 0과 타이머 2, 10 미국까지 계산 가능하다고 생각하지 않습니다 그래서 예, 타이머 1은 옵션 일뿐입니다. 모든 레지스터를 확인하는 방법은 무엇입니까? 너무 복잡하다면 arduino 칩에 avr 코드를 직접 프로그램하고 싶습니다. – flowian

+0

Arduino [소스 코드] (https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c#L241)를 확인한 후 Arduino 라이브러리가 구성 및 사용하려고합니다. 모든 타이머와 유일하게 "공식적인"방법은 라이브러리 기능을 사용하는 것입니다. 그러므로 나는이 사실에 따라 나의 대답을 바꾸었다. 댓글에서 귀하의 질문에 : 프로세서 레지스터를 확인하려면 그냥 일반 변수처럼 직렬에 콘텐츠를 써주세요 :) – klasyc