modbus protokol yardım

Başlatan EMKE, 06 Ekim 2015, 13:49:24

EMKE

Arkadaşlar modbus protokolü hakkında özellikle crc hesaplama kısmında öğrenmek istediklerim var internntten çok araştırdım ama bazı bilgileri kafamda oturtamadım bu konularda uygulama yapmış arkadaşlar bilgi verirlerse sevinirim, öğrenmek istediklerim crc hesaplamayı nasıl yapıyoruz neye göre yapıyoruz bunları anlatabilcek arkadaşlar varsa memnun olurum .

magic_gun

#1
CRC16:V1 = 0V2 = 0V3 = 0CRC_16 = 65535For V1 = 0 To SR_BYTE_CNT - 3V3 = CRC_16CRC_16.Byte0 = V3.Byte0 ^ SR_STR[V1] For V2 = 0 To 7If CRC_16.0 = 1 Then CRC_16 = CRC_16 >> 1 CRC_16 = CRC_16 ^ 40961ElseCRC_16 = CRC_16 >> 1 End IfNext V2Next V1 Return


bu arada :
http://web.eecs.umich.edu/~modbus/documents/PI_MBUS_300.pdf
hayal etemeden basaramazsınız
u cnt achieve w/out dreamin

Bahri Bilir

#2
Modbus ile 2 pic arası basit bir led kontrol kod örneği paylaşabilir misiniz?

Usart üzerinden 2 pic arası seri iletişimde bir sıkıntım yok.Ama CRC çevirip gönderme ve okurken crcden yine konu veriye çevirme kısmının mantığı hakkında hiçbir fikrim yok.Zaten bu kısım haricinde USARTtanda bir farkı yok sanırım.
"Hedeflerin bittiği tek yer, YENİ hedeflerin başlangıcıdır"

EMKE

Evet bende crc kısmının mantığını tam anlamıyla bilmiyorum eğer bu işi yapan bilen bir arkadaşımız  mantığını  anlatabilirse çok iyi olur .

Elzemefe

#4
Ekte deltanın verdiği örnekler aslında  mantık hepsinde  hemen  hemen aynı crc  toplamın komplementi alınmasıyla  oluşuyor
plc de  ama PIC  olarak nasıl işlenecek bilmiyorum

Bu  linktede bi tan örnek var

http://www.modbus.pl/node/18

magic_gun


umarım işinizi görür :)

