Cần trợ giúp để hiểu bộ định thời của bộ định thời ATM ATMEGA / ATTINY


10

Tôi đang cố gắng sử dụng Timer1 của vi điều khiển Atmel AVR, hoặc AtMega328 như được sử dụng trong Arduino, hoặc ATTiny85, để phát ra hai tín hiệu đồng hồ là hình ảnh phản chiếu của nhau. Tần số tôi đang cố gắng tạo là biến từ 1 MHz đến 2 MHz trở lên, quá cao để thực hiện điều này bằng cách sử dụng mã để chuyển đổi các chân đầu ra trừ khi tôi muốn làm hầu như không có gì khác trong bộ điều khiển. Vì vậy, tôi muốn sử dụng đầu ra bộ đếm thời gian trực tiếp trên các chân liên quan. Tôi đang sử dụng chuỗi công cụ GCC để không bị giới hạn bởi các thư viện hoặc ngôn ngữ arduino.

Timer1 trong Atmega328 có hai chân được liên kết với nó và tôi có thể nhận được hai tín hiệu 1 MHz đến 2 MHz giống hệt nhau từ chúng. Mặc dù bảng dữ liệu dường như nói rằng tôi có thể có được dạng sóng đảo ngược, nó làm tôi bối rối. Tôi cũng có thể nhận được hai tín hiệu có chu kỳ nhiệm vụ khác nhau ở 1 MHz, sử dụng cài đặt PWM với Timer1, nhưng cả hai tín hiệu đều tăng cao cùng một lúc, tín hiệu ngắn hơn xuống thấp trước đó. Điều này không phục vụ dự án của tôi. Tôi thậm chí không cần biến thể độ rộng xung PWM, tôi chỉ cần hai tín hiệu loại "đồng hồ" giống hệt nhau của pha ngược nhau, chỉ vậy thôi.

Tôi không yêu cầu ai viết mã cho tôi để làm điều này, tôi chỉ cần ai đó cho tôi biết chế độ / cờ nào của bộ hẹn giờ sẽ cho tôi một dạng sóng đảo ngược đơn giản trên một trong hai chân được liên kết với bộ hẹn giờ. Nếu có thể tôi muốn tránh sử dụng mạch đảo ngoài cho một trong các đầu ra trừ khi đó chỉ là tùy chọn.

Nếu điều này hoàn toàn có thể xảy ra trong ATTiny, điều đó sẽ còn tốt hơn nữa. ATTiny cũng có 2 chân được liên kết với một bộ đếm thời gian, nhưng tôi không chắc nó có các tùy chọn tương tự như ATMega.

Tôi đã có một tinh thể 20 MHz và các tụ điện được kết nối trên đồng hồ PCB và 20 MHz đang hoạt động đáng tin cậy trên ATMega328. Trên ATTiny85 PCB tôi có một tinh thể 8 MHz và nó cũng hoạt động đáng tin cậy.

Xin vui lòng giúp đỡ. Cảm ơn bạn.


CẬP NHẬT : Có một số giả định không hợp lệ trong các câu trả lời và nhận xét cho đến nay có lẽ tôi nên làm rõ: Lưu ý rằng trong bài viết gốc của tôi, tôi đã tuyên bố rằng tôi đang sử dụng đồng hồ 20 MHz, không phải 8 MHz và tôi cũng không cần PWM .

Chế độ duy nhất cung cấp tần số đầu ra đủ cao dường như là chế độ CTCchế độ PWM không hoạt động cho đầu ra 2 MHz. Có cách nào để đảo ngược đầu ra Timer 1 A, hoặc đầu ra B, trong chế độ CTC không?

Bây giờ tôi đã chuyển sang Arduino Uno tiêu chuẩn (ATMega328, 16 MHz) thay vì bảng 20 MHz của riêng tôi để kiểm tra mã của tôi và đây là mã của tôi cho đồng hồ 2 MHz ổn định ở chế độ CTC từ chân 9 và 10, Timer 1 chân đầu ra:

#define tick 9
#define tock 10

void setup() {
  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  TCCR1A = _BV(COM1A0) | _BV(COM1B0) ;   // activate both output pins 
  TCCR1B = _BV(WGM12)| 1;                // set CTC mode, prescaler mode 1

  // various frustrating attempts to invert OC1B failed. What do I put here?

  OCR1A = 3;                             // set the counter max for 2 MHz

}

void loop() {
}

Các dấu vết dao động cho cả hai chân là giống hệt nhau và đồng bộ, làm thế nào tôi có thể nhận được một trong hai tín hiệu đảo ngược? Chế độ đảo ngược trong biểu dữ liệu dường như không làm gì trong chế độ CTC. Tôi đang đọc bảng dữ liệu sai, hay tôi sẽ bị buộc phải sử dụng chế độ PWM và tần số thấp hơn?

Để thêm một câu hỏi "tiền thưởng" cụ thể vào truy vấn ban đầu của tôi:
Vì vậy, tôi cần thay đổi gì với mã của mình ở trên, để làm cho nó đưa ra tín hiệu đảo ngược hoàn toàn ở chân 9 và 11 ở tần số cao nhất có thể cho đồng hồ 16 MHz , cho dù đó là 2 MHz hay không?

