การตั้งค่า timer3 ในโหมด CTC - ขัดแย้งกับไลบรารีเซอร์โว


10

ฉันต้องการตั้งค่าตัวจับเวลาเพื่อเรียกใช้ฟังก์ชัน 800 ครั้งต่อวินาที ฉันใช้ Arduino Mega และ Timer3 กับ prescaler ที่ 1024 เพื่อเลือกตัวประกอบ prescaler ที่ฉันได้พิจารณาขั้นตอนต่อไปนี้:

  • CPU ความถี่: 16MHz
  • ความละเอียดตัวจับเวลา: 65536 (16 บิต)
  • ความถี่แบ่ง CPU โดย prescaler เลือก: 16x10 ^ 6/ 1024 = 15625
  • แบ่งส่วนที่เหลือผ่านความถี่ที่ต้องการ 62500/800 = 19
  • ใส่ผลลัพธ์ + 1 ในการลงทะเบียน OCR3

ฉันใช้ตารางต่อไปนี้เพื่อตั้งค่าการลงทะเบียนของ TCCR3B:

ป้อนคำอธิบายรูปภาพที่นี่

ข้อผิดพลาด

ไม่สามารถคอมไพล์โค้ดได้ นี่เป็นข้อผิดพลาดที่คอมไพเลอร์ส่งคืน:

Servo \ Servo.cpp.o: ในฟังก์ชั่น '__vector_32': C: \ Program Files (x86) \ Arduino \ libraries \ servers \ Servo / Servo.cpp: 110: นิยามหลายคำของ '__vector_32' AccelPart1_35.cpp.o: C: \ ไฟล์โปรแกรม (x86) \ Arduino / AccelPart1_35.ino: 457: กำหนดไว้ครั้งแรกที่นี่ c: / ไฟล์โปรแกรม (x86) / arduino / ฮาร์ดแวร์ / เครื่องมือ / 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

2
Servo.cpp น่าจะเป็นยังISR (TIMER3_COMPA_vect)
TMa

1
เพียงใช้ Timer1, 4 หรือ 5 แทน
Gerben

1
Servo กำหนดฟังก์ชั่นอินเตอร์รัปต์สำหรับตัวจับเวลา 1,3,4 และ 5 ต่อเมกะไบต์สำหรับ COMPA วิธีการเกี่ยวกับการใช้ COMPB?
BrettAM

1
คุณถูกต้อง พวกเขาเพียงแค่ hogging ตัวนับทั้งหมด ฉันเดาว่าคุณต้องเปลี่ยนไลบรารี่เล็กน้อยโดยลบ#define _useTimer3บรรทัดออกหรือลองใส่#undef _useTimer3หลังจากรวมไว้
Gerben

คำตอบ:


4

น่าเสียดายที่ห้องสมุดสำรองของ Servo เอาท์พุทเปรียบเทียบ A (OCR * A) บนตัวจับเวลา 1,3,4 และ 5 เมื่อโหลดบน mega arduino แต่ละอันสามารถมี ISR ได้เพียงตัวเดียวดังนั้นคุณจะไม่สามารถกำหนด TIMER * _COMPA_vect ของคุณเองในขณะที่คุณใช้ Servo โดยไม่ต้องแก้ไขไลบรารี

อย่างไรก็ตามตัวจับเวลาฮาร์ดแวร์แต่ละตัวมาพร้อมกับเอาต์พุต 2 รายการเปรียบเทียบ Servo ไม่เรียกร้องการขัดจังหวะ TIMER * _COMPB_vect ใด ๆ ดังนั้นสิ่งเหล่านี้จึงมีอิสระที่จะใช้และทำงานเหมือนกันทุกประการ

คุณควรระวังกิจกรรมของไลบรารี Servo ซึ่งอาจเปลี่ยนการกำหนดค่าตัวจับเวลาของคุณ คำสั่งซื้อเริ่มต้นคือ megas คือ 5,1,3,4 และมอบให้ 12 เซอร์โว มันกำหนดค่าตัวจับเวลาเมื่อจำเป็นเท่านั้นดังนั้นคุณควรใช้ตัวจับเวลา 3 จนกว่าคุณจะเพิ่มเซอร์โวที่ 25

ในการเปลี่ยนรหัสของคุณให้ใช้ OCR3B แทน OCR3A (Output Output Registers) และตั้งค่าบิต OCIE3B แทน OCIE3A เป็น TIMSK3 (บิตบิตเปรียบเทียบการขัดจังหวะผลลัพธ์) จากนั้นให้คุณเปลี่ยนฟังก์ชัน ISR เป็น ISR(TIMER3_COMPB_vect){}

โหมด CTC ใช้งานได้กับ OCR3A เท่านั้น แต่หากคุณตั้งค่า TCNT3 เป็น 0 ในฟังก์ชั่นการขัดจังหวะคุณจะได้รับพฤติกรรมที่คล้ายกัน อย่าลืมลบบรรทัดที่เปลี่ยนเป็นโหมด CTC โดยใช้ WGM12


โอเคขอบคุณ! มีคำแนะนำเกี่ยวกับการเพิ่มจำนวนของเคาน์เตอร์หรือไม่?
UserK
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.