CTC 모드에서 timer3 설정-서보 라이브러리와 충돌


10

초당 800 번 함수를 호출하기 위해 타이머를 설정하고 싶습니다. 프리스케일러가 1024 인 Arduino Mega 및 Timer3을 사용하고 있습니다. 프리스케일러 요소를 선택하려면 다음 단계를 고려했습니다.

  • CPU 주파수 : 16MHz
  • 타이머 해상도 : 65536 (16 비트)
  • 선택한 프리스케일러로 CPU 주파수를 나눕니다 : 16x10 ^ 6 / 1024 = 15625
  • 나머지를 원하는 주파수 62500 / 800 = 19로 나눕니다 .
  • 결과 + 1을 OCR3 레지스터에 넣습니다.

다음 표를 사용하여 TCCR3B의 레지스터를 설정했습니다.

여기에 이미지 설명을 입력하십시오

오류

코드를 컴파일하는 것은 불가능합니다. 이것은 컴파일러가 반환 한 오류입니다.

서보 \ Servo.cpp.o : 함수 '__vector_32'에서 : C : \ Program Files (x86) \ Arduino \ libraries \ Servo / Servo.cpp : 110 : '__vector_32'의 다중 정의 AccelPart1_35.cpp.o : C : \ 프로그램 파일 (x86) \ Arduino / AccelPart1_35.ino : 457 : 여기에 처음 정의 된 c : / 프로그램 파일 (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe : 완화 비활성화 : 여러 정의에서 작동하지 않습니다.

코드

volatile int cont = 0;
unsigned long aCont = 0;
void setup()
{
 [...]
  // initialize Timer3
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3A = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3A);
  // enable global interrupts:
  sei();
}

void loop()
{
 // Print every second the number of ISR invoked -> should be 100
 if ( millis() % 1000 == 0)
 {
   Serial.println();
   Serial.print(" tick: ");
   Serial.println(contatore);
   contatore = 0;
 }
}

[...]

// This is the 457-th line
ISR(TIMER3_COMPA_vect)
{
    accRoutine();
    contatore++;
}

void accRoutine()
{
  // reads analog values
}

서보 라이브러리와의 충돌을 해결하는 방법은 무엇입니까?

해결책

다음 코드를 사용하여 충돌을 해결했습니다. 컴파일되지만 800Hz 타이머와 관련된 카운터는 값을 증가시키지 않습니다.

volatile int cont = 0;

void setup()
{
  Serial.begin(9600);
  // Initialize Timer
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3B = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3B);
  // enable global interrupts:
  sei();

  Serial.println("Setup completed");
}

void loop()
{
  if (millis() % 1000 == 0)
  {
    Serial.print(" tick: ");
    Serial.println(cont);
    cont = 0;
  }
}

ISR(TIMER3_COMPB_vect)
{
  cont++;
}

주요 문제가 해결 되었기 때문에, 나는 또 다른 질문 만들었습니다 여기에 카운터 점진의 문제와 관련이 있습니다.


프로그램에서 서보 라이브러리를 사용합니까?
jfpoilpret 5

2
Servo.cpp는 또한 ISR (TIMER3_COMPA_vect)
TMa

1
대신 Timer1, 4 또는 5를 사용하십시오.
Gerben

1
서보는 COMPA의 메가에서 타이머 1, 3, 4 및 5에 대한 인터럽트 기능을 정의합니다. COMPB를 사용하는 것은 어떻습니까?
BrettAM

1
당신이 맞아요 . 그들은 모든 타이머를 호기하고 있습니다. #define _useTimer3줄 을 제거하여 라이브러리를 약간 변경 하거나 #undef _useTimer3포함 직후에 시도 해야한다고 생각합니다 .
Gerben

답변:


4

불행하게도, 서보 라이브러리는 arduino mega에로드 될 때 타이머 1, 3, 4 및 5에서 출력 비교 A (OCR * A)를 예약합니다. 각각 하나의 ISR 만 가질 수 있으므로 라이브러리를 수정하지 않고 서보를 사용하는 동안 고유 한 TIMER * _COMPA_vect를 정의 할 수 없습니다.

그러나 각 하드웨어 타이머에는 2 개의 출력 비교 레지스터가 장착되어 있습니다. 서보는 TIMER * _COMPB_vect 인터럽트를 요구하지 않으므로 자유롭게 사용할 수 있으며 정확히 동일하게 작동합니다.

서보 라이브러리 활동에주의해야합니다. 타이머 구성이 변경 될 수 있습니다. 메가에서 기본 순서는 5,1,3,4이며 각 12 개의 서보를 제공합니다. 타이머는 필요할 때만 구성하므로 25 번째 서보를 추가 할 때까지 타이머 3을 사용하는 것이 좋습니다.

코드를 변경하려면 OCR3A (출력 비교 레지스터) 대신 OCR3B를 사용하고 TIMSK3 (출력 비교 인터럽트 활성화 비트)에서 OCIE3A 대신 OCIE3B 비트를 설정하십시오. 그런 다음 ISR 기능을 ISR(TIMER3_COMPB_vect){}

CTC 모드는 OCR3A에서만 작동하지만 인터럽트 기능에서 TCNT3을 0으로 설정하면 유사한 동작을 얻을 수 있습니다. WGM12를 사용하여 CTC 모드를 설정하는 회선을 제거하십시오.


알았어 고마워! 카운터 증가에 대한 조언 ?
UserK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.