vb6 yada c# serial com port sorusu

Başlatan Karamel, 26 Temmuz 2015, 00:29:18

Karamel

merhaba. gecen yaz vb6 ile ilgilenirken. serial com port deneyi  yapmistim. orada soyle sorun vardi ve cozememistim.

comm port un threshold degeri vardi. ben bunu 5 yapmistim. yani her 5 byte tan sonra kendini basa aliyordu. microcontroller her veri gonderdiginde vb ile gelen veriyi parcalayip. pc ye yorum yaptirabiliyordum. mesela verimiz A00DR olsun. 1. 2-3. 4-5 i parcalayinca

A
00
DR

oluyor bende if ilk bastaki = "A" then seklinde yorum yapabiliyordum ama bunun bi sakincasi vardi. microcontroller tarafindan yanlislikla 5 değilde 4 yada 6 byte gelirse bu sefer bizim threshold degerimiz is yapamaz hale geliyor. gelen verinin anlamsiz oldugunu anlayabiliriz ama sorun olduktan sonra bir turlu threshold degerini resetleyememistim.

az once c# serial port communication ini incelerken ayni seylerin orada da oldugunu gordum. yani ayni mantik burada da var. offset ve count adiyla ayni seyler yapiliyor.

serialPort.Read(byte[] buffer, int offset, int count)


bu iste bir mantiksizlik var. serial com port ile surekli haberlesen bir alet dusunelim. bu alet gunde  1.000.000 byte gonderip alsin. birisinde sasirmasi normal olmali. vb6 da yada c# bu sorunun bir cozumu varmi?

hocalarim professional anlamda comm port u nasil kullaniyorlar?

magnetron

uC den bilgiyi eger sen talep ediyorsan

mesela xxxxyyyzzz paketini gönderip uC den bilgiyi sen talep edersen

her paket göndermeden sonra hemen 

Private Sub EmptySerialBuffer()
  MSComm1.InBufferCount = 0
End Sub

yap - böylece buffer da geçmiş paketlerden kalan artık byte olmaz

kudretuzuner

Merhaba,
Ben komporta gelen dataları tek tek okuyor ve ona göre işlem yaptırıyorum.Dikkat edilmesi gereken husus ise datalar HEX olarak gelir fakat siz PC'de bu HEX değerin desimal karşılığını okursunuz.Ben VB.Net 2010 express edition kullanmaktayım.Fikir vermesi bakımından bir projemde kullandığım kodlardan birkaç örnek vereyim.

       Dim gelen As String = SerialPort1.ReadByte


        '*****************ANAHTAR TESTİ BAŞLAR
        If gelen = 57 Then '----------'DEC'57'-----hex'31'-----"9"
            PictureBox23.Image = Image.FromFile("c:\resm" + "\SW_on.bmp")
        End If
        '-----------------

        If gelen = 65 Then '   A
            PictureBox35.Image = Image.FromFile("c:\resm" + "\F.bmp")
        End If
        If gelen = 97 Then '   a
            PictureBox36.Image = Image.FromFile("c:\resm" + "\F.bmp")
            '          PictureBox22.BackColor = Color.Red    ZATEN  KIRMIZI OLARAK BAŞLIYOR RED YAPMAYA GEREK YOK
            '           Label22.ForeColor = Color.Red
        End If
        '---------------------------------------------------
        If gelen = 65 Then '   A
            PictureBox35.Image = Image.FromFile("c:\resm" + "\F.bmp")
        End If
        If gelen = 98 Then '   b
            PictureBox36.Image = Image.FromFile("c:\resm" + "\E.bmp")
            PictureBox22.BackColor = Color.Teal
            Label22.ForeColor = Color.Teal
        End If
        '---------------------------------------------------
Amatör

Karamel

kudret hocam tek tek degilde daha complex birsey hayal edin. yukarida yazdigim gibi. o zaman isler karisiyor.


magetron hocam iletisimi hangi taraf baslatiyor hatirlayamadim ama MSComm1.InBufferCount = 0 ile counter sifirlanabiliyorsa. en kotu ihtimalle bir kerelik hatali alisverisle. system normale doner. diye dusunuyorum?

kudretuzuner

Alıntı yapılan: Karamel - 26 Temmuz 2015, 16:44:24
kudret hocam tek tek değilde daha complex birsey hayal edin. yukarida yazdigim gibi. o zaman isler karisiyor.


magetron hocam iletisimi hangi taraf baslatiyor hatirlayamadim ama MSComm1.InBufferCount = 0 ile counter sifirlanabiliyorsa. en kotu ihtimalle bir kerelik hatali alisverisle. system normale doner. diye dusunuyorum?
Merhaba,
Ben bu şekilde bir çözüm buldum.PIC'in 8 pinine 8 bitlik bir data gurubu FF-00 arası data giriyor. 255 olasılığı tek tek kontrol edip ona göre pikçırbakslarda gösteriyorum.Profesyonelce bir algoritma değil ama benim işimi görüyor.
Amatör

tunayk

