ASCII'den gelişmiş seri protokollere ne zaman geçilmelidir?


28

Bilgisayarımla UART üzerinden iletişim kurabilen tüm mikrodenetleyici aygıtlarım, komut göndermek ve veri almak için ASCII dizelerini kullanır (Arduino'da uygulandığı gibi). Elektroniği kazmaya başladığımda öğrendiğim şey buydu ve her zaman çıplak dizeler göndermeyi yeterli buldum. Ancak, karşılaştığım çoğu cihazın işlev kodları, adresler ve CRC hata denetimi içeren karmaşık ikili protokoller kullandığını fark ettim.

Temel ASCII iletişimi ne zaman kabul edilebilir ve ne zaman daha gelişmiş bir şeyi düşünmeliyim, Modbus gibi? Ticari cihazlar böyle ASCII kullanıyor mu? Sanayi?


3
Kısa cevap: Uygulamanız gerektiğinde. Evet, ticari cihazlar ASCII kullanır. Örnek olarak GPS NMEA'yı ele alalım. (Ve yine, burada kendi sorumu ele alacağım )
Eugene Sh.

1
Modbus bir ASCII moduna sahiptir. Bkz. Modicon Modbus Protokolü Referans Kılavuzu
Tut

@EugeneSh .: NMEA'nın bir sağlama toplamı alanı olduğuna dikkat çekiyor ve sağlama toplamı başarısızlığından (düşündüğünüzden daha sık gerçekleşen) tek bir numune atımının düşmesi genellikle kritik bir başarısızlık değildir. Bu çok iyi diğer protokoller için geçerli olmayabilir ... ve gerçekten kritik olabileceği uygulamalar için (ya da 1Hz'den daha yüksek bir örnekleme oranının yüksek olduğu) kullanılan birçok ikili GPS protokolü vardır (örneğin Garmin). için gerekli olan NMEA'nın çok ayrıntılı olması. Gerçi bu sadece amacını güçlendirir.
Monica

Yanıtlar:


28
  1. ASCII ve CRC birbirini dışlayan değil. ASCII bir kodlamadır ve CRC hata kontrolü içindir.

  2. Bir şey ASCII olarak gönderilebilir. Biz yaşlılar kesinlikle bir ASCII dizgisine dönüşen UUEncoding'i hatırlıyorlar.

  3. A) Benim için genellikle hız ve verimlilik sorunudur. ASCII tarafından büyük bir 32 bitlik numara göndermek çok uzun zaman alabilir, ancak seri bir protokol aracılığıyla ikilik olarak gönderilmesi sadece 4 bayt alır.

    B) NUMBERS'ı ASCII yoluyla gönderme, sayıyı ASCII'ye dönüştürmeniz gerektiği anlamına gelir; bu, açık bir ekstra adımdır (bu, "printf" nin yaptığı şeyin bir parçasıdır).

  4. Eğer bir şekilde yerinizi kaybederseniz, vidalayın, formatı kaybedersiniz, yanlış endian'ı vb. Alırsanız, bir ikili iletişim protokolü kesinlikle bozulabilir. ASCII gönderiyorsanız, veri akışına yalnızca girerek ve BAKMAK yoluyla vidalamalardan kurtulmak daha kolay olabilir.


12
"ASCII bir kodlamadır" için +1. Bu bir protokol değil; protokoller ASCII üzerine inşa edilebilir.
Pete Becker

8
Bir vidalamadan otomatik olarak kurtarma işlemi, metin tabanlı bir protokol için ikili bir protokol olarak kullanmak için kolay değildir, ancak kesinlikle denetlenir ve hata ayıklanır.
Nick Johnson

1
@NickJohnson - kesinlikle. Neleri kurtarabileceğinizi görmek için bir hex editöründe dosya açma noktasında olduğunuzda, SOP'a kadar zaten FUBAR'dasınız
Scott Seidman

1
@ nickjohnson bu gerçekten doğru değil. ASCII size, kanal tam genişlikli ikili veriler için kullanılıyorsa ek çıkış, bit doldurma, zaman aralığı veya diğer numaralar gerektiren senkronizasyon ve geri kazanıma yardımcı olacak birçok bant dışı çerçeve / sınırlayıcı seçeneği sunar.
Chris Stratton

2
Her zaman bariz faydalar (okunabilirlik, logability, vb.) İçin protokoller yazarken ASCII'yi tercih ederim. İkili sistemin daha anlamlı olduğu iki durum vardır : birincisi, eğer hız bir sorunsa ve akışa mümkün olduğunca çok veri toplamak için ikili, ikincisi ise, kasıtlı olarak gizlice karıştırmaya veya hatta şifrelemeye çalışıyorsanız, ikili olarak ihtiyacınız var. tersine mühendislik engellemek veya önlemek için akış. Bu noktada, tersine mühendislik yapılmış ikili protokollerim var ve bu durum eylemi engellemekten çok daha fazla rahatsız etti.
J ...