Bây giờ tôi sẽ gắn bó với Arduino Uno tiêu chuẩn, do đó không có chế độ lỗi nào được giới thiệu bởi hội đồng quản trị của tôi và để bất kỳ ai có arduino đều có thể thử mã của tôi ở trên và xác nhận rằng nó hoạt động như tôi đã đề cập chứ không phải như tôi nhu cầu!


1
Nhìn vào trang 97-98 của bảng dữ liệu atmega8L , có một bảng các chế độ hoạt động. Trang 108 nói rằng "Các bit COM21: 0 kiểm soát xem đầu ra của PWM được tạo ra có nên đảo ngược hay không (PWM đảo ngược hoặc không đảo ngược)". Giữ cho chúng tôi được đăng trên thành công của bạn!
Vorac

Tại sao không sử dụng một biến tần bóng bán dẫn đơn giản cho các đầu ra được nhân đôi?
Jonny B Tốt

Câu trả lời:


10

Từ bảng dữ liệu ATtiny85:

Chế độ hoạt động, nghĩa là hoạt động của các chân Timer / Counter và các chân So sánh đầu ra, được xác định bởi sự kết hợp của chế độ Tạo dạng sóng (WGM0 [2: 0]) và So sánh chế độ đầu ra (COM0x [1: 0]) chút ít. Các bit chế độ so sánh đầu ra không ảnh hưởng đến chuỗi đếm, trong khi các bit chế độ tạo dạng sóng thì có. Các bit COM0x [1: 0] kiểm soát xem đầu ra của PWM được tạo nên được đảo ngược hay không (PWM đảo ngược hoặc không đảo ngược ).

Bảng 11-5 cho thấy cách đặt Chế độ.

Mode   WGM  WGM  WGM  Timer/Counter Mode    TOP      Update of    TOV Flag
c0     02   01   00   of Operation                   OCRx at      Set on
==========================================================================
0      0    0    0    Normal                0xFF     Immediate    MAX(1)
1      0    0    1    PWM, Phase Correct    0xFF     TOP          BOTTOM
2      0    1    0    CTC                   OCRA     Immediate    MAX
3      0    1    1    Fast PWM              0xFF     BOTTOM       MAX
4      1    0    0    Reserved                                  
5      1    0    1    PWM, Phase Correct    OCRA     TOP          BOTTOM
6      1    1    0    Reserved                                  
7      1    1    1    Fast PWM              OCRA     BOTTOM       TOP

Bạn muốn có chế độ PWM nhanh (vì vậy chế độ 3 hoặc chế độ 7). Nếu bạn muốn thay đổi chu kỳ nhiệm vụ và có vẻ như bạn làm, bạn muốn chế độ 7 và thay đổi chu kỳ nhiệm vụ bằng cách đặt OCRA.

Bảng 11-3 cho thấy cách đặt chế độ đầu ra so sánh cho chế độ Fast PWM.

COM0A1/   COM0A0/
COM0B1    COM0B0     Description
===============================================================================
0         0          Normal port operation, OC0A/OC0B disconnected.
0         1          Reserved
1         0          Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
                     (non-inverting mode)
1         1          Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
                     (inverting mode)

Điều đó có nghĩa là, bạn có thể đặt đầu ra OC0A ở mức thấp khi giá trị Timer == OCR0A và cao khi giá trị Timer == 0x00 bằng cách đặt COM0A1: COM0A0 = 0b10. Hoặc ngược lại bằng cách đặt COM0A1: COM0A0 = 0b11. Và tương tự như vậy đối với OC0B, OCR0B, COM0B0, COM0B1.

Tần số PWM được xác định bởi Đồng hồ I / O (8 MHz có vẻ giống như bạn) và cài đặt bộ đếm thời gian hẹn giờ của bạn. Và phương trình được đưa ra là f_clk_IO / (N * 256) cho chế độ Fast PWM.

Vì vậy, bạn có thể sử dụng OC0A cho phân cực "bình thường" và OC0B cho phân cực "đảo ngược" bằng cách đặt OCR0A và OCR0B về cùng một giá trị và đặt COM0A1: COM0A0 = 0b10 và COM0B1: COM0B0 thành 0b11.

CẬP NHẬT

Do bạn muốn chuyển đổi đầu ra càng nhanh càng tốt và bạn đang sử dụng Mega328 hoạt động ở mức 16 MHz, chế độ vận hành CTC sẽ cho phép bạn có được tần số chuyển đổi là:

f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4 MHz

Chế độ Fast PWM sẽ cho phép bạn chuyển đổi pin tại:

f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8 MHz

Vì vậy, tôi vẫn nghĩ rằng bạn muốn chế độ Fast PWM. Cụ thể Chế độ 3 với OCR0A = OCR0B = 0x80 cho chu kỳ thuế 50%. Và đặt các bit COM0A thành các bit 0x3 và COM0B thành 0x2 để tạo hai dạng sóng trên các nghịch đảo OC0A và OC0B của nhau.

