logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Problem z komunikacją RS485 - bascom

luke_dra 26 Mar 2010 22:41 4130 2
  • #1 7884405
    luke_dra
    Poziom 10  
    Witam,

    Mam mały problem z komunikacją między uC. Ale od początku.
    Schemat układu pochodzi z EP
    Problem z komunikacją RS485 - bascom Problem z komunikacją RS485 - bascom

    Samą komunikację udało mi się zestawić i działa bardzo dobrze (załączony kod poniżej). Master non stop odpytuje slave i jest git. I teraz mój problem, chcę dodać w masterze odpytywanie powiedzmy co 0,5 s i tu zonk. Kiedy dodam Waitms 500 po każdej pętli komunikacja pada. Nic się nie dzieje. Co robię nie tak??
       
    Do 
          'Waitms 2 
          Set Re_de 
                                                      'czekaj 1ms 
          Print "{008}5r" 
    
          Waitms 10 
          Reset Re_de
     
          Call Odczyt_zn 
          
          Lcdat 40 , 60 , Zm_lan , Yellow , Red 
          Lcdat 80 , 60 , "8.2" , Yellow , Red 
          
          If Opcja <> 4 Then 
             Exit Do 
          End If 
          
          Waitms 500 
       Loop 



    Slave
    
    $regfile = "m8def.dat"                                      'informujekompilatoroplikudyrektywwykorzystywanego
                                                                'mikrontrolera
    $crystal = 16000000                                         'informuje kompilator o czestotliwosci rezonatora kwarcowego
    $baud = 19200                                               ' use baud rate
    $hwstack = 32                                               ' default use 32 for the hardware stack
    $swstack = 10                                               ' default use 10 for the SW stack
    $framesize = 40
    
    Config Lcdbus = 4
    Config Lcd = 16 * 2 : Cursor Off
    Config Lcdpin = Pin , Db4 = Pc.2 , Db5 = Pc.3 , Db6 = Pc.4 , Db7 = Pc.5 , E = Pc.1 , Rs = Pc.0
    
                                              'informuje kompilator o predkosci transmisji RS232
    
    Config Pind.2 = Output
    'Config Pinc.5 = Output
                                          'linia pd.2 jako wyjscie
    'Config Adc = Single , Prescaler = Auto , Reference = Avcc
                                                                   'konfiguracjawewnetrznegoprzetwornika
    Config Serialin = Buffered , Size = 15
                                                                   'konfiguracjabyinterfejsrs232uzywalprzyodbiorzetransmisji
                                                                   'buforowej (bufor o wielkosci 15 znakow)
    
    Const Adrr = 5                                              'adres ukladu - od 0 do 99
    
    Dim Wart_zm As Word                                         'zmienna przechowujaca wartosc zmierzona przez przetwornik A/C
    Dim Temp As Integer                                         'zmienna ktora przechowuje obliczona temperature
    Dim Zn As String * 1                                        'zmienna przecowujaca odebrany znak z rs232
    Dim Adr_s As String * 5                                     'zmienna w ktorej skladany jest w calosc otrzymany adres
    Dim Adres As Byte                                           'zmienna ktora przechowuje przekonwertowany
                                                                   'na dziesietnie otrzymany adres
    Dim Il_zn As Byte                                           'zmienna liczy ilosc otrzymanych znakow przy skladaniu adresu
    Re_de Alias Portd.2                                         'przypisanie aliasu linii pd.2, re_de steruje kierunkiem
    
    Cls
                                                                   'transmisji konwertera
    'Lcd "luke"
    'Start Adc                                                   'uruchamia wbudowany przetwornik A/C
    Enable Interrupts                                           'odblokowanie globalnych przerwan
    Reset Re_de                                                 'przelaczenie konwertera rs485 na odbiornik
    
    Temp = 0
    
    Do
       Reset Re_de                                              'poczatek petli programu
       Cls
    
    
       Temp = Temp + 1
       'Waitms 15
       If Temp = 255 Then
          Temp = 0
       End If                                                   'dalsze obliczenie zmierzonej temperatury
    
    
       Zn = Inkey()                                             'odczyt znaku z portu rs232
       If Zn = Chr(8) Then                                      'jesli otrzymany znak to BS (backspace - kod ascii 8) to
         ' Set Portc.5
          Adr_s = ""                                            'czysc zmienna adr_s
          Il_zn = 0                                             'oraz zeruj zmienna il_zn
          Do                                                    'poczatek petli do-loop
             Zn = Inkey()                                       'odczyt znaku z portu rs232
             If Zn >= "0" And Zn <= "9" Then                    'jesli otrzynany znak jest cyfra (0..9) to
                Incr Il_zn                                      'zwieksz o jeden il_zn
                Adr_s = Adr_s + Zn                              'dodaj otrzymany znak cyfry do zmiennej adr_s
             Else                                               'w przeciwnym razie
                If Zn > Chr(0) Then                             'jesli otrzymany znak ma kod ascii wiekszy od 0 to
                   Exit Do                                      'opusc petle do-loop
                End If
             End If
          Loop
          Locate 1 , 1
          Lcd Adr_s ; Zn
    
    
          If Zn = "r" Then                                      'jesli otrzymany znak to "r" oraz
          If Il_zn > 0 And Il_zn < 3 Then                       'jesli il_zn wynosi 1 lub 2 to
             Adres = Val(adr_s)                                 'zamien znakowa wartosc otrzymanego adresu                                 'na postac liczbowa i umiesc ja w adres
             If Adres = Adrr Then
                Do                                              'poczatek wewnetrznej petli do-loop
                   Zn = Inkey()                                 'odczyt znaku z portu rs232
                Loop Until Zn = Chr(13)                         'jesli otrzymany znak to cr - enter (kod ascii 13) to
                                                                   'przelaczenie konwertera rs485 na nadajnik
                Set Re_de
                Waitus 200                                      'czekaj 200 us
                Print Temp
                Waitms 10
                                       'czekaj 1ms
                Reset Re_de                                     'przelaczenie konwertera rs485 na odbiornik
             End If
          End If
       End If
    End If
    Loop                                                        'koniec glownej petli do-loop
    End 
    


    Master
    
    .......
    ......
    
       Do
          'Waitms 2
    
          Set Re_de
                                                      'czekaj 1ms
          Print "{008}5r"
    
          Waitms 10
    
          Reset Re_de
    
          Call Odczyt_zn
    
          Lcdat 40 , 60 , Zm_lan , Yellow , Red
    
          Lcdat 80 , 60 , "8.2" , Yellow , Red
    
          If Opcja <> 4 Then
             Exit Do
          End If
    
          'Waitms 500
       Loop
    
       Call Cz16
    
    Return
    
    
    Sub Odczyt_zn                                               'procedura odczytu znakow nadawanych przez uklady slave
       Czekaj = 0                                               'zerowanie zmiennej czekaj
       Zm_lan = ""                                              'czyszczenie zmiennej znakowej zm_lan
       Do                                                       'poczatek petli do-loop
          Incr Czekaj                                           'zwieksz o jeden zmienna czekaj
          Zn = Inkey()
         ' Lcdat 1 , 1 , "Oczyt " ; Zn , 0                       'odczyt znaku z bufora rs232
          If Zn >= "0" And Zn <= "9" Then                       'jesli odczytany znak na kod ascii liczby
                                           'z zakresu 0..9 to
             Zm_lan = Zm_lan + Zn                               'dodaj odczytany znak do zmiennej zm_lan
          End If
          'Waitms 1                                              'czekaj 1ms
       Loop Until Zn = Chr(13) Or Czekaj > 100                  'petla wykonywana az otrzymano znak CR (ascii 13)
    'lub zmienna czejaj> niz 100
    End Sub
    


    Proszę poprawić temat, reg. pkt 11.1.
    Robak
  • Pomocny post
    #3 7906735
    OlekM
    Poziom 17  
    Również nie jestem Bascomowcem ale być może moje uwagi okażą się cenne.

    Po instrukcji Print "{008}5r", dane jest 10 ms opóźnienia. W tym czasie slave mógł już przesłać wszystkie swoje dane - a master jeszcze nie rozpoczął nasłuchu.

    Inną sprawą jest to, że 100 obiegów pętli w procedurze Odczyt_zn może trwać krócej niż transmisja jednego znaku przez UART :-)

    Jak rozumiem opóźnienie 10ms ma gwarantować, że konwerter poziomów nie "puści" linii 485 dopóki ostatnie bity nie przejdą. Proponuję zmniejszyć to opóźnienie do długości kilku bitów transmisji (np. dla 9600 bps, to może być 0.1 ms - 0.2 ms). To w zupełności wystarcza, a UART nie zgubi żadnej danej.

    Proszę też pamiętać, by układ slave nie rozpoczynał odpowiedzi, zanim układ master nie przejdzie w nasłuch po wysłaniu komendy.

    PS.
    Jako programujący AVR'ki w C, nie widzę nic złego w:

    if((znak >= '0') && (znak <='9')) //gdzie znak jest typu char

    8-)
REKLAMA