10

İşte bu konuda bazı düşünceler:

  • ASCII iyidir, çünkü neyin gönderildiğini manuel olarak görmek için seri monitör kullanabilirsiniz.
  • Bağlantınız güvenilir değilse, iletim hatalarını beklemeli ve alınan her mesajın bütünlüğünü kontrol etmek için bir CRC kullanmalısınız. Bu, ASCII mesajlarında da yapılabilir.
  • bağlantınız çok yavaşsa, ikili bir formata geçerek mesajlarınızın boyutunu azaltabilirsiniz.
  • Özel bir ikili formatın kod çözülmesi alıcı tarafında ASCII'den daha kolay olabilir

7

En basit seviyede, basit bir iletişim protokolünün üç katmana sahip olduğunu söyleyebilirsiniz: fiziksel, nakil ve uygulama. ( OSI gibi 7'li veya TCP / IP'li 4'li modeller vardır . Katman sayısı bu soru bağlamında çok önemli değildir.)

Uygulama katmanı, doğrudan kodunuzda ele aldığınız katman ve sorunun odak noktasıdır. Aktarım katmanı söz konusu olduğunda, send_data'da kendisine ilettiğiniz bayt yalnızca ikili bir desendir, ancak uygulama kodunuzda 'A' harfi olarak yorumlayabilirsiniz. CRC veya sağlama toplamı hesaplaması, baytın 'A,' 0x41 veya 0b01000001 olduğunu düşünmenize bakılmaksızın aynı olacaktır.

Aktarım katmanı, mesaj başlıklarınızın bulunduğu paket seviyedir ve CRC veya temel bir sağlama toplamı olup olmadığına dair hata kontrolüdür. Firmware bağlamında, send_data gibi bir fonksiyona sahip olabilirsiniz, burada onu göndermek için bir bayt geçirirsiniz. Bu işlevin içinde, "Hey bu normal bir mesajdır, bir onay gerektirir ve sağlama toplamı 0x47, şu anki saat X'dir." Bu paket, fiziksel katman üzerinden alıcı düğüme gönderilir.

Fiziksel katman, elektronik ve arayüzün tanımlandığı yerdir: konektörler, voltaj seviyeleri, zamanlama, vb. CAN uygulamaları.

Alıcı düğümde, paket fiziksel katmana gelir, taşıma katmanında açılır ve ardından ikili kalıbınız uygulama katmanına kullanılabilir. Bu desenin 'A,' 0x41 veya 0b01000001 olarak yorumlanması gerekip gerekmediğini ve bununla ne yapılması gerektiğini bilmek alıcı düğüm uygulama katmanına bağlıdır.

Sonuç olarak, uygulamanın istediği şey buysa, ASCII karakterlerini göndermek her zaman kabul edilebilir. Önemli olan, iletişim planınızı anlamak ve bir hata kontrol mekanizması içermektir.


Ascii protokolleri aynı zamanda sağlama toplamı içerebilir. Ascii sayıların gösterimini kullanarak Hex-ascii as varyasyonları ile karşılaştım.
Eugene Sh.

@EugeneSh. Bu noktaya açıklık getirdi
Matt Young 15

Nitpick değil, ama TCP dört katman değildir; OSI modelinin dördüncü katmanına sığdığı görülmektedir. Seri haberleşme OSI modeline pek uymuyor.
batsplatsterson

@batsplatsterson Bu nitpicking ve yaptığım noktaya oldukça ilgisiz.
Matt Young

5

Henüz belirtilmeyen bir nokta, birinin ASCII veya ikili protokol kullanıp kullanmadığı, her paketten önce bir ovalama karakteri gönderilmesi, bir satırın başlangıcından önce satır gürültüsü veya çerçeveleme hataları görünse bile, paketten sonraki tüm karakterlerin elde edilmesini sağlayacaktır. Daha fazla gürültü olmadığında, doğru şekilde çerçevelenir. Aksi halde, biri sürekli olarak paketler gönderirse ve yeniden senkronizasyonu sağlama garantisi verilen herhangi bir karakter içermiyorsa, bir aksaklık aktarımdaki bir sonraki duraklamaya kadar takip eden her şeyi bozabilir. 0xFF karakteri güzeldir, çünkü herhangi bir alıcının aşağıdaki karakterde senkronizasyon yapabileceğini garanti eder.

(*) 0xFF - bir kağıt kaset üzerine veri yazarken hatalı bir karakter yazan bir kişi "bantı geriye doğru bastır" düğmesine basabilir ve hatalı bir şekilde delinmiş karakteri 0xFF ile değiştirir; çoğu alıcı tarafından dikkate alınma).


2