Cập nhật # 2 Thêm Mega328 Hãy thử mã Arduino này:

#define tick 9
#define tock 10

void setup(){

  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  // Setup Waveform Generation Mode 15
  // OC1A Compare Output Mode = inverting mode
  // OC1B Compare Output Mode = non-inverting mode
  // Timer Prescaler = 1
  // TOP = OCR1A = 1

  //COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);

  //WGM1[3:2] = 0b11, CS1[2:0] = 0b001
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  OCR1A = 0x0001;
  OCR1B = 0x0001;
}

void loop(){

}

Hãy để tôi nhai nó một chút và xem nếu nó hoạt động. Cảm ơn bạn.
thú vị

Sau khi đọc lại câu trả lời của bạn để dùng thử ngày hôm nay, tôi thấy một vài giả định không hợp lệ: Tôi đã chỉ định đồng hồ 20 MHz (và bây giờ tôi đã chuyển sang 16 MHz), chứ không phải "(8 MHz có vẻ như dành cho bạn)" . Ngoài ra, tôi đã xác định rằng tôi không cần biến thể độ rộng xung PWM, vì vậy không chắc chắn nơi bạn phỏng đoán "Nếu bạn muốn thay đổi chu kỳ nhiệm vụ, và nó có vẻ như bạn làm" .
thú vị

@ExcitingProjects Tôi đã khóa câu lệnh của bạn "Trên ATTiny85 PCB tôi có một tinh thể 8 MHz và nó cũng hoạt động đáng tin cậy." và câu trả lời của tôi có liên quan đến ATtiny85. Tôi sẽ thử và cập nhật câu trả lời của tôi để trả lời câu hỏi cập nhật của bạn.
Abbeyatcu

@vicateu Cảm ơn bạn. Tôi đã cập nhật câu hỏi, xem như chế độ đảo ngược dường như không có tác dụng trong chế độ CTC trừ khi tôi thiếu một số bước.
thú vị

@ExcitingProjects từ bảng dữ liệu ATmega328: "Đối với các chế độ không phải là PWM, các bit COM0x1: 0 kiểm soát xem đầu ra có nên được đặt, xóa hoặc chuyển đổi trong một trận đấu so sánh hay không"
Abbeyatcu

1

Gia đình ATtinyX5 có PLL bên trong, sử dụng nó lớn.

Tôi cũng sử dụng PLL nội bộ để cấp nguồn cho xung nhịp CPU và có 16Mhz mà không có XTAL. Điều này là quý giá vì bạn chỉ có 5 chân. (Tôi không tính pin thiết lập lại). Ngoài ra, một PLL'ed PWM (OCR1B) chạy ở chân XTAL với đầu ra miễn phí tùy chọn. Bạn chỉ cần điều chỉnh cầu chì cho Xtalless ATtiny 16Mhz ... Hoặc chỉ để CPU chạy ở tốc độ 8Mhz nhưng chạy PWM với xung nhịp 64Mhz mà không thay đổi cầu chì ..

Bạn có thể có xung nhịp lên đến 64 Mhz (nhưng độ phân giải 1 bit). Hoặc độ phân giải 125Khz @ 8 bit. Bạn có thể giảm độ phân giải PWM và tăng tốc độ thông qua việc giảm thanh ghi OCR1C.

Đối với 1 Mhz, bạn cần đặt OCR1C thành 63. Đối với 2 Mhz, bạn cần đặt OCR1C thành 31. Đối với 4 Mhz, bạn cần đặt OCR1C thành 15. ...

Chỉ cần kích hoạt PLL với mã này:

PLLCSR |= (1 << PLLE);           //Start PLL
while( !(PLLCSR & (1<<PLOCK)) ); //Wait for PLL lock
//PLLCSR |= (1<<LSM );           //Low Speed PLL that clocks 32Mhz, not 64Mhz
PLLCSR |= (1 << PCKE);           //Enable PLL

Bây giờ bạn có đồng hồ 64 Mhz trên các xung "OCR1B0 / OCR1A0".

Ngoài ra, bạn có thể điều chỉnh OCR1 [A / B] 0 & XOCR1 [A / B] 0 cho đầu ra được nhân đôi.

if(0){ //Synch mode
     //OCR1A & XOCR1A enable for Synch operation but not allow odd PWM values!
     TCCR1 |= (1 << PWM1A) | (0 << COM1A1) | (1 << COM1A0); 
     //Also ATtinyX5 has "Dead Time Generator", use it ;)
     DTPS1 = 3;   //8x Prescaler for dead time generator (maximum)
     DT1A = 0xff; //Clk dead on both channels (maximum)
     }
   else
     TCCR1 |= (1 << PWM1A) | (1 << COM1A1) | (0 << COM1A0);  //ONLY OCR1A enabled

Bạn cần biết, Dead Time Generator sẽ ăn hết outback nếu bạn đặt OCR1A = 1. Bạn cần giá trị cao hơn thời gian chết.

Trân trọng,

Erdem

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.