Đặt timer3 ở chế độ CTC - xung đột với thư viện servo


10

Tôi muốn thiết lập một bộ đếm thời gian để gọi một chức năng 800 lần mỗi giây. Tôi đang sử dụng Arduino Mega và Timer3 với bộ tổng hợp 1024. Để chọn yếu tố bộ đếm trước tôi đã xem xét các bước sau:

  • CPU yêu cầu: 16 MHz
  • Độ phân giải thời gian: 65536 (16 bit)
  • Chia CPU freq bởi prescaler chọn: 16x10 ^ 6/ 1024 = 15.625
  • Chia phần còn lại thông qua freq 62500/800 = 19 mong muốn .
  • Đặt kết quả + 1 vào thanh ghi OCR3.

Tôi đã sử dụng bảng sau để đặt các thanh ghi của TCCR3B:

nhập mô tả hình ảnh ở đây

Lỗi

Không thể biên dịch mã. Đây là lỗi được trả về bởi trình biên dịch:

Servo \ Servo.cpp.o: Trong chức năng '__vector_32': C: \ Chương trình tập tin (x86) \ Arduino \ library \ Servo / Servo.cpp: 110: nhiều định nghĩa của '__vector_32' AccelPart1_35.cpp.o: C: \ Tệp chương trình (x86) \ Arduino / AccelPart1_35.ino: 457: lần đầu tiên được xác định tại đây c: / tệp chương trình (x86) / arduino / phần cứng / công cụ / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Vô hiệu hóa thư giãn: nó sẽ không hoạt động với nhiều định nghĩa

Mật mã

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
}

Làm thế nào để giải quyết xung đột với thư viện servo?

GIẢI PHÁP

Xung đột được giải quyết bằng cách sử dụng mã sau đây. Nó biên dịch nhưng bộ đếm được liên kết với bộ định thời 800Hz không làm tăng giá trị của nó.

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

Vì vấn đề chính đã được giải quyết, tôi đã tạo một câu hỏi khác ở đây liên quan đến vấn đề tăng số lượt truy cập.


Bạn có sử dụng thư viện servo trong progam của mình hay không?
jfpoilpret

2
Servo.cpp có thể xảy ra cũng ISR (TIMER3_COMPA_vect)
TMa

1
Chỉ cần sử dụng Timer1, 4 hoặc 5 thay thế.
Gerben

1
Servo xác định các chức năng ngắt cho bộ định thời 1,3,4 và 5 trên megas cho COMPA. Làm thế nào về việc sử dụng COMPB?
BrettAM

1
Bạn là đúng . Họ chỉ đang ăn xin tất cả các bộ tính giờ. Tôi đoán bạn phải thay đổi thư viện một chút bằng cách xóa #define _useTimer3dòng hoặc thử đặt #undef _useTimer3quyền sau khi bao gồm.
Gerben

Câu trả lời:


4

Thật không may, thư viện Servo dự trữ đầu ra so sánh A (OCR * A) trên bộ định thời 1,3,4 và 5 khi được tải trên một arduino mega. Mỗi người chỉ có thể có một ISR, vì vậy bạn sẽ không thể xác định TIMER * _COMPA_vect của riêng mình trong khi bạn sử dụng Servo mà không sửa đổi thư viện.

Tuy nhiên, mỗi bộ đếm thời gian phần cứng được trang bị 2 thanh ghi so sánh đầu ra. Servo không yêu cầu bất kỳ ngắt TIMER * _COMPB_vect nào, vì vậy những ngắt này được sử dụng miễn phí và hoạt động chính xác như nhau.

Bạn nên coi chừng các hoạt động của thư viện Servo, nó có thể thay đổi cấu hình của bộ đếm thời gian của bạn. Thứ tự mặc định là trên megas là 5,1,3,4 và để cung cấp cho mỗi 12 servo. Nó chỉ cấu hình bộ hẹn giờ một khi nó cần, vì vậy bạn sẽ ổn khi sử dụng bộ định thời 3 cho đến khi bạn thêm servo thứ 25 đó.

Để thay đổi mã của bạn, hãy sử dụng OCR3B thay vì OCR3A (Thanh ghi so sánh đầu ra) và đặt bit OCIE3B thay vì OCIE3A trong TIMSK3 (các bit cho phép ngắt so sánh đầu ra). Sau đó, bạn thay đổi chức năng ISR của mình thành ISR(TIMER3_COMPB_vect){}

Chế độ CTC chỉ hoạt động với OCR3A, nhưng nếu bạn đặt TCNT3 thành 0 trong chức năng ngắt, bạn có thể có hành vi tương tự. Nhớ xóa dòng bật chế độ CTC bằng WGM12.


Được rồi cảm ơn! Bất kỳ lời khuyên về sự gia tăng của quầy ?
Người dùng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.