UART etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
UART etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

12 Ağustos 2026 Çarşamba

MODBUS'a Hızlı Bir Giriş

Bir enerji analizörünün kılavuzunu açıyorsunuz, karşınıza "Fonksiyon kodu: 03" yazan bir tablo çıkıyor. Yandaki inverterin kılavuzunda ise "Sadece 04 destekler" yazıyor. Peki bu numaralar da ne? 🤔 Bu yazıda MODBUS'un tüm fonksiyon kodlarını tek tek, örnek çerçeveleriyle ve sahada başınıza gelebilecek tuzaklarıyla birlikte ele alıyoruz.

MODBUS RTU çerçeve yapısını gösteren teknik illüstrasyon: adres, fonksiyon kodu, veri ve CRC baytları; fonksiyon kodu alanı vurgulanmış, altında RS-485 hattına bağlı PLC ve saha cihazları.


MODBUS'a hızlı bir giriş 🔌

MODBUS, 1979 yılında Modicon tarafından PLC'ler için tasarlanmış bir haberleşme protokolü. Yani sizden, benden, muhtemelen bu yazıyı okuyan çoğu mühendisten daha yaşlı. Buna rağmen hâlâ her yerde: enerji analizörlerinde, ısı kontrolörlerinde, inverterlerde, debimetrelerde, güneş invertörlerinde, jeneratör kontrol kartlarında...

Bu kadar uzun yaşamasının sebebi çok basit: protokol gerçekten sade ve açık. Telif ücreti yok, lisans yok, karmaşık bir yığın yok. Bir tarafta soru soran (client / master), diğer tarafta cevap veren (server / slave) var. Master sorar, slave cevaplar. Slave asla kendiliğinden konuşmaz — bu detay ilerideki birçok tasarım kararını açıklıyor.

