Dengan mengacu pada Arduino Uno, Mega2560, Leonardo dan papan serupa:
- Bagaimana cara kerja komunikasi serial?
- Seberapa cepat serial?
- Bagaimana saya terhubung antara pengirim dan penerima?
Harap dicatat: Ini dimaksudkan sebagai pertanyaan referensi.
Dengan mengacu pada Arduino Uno, Mega2560, Leonardo dan papan serupa:
Harap dicatat: Ini dimaksudkan sebagai pertanyaan referensi.
Jawaban:
Komunikasi serial asinkron (biasanya disebut sebagai serial) digunakan untuk mengirim byte dari satu perangkat ke perangkat lainnya. Perangkat dapat berupa satu atau lebih dari yang berikut:
Tidak seperti komunikasi serial SPI / USB / I2C tidak memiliki sinyal clock. Jam pengambilan sampel adalah laju sampel yang disepakati (dikenal sebagai laju baud). Baik pengirim dan penerima harus dikonfigurasikan untuk menggunakan laju yang sama atau penerima akan menerima data yang tidak berarti (karena bit tidak diambil sampel pada laju yang sama dengan yang dikirim).
Transmisinya asinkron yang pada dasarnya berarti byte dapat dikirim kapan saja, dengan celah yang berbeda di antaranya. Grafik ini menggambarkan satu byte yang dikirim:
Grafik di atas menunjukkan huruf 'F' sedang dikirim. Dalam ASCII ini adalah 0x46 (dalam hex) atau 0b01000110 (dalam biner). The setidaknya signifikan (low-order) bit ditransmisikan pertama, sehingga dalam grafik di atas Anda melihat bit tiba di urutan: 01100010
.
Waktu "idle" antara byte ditransmisikan sebagai bit "1" kontinu (secara efektif, jalur transmisi dipegang tinggi terus menerus).
Untuk menunjukkan awal byte, Bit Mulai selalu ditunjukkan dengan menarik garis rendah seperti yang ditunjukkan pada grafik. Setelah penerima melihat bit mulai, itu menunggu 1,5 kali waktu sampel, dan kemudian sampel bit data. Ia menunggu 1,5 kali sehingga:
Jika laju baud adalah 9600 baud, misalnya, maka laju sampel akan menjadi 1/9600 = 0.00010416
detik (104,16 μs).
Jadi, pada 9600 baud, setelah menerima bit mulai penerima menunggu 156,25 μs, dan kemudian sampel setiap 104,16 μs.
Tujuan dari Bit Stop adalah untuk memastikan bahwa pasti ada 1-bit antara setiap byte. Tanpa bit stop, jika byte berakhir dengan nol, maka tidak mungkin bagi perangkat keras untuk mengetahui perbedaan antara itu dan bit mulai dari byte berikutnya.
Untuk menghasilkan output di atas pada Uno Anda dapat menulis kode ini:
void setup()
{
Serial.begin(9600);
Serial.print("F");
}
void loop ()
{
}
Untuk menghemat waktu transmisi (di masa lalu, heh) Anda diizinkan untuk menentukan jumlah bit data yang berbeda. Perangkat keras AtMega mendukung bit data penomoran dari 5 hingga 9. Jelas semakin sedikit bit data semakin sedikit informasi yang dapat Anda kirim, tetapi semakin cepat akan.
Anda dapat memiliki sedikit paritas. Ini dihitung, jika diperlukan, dengan menghitung angka 1 pada karakter, dan kemudian memastikan bahwa angka ini ganjil atau genap dengan mengatur bit paritas ke 0 atau 1 seperti yang diperlukan.
Misalnya, untuk huruf "F" (atau 0x46 atau 0b01000110) Anda dapat melihat bahwa ada 3 huruf di sana (pada 01000110). Jadi kita sudah memiliki paritas aneh. Jadi, bit paritasnya adalah sebagai berikut:
Bit paritas, jika ada, muncul setelah bit data terakhir tetapi sebelum bit berhenti.
Jika penerima tidak mendapatkan bit paritas yang benar, itu disebut "kesalahan paritas". Ini menunjukkan bahwa ada beberapa masalah. Mungkin pengirim dan penerima dikonfigurasikan untuk menggunakan tingkat baud (bit) yang berbeda, atau ada suara di saluran yang mengubah nol menjadi satu atau sebaliknya.
Beberapa sistem awal juga menggunakan paritas "mark" (di mana bit paritas selalu 1 terlepas dari data), atau paritas "spasi" (di mana bit paritas selalu 0 terlepas dari data).
Beberapa peralatan komunikasi menggunakan data 9-bit, sehingga dalam kasus ini bit paritas diubah menjadi bit ke-9. Ada teknik khusus untuk mengirim bit ke-9 ini (register adalah register 8-bit sehingga bit ke-9 harus diletakkan di tempat lain).
Peralatan awal cenderung lebih lambat secara elektronik, sehingga untuk memberi waktu penerima untuk memproses byte yang masuk, kadang-kadang ditentukan bahwa pengirim akan mengirim dua bit penghenti. Ini pada dasarnya menambahkan lebih banyak waktu di mana garis data dijaga tinggi (sekali lagi bit) sebelum bit mulai berikutnya dapat muncul. Waktu bit ekstra ini memberi waktu penerima untuk memproses byte yang masuk terakhir.
Jika penerima tidak mendapatkan 1 logis ketika bit stop seharusnya, itu disebut "kesalahan pembingkaian". Ini menunjukkan bahwa ada beberapa masalah. Sangat mungkin pengirim dan penerima dikonfigurasikan untuk menggunakan tingkat baud (bit) yang berbeda.
Umumnya, komunikasi serial ditunjukkan dengan memberi tahu Anda kecepatan, jumlah bit data, jenis paritas, dan jumlah bit stop, seperti ini:
9600/8-N-1
Ini memberitahu kita:
Penting bahwa pengirim dan penerima menyetujui hal di atas, jika tidak komunikasi tidak akan berhasil.
Arduino Uno memiliki pin digital 0 dan 1 yang tersedia untuk serial perangkat keras:
Untuk menghubungkan dua Arduino Anda menukar Tx dan Rx seperti ini:
Berbagai kecepatan didukung (lihat grafik di bawah). "Standar" kecepatan biasanya kelipatan 300 baud (mis. 300/600/1200/2400 dll.).
Kecepatan "non-standar" lainnya dapat ditangani dengan mengatur register yang sesuai. Kelas HardwareSerial melakukan ini untuk Anda. misalnya.
Serial.begin (115200); // set speed to 115200 baud
Sebagai aturan umum, dengan asumsi Anda menggunakan data 8-bit, maka Anda dapat memperkirakan jumlah byte yang dapat Anda kirimkan per detik dengan membagi baud rate dengan 10 (karena bit awal dan bit berhenti).
Dengan demikian, pada 9600 baud Anda dapat mengirimkan 960 byte ( 9600 / 10 = 960
) per detik.
Baud rate pada Atmega dihasilkan dengan membagi jam sistem, dan kemudian menghitung hingga nomor yang telah ditetapkan. Tabel ini dari lembar data menunjukkan nilai register, dan persentase kesalahan, untuk jam 16 MHz (seperti yang ada di Arduino Uno).
Bit U2Xn mempengaruhi pembagi laju jam (0 = bagi dengan 16, 1 = bagi dengan 8). Register UBRRn berisi nomor yang dihitung oleh prosesor.
Jadi dari tabel di atas, kita melihat bahwa kita mendapatkan 9600 baud dari clock 16 MHz sebagai berikut:
16000000 / 16 / 104 = 9615
Kami membagi dengan 104 dan bukan 103 karena penghitungnya adalah nol relatif. Jadi kesalahan di sini adalah 15 / 9600 = 0.0016
yang dekat dengan apa yang dikatakan tabel di atas (0,02%).
Anda akan melihat bahwa beberapa baud rate memiliki jumlah kesalahan yang lebih tinggi daripada yang lain.
Menurut datasheet, persentase kesalahan maksimum untuk 8 bit data adalah dalam kisaran 1,5% hingga 2,0% (lihat datasheet untuk rincian lebih lanjut).
Arduino Leonardo dan Micro memiliki pendekatan yang berbeda untuk komunikasi serial, karena mereka terhubung langsung melalui USB ke komputer host, bukan melalui port serial.
Karena itu, Anda harus menunggu Serial menjadi "siap" (karena perangkat lunak membuat koneksi USB), dengan beberapa baris tambahan, seperti ini:
void setup()
{
Serial.begin(115200);
while (!Serial)
{} // wait for Serial comms to become ready
Serial.print("Fab");
}
void loop ()
{
}
Namun, jika Anda ingin benar-benar berkomunikasi melalui pin D0 dan D1, (bukan dengan kabel USB) maka Anda perlu menggunakan Serial1 daripada Serial. Anda melakukannya seperti ini:
void setup()
{
Serial1.begin(115200);
Serial1.print("Fab");
}
void loop ()
{
}
Perhatikan bahwa Arduino menggunakan level TTL untuk komunikasi serial. Ini berarti bahwa ia mengharapkan:
Peralatan serial yang lebih tua yang dirancang untuk dihubungkan ke port serial PC mungkin menggunakan level tegangan RS232, yaitu:
Tidak hanya ini "terbalik" sehubungan dengan level TTL ("satu" lebih negatif daripada "nol"), Arduino tidak dapat menangani tegangan negatif pada pin inputnya (atau yang positif lebih besar dari 5V).
Dengan demikian Anda memerlukan sirkuit antarmuka untuk berkomunikasi dengan perangkat tersebut. Untuk input (ke Arduino) saja, transistor sederhana, dioda, dan beberapa resistor akan melakukannya:
Untuk komunikasi dua arah Anda harus dapat menghasilkan tegangan negatif, sehingga diperlukan sirkuit yang lebih kompleks. Sebagai contoh, chip MAX232 akan melakukan itu, bersama dengan empat kapasitor 1 μF untuk bertindak sebagai sirkuit pompa pengisian daya.
Ada perpustakaan yang disebut SoftwareSerial yang memungkinkan Anda melakukan komunikasi serial (sampai titik tertentu) dalam perangkat lunak daripada perangkat keras. Ini memiliki keuntungan bahwa Anda dapat menggunakan konfigurasi pin yang berbeda untuk komunikasi serial. Kerugiannya adalah melakukan serial dalam perangkat lunak lebih intensif prosesor dan lebih rentan terhadap kesalahan. Lihat Serial Perangkat Lunak untuk lebih jelasnya.
Arduino "Mega" memiliki 3 port serial perangkat keras tambahan. Mereka ditandai di papan sebagai Tx1 / Rx1, Tx2 / Rx2, Tx3 / Rx3. Mereka harus digunakan dalam preferensi untuk SoftwareSerial jika memungkinkan. Untuk membuka port lain tersebut Anda menggunakan nama Serial1, Serial2, Serial3, seperti ini:
Serial1.begin (115200); // start hardware serial port Tx1/Rx1
Serial2.begin (115200); // start hardware serial port Tx2/Rx2
Serial3.begin (115200); // start hardware serial port Tx3/Rx3
Baik mengirim dan menerima, menggunakan pustaka HardwareSerial, menggunakan interupsi.
Ketika Anda melakukan Serial.print
, data yang Anda coba cetak ditempatkan dalam buffer "transmit" internal. Jika Anda memiliki 1024 byte atau lebih dari RAM (seperti pada Uno) Anda mendapatkan buffer 64-byte, jika tidak, Anda mendapatkan buffer 16-byte. Jika buffer memiliki ruang, maka Serial.print
return segera, sehingga tidak menunda kode Anda. Jika tidak ada ruang, maka itu "blok" menunggu buffer dikosongkan cukup untuk ada ruang.
Kemudian, karena setiap byte ditransmisikan oleh perangkat keras interupsi disebut ("USART, Data Register Empty" interrupt) dan rutin interupsi mengirimkan byte berikutnya dari buffer keluar dari port serial.
Ketika data yang masuk diterima, rutin interupsi disebut (interupsi "USART Rx Complete") dan byte yang masuk ditempatkan ke dalam buffer "terima" (ukuran yang sama dengan buffer transmisi yang disebutkan di atas).
Saat Anda menelepon, Serial.available
cari tahu berapa byte yang tersedia di buffer "terima" itu. Ketika Anda memanggil Serial.read
byte dihapus dari buffer terima dan kembali ke kode Anda.
Pada Arduino dengan 1000 byte atau lebih dari RAM, tidak ada terburu-buru untuk menghapus data dari buffer terima, asalkan Anda tidak membiarkannya mengisi. Jika terisi maka data yang masuk lebih lanjut dibuang.
Perhatikan bahwa karena ukuran buffer ini, tidak ada gunanya menunggu jumlah byte yang sangat besar untuk tiba, misalnya:
while (Serial.available () < 200)
{ } // wait for 200 bytes to arrive
Ini tidak akan berhasil karena buffer tidak dapat menampung sebanyak itu.
Sebelum membaca, selalu pastikan data tersedia. Misalnya, ini salah:
if (Serial.available ())
{
char a = Serial.read ();
char b = Serial.read (); // may not be available
}
The Serial.available
tes hanya memastikan Anda memiliki satu byte tersedia, namun kode mencoba untuk membaca dua. Mungkin berhasil, jika ada dua byte dalam buffer, jika tidak Anda akan mendapatkan -1 yang akan terlihat seperti 'ÿ' jika dicetak.
Waspadai berapa lama waktu yang dibutuhkan untuk mengirim data. Seperti disebutkan di atas, pada 9600 baud Anda yang hanya mentransmisikan 960 byte per detik, jadi mencoba mengirim 1000 bacaan dari port analog, pada 9600 baud, tidak akan terlalu berhasil.