Saya mencoba menggunakan Timer1 dari mikrokontroler Atmel AVR, baik AtMega328 seperti yang digunakan dalam Arduino, atau ATTiny85, untuk menghasilkan dua sinyal jam yang merupakan gambar cermin satu sama lain. Frekuensi yang saya coba hasilkan adalah variabel 1 MHz hingga 2 MHz atau lebih yang terlalu tinggi untuk melakukan ini menggunakan kode untuk beralih pin output kecuali saya ingin melakukan hampir tidak ada yang lain di controller. Jadi saya ingin menggunakan penghitung waktu langsung pada pin terkait. Saya menggunakan toolchain GCC sehingga tidak dibatasi oleh pustaka arduino atau bahasa.
Timer1 di Atmega328 memiliki dua pin yang terkait dengannya dan saya bisa mendapatkan dua sinyal 1MHz hingga 2MHz yang identik. Meskipun datasheet sepertinya mengatakan saya bisa mendapatkan gelombang terbalik, ini membingungkan saya. Saya juga bisa mendapatkan dua sinyal yang berbeda siklus tugas pada 1 MHz, menggunakan pengaturan PWM dengan Timer1, tetapi kedua sinyal menjadi tinggi pada saat yang sama, yang lebih pendek menjadi rendah sebelumnya. Ini tidak melayani proyek saya. Saya bahkan tidak memerlukan variasi lebar pulsa PWM, saya hanya perlu dua sinyal tipe "jam" identik dari fase berlawanan, itu saja.
Saya tidak meminta siapa pun untuk menulis kode agar saya melakukan ini, saya hanya perlu seseorang untuk memberi tahu saya mode / flag timer mana yang harus memberi saya bentuk gelombang terbalik sederhana pada salah satu dari dua pin yang terkait dengan timer. Jika mungkin saya ingin menghindari menggunakan sirkuit pembalik eksternal untuk salah satu output kecuali itu hanya pilihan.
Jika ini mungkin sama sekali dalam ATTiny, itu akan menjadi lebih baik. ATTiny juga memiliki 2 pin yang terkait dengan satu timer, tetapi saya tidak yakin ia memiliki opsi yang sama dengan ATMega.
Saya sudah memiliki kristal 20 MHz dan kapasitor yang terhubung pada PCB dan jam 20 MHz bekerja dengan andal pada ATMega328. Pada ATTiny85 PCB saya memiliki kristal 8 MHz dan itu juga berfungsi dengan baik.
Tolong bantu. Terima kasih.
UPDATE : Ada beberapa asumsi yang tidak valid dalam jawaban dan komentar sejauh ini jadi mungkin saya harus mengklarifikasi: Perhatikan bahwa dalam posting asli saya, saya telah menyatakan bahwa saya menggunakan jam 20 MHz, bukan 8 MHz , dan juga bahwa saya tidak perlu PWM .
Satu-satunya mode yang memberikan frekuensi output cukup tinggi tampaknya adalah mode CTC karena mode PWM tidak berfungsi untuk output 2 MHz. Apakah ada cara untuk membalikkan Timer 1 output A, atau output B, dalam mode CTC?
Saya sekarang telah beralih ke standar Arduino Uno (ATMega328, 16 MHz) daripada papan 20 MHz saya sendiri untuk memeriksa kode saya, dan ini adalah kode saya untuk jam 2 MHz stabil yang bagus dalam mode CTC dari pin 9 dan 10, Timer 1 pin output:
#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() {
}
Jejak osiloskop untuk kedua pin identik dan sinkron, bagaimana saya bisa mendapatkan salah satu dari dua sinyal terbalik? Mode membalikkan dalam lembar data tampaknya tidak melakukan apa pun dalam mode CTC. Apakah saya salah membaca datasheet, atau apakah saya akan terpaksa menggunakan frekuensi yang lebih rendah dan mode PWM?
Untuk menambahkan pertanyaan "karunia" tertentu ke permintaan asli saya:
Jadi, perubahan apa yang perlu saya lakukan pada kode di atas, untuk membuatnya memberikan sinyal terbalik sempurna pada pin 9 dan 11 pada frekuensi tertinggi yang dimungkinkan untuk jam 16 MHz , apakah itu 2 MHz atau tidak?
Saya akan tetap menggunakan Arduino Uno standar untuk saat ini, sehingga tidak ada mode kesalahan yang diperkenalkan oleh papan tenunan saya, dan agar siapa pun yang menggunakan Arduino dapat mencoba kode saya di atas dan mengonfirmasi bahwa itu berfungsi seperti yang telah saya sebutkan dan bukan seperti yang saya lakukan. perlu!
Jawaban:
Dari Lembar Data ATtiny85:
Tabel 11-5 menunjukkan cara mengatur Mode.
Anda menginginkan mode PWM Cepat (jadi mode 3 atau mode 7). Jika Anda ingin memvariasikan siklus tugas, dan sepertinya Anda lakukan, Anda ingin mode 7 dan memvariasikan siklus tugas dengan mengatur OCRA.
Tabel 11-3 menunjukkan cara mengatur mode keluaran perbandingan untuk mode PWM Cepat.
Artinya, Anda dapat mengatur output OC0A menjadi rendah ketika nilai Timer == OCR0A dan tinggi ketika nilai Timer == 0x00 dengan mengatur COM0A1: COM0A0 = 0b10. Atau sebaliknya dengan menetapkan COM0A1: COM0A0 = 0b11. Dan juga untuk OC0B, OCR0B, COM0B0, COM0B1.
Frekuensi PWM ditentukan oleh Jam I / O (8Mhz bagi Anda) dan pengaturan prescaler timer Anda. Dan persamaan diberikan sebagai f_clk_IO / (N * 256) untuk mode PWM Cepat.
Jadi Anda dapat menggunakan OC0A untuk polaritas "normal" dan OC0B untuk polaritas "terbalik" dengan mengatur OCR0A dan OCR0B ke nilai yang sama dan mengatur COM0A1: COM0A0 = 0b10 dan COM0B1: COM0B0 ke 0b11.
MEMPERBARUI
Mengingat Anda ingin beralih output secepat mungkin dan Anda menggunakan Mega328 yang beroperasi pada 16MHz, mode operasi CTC akan memungkinkan Anda untuk mendapatkan frekuensi switching:
f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4MHz
Mode Fast PWM akan memungkinkan Anda beralih pin di:
f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8MHz
Jadi saya masih berpikir Anda ingin mode Fast PWM. Khusus Mode 3 dengan OCR0A = OCR0B = 0x80 untuk 50% siklus kerja. Dan atur COM0A bit ke 0x3 dan COM0B bit ke 0x2 untuk membuat dua gelombang pada OC0A dan OC0B inversi satu sama lain.
Perbarui # 2 Lebih banyak lagi Mega328 Cobalah kode Arduino ini:
sumber
Keluarga ATtinyX5 memiliki PLL di dalamnya, gunakan anak besar.
Saya menggunakan PLL internal untuk menyalakan jam CPU juga dan memiliki 16Mhz tanpa XTAL. Ini sangat berharga karena Anda hanya memiliki 5 pin. (Saya tidak menghitung pin reset). Juga satu PLL'ed PWM (OCR1B) berjalan pada pin XTAL dengan output gratis opsional. Anda hanya perlu menyesuaikan sekering untuk 16Mhz Xtalless ATtiny ... Atau biarkan CPU berjalan dalam 8Mhz tetapi jalankan PWM dengan clock 64Mhz tanpa mengubah sekering ..
Anda dapat memiliki PWM hingga 64 Mhz clock (tetapi resolusi 1 bit). Atau resolusi 125Khz @ 8 bit. Anda dapat mengurangi resolusi PWM & meningkatkan kecepatan melalui penurunan register OCR1C.
Untuk 1 Mhz Anda perlu mengatur OCR1C ke 63. Untuk 2 Mhz Anda perlu mengatur OCR1C ke 31. Untuk 4 Mhz Anda perlu mengatur OCR1C ke 15. ...
Cukup aktifkan PLL dengan kode ini:
Sekarang Anda memiliki jam 64 Mhz pada PWM "OCR1B0 / OCR1A0".
Anda juga dapat menyesuaikan OCR1 [A / B] 0 & XOCR1 [A / B] 0 untuk output yang dicerminkan.
Anda perlu tahu, Dead Time Generator akan memakan PWM jika Anda menetapkan OCR1A = 1. Anda membutuhkan nilai yang lebih tinggi daripada waktu mati.
Salam,
Erdem
sumber