Üç yaygın taşıma katmanı var:

  • MODBUS RTU — Seri hat üzerinden (genelde RS-485), veriler ikili (binary) formatta. En yaygın kullanım.
  • MODBUS ASCII — Yine seri hat, ama veriler okunabilir ASCII karakterler olarak. Bugün nadir.
  • MODBUS TCP — Ethernet üzerinden, 502 numaralı port. (TLS'li güvenli sürümü ise 802 portunu kullanır.)

Taşıma katmanı değişse de fonksiyon kodları aynı kalır. Yani bu yazıda öğrendikleriniz hem RS-485 hattındaki bir sayaçta hem de Ethernet'teki bir gateway'de geçerli olacak. 👌

Fonksiyon kodu tam olarak nedir?

Fonksiyon kodu, mesajın içindeki tek bir bayttır ve "ne yapmak istiyorum?" sorusunun cevabıdır. Okumak mı istiyorum, yazmak mı? Bit mi okuyacağım, register mı? Cihazın kimliğini mi soracağım?

Bir MODBUS RTU çerçevesinin anatomisi şöyle görünür:

┌──────────┬──────────┬─────────────────────┬──────────┐
│ Adres    │ Fonksiyon│ Veri                │ CRC      │
│ 1 bayt   │ 1 bayt   │ 0 – 252 bayt        │ 2 bayt   │
└──────────┴──────────┴─────────────────────┴──────────┘
     ▲          ▲               ▲                 ▲
     │          │               │                 └─ Hata kontrolü
     │          │               └─ Adres, adet, değerler...
     │          └─ NE yapılacak  (bizim konumuz!)
     └─ KİM yapacak (1–247, 0 = broadcast)

Gerçek örnek:   11 03 00 6B 00 03 76 87
                ▲  ▲  └───┘ └───┘ └───┘
                │  │    │     │     └─ CRC
                │  │    │     └─ 3 adet register oku
                │  │    └─ Başlangıç adresi 0x006B (107)
                │  └─ Fonksiyon 0x03 = Read Holding Registers
                └─ 17 numaralı cihaza soruyorum

MODBUS TCP'de ise adres ve CRC yerine 7 baytlık bir MBAP başlığı gelir; ortadaki "fonksiyon + veri" kısmı (buna PDU deniyor) bire bir aynı kalır:

MODBUS TCP:  00 01 00 00 00 06 11 03 00 6B 00 03
             └─────── MBAP (7 bayt) ──────┘└─ PDU ─┘
             │     │     │     │
             │     │     │     └─ Unit ID (11)
             │     │     └─ Uzunluk
             │     └─ Protokol ID (her zaman 0000)
             └─ İşlem (transaction) ID — cevabı eşleştirmek için

💡 Aklınızda kalsın: RTU'da 0x11 ilk bayttaysa "17 numaralı cihaz", ikinci bayttaysa "Report Server ID fonksiyonu" demektir. Aynı hex değeri, konuma göre bambaşka anlam taşır. Çerçeve okurken en sık yapılan karışıklıklardan biri budur.

Fonksiyonlardan önce: dört tip veri

Fonksiyon kodlarının neden bu kadar çok olduğunu anlamak için önce MODBUS'un veri modelini bilmek gerekiyor. Protokol her şeyi dört kutuya ayırır:

Veri tipiBoyutErişimKlasik adresTipik örnek
Coil (Bobin)1 bitOku / Yaz0xxxxRöle çıkışı, start/stop komutu
Discrete Input (Ayrık giriş)1 bitSalt okunur1xxxxLimit switch, kapı sensörü
Input Register (Giriş register'ı)16 bitSalt okunur3xxxxÖlçülen sıcaklık, akım değeri
Holding Register (Tutma register'ı)16 bitOku / Yaz4xxxxSet değeri, PID parametresi, frekans referansı

Mantık şu: bir şey bit mi yoksa sayı mı, ve onu yazabiliyor musunuz yoksa sadece okuyabiliyor musunuz? Bu iki soru 2 × 2 = 4 kutu yapıyor ve fonksiyon kodlarının büyük kısmı bu kutulara okuma/yazma yapmaktan ibaret. 😊

📋 Tam MODBUS Fonksiyon Listesi

İşte MODBUS Application Protocol Specification V1.1b3'te tanımlı tüm public (standart) fonksiyon kodları. Toplamda 19 tane; standartta bunların dışında tanımlı bir fonksiyon yok.

HexDecİsimNe yapar?Not
0x011Read CoilsYazılabilir bitleri okurYaygın
0x022Read Discrete InputsSalt okunur bitleri okurYaygın
0x033Read Holding RegistersYazılabilir register'ları okurYaygın
0x044Read Input RegistersSalt okunur register'ları okurYaygın
0x055Write Single CoilTek bir biti 1 veya 0 yaparYaygın
0x066Write Single RegisterTek bir register'a değer yazarYaygın
0x077Read Exception Status8 bitlik özel durum baytını okurSeri hat
0x088DiagnosticsAlt fonksiyonlarla hat tanılaması yaparSeri hat
0x0B11Get Comm Event CounterHaberleşme olay sayacını okurSeri hat
0x0C12Get Comm Event LogOlay günlüğünü okurSeri hat
0x0F15Write Multiple CoilsBirden çok biti tek seferde yazarYaygın
0x1016Write Multiple RegistersBirden çok register'ı tek seferde yazarYaygın
0x1117Report Server IDCihazın kimliğini ve çalışma durumunu sorarSeri hat
0x1420Read File RecordDosya kaydı okurNadir
0x1521Write File RecordDosya kaydı yazarNadir
0x1622Mask Write RegisterMaske ile tek bit düzeyinde yazarNadir
0x1723Read/Write Multiple RegistersTek işlemde hem okur hem yazarNadir
0x1824Read FIFO QueueFIFO kuyruğundaki verileri okurNadir
0x2B43Encapsulated Interface TransportMEI kapsülleme (cihaz kimliği, CANopen)Nadir

Gerçek hayat notu 🔧 Bu 19 fonksiyondan sahada karşılaşacağınızın %95'i şu sekiz tanedir: 01, 02, 03, 04, 05, 06, 0F, 10. Geri kalanı çoğu ticari cihazda desteklenmez; sorduğunuzda size nazikçe "Illegal Function" hatası döner.

Bit tabanlı fonksiyonlar: 01, 02, 05, 0F

0x01 — Read Coils (Bobinleri Oku)

Yazılabilir bitleri okur. Cevapta bitler paketlenmiş gelir: her bayt 8 bit taşır ve en düşük anlamlı bit (LSB) ilk coil'e denk gelir. Bu ters sıralama ilk defa gören herkesi şaşırtır. 😅

İstek:  11 01 00 13 00 25 0E 84
        └ 17 nolu cihaz, 19. adresten başla, 37 coil oku

Cevap:  11 01 05 CD 6B B2 0E 1B 45 E6
              └ 5 bayt veri geliyor

İlk bayt CD = 1100 1101 (binary)
                       ▲
                       └ Bu bit ilk coil (adres 19)

Sıra:  coil19=1, 20=0, 21=1, 22=1, 23=0, 24=0, 25=1, 26=1

0x02 — Read Discrete Inputs (Ayrık Girişleri Oku)

0x01 ile bire bir aynı mantık, tek farkı salt okunur bitlere erişmesi. Bir sensörün durumunu okuyorsanız muhtemelen bu fonksiyonu kullanıyorsunuzdur.

İstek:  11 02 00 C4 00 16 BA A9
        └ 196. adresten başla, 22 giriş oku

Cevap:  11 02 03 AC DB 35 20 18

0x05 — Write Single Coil (Tek Bobin Yaz)

Burada sevimli bir tuhaflık var: değer alanı 1 bit değil, 2 bayt. Ve sadece iki geçerli değer kabul eder — 0xFF00 = AÇ, 0x0000 = KAPAT. Neden 0x0001 değil? 1979'dan kalma bir tasarım tercihi diyelim. 🙂

İstek:  11 05 00 AC FF 00 4E 8B
        └ 172. coil'i AÇ

Cevap:  isteğin aynısı geri döner (echo)

0x0F — Write Multiple Coils (Çoklu Bobin Yaz)

Tek seferde 1968 coil'e kadar yazabilirsiniz. Veri yine paketlenmiş bit halinde gider. Cevap ise sadece "şu adresten şu kadarını yazdım" özetidir — verinin tamamını geri döndürmez.

İstek:  11 0F 00 13 00 0A 02 CD 01 BF 0B
        └ 19. adresten başla, 10 coil yaz, 2 bayt veri: CD 01

Cevap:  11 0F 00 13 00 0A 26 99

Register fonksiyonları: 03, 04, 06, 10, 16, 17, 18

0x03 — Read Holding Registers (Tutma Register'larını Oku)

Bu, MODBUS dünyasının en çok kullanılan fonksiyonu. 🏆 Bir enerji analizöründen gerilim okumak, bir inverterden çalışma frekansını almak, bir kontrolörden set değerini öğrenmek — hepsi bu fonksiyonla.

İstek:  11 03 00 6B 00 03 76 87
        └ 107. adresten başla, 3 register oku

Cevap:  11 03 06 02 2B 00 00 00 64 C8 BA
              │  └─┬─┘ └─┬─┘ └─┬─┘
              │    │     │     └─ Register 109 = 0x0064 = 100
              │    │     └─ Register 108 = 0x0000 = 0
              │    └─ Register 107 = 0x022B = 555
              └─ 6 bayt (3 register × 2 bayt)

0x04 — Read Input Registers (Giriş Register'larını Oku)

0x03 ile teknik olarak neredeyse aynı; fark, salt okunur register'lara erişmesi. Bazı üreticiler ölçüm değerlerini 0x04'e, ayarları 0x03'e koyar. Bazıları ise her şeyi 0x03'e yığar ve 0x04'ü hiç desteklemez. Kılavuz okumaktan kaçış yok. 📖

0x06 — Write Single Register (Tek Register Yaz)

Tek bir 16 bit değeri yazar. Basit, hızlı, cevabı isteğin kopyasıdır.

İstek:  11 06 00 01 00 03 9A 9B
        └ 1. register'a 3 değerini yaz

Cevap:  11 06 00 01 00 03 9A 9B  (echo)

0x10 — Write Multiple Registers (Çoklu Register Yaz)

Tek seferde 123 register'a kadar yazar. 32 bitlik bir değeri (float, uzun tamsayı) yazacaksanız bu fonksiyonu kullanmanız zorunlu sayılır — çünkü iki register'ı 0x06 ile ayrı ayrı yazarsanız cihaz arada yarım değeri işleme alabilir.

İstek:  11 10 00 01 00 02 04 00 0A 01 02 C6 F0
        │        │     │     │  └───┬───┘
        │        │     │     │      └─ Veri: 0x000A ve 0x0102
        │        │     │     └─ 4 bayt veri
        │        │     └─ 2 register yazılacak
        │        └─ 1. adresten başla
        └ Fonksiyon 0x10

Cevap:  11 10 00 01 00 02 12 98

0x16 — Mask Write Register (Maskeli Register Yazma)

Bir register'ın tamamını değil, sadece belirli bitlerini değiştirmek istediğinizde işe yarar. Klasik "oku–değiştir–yaz" döngüsünü tek işleme indirger, böylece arada başka biri araya girip register'ı bozamaz.

Formül:  Sonuç = (Mevcut AND And_Mask) OR (Or_Mask AND (NOT And_Mask))

İstek:  11 16 00 04 00 F2 00 25 66 E2
        │        │     │     └─ Or_Mask  = 0x0025
        │        │     └─ And_Mask = 0x00F2
        │        └─ Register adresi 4
        └ Fonksiyon 0x16

0x17 — Read/Write Multiple Registers (Oku ve Yaz)

Tek mesajda önce yazma, sonra okuma yapar. Hat trafiğini yarıya indirdiği için hızlı döngü gerektiren uygulamalarda değerlidir. Ancak destekleyen cihaz sayısı sınırlıdır.

İstek:  11 17 00 03 00 06 00 0E 00 03 06 00 FF 00 FF 00 FF 4B 54
        │     └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ │  └──────┬──────┘
        │     Oku adres  Oku adet Yaz adres Yaz adet Bayt  Yazılacak veri
        └ Fonksiyon 0x17

0x18 — Read FIFO Queue (FIFO Kuyruğunu Oku)

Cihazın içindeki sıra tipi bir tampondan (kuyruk) veri çeker. En fazla 31 register döndürebilir. Alarm geçmişi ya da olay kuyruğu tutan özel cihazlarda karşınıza çıkabilir; genel amaçlı cihazlarda neredeyse hiç yok.

Tanılama ve cihaz bilgisi: 07, 08, 0B, 0C, 11, 2B

Bu grup "veri okuma" değil, "cihazla ilgili bilgi alma" işi görür. Büyük kısmı yalnızca seri hat (RTU/ASCII) için tanımlıdır ve MODBUS TCP'de standart değildir.

0x07 — Read Exception Status

Cihazın 8 bitlik özel durum baytını okur. Bu 8 bitin ne anlama geldiği tamamen üreticiye bağlıdır — biri "aşırı sıcaklık" der, diğeri "kalibrasyon gerekli" der. Çok kısa bir mesaj olduğu için hızlı durum sorgulamada tercih edilirdi.

0x08 — Diagnostics

Aslında tek bir fonksiyon değil, bir avuç alt fonksiyonun şemsiyesi. Fonksiyon kodundan hemen sonra 2 baytlık bir alt fonksiyon numarası gelir:

Alt fonk.Decİşlev
0x000Return Query Data — gönderdiğinizi aynen geri yollar (echo testi)
0x011Restart Communications Option — haberleşme portunu yeniden başlatır
0x022Return Diagnostic Register — tanılama register'ını döndürür
0x033Change ASCII Input Delimiter — ASCII ayırıcı karakteri değiştirir
0x044Force Listen Only Mode — cihazı sadece dinleme moduna alır
0x0A10Clear Counters and Diagnostic Register — sayaçları sıfırlar
0x0B11Return Bus Message Count — hattaki toplam mesaj sayısı
0x0C12Return Bus Communication Error Count — CRC hatası sayısı
0x0D13Return Bus Exception Error Count — exception cevap sayısı
0x0E14Return Server Message Count — cihaza gelen mesaj sayısı
0x0F15Return Server No Response Count — cevapsız kalan mesaj sayısı
0x1016Return Server NAK Count
0x1117Return Server Busy Count
0x1218Return Bus Character Overrun Count — taşma hatası sayısı
0x1420Clear Overrun Counter and Flag

Özellikle 0x0C (CRC hata sayacı) çok değerlidir: RS-485 hattınızda gürültü olup olmadığını anlamanın en dolaysız yoludur. Sayaç sürekli artıyorsa kablolamaya, sonlandırma direncine ve topraklamaya bakma vaktidir. ⚡

0x0B ve 0x0C — Comm Event Counter / Event Log

Cihazın kaç başarılı işlem yaptığını ve son olayların günlüğünü verir. Event log en fazla 64 olay taşır. Bugün pek kullanılmıyor, ama eski Modicon sistemlerinde hat sağlığını izlemenin standart yoluydu.

0x11 — Report Server ID

"Sen kimsin?" sorusunun MODBUS'çası. Cevap şu alanları içerir:

AlanAçıklama
Byte CountTakip eden veri uzunluğu
Server IDÜreticiye özel cihaz kimliği (standart değil!)
Run Indicator0x00 = durmuş, 0xFF = çalışıyor
Ek veriFirmware sürümü, model adı vb. — tamamen üreticinin keyfine kalmış
İstek:  11 11 CD EC     ← veri alanı boş, sadece soruyoruz

0x2B — Encapsulated Interface Transport (MEI)

Bu fonksiyon bir "zarf" gibi çalışır: içine başka bir protokolün mesajını koyar. İki alt tipi var:

  • 0x0D — CANopen General Reference
  • 0x0ERead Device Identification (asıl işe yarayan)

0x2B/0x0E, cihazdan yapılandırılmış metin bilgileri çeker. 0x11'in aksine bu alanlar standarttır:

Nesne IDİsimSeviye
0x00VendorName — üretici adıBasic (zorunlu)
0x01ProductCode — ürün koduBasic (zorunlu)
0x02MajorMinorRevision — sürümBasic (zorunlu)
0x03VendorUrl — üretici web adresiRegular
0x04ProductName — ürün adıRegular
0x05ModelName — model adıRegular
0x06UserApplicationName — uygulama adıRegular
0x80–0xFFÜreticiye özel alanlarExtended

Dosya kaydı fonksiyonları: 14 ve 15

MODBUS'un en az bilinen köşesi. 0x14 (Read File Record) ve 0x15 (Write File Record), cihazın içindeki "dosya" benzeri yapılara erişir. Burada dosya, 16 bitlik kayıtlardan oluşan bir bloktur; klasik adreslemede 6xxxxx aralığına denk gelir.

  • Dosya numarası: 0x0001 – 0xFFFF
  • Kayıt numarası: 0 – 9999
  • Tek mesajda birden fazla alt-istek gönderilebilir

Pratikte veri kaydediciler (data logger), trend kaydı tutan cihazlar ve bazı akış bilgisayarları kullanır. Standart bir sensörde göremezsiniz.

İşler ters gittiğinde: Exception kodları ⚠️

Cihaz isteğinizi yerine getiremezse sessiz kalmaz — size bir hata cevabı döner. Bunu anlamanın yolu çok zarif: cevaptaki fonksiyon koduna 0x80 eklenir.

İstek:   11 03 00 6B 00 03 76 87    ← 0x03 ile okuma denemesi
Hata:    11 83 02 C1 34             ← 0x03 + 0x80 = 0x83
            │  └─ Exception kodu 02 = Illegal Data Address
            └─ "Bu bir hata cevabı" işareti
KodİsimTürkçesi ve tipik sebebi
0x01Illegal FunctionCihaz bu fonksiyonu desteklemiyor. 0x04 sorup 0x03 kullanmanız gerekiyor olabilir.
0x02Illegal Data AddressAdres cihazda yok. En sık sebep: 40001 / 0 kaymasını yanlış hesaplamak.
0x03Illegal Data ValueDeğer veya adet geçersiz. Örneğin 200 register birden okumaya çalışmak.
0x04Server Device FailureCihazın içinde bir arıza oluştu.
0x05Acknowledge"İsteğini aldım ama uzun sürecek, bekle." Sonucu 0x0B ile sorabilirsiniz.
0x06Server Device BusyCihaz meşgul, biraz sonra tekrar deneyin.
0x08Memory Parity ErrorDosya kaydı okurken hafıza parite hatası (sadece 0x14 / 0x15).
0x0AGateway Path UnavailableGateway hedefe giden yolu bulamadı — genelde gateway ayarı yanlış.
0x0BGateway Target Device Failed to RespondGateway'in arkasındaki cihaz cevap vermiyor — kablo, adres veya baud hatası.

🚨 En çok zaman kaybettiren ikili: 0x02 ve 0x0B. İlkinde adres haritasını, ikincisinde fiziksel bağlantıyı kontrol edin. Exception alıyor olmanız aslında iyi haberdir — demek ki hat çalışıyor, cihaz sizi duyuyor ve cevap veriyor. Hiç cevap alamamak çok daha kötüdür.

Kod aralıkları: public, user-defined ve reserved

Fonksiyon kodu bir bayt olduğuna göre teorik olarak 255 farklı değer alabilir. Standart bu alanı şöyle paylaştırmış:

Aralık (Dec)SınıfAnlamı
1 – 64PublicStandartta tanımlı; boş kalanlar Modbus Organization rezervinde
65 – 72User-definedÜretici istediği fonksiyonu koyabilir
73 – 99PublicStandart alan
100 – 110User-definedÜretici serbest alanı
111 – 127PublicStandart alan
128 – 255ExceptionHata cevaplarına ayrılmış; burada asla yeni fonksiyon tanımlanmaz

Bir de reserved kodlar var: 9, 10, 13, 14, 41, 42, 90, 91, 125, 126, 127. Bunlar eski Modicon ürünlerinde kullanılmış, public sayılmıyor ve yeni tasarımlarda kullanılmaması isteniyor. Yani "boş görünüyor, ben buraya kendi fonksiyonumu koyayım" demeyin — geriye dönük uyumluluk sorunları çıkarır. 🙃

Limitler ve seri hat / TCP farkı

Her fonksiyonun tek mesajda taşıyabileceği veri miktarı sınırlı, çünkü bir MODBUS PDU'su en fazla 253 bayt olabiliyor. Bu limitler ezberlenmeye değer:

FonksiyonMaksimum adet
0x01 Read Coils2000 bit
0x02 Read Discrete Inputs2000 bit
0x03 Read Holding Registers125 register
0x04 Read Input Registers125 register
0x0F Write Multiple Coils1968 bit
0x10 Write Multiple Registers123 register
0x17 Read/Write Multiple125 okuma / 121 yazma
0x18 Read FIFO Queue31 register

Çerçeve boyutları da şöyle: RTU'da toplam 256 bayt (adres + PDU + CRC), TCP'de 260 bayt (7 baytlık MBAP + PDU).

Taşıma katmanı farkına gelirsek — 0x07, 0x08, 0x0B, 0x0C ve 0x11 fonksiyonları seri hat için tanımlanmıştır. MODBUS TCP'de bunları sormak genelde boşuna; bazı gateway'ler kabul eder, çoğu "Illegal Function" der.

Sahadan pratik ipuçları 🛠️

1. 40001 tuzağı

Kılavuzda "40001: Gerilim" yazıyorsa, protokol seviyesinde okumanız gereken adres 0'dır. Klasik gösterimde numaralandırma 1'den, protokolde 0'dan başlar. 40108 → adres 107. Bu tek satırlık bilgi, MODBUS'ta yaşanan hataların herhalde üçte birini önler. 😄

Kılavuzdaki gösterim  →  Protokol adresi
40001                 →  0x0000  (fonksiyon 0x03)
40108                 →  0x006B  (fonksiyon 0x03)
30001                 →  0x0000  (fonksiyon 0x04)
10001                 →  0x0000  (fonksiyon 0x02)
00001                 →  0x0000  (fonksiyon 0x01)

2. Bayt ve kelime sırası (endianness)

MODBUS register içindeki 2 baytı big-endian gönderir; bu standarttır. Ama 32 bitlik bir değer iki register'a yayıldığında hangi register önce gelir sorusunun cevabı standartta yoktur. Üretici A "yüksek kelime önce" der, üretici B tersini yapar. Bu yüzden float okurken saçma sayılar görüyorsanız, önce kelime sırasını (word swap) deneyin.

3. RS-485 sessizlik kuralı

RTU'da çerçevelerin nerede başlayıp bittiği, aradaki sessizlik süresiyle belirlenir: en az 3,5 karakterlik boşluk. 19200 baud üstünde ise sabit değerler kullanılır (t3.5 ≈ 1,75 ms). Yazılımınız çerçeveleri karıştırıyorsa, çoğu zaman suçlu bu zamanlamadır.

4. Broadcast'e cevap beklemeyin

Adres 0'a gönderilen mesaj tüm cihazlara gider ve hiçbiri cevap vermez. Sadece yazma fonksiyonlarıyla anlamlıdır; broadcast ile okuma yapamazsınız.

5. Az sorgu, çok veri

Ardışık 20 register'ı 20 ayrı istekle okumak yerine tek istekle okuyun. Her istek, hat üzerinde gidiş-dönüş gecikmesi demektir; RS-485'te bu gecikme veriden çok daha pahalıdır. Haritanızı ardışık okunabilecek şekilde planlamak performansı katbekat artırır. 🚀

6. Timeout'u baud hızına göre ayarlayın

9600 baud'da 125 register okumak, sadece veri iletimi için ~270 ms sürer. Varsayılan 100 ms'lik timeout ile çalışıyorsanız cihaz suçsuzdur, ayarınız yanlıştır.

Sık sorulan sorular ❓

0x03 mü kullanmalıyım, 0x04 mü?

Cihazın kılavuzu ne diyorsa o. Adres 40xxx ile gösterilmişse 0x03, 30xxx ile gösterilmişse 0x04. Emin değilseniz ikisini de deneyin — yanlış olan size "Illegal Function" ya da "Illegal Data Address" döner, zararı olmaz.

MODBUS TCP'de slave adresi (Unit ID) ne olmalı?

Doğrudan bir Ethernet cihazına bağlanıyorsanız genelde 1 veya 255 (bazı cihazlar 0 da kabul eder). Ama bir gateway'in arkasındaki seri cihaza ulaşıyorsanız, Unit ID o cihazın gerçek RS-485 adresidir ve kritiktir.

Neden hiç cevap alamıyorum?

Sırasıyla kontrol edin: baud hızı, parite, stop bit, slave adresi, A/B hatlarının ters bağlanmış olması, hat sonu 120 Ω sonlandırma direnci, ortak toprak. Exception almak bile bunlardan iyidir — demek ki hat sağlam.

Fonksiyon listesinde olmayan bir kod gördüm, ne yapmalıyım?

Önce 65–72 veya 100–110 aralığında mı bakın; öyleyse üreticiye özel bir fonksiyondur, cevabı sadece kılavuzda bulunur. 128'in üstündeyse bu bir fonksiyon değil, hata cevabıdır: 0x80 çıkarın, hangi isteğe cevap geldiğini görürsünüz.

Modbus güvenli mi?

Tek kelimeyle: hayır. Protokolde kimlik doğrulama, şifreleme, yetkilendirme yok. Hatta bağlanabilen herkes yazma yapabilir. Bu yüzden MODBUS ağlarını mutlaka izole edin. TLS tabanlı Modbus Security sürümü (port 802) bu boşluğu kapatmak için tanımlandı, ama saha yaygınlığı hâlâ düşük.


🔖 Terimler Sözlüğü

TerimAçıklama
ADUApplication Data Unit — adres, PDU ve hata kontrolünü içeren tam çerçeve.
PDUProtocol Data Unit — fonksiyon kodu ve verisinden oluşan, taşıma katmanından bağımsız çekirdek kısım.
MBAPMODBUS Application Protocol Header — MODBUS TCP'de mesajın başına eklenen 7 baytlık başlık.
Master / ClientSoruyu soran taraf. Haberleşmeyi her zaman o başlatır.
Slave / ServerCevap veren taraf. Kendiliğinden asla konuşmaz.
CoilOkunup yazılabilen 1 bitlik veri. Genelde bir röle veya komut bitidir.
Discrete InputSadece okunabilen 1 bitlik veri. Genelde bir sensör durumudur.
Holding RegisterOkunup yazılabilen 16 bitlik değer. Ayarlar ve set değerleri burada durur.
Input RegisterSadece okunabilen 16 bitlik değer. Ölçüm sonuçları burada durur.
CRCCyclic Redundancy Check — RTU'da mesajın bozulup bozulmadığını kontrol eden 2 baytlık kod.
ExceptionCihazın "yapamıyorum" cevabı. Fonksiyon koduna 0x80 eklenerek gönderilir.
Broadcast0 adresine gönderilen, tüm cihazların dinlediği ve hiçbirinin cevaplamadığı mesaj.
MEIModbus Encapsulated Interface — 0x2B fonksiyonuyla başka protokol mesajlarını taşıma yöntemi.
Big-endianÇok baytlı sayılarda en anlamlı baytın önce gönderilmesi. MODBUS register'ları böyle çalışır.
RS-485MODBUS RTU'nun en yaygın kullanıldığı, iki telli ve çok noktalı seri haberleşme standardı.

📌 Ekstra Kaynaklar

  • Modbus Organization — Resmî Spesifikasyonlar · Tüm standart dokümanların (uygulama protokolü, seri hat, TCP/IP, Modbus Security) tek adresten indirilebildiği kaynak. Herhangi bir tartışmada son sözü bu sayfa söyler.
  • MODBUS Application Protocol Specification V1.1b3 (PDF) · Bu yazının temel aldığı 50 sayfalık ana doküman. Her fonksiyon kodunun tam gövde yapısı, durum diyagramları ve örnek çerçeveleri burada.
  • Simply Modbus · Fonksiyon kodlarını bayt bayt, örnekli anlatan klasik referans site. Bir çerçeveyi elle çözümlerken açık tutulacak sekme.
  • Wikipedia — Modbus · Protokolün tarihçesi, varyantları ve güvenlik konularına dair derli toplu bir genel bakış.
  • libmodbus · Açık kaynak C kütüphanesi. Fonksiyonların gerçekte nasıl kodlandığını merak ediyorsanız, kaynak koda bakmak spesifikasyonu okumaktan daha öğretici olabilir.

Son söz: MODBUS'un 19 public fonksiyonu var, ama günlük hayatınızda sekiz tanesi işinizi görecek. Geri kalanları bilmenin faydası şu: bir gün karşınıza 0x2B ya da 0x16 çıktığında panik yapmak yerine "aa, bu cihaz kimliği soruyor" diyebileceksiniz. 😊

Siz sahada en çok hangi fonksiyonu kullanıyorsunuz? Ya da hangi cihaz size en tuhaf exception'ı döndürdü? Yorumlarda paylaşın. 👇

8 Nisan 2025 Salı

STM32CubeIDE’de Canlı Değişken Takibi: Debug Sürecini Güçlendiren İpucu

STM32CubeIDE, STM32 mikrodenetleyici projelerinde hem geliştirme hem de hata ayıklama süreçlerini kolaylaştıran güçlü bir araç. Ancak çoğu kullanıcı, debug sürecini sadece breakpoint koyup değişkenleri tek tek kontrol ederek geçiriyor. Oysa ki “Live Expressions” (canlı ifadeler) özelliği ile, debug sırasında gerçek zamanlı değişken değişimlerini izleyerek çok daha verimli bir şekilde sorunları analiz edebilirsiniz.

Bu yazıda, STM32CubeIDE’de canlı değişken takibi nasıl yapılır, ne gibi avantajlar sağlar ve bunu bir örnek proje üzerinden nasıl kullanabileceğinizi adım adım anlatacağım.


Nedir Bu "Live Expressions"?

Live Expressions penceresi, kodunuz çalışırken belirli değişkenleri (ya da ifadeleri) sürekli gözlemlemenizi sağlar. Kod breakpoint’te durmasa bile, değişkenlerin değerleri anlık olarak güncellenir. Bu, özellikle zamanla değişen sayıcılar, PWM duty cycle’ları veya sensör değerleri gibi dinamik verileri takip etmek için çok faydalıdır.


Neden Kullanmalısınız?

Live Expressions ile şunları kolaylıkla yapabilirsiniz:

  • Kod kesintiye uğramadan değişkenleri takip edebilirsiniz.

  • Belirli bir algoritmanın anlık çıktısını grafiksel ya da sayısal olarak izleyebilirsiniz.

  • Delay’lerle uğraşmadan, breakpoint koymadan performans sorunlarını veya mantıksal hataları yakalayabilirsiniz.

  • Gerçek zamanlı sistemlerde, kod akışını bozmadan değerlerin nasıl değiştiğini görme imkânı sağlar.


Uygulamalı Örnek: ADC ile Sıcaklık Ölçümü

Diyelim ki bir STM32F103RB mikrodenetleyici ile dahili sıcaklık sensöründen ADC kullanarak sıcaklık değeri okuyoruz. Kodumuz şöyle:

c
#include "main.h" ADC_HandleTypeDef hadc1; float temperature = 0; void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc->Instance == ADC1) { uint32_t adc_val = HAL_ADC_GetValue(&hadc1); temperature = ((float)adc_val) * 3.3f / 4096.0f; // Voltaj temperature = ((temperature - 0.76f) / 0.0025f) + 25; // Sıcaklık (yaklaşık hesap) } } int main(void) { HAL_Init(); SystemClock_Config(); MX_ADC1_Init(); HAL_ADC_Start_IT(&hadc1); while (1) { HAL_Delay(500); // Sıcaklık değerini yarım saniyede bir güncelliyoruz } }

Adım Adım: Live Expressions Kullanımı

1. Debug Moduna Geçin

Projeyi build ettikten sonra Debug moduna geçin (F11 veya üstteki bug ikonuna tıklayarak).

2. Live Expressions Panelini Açın

Debug görünümüne geçtikten sonra:

  • Menüden Window > Show View > Expressions yolunu izleyin.

  • Açılan panelin ismi "Expressions" olabilir ama bu panel canlı güncelleme desteği sunar.

3. Değişken Ekleyin

  • Expressions paneline sağ tıklayın ve Add Watch Expression seçeneğine tıklayın.

  • Açılan kutuya temperature yazın.

  • Enter’a bastığınızda, değişken panelde belirecek.

4. Canlı Güncellemeyi Görüntüleyin

  • Kod hala çalışırken (pause durumda değilken!) temperature değerinin saniyede iki kez güncellendiğini göreceksiniz.

  • Değer sürekli güncelleniyorsa, sisteminizde herhangi bir kesinti olmadan anlık sıcaklık verisini izleyebiliyorsunuz demektir.


İleri Seviye: İfade Takibi (Expression Tracking)

Bu panelde sadece değişken değil, ifade de yazabilirsiniz. Örneğin:

temperature > 30

şeklinde yazarsanız, bu ifade true veya false olarak sürekli değerlendirilir. Bu da debug sürecinde koşul kontrollerini anında görmek için ideal bir yöntemdir.


İpuçları & Dikkat Edilmesi Gerekenler

  • Optimization seviyeleri yüksekse (-O2, -O3) bazı değişkenler derleyici tarafından optimize edilebilir ve debug sırasında görünmeyebilir. Geliştirme aşamasında -O0 (optimizasyon kapalı) kullanmanızı öneririm.

  • Eğer değişken global değilse, yani fonksiyon içindeyse ve static değilse, Live Expressions’da gözükmeyebilir. Bu durumda değişkenin kapsamını değiştirin.

  • volatile tanımlaması, anlık değişen donanım temelli değişkenlerde kritik öneme sahiptir. Bu sayede değer her seferinde RAM’den okunur.


Sonuç: Canlı Takiple Daha Akıllı Debug

Live Expressions, STM32CubeIDE’nin az bilinen ama çok etkili bir özelliği. Özellikle gömülü sistemlerde, zamanla değişen verileri izlemek ve mantıksal hataları tespit etmek için oldukça kullanışlıdır.

Her debug seansında breakpoint koymak yerine, bu özelliği kullanarak sisteminizi çalışır haldeyken analiz edebilir, daha kısa sürede daha isabetli çözümler üretebilirsiniz.


Eğer bu özelliği daha önce kullanmadıysanız, bir sonraki debug seansınızda denemenizi kesinlikle tavsiye ederim. STM32CubeIDE’nin sunduğu bu ve benzeri küçük araçlar, geliştirme sürecinizde büyük farklar yaratabilir.

24 Ocak 2022 Pazartesi

C dilinde, İyi Yazılmış, Taşınabilir Bir Sensör Sürücü Paketi İncelemesi

Bu yazıda gömülü sistemlere düşük seviyede sürücü geliştiren kişilere referans niteliğinde olan, BOSCH'un  sıcaklık, nem ve basınç sensörü BME280 için geliştirdiği, github üzerinden yayınladığı açık kaynak kütüphaneyi [1] inceleyeceğiz. Başlıkta da belirttiğim gibi kütüphane gerçekten çok modüler bir şekilde oluşturulmuş. Geliştirilen kütüphane platform-bağımsız olduğu için herhangi bir altyapıya adapte edilebilir. Bu yapıyı herhangi bir mikrodenetleyicide veya OS ile çalışan bir gömülü yapıya entegre edebilirsiniz.



Kütüphane geliştirilirken low-coupling, high-coherence kavramlarını başarılı bir şekilde uygulamış. Kütüphane içerisinde herhangi bir dış bağımlılık olmadığı gibi kendi içerisindeki fonksiyon ve veri setleri de tam olarak amaca yöneliktir.

Öncelikle kütüphanenin güzel bir README.md dosyası var. İçerisinde bu kütüphanenin nasıl kullanılabileceği detaylı bir şekilde anlatılmıştır.

Bu yazıda, ilgili kütüphaneyi SPI üzerinden nasıl kendi sisteminize entegre edeceğinizi yine README.md deki örnek üzerinden ele alacağız.

Kütüphane bme280_dev structure'ı üzerinden çalışıyor. Bu yapı aşağıda verilmiştir.

Bu yapıda öncelikle ilgili sensörün hangi arayüz ile hangi modda kullanılacağı çeşitli değişkenlerle seçilir. Bu seçimler değişken isimleri ve gerekli yorumlarla desteklenmiş ve açık bir şekilde belirtilmiştir.

Bunun haricinde taşınabilirlik açısında bizim en çok işimize yarayan kısım fonksiyon pointer yapılarıdır. SPI örneği üzerinden devam edecek olursak bme280_dev yapısı içerisinde okuma yazma fonksiyonları için dev.read ve dev.write fonksiyon pointerlarına ilgili platforma ait SPI yazma okuma fonksiyonları atanır. SPI okuma ve yazma fonksiyonları kendi içerisinde CS operasyonunu gerçekleştirmelidir. Fonksiyonel olarak yazılmış sensör sürücüsü soyutlanmış okuma, yazma fonksiyonları üzerinden çalışır. Bu iki fonksiyona ek olarak kütüphane içerisinde kullanmak üzere 1 ms çözünürlüklü bir delay fonksiyonunun da pointerı structure'a atanır.

Bu noktada önemli bir parantez olarak ilgili fonksiyon pointerları mevcut altyapınızla birebir uyumlu olmayabilir. Hatta muhtemelen farklıdır. Bu noktada sizin altyapınız ile kütüphane arasına bir adaptör katmanı yazmanız gerekebilir. Örnek olarak aşağıdaki fonksiyon incelenebilir. myusleep fonksiyonu platform tabanlı bir fonksiyondur. Örnek olarak ms gecikmesi için STM32 altyapısında HAL_Delay fonksiyonunu düşünebilirsiniz. Arduino altyapısında buna delay fonksiyonu karşılık gelir. Biz her iki platformda da mevcut fonksiyonun adresini aşağıdaki gibi bir adaptör vasıtasıyla bme280_dev yapısına atanır. Böylece kütüphane fonksiyonları platform bağımsız çalışır.

Bu kütüphane kullanılarak oluşturulmuş tam bir örneğe aşağıdaki linkten erişebilirsiniz. En başta da ifade ettiğim gibi gömülü sistemlerde sürücü seviyesinde yazılım geliştiriyorsanız bu kütüphaneleri hiç bir zaman başka bir platformda kullanmayacaksanız bile bu yaklaşımla geliştirmenizi öneririm. Kodun okunabilirliği, güncellenebilirliği ve bakım yapılabilirşliği açısından da oldukça faydalı olacaktır.

https://github.com/BoschSensortec/BME280_driver/blob/master/examples/bsd_userspace.c

Referanslar

[1] https://github.com/BoschSensortec/BME280_driver/

6 Ocak 2021 Çarşamba

Lineer/Proportional/Oransal Çıkışlı Bir Analog Sensörün Okunması, Sensör Okuma ile ilgili Temel Mantıklar

 Sensör verilerinin okunması ve anlamlandırılması kontrol sistemleri için en temel girdiyi oluşturur. Sensör bilgileri, sensörün tipine, iç yapısına, ölçtüğü fiziksel niteliğin davranışına göre farklılık gösterebilir. Sensör çıkışları lineer veya bir polinoma bağlı olabilir.

Bu yazı kapsamında lineer çıkışlı sensörler hakkında detaylı bir açıklama yaptıktan sonra polinomsal çıkışlı bir sensör hakkında da kısa bir yorum yapıp bitireceğim.

Lineer çıkışlı analog bir sensöre örnek olarak SS495B ve LM35 üzerinden ilerleyeceğiz. Aşağıda gördüğünüz görselde SS495B'nin gauss/çıkış voltaj grafiği verilmiştir. Bu sensörün ölçüm yaptığı fiziksel nitelik ile çıkış voltajının lineer olduğu grafikten bellidir. Çıkış gerilimi gauss değerine göre lineer olarak artıp azalır.

SS495B Çıkış Karakteristiği
Bu şekilde çıkış veren sensörler çok basit bir matematiksel formülle tanımlanır. ADC değerini okuyup voltaja çevirdikten sonra, gerilim değerinden ilgili fiziksel değere geçilir. Bu örnekte o değer gauss'tur.

Grafikten görüldüğü gibi sensör 0.5V-4.5V arasıda tanımlıdır. Aralık dışıda bir değer okunması halinde uygulamanın çeşidine göre bir senaryo planlanır. Bu aralıkta da direkt bir eğik doğru formülü ile tanımlanır. Bu formül;

Gauss = ( Vout - 2.5 ) * ( 640 / 4.5 )

şeklindedir. Bu formüldeki ( 640 / 4.5 ) ifadesi grafiğin eğimidir. Bu değer sayısal olarak sadeleştirilip sadece bir çarpım ifadesi şeklinde de yazılabilir.

LM35 sensörü de sıcaklığa bağlı lineer çıkış veren bir sensördür. Bu sensörün datasheetinde çıkış aşağıdaki şekilde ifade edilmiştir. Sensör 2°C-150°C aralığında her bir derece için 10mV çıkış verir.
LM35 Çıkış Karakteristiği

Bu bilgilerden hareketle bu sensörün çıkışını santigrat derece şeklinde ifade etmek için aşağıdaki formül kullanılır.

Temperature = 2 + ( Vout / 0.01 ) = 2 + ( Vout * 100 )

İki ayrı sensör değerinin nasıl dijital veriye çevrildiğini bu iki örnekle özetlemiş olduk. Bir de polinomsal çıkış veren sensörler vardır. Bunlar için en yaygın örnekler NTC tipi sıcaklık sensörleri olabilir. Bu sensörlerin direnç değerleri sıcaklığa bağlı değişir ve en basit şekilde başka bir direnç ile seri bağlanarak orta noktanın gerilimi üzerinden bir dönüşüm yapılır. Burada ilk olarak basit gerilim bölücü mantığından sıcaklık sensörünün direnç değeri bulunur ve bu direnç değeri -nispeten- kopleks bir matematik denkleminden geçerek sıcaklık elde edilir. Bu denklem "Steinhart and Hart Equation" olarak adlandırılır. Burada yer alan A, B ve C sabitleri ilgili sensörün datasheetinde verilir. R değeri ise NTC'nin o anki direnç değeridir.


Bir NTC'nin direnç değerinin sıcaklığa bağlı değişimini gösteren grafikte aşağıdaki gibidir. Grafikte görünen PTC, NTC ile ters çalışan ama aynı amaçla kullanılan bir sensör türüdür.




Bu yazı kapsamında sensör okuma ve okunan değerleri fiziksel değere çevirme hakkında genel bilgiler vermeye çalıştım. Umarım faydalı olur. Çalışmalarınızda başarılar.



7 Aralık 2020 Pazartesi

Cooperative Multitasking

 Bu yazıda cooperative multitasking (CM olarak anılacak) kavramı üzerine bildiklerimi ve gömülü sistemler üzerinde bu yapıya benzer bir çalışma metodolojisi ile nasıl geliştirme yaptığımdan bahsedeceğim.

CM kavramı non-preemptive multitasking olarakta bilinir. Temel olarak görevi taskları sıralı bir şekilde işletmektir. Bilinen modern multitasking yapılarından farkı ise önceliğe göre aktif bir task switching yapmamasıdır. CM yapısında, işlemci aynı anda bir task ile ilgilenir ve o task tamamlanana kadar diğer taskların çalışmasına izin vermez. Bu yapı Windows 3.1x'te kullanılmıştır.[1]

CM yapısı ile çalışacak bir sistemde taskların zamanları önemlidir. Bu yüzden yazılacak taskların süreleri ve gereksinim durumu iyi analiz edilmelidir. Vakit alan bir task önemli bir taskı engellerse bu sistemi verimsiz/anlamsız/zararlı hale getirebilir.

CM kavramını görselleştirmek için aşağıdaki görseli kullanalım. Burada örnek olarak Task A 20ms de bir çalışır ve task aktif olduktan sonra 3 ms boyunca iş yapar. Diğer tasklarda da benzer şekilde çalışma periyotları ve çalışma süreleri tanımlanmıştır.

İlk ve en basit kural çalışma süresi, çalışma periyodundan büyük olmalıdır. Bu ikisi arasındaki fark ne kadar yüksek olursa ilgili taskın işlemciye yükü o kadar düşük olur.



Görselde CM metodu içe çalışan bir yapı verilmiş ve Task A, B, C tanımlanmıştır. Her bir taskın çalışma sürelerine göre işlemler grafikteki gibi verilir. Burada zamanları tek tek inceleyeceğiz.
  • @10. ms Task C çalışır ve 11. ms'de biter.
  • @15. ms Task B çalışır ve 17. ms'de biter.
  • @20. ms Task A çalışır ve 23. ms'de biter. Bu esnada Task A'nın da çalışma periyodu gelir ancak Task A bitmediği için sırasını bekler. Task A biter bitmez 23. ms'de Task C başlar. 24. ms'de biter. Bu kaymadan dolayı Task C'nin bir sonraki başlama zamanı kayar ve Task C 33. ms'de çalışır.
  • @30. ms Task B çalışır ve 32. ms'de biter.
  • @33. ms Task C çalışır ve 34. ms'de biter.
  • @40. ms Task A çalışır ve 43. ms'de biter.
  • @43. ms Task C çalışır ve 44. ms'de biter.
  • @45. ms Task B çalışır ve 47. ms'de biter.
Bu yapıda en önemli konu 20. ms'de yaşanan kaymaların olabileceğidir. Bu yüzden doğru bir düzen içerisinde tasarlanmalıdır. Çok daha uzun sürecek tasklar da olabilir. Bu durumda diğer taskların kritik görevlerinin olmaması önemlidir.

Bu yapıyı kurarken genelde tüm tasklar tek bir zaman sayacı üzerine kurulur ve ilgili zaman sayacını referans alark her bir task çalışma başlangıcını belirler.

Gömülü sistemlerde çalışırken, RTOS kullanmadan geliştirilecek uygulamlarda oldukça faydalı bir yöntemdir. RTOS'lara göre eksik kaldığı bir nokta normalde delay koyarak geliştirilebilecek basit akış diyagramlarını oluşturmak için switch case yapılarının gerekmesi olabilir ancak alışkanlık sağladığınızda fazlasıyla kolaylık sağlayacaktır.

Bu yazı kapsamında interruptsız bir program üzerine konuyu anlattım. Ek ve özet bilgi olarak bu yapılar çalışırken çalıştıracağınız interruptlar ile de tam gerçek zamanlı tasklar çalıştırabilirsiniz. Kurgulanacak bu yapıda yukarıda verilen tasklar interruptlar tarafından bölünür ve sizin hem interrupt yapınız hem de ana döngü yapınız sağlıklı bir şekilde çalışabilir.

Ana döngü içerisinde yavaş toplanacak veriler, haberleşme değerlendirme algoritmaları, dosya okuma/yazma yapıları vs. geliştirilebilir. Interruptlar içerisinde ise hızlı tepki verilmesi gereken giriş/çıkış yapıları, kontrol algoritmaları, periyoda bağımlı algoritmalar vs. çalıştırılabilir.

Umarım faydalı olur.

Referanslar

[1]. https://en.wikipedia.org/wiki/Cooperative_multitasking

30 Temmuz 2020 Perşembe

RS-232, RS-485, RS-422 Nedir? Temel Kavramlar, Açıklamalar ve Karşılaştırmalar

Bir haberleşme yapısı farklı seviyede katmanlardan oluşur. Bu yazıda bahsedeceğim RS-232, RS-485 ve RS-422 katmanları fiziksel katman seviyesinde çalışırlar. Fiziksel katman haberleşme yapılarının en alt noktasıdır.

Aşağıdaki görsellerde haberleşme yapılarının yüksek seviyeden düşük seviyeye giden genel yapısı verilmiştir. İlk görsel genel bir gösterimdir. İkinci görselde ise RS-232 ve RS-485 özelinde fiziksel katmandan uygulama katmanına giden yapı gösterilmiştir. Transfer edilecek veriye her bir katmanda çeşitli eklemeler yapılır. Bunun yapılıp yapılmayacağı ve boyutu yapıya göre değişkenlik gösterir.




Giriş


İlgili standartlar mikrodenetleyici tarafındaki seri haberleşme (Genellikle UART olarka anılır.) yapısını dış dünyaya açabilmek için kullanılır. Pratikte verinin cihaz veya sistem dışına, daha uzun mesafelere gönderilmesi için kullanılır. Bununla birlikte UART birimi alıcı-verici çifti ile iki yapı arası haberleşmeye imkan sağlar. RS-485, RS-422 gibi yapılarda çoklu haberleşme topolojileri kurulabilir.

RS-232 genellikle iki cihaz arası kısa haberleşmelerde tercih edilir.

RS-485 ve RS-422 üzerine bir çok endüstriyel haberleşme standardı inşa edilmiştir. Özellikle RS-485 yüksek hız ve sadece 2 kablo gereksinimi dolayısı ile bir çok sektör ve alanda tercih edilir. MODBUS, Profibus, BACnet gibi otomasyon standardları fiziksel katmanda RS-485'i kullanır.

RS-232


  • Single-ended. Veri GND referansına göre gönderilir.
  • RX, TX ve GND bağlantıları ile haberleşir. Hat üzerinde 2 cihaz olabilir.
  • Azami uzunluk: 15 Metre 19.2 kbps
  • Azami hız: 1 MBPS 15 Metre

RS-485


  • Differential. Veri AB arasındaki voltaj farkına göre iletilir. GND gereksinimi duymaz.
  • AB hattı üzerinden 32 alıcı/verici cihazı destekler. Bu değer kullanılan transreceiver ve sonlandırma direncine göre farklılıklar gösterebilir.
  • Azami uzunluk:1.2 KM 100 kbps
  • Azami hız: 10 MBPS 15 Metre


RS-422


  • Differential. Veri AB arasındaki voltaj farkına göre iletilir. GND gereksinimi duymaz.
  • RX+,RX-,TX+,TX- hatları üzerinden 1 gönderici 10 adet alıcıya kadar destekler.
  • Azami uzunluk:1.2 KM 100 kbps
  • Azami hız: 10 MBPS 15 Metre


Teknik Karşılaştırma Tablosu






Görsel Kaynakları:
  • https://www.omega.com/en-us/resources/rs422-rs485-rs232
  • https://iebmedia.com/ethernet.php?id=4582&parentid=74&themeid=255&hft=23&showdetail=true&bb=1
  • https://hvac-talk.com/vbb/attachment.php?attachmentid=643921&d=1447971918
  • http://www.rs485.com/rs485spec.html
  • ti.com

UART Nedir?

Giriş


Universal Asynchronous Receiver Transmitter (Evrensel Asenkron Alıcı/Verici) kelimelerinin baş harflerinden oluşur. Adından anlaşılabileceği gibi iki ayrı birim arasında asenkron olarak gerçekleştirilen haberleşme protokolüdür. Temel prensip olarak iki tarafın haberleşme hızını bildikleri, başlangıcı, sonu belli haberleşme yapısıdır. Arada senkronlayıcı bir sinyal olmadığı için asenkron olarak isimlendirilir. Mikrodenetleyiciler veya mikroişlemciler üzerinde gerçekleştirilen uygulamalarda sıklıkla kullanılır. Arduino gibi low-level veya Raspberry Pi gibi high-level geliştirme kartlarında muhakkak karşınıza çıkar. Anlaması, uygulaması ve geliştirilmesi basit bir yapı olduğu için bir çok uygulamanın ve sistemin temelini oluşturur. Devre içi haberleşmede kullanıldığı gibi uzak mesafelere kablolu iletimde de temeli oluşturur. RS232, RS485, RS422 gibi fiziksel katmanlara da imkan verdiği için otomasyon, kontrol, ve robotik gibi bir çok alanda kullanımı vardır. Bu katmanlar ile veri kilometrelerce uzağa iletilebilir ve bir hat üzerine ikiden fazla cihaz bağlanabilir.


Temeller


Temel yapı olarak iki birim arasında Rx ve Tx çiftineden oluşur. Karşılıklı veri alış-verişi yapabilmek için RxTx çifti TxRx çifti ile eşleşerek çalışır. Full-duplex bir UART yapısında Rx, Tx bağımsız birer modül gibi çalışır.

Aşağıdaki gibi ara bir fiziksel bağlantı olmadan direkt UART haberleşmesi kullanılacaksa ground lar birleştirilmelidir. Veri Tx hattından Rx’e gider. Pinler fiziksel olarak Tx çıkış, Rx giriş modundadır.


UART’ın genel veri/frame yapısı aşağıdaki gibidir. Tx pini normal durumda HIGH konumunda bekler. LOW’a düştüğü anda frame transferi başlar. Bu noktadan sonra UART yapısı 8 biti kendi register ı üzerine kayıt eder. Eğer stop bitini de doğru şekilde alırsa bir byte alındığına dair bir flag set eder veya ilgili interrupta girer. Tx tarafında ise Tx modülü busy flag’i düşer veya ready flag’i kalkar veya complete interruptına girebilir.


Kavramlar

  • Data Frame: Aktarılan asıl veridir. 5–9 arası değişebilir/ayarlanabilir. Bazı işlemcilerde sabitte olabilir.
  • Baud rate/Bit rate: Bir bitin gönderilme frekansı. (1/baud rate) Bir bitin iletilme süresi. 1-bit start 1-bit stop bitten oluşan bir paketin gönderilme süresi (10/baud rate) kadar sürer.
  • Start Bit: Başlangıç bitidir. Standard bir yapıda (1/baud rate) kadar sürer ve LOW seviyedir.
  • Stop Bit: Sonlandırma bitidir. Standard bir yapıda (1/baud rate) kadar sürer ve HIGH seviyedir. Bir hatadan dolayı LOW olarak okunursa ilgili paket hatalı olarak sınıflandırılır.
  • Parity Bit: Doğrulama bitidir. Genelde opsiyonel olarak kullanılır. Bir paket içerisindeki bitlere göre hesaplanır. Even veya Odd seçilir. Bu koşula göre hesaplanan bit pakete uygunsa paket sağlamdır. Değilse paket içerisinde hatalı bir bit vardır.

Lojik Seviye


Bu kısımda yer alan bilgiler lojik tasarım ile ilgilenen kişilerin ilgisini çekebilir. FPGA, CPLD gibi yapılarda UART modülü aşağıdaki mantıklar çerçevesinde tasarlanır. Modüllerin giriş çıkışları kullanılacak yapılara göre farklı şekillerde genişletilebilir. Örnek olarak hiç bir veriyi kaçırmamak için UART RX modülünün arkasına bir FIFO yapısı bağlanır ve ana kontrol modülü verileri FIFO üzerinden çeker. Bu durumda RX modülü ile FIFO’nun senkron çalışması için -varsa- gereken kontrol pinleri eklenir.

Bu kısımda genellikle modüllerin RTL gösterimi yer alacaktır. RTL lojik tasarımlarda register-transfer level gösterimidir.

RX Bloğu


Alıcı yapı, belirlenen UART hızının birkaç katı hızla çalışır. Örnek olarak STM32 işlemcilerde 8 veya 16 örneklem alır. Bunun sebebi alınan frame i doğrulamaktır. Bir bit gelecek zamanda farklı değerler okunursa o frame hatalı kabul edilir.

rx hattından yeni bir veri gelip iletim tamamlandığında Data_ready çıkışı HIGH olur ve ana kontrol yapısı Data_output üzerinden register a yazılan veri okunur.

TX Bloğu


Gönderici yapı alıcı yapıya göre daha basittir. Kendi içerisindeki paralel veriyi txTrigger sinyali ile UART baud rate hızında seri hattan gönderir. Genellikle ek bir doğrulama veya kontrol gerekmez.

Data_input hattındaki veri start pininin tetiklemesiyle iletime başlar ve frame yapısına uygun olarak(start bit, stop bit, parity) veri tx pini üzerinden aktarılır. Parity hesabının nasıl yapıldığı aşağıdaki şekilde de gösterilmiştir.



Görsel Kaynakları:
  • https://www.slideshare.net/n380/uart-vhdl-rtl-design-tutorial
  • https://www.allaboutcircuits.com/technical-articles/back-to-basics-the-universal-asynchronous-receiver-transmitter-uart/


MODBUS'a Hızlı Bir Giriş

Bir enerji analizörünün kılavuzunu açıyorsunuz, karşınıza "Fonksiyon kodu: 03" yazan bir tablo çıkıyor. Yandaki inverterin ...