Xtal = 20ADCON1 = 7Declare Adin_Res 10       Declare Adin_Tad FRC      Declare Adin_Stime 50     Declare Hserial_RCSTA = %10010000  Declare Hserial_TXSTA = %00100000        Declare Hserial_Baud = 38400        Declare Hserial_Clear = On         Symbol RS485AKT = PORTB.1'standart variableDim RCV_BYTE As ByteDim SR_BYTE_CNT As ByteDim SEND_BYTE_CNT As WordDim START_ADRESS As WordDim ZAMAN As ByteDim AI_ZAMAN As ByteDim SR_STR[110] As ByteDim IQ_TABLE[100] As ByteDim V1 As ByteDim V2 As ByteDim V3 As WordDim CRC_16 As Word'Demo variableDim sayac As ByteDim sayac2 As ByteClear'INTERRUPTINTCON = %11100000T0CON = %11000001        PIE1.5 = 1DelayMS 1000         On Interrupt GoTo INT_LOOPEnableLow RS485AKTIQ_TABLE[1] = ERead 0   'Modul adress;********************** START ***********************************start:Inc sayacIf sayac = 0 Then Inc sayac2IQ_TABLE[5] = sayac2If sayac2.1 = 1 Then Inc IQ_TABLE[5]If sayac2.2 = 1 Then Inc IQ_TABLE[7]If PIE1.4 = 0 And PIE1.5 = 0  And ZAMAN > 5 Then  Low RS485AKT : ZAMAN = 0 : PIE1.5 = 1GoTo start;-------------------------------------------------------------------;*********************** INTERRUPT *********************************INT_LOOP: Disable'RECEIVE BUFFER'DA BILGI VARSA ALMA ISLEMLERIIf PIE1.5 = 1 Then    If PIR1.5 = 1 Then        If ZAMAN > 4 Then SR_BYTE_CNT = 0         ZAMAN = 0        HSerIn [RCV_BYTE]        SR_STR[SR_BYTE_CNT] = RCV_BYTE         SR_BYTE_CNT = SR_BYTE_CNT + 1         GoTo CIKIS    EndIf        EndIf'OUTPUT BUFFER'DA BILGI YOKSA YENİSİNİ GÖNDERME ISLEMLERIIf PIE1.4 = 1 Then    If PIR1.4 = 1 Then        ZAMAN = 0        If SR_BYTE_CNT > SEND_BYTE_CNT - 1  Then             PIE1.4 = 0 :  SR_BYTE_CNT = 0 : GoTo CIKIS         EndIf        HSerOut [SR_STR[SR_BYTE_CNT]]        SR_BYTE_CNT = SR_BYTE_CNT + 1        GoTo CIKIS    EndIfEndIfIf INTCON.2 = 1 Then    INTCON.2 = 0    Inc ZAMAN    Inc AI_ZAMAN    If ZAMAN > 6 Then        ZAMAN = 0         GoSub MODBUS    EndIfEndIfCIKIS:ResumeEnable;;******************* MODBUS SORGU ÇÖZME İŞLEMLERİ ******************MODBUS: If PIE1.5 = 0 Then ReturnIf SR_BYTE_CNT < 8 Then ReturnPIE1.5 = 0  'RCV İNTERRUPT KAPATILIYOR'ALINAN BİLGİLER TAMAMLANDI KONTROL EDİLİYOR       If SR_STR[0] = IQ_TABLE[1] Then  'ADRES KONTROL EDİLİYOR     GoSub CRC16 'CRC16 HESAPLA    If CRC_16.Byte0 = SR_STR[SR_BYTE_CNT-2] Then              If CRC_16.Byte1 = SR_STR[SR_BYTE_CNT-1] Then            High RS485AKT                START_ADRESS = ((SR_STR[2]*256) + SR_STR[3]) * 2            'BİLGİLER OKUNMAK İSTENDİ             If SR_STR[1] = 3 Or SR_STR[1] = 4 Then                                     SEND_BYTE_CNT = (((SR_STR[4]*256) + SR_STR[5])* 2) + 5                'İSTENİLEN ADRES SINIR DIŞINDA                If START_ADRESS  + SEND_BYTE_CNT - 5 > 102 Then GoTo REG_ADR                 'GÖNDERİLEN STRİNG OLUŞTURMA                SR_STR[2] = SEND_BYTE_CNT - 5                For V1 = START_ADRESS To START_ADRESS + SEND_BYTE_CNT                    SR_STR[V1-START_ADRESS + 3] = IQ_TABLE[V1]                                   Next                GoSub SEND_CRC16                Return            EndIf             'TEK VARİABLE DEĞİŞTİRİLDİ             If SR_STR[1] = 6 Then                 'İSTENİLEN ADRES SINIR DIŞINDA                If START_ADRESS > 100 Then GoTo REG_ADR                 'LİMİT KONTROL                    If START_ADRESS < 21 Then                     If (SR_STR[4]*256) + SR_STR[5] > 1023 Then GoTo LIMIT_OUT                EndIf                                 If START_ADRESS > 20 Then                     If START_ADRESS < 35 Then                         If (SR_STR[4]*256) + SR_STR[5] = 0 Then GoTo LIMIT_OUT                        If (SR_STR[4]*256) + SR_STR[5] > 255 Then GoTo LIMIT_OUT                    EndIf                EndIf                                                                                                         IQ_TABLE[START_ADRESS] = SR_STR[4]                IQ_TABLE[START_ADRESS + 1] = SR_STR[5]                GoSub KAYIT                'GÖNDERİLEN STRİNG OLUŞTURMA                SEND_BYTE_CNT = 8                GoSub SEND_CRC16                Return            EndIf                        'ÇOKLU VARİABLE DEĞİŞTİRİLDİ             If SR_STR[1] = 16 Then                   SEND_BYTE_CNT = SR_STR[6] + 5  'GONDERİLEN DATA BYTE SAYISI                 'İSTENİLEN ADRES SINIR DIŞINDA                If START_ADRESS  + SEND_BYTE_CNT - 5 > 102 Then GoTo REG_ADR                'STRİNG BOYU HATALI                If SEND_BYTE_CNT + 4 <> SR_BYTE_CNT Then GoTo REG_ADR                                  For V1 = START_ADRESS To START_ADRESS + SEND_BYTE_CNT - 6                                        'LİMİT KONTROL                        If V1.0 = 0 Then 'SADECE FİRST BYTE'DA ÇALIŞMASI İÇİN                        V3 = SR_STR[V1 - START_ADRESS + 7] * 256  'YAZILMAK İSTENEN DEĞER                         V3 = V3 + SR_STR[V1 - START_ADRESS + 8]   'TESPİT EDİLİYOR                        If START_ADRESS < 21 Then                             If V3 > 1023 Then GoTo LIMIT_OUT                        EndIf                         If V1 > 20 Then                             If V1 < 35 Then                                 If V3 = 0 Then GoTo LIMIT_OUT                                If V3 > 255 Then GoTo LIMIT_OUT                            EndIf                        EndIf                                                                                                                                                  EndIf                                                                                                                                                    IQ_TABLE[V1] = SR_STR[V1 - START_ADRESS + 7]                Next                GoSub KAYIT                'GÖNDERİLEN STRİNG OLUŞTURMA                SEND_BYTE_CNT = 8                                                GoSub SEND_CRC16                Return            EndIf                                                                 'GEÇERSİZ FONKSİYON KODU            SEND_BYTE_CNT = 5            SR_STR[2] = 1            GoSub SEND_CRC16             Return        EndIf        EndIfEndIf    SR_BYTE_CNT = 0Return  'REGISTIR ADRES SINIR DIŞIREG_ADR:SEND_BYTE_CNT = 5SR_STR[2] = 2GoSub SEND_CRC16 Return'LİMİT SINIR DIŞILIMIT_OUT:SEND_BYTE_CNT = 5SR_STR[2] = 3GoSub SEND_CRC16 Return   ;;************************** GÖNDERİLEN CRC-HESAPLATMA ****************SEND_CRC16:SR_BYTE_CNT = SEND_BYTE_CNTGoSub CRC16SR_STR[SEND_BYTE_CNT - 2] = CRC_16.Byte0SR_STR[SEND_BYTE_CNT - 1] = CRC_16.Byte1SR_BYTE_CNT = 0PIE1.4 = 1  Return;;**************************  CRC-16 hesap *************************CRC16:V1 = 0V2 = 0V3 = 0CRC_16 = 65535For V1 = 0 To SR_BYTE_CNT - 3    V3 = CRC_16    CRC_16.Byte0 = V3.Byte0 ^ SR_STR[V1]       For V2 = 0 To 7        If CRC_16.0 = 1 Then             CRC_16 = CRC_16 >> 1                        CRC_16 = CRC_16 ^ 40961        Else            CRC_16 = CRC_16 >> 1         End If    Next V2Next V1 Return;KAYIT:If IQ_TABLE[1] <> ERead 0 Then EWrite 0,[IQ_TABLE[1]]Return
hayal etemeden basaramazsınız
u cnt achieve w/out dreamin