Veri parçalanma olayı genel bir sorun.  Özellikle byte sayısı fazla ise daha ciddi sıkıntı oluyor.  Profibus,  Modbus vb. Protokoller haberleşmenin belli kalıplarda yapılması için kullanılıyor.  Normal şartlarda seri haberleşme hattına kimse kafasına göre data göndermemesi gerekmektedir.
Bunun için temel yapı, bir master ve diğer Slave elemanlar bulunur.  Master sorar Slave belirli bir sürede cevaplar. Soru sorulduktan sonra cevap paketindeki tüm bytelar gelene kadar master bekler. Örneğin 100ms.  Bu sayede datalar parçalansa bile süre sonunda değerlendirme olacağı için, hepsi gelmiş olur. Eğer bu sürede doğru cevap gelmemiş ise master tekrar soru sorar. Ancak özel durumlar haricinde herkes sırasını beklemelidir. Aksi takdirde kargaşa olur.
Bununla birlikte gönderme ve alma hatları ayrı olan bir yapı varsa, Herkesin konuşma başlatma zorunlu luğu varsa bu durumda gidecek verinin başına ve sonuna tanımlama bilgileri eklenir. Örneğin başlangıç byte, adres, bitiş byte'ı byte sayısı vb. Bu şekilde bir veri paketi alındığında gerekli çözümleme yapılabilir ve kim ne demek istemiş kolayca anlaşılır.Birde hata kontrolleri Crc vb. Eklenmeli çoğu kez.
Protokol konusu oldukça detaylı. Biraz araştırmanız gerek.
Biraz fikir verebilmişimdir umarım.

OG

"threshold değeri ile başa alıyordu" demişsin anlayamadım.
threshold değeri kadar veri gelirse kesme oluşturur. Bu donanım kesmesidir. Bu kesme olustu ise

Private Sub MSComm1_OnComm()
.
.
End Sub

fonksiyonu içine girer. Bunun içini doldururken dikkatli olunursa sıkıntı oluşmaz.

MSComm1.RThreshold = 0     
Yapılırsa data gelsede kesme hiç oluşmaz ve bu rutine uğramaz.

Kesme tipi donanım kesmesi olması sebebiyle MSComm1.RThreshold = 1 kullanıyorum, yani sizin haberleşme treniniz 5 byte da olsa, 1 byte bile alınsa buraya uğrar. Her uğrayışta yeni geleni eski gelenler üzerine ilave ederiz.

Gelenleri toplamak için variant tipi bir değişken, mesela
Dim data_buffer As Variant
Gerekirse bir tane de yedek
Dim yed_alinan As Variant

Program başlarken veya gerektiği yerlerde bunun içeriğini Null yaparız.

MSComm1.RThreshold = 0      ''On_comm u şimdilik devre dışı bırak
MSComm1.InputLen = 0        '' alışta sınırlama yapma
data_buffer = MSComm1.Input     ''' bufferda bir şey varsa çekelim buffer temizlensin
data_buffer = Null
yed_alinan = Null

Şimdi
MSComm1.RThreshold = 1
yaptığım anda seri port donanım kesmesi hazır hale gelecektir. O sebeple kesmeden hemen önce gerekli içerik temizliklerini yaparız.

Her bir bayte data alışı kesmeye sebep olur çünkü MSComm1.RThreshold = 1

Kesme olunca da
Private Sub MSComm1_OnComm()
.
.
End Sub
buraya kesin uğrayacaktır.

Private Sub MSComm1_OnComm()
data_buffer = data_buffer & MSComm1.Input
End Sub

dersek her gelen data_buffer değişkeni içine sıra ile ilave olacaktır.

Bir değişkenimiz daha var, mesela
Dim data_boyutu as Integer

gelen toplam datanın boyutunu tespit ederiz
data_boyutu = Len(data_buffer)

Bize 5 tane gerekliydi data_boyutu da en az 5
yed_alinan = yed_alinan & data_buffer
data_buffer = Null

der ve yed_alinan ile gerekli değerlendirmeleri yaparım.

Her zaman, trende bir ilk beklediğim değer olmalıdır. Genelde "start of text" (ASCII CODE 2) kullanırlar. Ben ise mesela "O" kullanırım.

Yine gelen data trenini doğruluğunun kontrolu değişik crc usulleri ile kodlarım/kodlarlar.
En basiti,
İlk data "start of text" (0x02)   ... 0. byte
data byte 1                             ... 1. byte
data byte 2                             ... 2. byte
data byte 3                             ... 3. byte
.
data byte n                             ... n. byte
data crc                                  ... n+1. byte
Son data End of Text (0x03)    ... n+2. byte

En basit CRC alma  1. byte ila n. byte a kadar olan hepsini toplamak ve byte boyutunda bırakmak gibi bir usul olabilir. Veya kendiniz bir şey uretebilirsiniz, veya biline CRC yöntemlerini kullanabilirsiniz.

Kendi data akışına göre öncelikle data_boyutu kafimidir kontrol ederiz. Yeterli ise 0. byte start byte mı,  n+2. byte stop byte mı kontrol ederiz Tutmuyorsa 0. byte ı silip 1. byte ı 0. olarak kaydırırırız, ve tabi diğer hepsini 1 geri kaydırırız. data_boyutu değerini de 1 eksiltiriz.

Bu şekilde kontrolleri yaparız, crc kontrolleri dahil.


FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.