XC8 için Modbus RTU Slave Kütüphanesi

Başlatan Tagli, 15 Ağustos 2015, 10:41:53

Tagli

Normalde hiç aklımda yoktu ama bir projede ihtiyaç duyulması sebebiyle XC8 için Modbus RTU Slave kütüphanesi yazmam gerekti ve paylaşayım dedim.

Ortaya çıkan kütüphane çok öyle hazır ve tak-çalıştır rahatlığında değil, projenizde kullanabilmek için biraz oynamanız gerekecek. Zaten bu yüzden PIC16F88 için örnek proje şeklinde verdim. Genel olarak, USART, kesme ve timer ayarlarının ana kod tarafında sizin tarafınızdan yapılması gerekiyor. Ayrıca, modbus.h dosyasında da yapılması gereken bazı ayarlar var.

Kütüphane üzerinde çok fazla çalışmadım ve pek çok eksiği var. Şu anda sadece sınırlı sayıda Modbus fonksiyonunu destekliyor. Ayrıca byte'lar arası 1.5 byte'lık süre kontrolü de yapmıyor. Seri iletişim ise sadece 8N2 şeklinde (gerçi rahatlıkla 8N1 de yapılabilir ama standarta uymaz).

Takıldığınız yerler olursa soru sormaktan çekinmeyin. Ayrıca bulduğunuz hataları bildirirseniz iyi olur. Projenin bir ucundan da siz tutup "pull request" falan yollarsanız çok makbule geçer, çorbada sizin de tuzunuz olur.

Git reposunun adresi:
https://bitbucket.org/tagli/xc8_modbus_slave_template
Gökçe Tağlıoğlu

Tagli

Slave adresi değiştirme desteği eklendi. Eskiden adres bir sabit idi ama artık bir değişkende saklanıyor. Örnek uygulamada adresin bir kopyası da eeprom'da tutuluyor. Böylece değiştirilen adres PIC'in elektriği kesilse bile geçerli kalmaya devam ediyor. Slave adresini değiştirmek için 0 numaralı holding register'ı değiştirmek gerekiyor. Elbette bu sadece bir uygulama örneği, daha farklı bir kullanım da söz konusu olabilir. Şu an için eeprom fonksiyonları PIC18'de desteklenmiyor. Bu durum XC8'in bir kısıtlamasından kaynaklanıyor ve etrafından dolanmak her ne kadar mümkün olsa da üşendiğim için uğraşmadım.
Gökçe Tağlıoğlu

kantirici

teşekkürler hocam. Bir istek olarak birazda tekniğinden bahsedermeisin. Protokol, mesaj yapısı ve programda nelerin döndüğü gibi.

Tagli

Hocam protokol ve mesaj yapısı zaten Modbus standartına uygun ancak henüz tüm fonksiyonlar desteklenmiyor. Ama en önemlileri olan register tabanlı tekli ve çoklu okuma yazma işlemleri yapılabiliyor.

İletişim kesme tabanlı. Gelen her byte kesme kodu içinde bir durum makinesine sokularak değerlendiriliyor. CRC kontrolünü de başarılı olarak geçen paketler ise ana program döngüsü içinde işleme sokuluyor. Master cihaza gönderilecek olan paketler ise bir tampon belleğe alınarak yine kesme ile gönderiliyor. Modbus standartı gereğince, iletişim hattı üzerindeki 3.5 karakter süreli bir sessizlik durum makinesini sıfırlıyor.
Gökçe Tağlıoğlu

a.zorba

#4
hocam sizin kodları örnek alarak modbus u anlamaya çalışıyorum .
kendımce bir yere kadar geldim . sınırlı C bilgimle giddigim yol ve PC de  aldıgım bilgiler dogrumu .

modbusProcessRequest  bu fonksiyonu biraz açıklayabilirmisiniz
18f4550 , 8N1 , 9600 baud ayarlamaya çalışdım





Bilenler bilir . Biz maraşlilar için şehir olarak şubat ay' i bayram ,kurtuluş ,yaz in gelmesiydi. Şimdi karalar in yas in ayı oldu.

Tagli

modbusProcessRequest fonksiyonu, CRC kontrolünden başarı ile geçmiş bir Modbus paketi alındığında devreye giriyor ve master tarafından talep edilen fonksiyona göre bir cevap paketi hazırlayıp TX kesmesi yardımıyla gönderiyor. Aslında fonksiyon TX tampon belleğini uygun şekilde doldurup TX kesmesini etkinleştiriyor. Asıl gönderme işlemini kesme içinde çağrılan modbusTxInterrupt fonksiyonu yapıyor.

Kodu 8N2'ye göre yazmıştım ama rahatlıkla 8N1'e de çevrilebilir (ki bir başka projede ben de 8N1 kullandım). Modbus standartında, parity bit kullanılmayacaksa 2 stop biti olması gerektiği belirtilmişti, örnek kodu o yüzden 8N2 şeklinde yazdım ama sanırım 8N1 daha yaygın olarak kullanılıyor.

Ekran görüntüsünde bir timeout hatası gözüküyor. Buna debug işlemi için yerleştirilen breakpoint sebep olmuş olabilir. Ayrıca, bilgisayardaki master tarafının timeout süresi çok düşükse cevap gelemeden hata verebilir. Çok emin olmamakla birlikte, 30 ms altının sorun çıkarabileceğini tahmin ediyorum. Bu süre, tek komutta yapılacak okuma veya yazma boyutuna göre değişebilir.
Gökçe Tağlıoğlu

ahuramazda

kütüphanenizi boş vakit bulup RS485 haberleşmesiyle denedim. SN75176 DE ve RE pinleriyle kullanabilmek için aşağıdaki değişiklikleri yapmak yetrli oluyor.

modbusProcessRequest fonksiyonunun sonunda PIE1bits.TXIE = 1; yapılmadan önce transmit moduna geçmek gerekiyor.
    DREnab = 1;
    PIE1bits.TXIE = 1;
// Request is served
    modbusState = MODBUS_IDLE;

TX interrupt içinde ise TRMT bitini kontrol etmek gerekiyor.

void modbusTxInterrupt(void) {
    TX1REG = *txBytePtr;
    
    while(TX1STAbits.TRMT == 0);
    ++txBytePtr;
    
    if (--modbusTxByteCounter == 0){
        PIE1bits.TXIE = 0;
        DREnab = 0;
    }
}