1. Pendahuluan
XMODEM adalah protokol transfer file asinkron yang banyak digunakan dalam komunikasi serial, dibagi menjadi dua protokol: XMODEM (menggunakan blok data 128-byte) dan 1K-xModem (menggunakan blok data 1024-byte, mis. Blok data 1K-byte).
Artikel ini mengimplementasikan protokol xmodem dari blok data 128-byte, yang mengadopsi verifikasi CRC16. Ketika diterapkan dalam proyek, akhir pengiriman dan penerima dapat memodifikasi perjanjian antara kedua belah pihak sesuai dengan keadaan tertentu.
Jika Anda tidak tahu banyak tentang komunikasi serial, Anda dapat membaca blog yang saya tulis untuk menggunakan Java untuk mengimplementasikan komunikasi serial.
2. Implementasi
Selama proses debugging dengan siswa tertanam, ditemukan bahwa sisi pengiriman mengirim data terlalu cepat, yang menyebabkan sisi penerima tidak dapat memprosesnya. Oleh karena itu, utas anak dibuka dalam metode Kirim untuk memproses data Send Logic, yang memfasilitasi penambahan pemrosesan penundaan.
Dalam metode penerima, pengiriman C berarti verifikasi di CRC.
kelas publik xmodem {// Mulai byte final pribadi SOH = 0x01; // Akhiri byte final pribadi eot = 0x04; // Jawab byte final privat ack = 0x06; // Transmit Byte Final Privat NAK = 0x15; // byte akhir pribadi akhir tanpa syarat dapat = 0x18; // Transfer data dalam 128 byte blok private final int sector_size = 128; // kesalahan maksimum (tidak ada respons) Jumlah paket private final int max_errors = 10; // aliran input, digunakan untuk membaca data port serial inputstream inputstream; // aliran output, digunakan untuk mengirim data port serial outputStream outputStream; publik xmodem (inputStream inputStream, outputStream outputStream) {this.inputStream = inputStream; this.outputStream = outputStream; } / *** Kirim data** @param filepath* path file* / public void kirim (final string filepath) {thread baru () {public void run () {coba {// Jumlah paket kesalahan int errorCount; // Paket Nomor Byte BlockNumber = 0x01; // checksum int checksum; // Jumlah byte yang dibaca ke buffer int nbytes; // inisialisasi byte buffer data [] bagian = byte baru [secector_size]; // Baca inisialisasi file DataInputStream inputStream = new DatalputStream (FileInputStream baru (FilePath)); while ((nbytes = inputStream.read (sektor))> 0) {// Jika paket data terakhir kurang dari 128 byte, isi dengan 0xff if (nbytes <sector_size) {for (int i = nbytes; i <secector_size; i ++) {sector [i] = (i] = (byte) 0xx; }} // Paket data yang sama dikirim hingga 10 kali errorCount = 0; while (errorCount <max_errors) {// grup packet // karakter kontrol + nomor paket + kode terbalik dari nomor paket + data + checksum putdata (SOH); putdata (blocknumber); putdata (~ blocknumber); checksum = crc16.calc (sektor) & 0x00ffff; putchar (sektor, (pendek) checksum); outputStream.flush (); // Dapatkan data jawaban data byte = getData (); // Jika jawabannya diterima, paket data berikutnya akan melompat keluar dan mengirim paket data berikutnya // tidak ada respons yang diterima, jumlah paket yang salah +1, terus ulangi jika (data == ack) {break; } else {++ errorCount; }} // Nomor paket ditingkatkan oleh blockNumber = (byte) ((++ blockNumber) % 256); } // Setelah semua data dikirim, kirim bendera end boolean isack = false; while (! Isack) {putdata (eot); isack = getData () == ack; }} catch (Exception e) {e.printstacktrace (); }}; }.awal(); } / *** Menerima data** @param filepath* path file* @return apakah resepsi selesai* @throws ioException* pengecualian* / public boolean menerima (string filepath) melempar pengecualian {// paket kesalahan int errorCount = 0; // Paket Nomor Byte BlockNumber = 0x01; // data byte data; // checksum int checksum; // inisialisasi byte buffer data [] bagian = byte baru [secector_size]; // tulis ke file untuk menginisialisasi dataOutputStream outputStream = new DataOutputStream (FileOutputStream baru (FilePath)); // Kirim karakter C dan CRC verifikasi putData ((byte) 0x43); while (true) {if (errorCount> max_errors) {outputStream.close (); mengembalikan false; } // Dapatkan data balasan data = getData (); if (data! = eot) {coba {// tentukan apakah pengidentifikasi mulai yang diterima (data! = soH) {errorCount ++; melanjutkan; } // Dapatkan data nomor seri paket = getData (); // Tentukan apakah nomor seri paket benar jika (data! = BlockNumber) {errorCount ++; melanjutkan; } // Dapatkan kode terbalik dari byte nomor seri paket _blockNumber = (byte) ~ getData (); // Tentukan apakah kode terbalik dari nomor seri paket sudah benar jika (data! = _BlockNumber) {errorCount ++; melanjutkan; } // Dapatkan data untuk (int i = 0; i <sector_size; i ++) {sektor [i] = getData (); } // Dapatkan checksum checksum = (getData () & 0xff) << 8; checksum | = (getData () & 0xff); // Tentukan apakah checksum benar int crc = crc16.calc (sektor); if (crc! = checksum) {errorCount ++; melanjutkan; } // Kirim Balas Putdata (ACK); // Nomor Paket bertambah dengan BlockNumber ++; // Tulis data ke outputStream.write (sektor) lokal; // ErrorCount diatur ulang ke nol = 0; } catch (Exception e) {E.PrintStackTrace (); } akhirnya {// Jika terjadi kesalahan, kirim pengidentifikasi ulang if (errorCount! = 0) {putdata (nak); }}} else {break; }} // tutup output stream outputStream.close (); // Kirim balasan putdata (ACK); Kembali Benar; } / *** Dapatkan data** @return data* @throws IoException* Exception* / private byte getData () melempar ioException {return (byte) inputStream.read (); } / *** Kirim Data** @param Data* Data* @Throws IoException* Pengecualian* / Private void putData (int data) melempar ioException {outputStream.write ((byte) data); } / *** Kirim Data** @param Data* Data* @param checksum* checksum* @throws ioException* pengecualian* / private void putchar (byte [] data, checksum pendek) melempar ioException {bytebuffer bb = bytebuffer.alloced (data.length + 2). ByteBuffer BB = BYTEBUFFER.ALLOCOUCE (data.length + 2). BytEbuffer. bb.put (data); bb.putshort (checksum); outputStream.write (bb.array ()); }}Algoritma verifikasi CRC16 menggunakan metode pencarian tabel.
Kelas Publik CRC16 {private static final char crctable [] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b16b16b18b18b18b 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5E, 0xf5cf, 0x8528, 0x9509, 0xe5E, 0xf5cf, 0x8An 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x87d, 0xf7df, 0xe7fe, 0xd7end, 0xcral, 0xc4df, 0xe7fe, 0xd79d, 0xc4d, 0xe7fe yang ” 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x969, 0xa90a, 0xb92b, 0x4ad 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eB6, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81A9, 0xB1CA, 0XA1188, 0X81A9, 0xB1CA, 0XA1188, 0XA1B11 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x933, 0xa3fb, 0xb3da, 0x -0x933, 0xa3fb, 0xb3da, 0xc3da, 0xc3da, 0xb3da, 0xb3da, 0x1 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9., 0xe92f, 0x99c8, 0x89e9., 0x892f, 0x99c8, 0x89., 0x89., 0x99c8, 0x89, 0x89. 0x892F, 0x89, 0X892F, 0X892F, 0X99C8, 0X89, 0X892F, 0X8919 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2Ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x9de8, 0x8dc9, 0x7c26 0x4c45, 0x3Ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; public static char calc (byte [] bytes) {char crc = 0x0000; untuk (byte b: bytes) {crc = (char) ((crc << 8) ^ crctable [((crc >> 8) ^ b) & 0x00ff]); } return (char) (CRC); }}3. Gunakan
// Serialport adalah objek port serial xmodem xmodem = new xmodem (serialport.getInputStream (), serialport.getoutputStream ()); // filepath adalah jalur file // ./bin/xxx.binxmodem.send(filepath);
4. Tulis di akhir
Unduh Kode Lengkap
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.