Ada banyak cara untuk menulis protokol serial tergantung pada fungsionalitas apa yang Anda inginkan dan berapa banyak pengecekan kesalahan yang Anda butuhkan.
Beberapa hal umum yang Anda lihat dalam protokol point to point adalah:
Akhir dari pesan
Protokol ASCII paling sederhana hanya memiliki akhir dari urutan karakter pesan, sering \r
atau \n
karena ini adalah apa yang akan dicetak ketika tombol enter ditekan. Protokol biner mungkin menggunakan 0x03
atau byte umum lainnya.
Mulai dari pesan
Masalah dengan hanya memiliki akhir pesan adalah bahwa Anda tidak tahu byte lain apa yang telah diterima ketika Anda mengirim pesan Anda. Bytes ini kemudian akan diawali dengan pesan dan menyebabkannya ditafsirkan secara salah. Misalnya, jika Arduino baru saja bangun dari tidur mungkin ada beberapa sampah di buffer serial. Untuk menyiasatinya, Anda memiliki urutan pesan yang dimulai. Dalam contoh Anda, ^
sering dalam protokol biner0x02
Pemeriksaan Kesalahan
Jika pesan dapat rusak kami perlu memeriksa kesalahan. Ini bisa berupa checksum atau kesalahan CRC atau yang lainnya.
Karakter Escape
Bisa jadi checksum itu menambah karakter kontrol, seperti byte 'awal pesan' atau 'akhir pesan', atau pesan berisi nilai yang sama dengan karakter kontrol. Solusinya adalah memperkenalkan karakter pelarian. Karakter melarikan diri ditempatkan sebelum karakter kontrol yang dimodifikasi sehingga karakter kontrol yang sebenarnya tidak ada. Misalnya, jika karakter awal adalah 0x02, menggunakan karakter escape 0x10 kita dapat mengirim nilai 0x02 dalam pesan sebagai pasangan byte 0x10 0x12 (karakter kontrol XOR byte)
Nomor paket
Jika sebuah pesan rusak, kami dapat meminta pengiriman ulang dengan pesan kosong atau coba lagi, tetapi jika beberapa pesan telah terkirim maka hanya pesan terbaru yang dapat dikirim ulang. Sebaliknya paket tersebut dapat diberi nomor yang berguling setelah sejumlah pesan. Misalnya, jika nomor ini 16, perangkat pengirim dapat menyimpan 16 pesan terakhir yang dikirim dan jika ada yang rusak, perangkat penerima dapat meminta pengiriman ulang menggunakan nomor paket.
Panjangnya
Seringkali dalam protokol biner Anda melihat byte panjang yang memberitahu perangkat penerima berapa banyak karakter dalam pesan. Ini menambahkan tingkat lain pengecekan kesalahan seolah-olah jumlah byte yang benar tidak diterima maka ada kesalahan.
Khusus Arduino
Saat membuat protokol untuk Arduino, pertimbangan pertama adalah seberapa andal saluran komunikasi. Jika Anda mengirim lebih dari sebagian besar media nirkabel, XBee, WiFi, dll, sudah ada built in pengecekan dan coba ulang kesalahan dan dengan demikian tidak ada gunanya menempatkan ini dalam protokol Anda. Jika Anda mengirim lebih dari RS422 selama beberapa kilometer maka itu akan diperlukan. Hal-hal yang akan saya sertakan adalah mulai dari pesan dan akhir karakter pesan, seperti yang Anda miliki. Implementasi khas saya terlihat seperti:
>messageType,data1,data2,…,dataN\n
Membatasi bagian data dengan koma memungkinkan penguraian yang mudah, dan pesan dikirim menggunakan ASCII. Protokol ASCII sangat bagus karena Anda dapat mengetik pesan ke monitor serial.
Jika Anda menginginkan protokol biner, mungkin untuk mempersingkat ukuran pesan, Anda harus menerapkan melarikan diri jika byte data dapat sama dengan byte kontrol. Karakter kontrol biner lebih baik untuk sistem di mana spektrum penuh pengecekan kesalahan dan coba lagi diinginkan. Payloadnya masih bisa ASCII jika diinginkan.
Saya tidak memiliki keahlian formal tentang protokol serial, tetapi saya telah menggunakannya beberapa kali, dan kurang lebih puas dengan skema ini:
(Header paket) (ID byte) (data) (fletcher16 checksum) (Packet Footer)
Saya biasanya membuat header 2 byte dan Footer 1 byte. Parser saya akan membuang semuanya ketika ia melihat header paket baru, dan berusaha mengurai pesan jika ia melihat catatan kaki. Jika checksum gagal, itu tidak akan membuang pesan, tetapi terus menambahkan sampai karakter footer ditemukan dan checksum berhasil. Dengan begitu, catatan kaki hanya perlu satu byte karena tabrakan tidak mengganggu pesan.
ID arbitrer, kadang-kadang dengan panjang bagian data menjadi bagian bawah menggigit (4 bit). Bit panjang kedua bisa digunakan tetapi saya biasanya tidak repot karena panjangnya tidak perlu diketahui untuk diuraikan dengan benar, jadi melihat panjang yang tepat untuk mendapatkan ID yang diberikan hanya konfirmasi lebih lanjut bahwa pesan itu benar.
Fletcher16 checksum adalah checksum 2 byte dengan kualitas yang hampir sama dengan CRC tetapi jauh lebih mudah untuk diimplementasikan. beberapa detail di sini . Kode dapat sesederhana ini:
Saya juga telah menggunakan sistem panggilan dan tanggap untuk pesan-pesan penting, Di mana PC akan mengirim pesan setiap 500ms atau lebih sampai menerima pesan OK dengan checksum dari seluruh pesan asli sebagai data (termasuk checksum asli).
Skema ini, tentu saja, tidak cocok untuk diketik ke terminal seperti contoh Anda. Protokol Anda tampaknya cukup bagus karena terbatas pada ASCII dan saya yakin lebih mudah untuk proyek cepat yang Anda ingin dapat langsung membaca dan mengirim pesan. Untuk proyek yang lebih besar, sangat menyenangkan memiliki kepadatan protokol biner dan keamanan checksum.
sumber
Jika Anda masuk ke standar, maka Anda dapat melihat pengkodean ASN.1 / BER TLV. ASN.1 adalah bahasa yang digunakan untuk menggambarkan struktur data, dibuat khusus untuk komunikasi. BER adalah metode TLV untuk pengkodean data yang terstruktur menggunakan ASN.1. Masalahnya adalah bahwa pengkodean ASN.1 mungkin rumit di terbaik. Membuat kompiler ASN.1 yang lengkap adalah proyek itu sendiri (dan yang sangat rumit pada saat itu, pikirkan bulan ).
Mungkin lebih baik menjaga struktur TLV saja. TLV pada dasarnya terdiri dari tiga elemen: tag, panjang, dan bidang nilai. Tag mendefinisikan tipe data (string teks, string oktet, integer dll.) Dan panjangnya panjang nilainya .
Dalam BER, T juga menunjukkan jika nilainya adalah seperangkat struktur TLV itu sendiri (sebuah node yang dikonstruksi) atau secara langsung sebuah nilai (sebuah node primitif). Dengan begitu Anda dapat membuat pohon dalam biner, seperti XML (tetapi tanpa overhead XML).
Contoh:
adalah integer (tag
02
) dengan panjang nilai 1 (panjang01
) dan nilai -1 (nilaiFF
). Dalam ASN.1 / BER bilangan bulat adalah tanda angka big endian, tetapi Anda tentu saja dapat menggunakan format Anda sendiri.adalah urutan (daftar) dengan panjang 7 yang mengandung dua bilangan bulat, satu dengan nilai -1 dan satu dengan nilai 255. Kedua penyandian bilangan bulat bersama-sama membentuk nilai urutan.
Anda bisa melemparkan ini ke dekoder online juga, bukankah itu bagus?
Anda juga dapat menggunakan panjang tak terbatas dalam BER yang akan memungkinkan Anda untuk mengalirkan data. Dalam hal ini Anda perlu mengurai pohon Anda dengan benar. Saya akan menganggapnya sebagai topik lanjutan, Anda perlu tahu tentang luasnya parsing pertama dan kedalaman, untuk satu.
Menggunakan skema TLV pada dasarnya memungkinkan Anda untuk memikirkan segala jenis struktur data dan menyandikannya. ASN.1 melangkah lebih jauh dari itu, memberi Anda pengidentifikasi unik (OID), pilihan (banyak seperti C-serikat pekerja), termasuk struktur ASN.1 lain dll. Dll tetapi itu mungkin berlebihan untuk proyek Anda. Mungkin struktur yang didefinisikan ASN.1 yang paling terkenal saat ini adalah sertifikat yang digunakan oleh peramban Anda.
sumber
Jika tidak, Anda sudah mendapatkan dasar-dasarnya. Perintah Anda dapat dibuat dan dibaca oleh manusia dan mesin yang merupakan nilai tambah besar. Anda mungkin menambahkan checksum untuk mendeteksi perintah yang salah bentuk atau rusak dalam perjalanan, terutama jika saluran Anda menyertakan kabel panjang atau tautan radio.
Jika Anda membutuhkan kekuatan industri (perangkat Anda tidak boleh menyebabkan atau membiarkan seseorang terluka atau mati; Anda memerlukan kecepatan data tinggi, pemulihan kesalahan, deteksi paket yang hilang, dll.) Kemudian lihat ke beberapa protokol standar dan praktik desain.
sumber