ASCII dizgilerini göndermenin bir avantajı, kontrol kodlarının daha sonra mesajın başlangıcını / bitişini işaret etmek için kullanılabiliyor olmasıdır. örneğin STX (karakter 2) ve ETX (karakter 3), başlatma iletimini ve iletim iletimini işaret edebilir. Alternatif olarak, iletimin sonunu işaretlemek için basit bir satır besleme ekleyebilirsiniz.

İkili veri gönderilirken, bu daha karmaşık bir hal alır, çünkü geçerli bir veri baytı aynı düzende olabileceğinden, bir kontrol kodu için (bazı ek yükler veya karmaşıklık olmadan) belirli bir bit deseni ayrılmaz.


3
Birçok ikili protokol DO ya da daha fazla bit desenini kontrol kodları olarak saklar, fakat aynı zamanda verilerde göründüklerinde bu kodları işlemek için bir kaçış mekanizması içerirler.
Dave Tweed

İstediğiniz herhangi bir şeyi ikili olarak işaretlemek için herhangi bir deseni rezerve edebilirsiniz. Örneğin, hızlı bir veri akışı ve aynı uarttan çıkan yavaş bir veri akışı olan bir projeyim. En büyük negatif int32'yi yavaş verilerimin bayrağı olarak ayırdım ve negatif verilerimi en büyük negatif + 1 ile
doyurdum

Kabul. Düzenlenmiş cevabında bunu açıklığa kavuşturdum, umarım.
Transistör

2

ASCII gayet iyi, hemen hemen bütün projelerde kullanıyorum. Bağlantı noktasını izlemek için hata ayıklamayı çok daha kolaylaştırır ve yalnızca gönderilecek çok veri varsa sorun olur.

Başka bir bonus, arduinolar arasında mesajlar almak için seri radyo cihazları kullanıyorum ve dizüstü bilgisayarıma bağlı seri monitörü kullanabilirim ve bazı şeyleri gerçekleştirmek için mesajlar enjekte edebilirim. Test için harika.

Ayrıca, şeyleri ikili olarak göndermek hata ayıklamak imkansız değildir ve araçlarınıza bağlı olarak, ikili dosyayı çıkarıp insan tarafından okunabilir bir şeye dönüştürmesini sağlayabilirsiniz. Veya ne aradığınızı biliyorsanız, veri akışını görsel olarak inceleyebilir ve nerede olmaları gerektiğinin farkına varabilirsiniz ve hata bu kadar kolay olmasa da bu şekilde bulur. yani, bayt kalıplarını tanıyacak ve beklenen değerleri tanıyacaksınız


2

Bunun yerine Modbus'un düşünün HDLC . Hata algılama (gürültülü seri hatlarda önemli olan) alırsınız. Senkronizasyon sağlam, kaçmak sağlam.

HDLC'yi RS-485 ağlarında problemsiz kullandım ve PPP de kullandı.


2
Neden Modbus'a önerdiğini söylesen iyi olur.
ne yaptığım hakkında hiçbir fikrim yok.

1

UART üzerindeki ASCII kısmen en popüler çünkü:

  • Hata ayıklama sırasında okunabilir bir insandır (ASCII'yi çözmeyen bir mantık analizörü görmedim).

  • Uygulaması çok kolay, hızlı bir şekilde google üzerinden iyi standartlaştırılmış bir ASCII masanız var.

  • Başlat / durdur bitleriyle senkronize olarak oluşturulmuştur.

  • Neredeyse tüm hobist dünyası ASCII'yi seri üzerinden kurdu, bu yüzden herhangi bir yeni yöntem bununla baş etmek zorunda kalacak ve bu hiçbir şekilde kolay değil.

Bir şamandıranın ASCII'ye dönüştürülmesine kıyasla bir şamandıranın bellekteki gösterimini gönderme, özel bir kodlamayı ASCII'ye dönüştürmeye kıyasla, 4 bayttan çok daha fazla olabilen seri üzerinden gönderme ve daha sonra geri dönüştürme gibi bir duruma girersiniz. ana bilgisayardaki bir hafıza içi temsiline. Bunun yerine, her defasında 4 baytlık gösterimi gönderirsiniz. Elbette, kodlamayı kendiniz yapmaya başlayabilirsiniz ancak başlangıç ​​/ bitiş etiketlerini, sırasını vb. Ayarlamanız gerekir.

Bunun yerine Protobuf gibi şeyler kullanılabilir. Bu aslında üzerinde çalıştığım bir projede kullanıldı ve son derece faydalıydı, değişken uzunluklu mesajlar veriyor, sizin için endian'ı kullanıyor ve birkaç harika özellik daha var. Ayrıca kod boyutunda büyük değildir ve başlangıçta statik olarak atanacak her şeyi belirleyebilirsiniz. Gerektiğinde, kendin sağlama toplamı atmak zorunda kalacaksın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.