Elzemefe

magic_gun hocam
süper bir algoritma  görüyorum ama  o kadar karışık ki ..  yada bana karışık geliyor
hmı panel ile okunan 2 adet adc bilgisini panelde göstermek için bir  örnek yapalım
bende panel var delta  devreyi ben  kurarım burayada  örnek  olur pıc  yazılımınıda
siz yazarım derseniz. Ben varım

efor

gun han bey :D merhaba,

'LİMİT KONTROL   
                    If V1.0 = 0 Then 'SADECE FİRST BYTE'DA ÇALIŞMASI İÇİN
                        V3 = SR_STR[V1 - START_ADRESS + 7] * 256  'YAZILMAK İSTENEN DEĞER
                        V3 = V3 + SR_STR[V1 - START_ADRESS + 8]   'TESPİT EDİLİYOR
                        If START_ADRESS < 21 Then
                            If V3 > 1023 Then GoTo LIMIT_OUT
                        EndIf
                        If V1 > 20 Then
                            If V1 < 35 Then
                                If V3 = 0 Then GoTo LIMIT_OUT
                                If V3 > 255 Then GoTo LIMIT_OUT
                            EndIf
                        EndIf                                                                                                                             
                    EndIf               

kodu derlerken şu kısımda hata alıyorum;

                        V3 = SR_STR[V1 - START_ADRESS + 7] * 256  'YAZILMAK İSTENEN DEĞER
                        V3 = V3 + SR_STR[V1 - START_ADRESS + 8]   'TESPİT EDİLİYOR


bunun yerine ;
                        dım str1 as byte
                        dım str2 as byte

                        str1=V1 - START_ADRESS + 7
                        str2=V1 - START_ADRESS + 8

                        V3 = SR_STR[str1] * 256  'YAZILMAK İSTENEN DEĞER
                        V3 = V3 + SR_STR[str2]   'TESPİT EDİLİYOR


şeklinde düzeltsek aynı işlem olurmu ?


birde bu kod için isiste şema kurdum fakat çalıştırmadım. isis simulasyonu kurabilirmsiniz?


emrah...


magic_gun


aldığın hata zannedersem kulladigin compilerden kaynaklı

ky=V1 - START_ADRESS + 7V3 = SR_STR[ky] * 256 V3 = V3 + SR_STR[V1 - START_ADRESS + 8]




tabiki olur :)

tahmin ediyorumki elinde plc var direk canlı canlı dene :)

hayal etemeden basaramazsınız
u cnt achieve w/out dreamin

gogoce

Merhaba . Konuyu hortlatıyorum ama bu crc olayını çözebildiniz mi?
benzer projem var
Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

Powered by EzPortal