Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATMEGA][BASCOM]Niesprawna komunikacja SPI. Rozwiązane.

Ciapol 08 Feb 2010 22:46 3625 2
  • #1
    Ciapol
    Level 24  
    Witam szanowne grono forumowiczów. Od pewnego czasu borykam się z problemem konfiguracji SPI.

    Mam połączoną jedną atmegę8 jako master i 4 jako slave w sprzętowym SPI.

    Cztery atmegi pracujące w trybie slave zajmują się obsługą wyświetlaczy ledowych (dla każdej atmegi 4 8 segmentowe wyświetlacze obsługiwane multiplekowo). Obsługa samych wyświetlaczy działa bezproblemowo i nie przysparza najmniejszych problemów. Problem polega na samej komunikacji. Jeśli w masterze usunę całą pętlę nieskończoną i wyślę 4 zmienne (do któych wcześniej przypisałem wartości na stałe) do slave'a, w którym PRZED nieskończoną pętlą wczytam z SPI te bajty - wszystko hula jak należy. Wyświetlają się dokładnie takie liczby jakie wysłałem. Nie ma efekt "migania" wyświetlaczy. Problem pojawia się kiedy chcę wykonać taki oto kod:

    MASTER:
    Code:
    $regfile = "m8def.DAT"
    
    $crystal = 1000000
    '$sim                                                        'szybsza symulacja - wyłącz przy programowaniu!

    Config Portd.7 = Output
    Portd.7 = 1
    Config Spi = Hard , Master = Yes , Noss = 0 , Interrupt = On , Data Order = Msb , Polarity = Low , Clockrate = 4
    Config Portb = Output
    Spiinit


    Dim Minus As Byte
    Dim D As Byte
    Dim J As Byte
    Dim P As Byte

    Do


    For D = 0 To 9
       For J = 0 To 9
         For P = 0 To 9
             Portd.7 = 0
             Spiout D , 1
             Spiout J , 1
             Spiout P , 1
             Portd.7 = 1
             Waitms 200
          Next P
       Next J
    Next D


    Loop


    SLAVE:
    Code:
    $regfile = "m8def.DAT"
    
    $crystal = 1000000
    '$sim                                                        'szybsza symulacja - wyłącz przy programowaniu!


    Config Portc = Output                                       'port c jako wyjścia
    Config Portd = Output                                       'port d jako wyjścia
    Config Portb = Output




    'Konfiguracja SPI
    Config Spi = Hard , Master = No , Noss = 0 , Interrupt = On , Data Order = Msb , Polarity = Low , Clockrate = 4
    Spiinit


    Dim Minus As Byte
    Dim Dziesiatki As Integer
    Dim Jednosci As Integer                                     'ta liczba zawsze z kropką! Ta atmega tego nie będzie przetwarzać
    Dim Dziesietne As Integer


    Minus = 1



    Do
       'On Spi Odczytaj_nowe
    Portd = &B00000000                                          ' ustawian stany
    Portc = &B11111111                                          ' "nieświecenia" wyswietlaczy

    '========== Wczytywanie do zmiennych kolejnych bajtów przesłanych przes ATMEGA MASTER ==================
    'Spiin Minus , 1
    Spiin Dziesiatki , 1
    Spiin Jednosci , 1
    Spiin Dziesietne , 1
    '========================================== Koniec pobierania danych ===================================

    '============= wyswietlacz znaku ==========================
       If Minus = 1 Then
          Portc.3 = 0                                           'aktywuje wyswietlacz odpowiedzialny za minus/plus
          Portd.6 = 1                                           ' wyswietla znak "-"
       End If
       Waitms 2
       Portc.3 = 1                                              'wygaszanie wyswietlacza odpowiedzialnego za minus/plus


    '============= wyswietlacz dziesiatek======================
       Portc.2 = 0                                              'aktywuje wyswietlacz odpowiedzialny za dziesiatki
          Select Case Dziesiatki
            Case 0 : Portd = &B00111111
            Case 1 : Portd = &B00000110
            Case 2 : Portd = &B01011011
            Case 3 : Portd = &B01001111
            Case 4 : Portd = &B01100110
            Case 5 : Portd = &B01101101
            Case 6 : Portd = &B01111101
            Case 7 : Portd = &B00000111
            Case 8 : Portd = &B01111111
            Case 9 : Portd = &B01101111
          End Select
       Waitms 2
       Portc.2 = 1
                                                    'wygaszenie wyswietlacza odpowiedzialnego za dziesiatki

    '============= wyswietlacz jednosci=========================

       Portc.1 = 0                                              'aktywuje wyswietlacz odpowiedzialny za jednosci
          Select Case Jednosci
            Case 0 : Portd = &B10111111
            Case 1 : Portd = &B10000110
            Case 2 : Portd = &B11011011
            Case 3 : Portd = &B11001111
            Case 4 : Portd = &B11100110
            Case 5 : Portd = &B11101101
            Case 6 : Portd = &B11111101
            Case 7 : Portd = &B10000111
            Case 8 : Portd = &B11111111
            Case 9 : Portd = &B11101111
          End Select
         Waitms 2
         Portc.1 = 1
                                            'wygaszenie wyswietlacza odpowiedzialnego za jednosci

    '=========== wyswietlacz cyfry dziesiętnej ==================

       Portc.0 = 0                                              'aktywuje wyswietlacz odpowiedzialny za cyfry po przecinu
          Select Case Dziesietne
            Case 0 : Portd = &B00111111
            Case 1 : Portd = &B00000110
            Case 2 : Portd = &B01011011
            Case 3 : Portd = &B01001111
            Case 4 : Portd = &B01100110
            Case 5 : Portd = &B01101101
            Case 6 : Portd = &B01111101
            Case 7 : Portd = &B00000111
            Case 8 : Portd = &B01111111
            Case 9 : Portd = &B01101111
          End Select
       Waitms 2
       Portc.0 = 1
                                                    'wygaszenie wyswietlacza odpowiedzialnego za cyfry po przecinu
    Loop


    Wyświetlacz przez ułamek sekundy wyświetla jakieś liczby (wygenerowane przez pętle for jak się domyślam) i na ok 200ms przygasa. Jeżeli w masterze usunę linię Waitms 200 to wyświetlacz wyświetla liczby tak szybko, że nie jestem w stanie ich odczytać (co jest poprawne wg mnie). Nie rozumiem jednak dlaczego w pierwszym przypadku wyświetlacze są wygaszane na 200 ms i na ułamek sekundy pojawiają się cyfry. Wydaje mi się, że ten kod powinien wyświetlić na wyświetlaczach liczbę 00.0, po 200ms 00.1 itd. Przekopałem już setki stron. Kilkakrotnie czytałem helpa bascoma jak i samą notę Atmela o SPI. Nic nie przychodzi mi do głowy. Próbowałem już wielu konfiguracji SPI - bez zmian. Aha - jeśli chodzi o samą obsługę wyświetlaczy to jestem pewien, że jest ok (lcd'ki są podłączone przez inwerter, stąd takie a nie inne ustawianie stanów na portach). Proszę nie pytać dlaczego akurat tak a nie poprzez zadeklarowane tablice obsługuje lcd - musi zostać tak jak jest. Dla testów podłączam tylko jednego slave'a na razie pod PD7. Za pomoc oczywiście będą punkty.
  • #2
    marco47
    Level 41  
    A dlaczego kolega zastosował cztery atmega8 do wyświetlania na LED'ach 4x4=16 . Przecież spokojnie zrobi to jedna atmega8 i jeszcze można dołożyć wyświetlacz LCD , a wyrobi się spokojnie i bez jakichkolwiek problemów i zajmuje to tylko jeden port .
  • #3
    Ciapol
    Level 24  
    Bo master zajmować się będzie jeszcze obsługą uart i 4 czujnikami ds. Generalnie niewielki miałem na to wpływ. Obwody były już wcześniej przez kogoś zaprojektowane. Ja mam to tylko oprogramować.

    A skąd wyliczenia 4x4 = 16?

    Naprawdę nikt nie jest w stanie pomóc?

    EDIT: Problem został rozwiązany. Główną przyczyną było odpowiednie zakomunikowanie Atmedze, że wykorzystujemy przerywania. Druga rzecz to odpowiednie rozpoczęcie wysyłania w masterze i odbieranie danych w slave - otóż przed wysłaniem prawidłowych danych wysyłam teraz zmienną w której zapisane jest 0, odbieram ją w slavie do niewykorzystywanej później zmiennej i wszystko działa. Poniżej kody.

    Slave:

    Code:
    $regfile = "m8def.DAT"
    
    $crystal = 8000000
    '$sim                                                        'szybsza symulacja - wyłącz przy programowaniu!


    Config Portc = Output                                       'port c jako wyjścia
    Config Portd = Output                                       'port d jako wyjścia
    Config Portb.4 = Output
    Config Portb.3 = Input
    Config Portb.5 = Input
    Config Portb.2 = Input


    'Konfiguracja SPI
    'Config Spi = Soft , Din = Pinb.4 , Dout = Portb.3 , Ss = PortB.2 , Clock = Portb.5
    Config Spi = Hard , Master = No , Noss = 0 , Interrupt = On , Data Order = Msb , Polarity = Low , Clockrate = 128 , Phase = 0,


    Wait 1

    Dim M As Byte
    Dim D As Byte
    Dim J As Byte
    Dim U As Byte
    Dim Temp As Byte


    Spiinit

    On Spi Odczytaj_nowe
    Enable Interrupts

    Spiinit



    Portd = &B00000000                                          ' ustawian stany
    Portc = &B11111111

    Wait 1
    Do

    'Portd = &B00000000                                          ' ustawian stany
    'Portc = &B11111111                                          ' "nieświecenia" wyswietlaczy

    '========== Wczytywanie do zmiennych kolejnych bajtów przesłanych przes ATMEGA MASTER ==================
    'Spiin Dziesiatki , 1
    'Spiin Jednosci , 1
    'Spiin Dziesietne , 1
    '========================================== Koniec pobierania danych ===================================
    '

    '============= wyswietlacz znaku ==========================

          Select Case M
            Case 0 : Portd = &B00000000
            Case 1 : Portd = &B01000000
          End Select
       Portc = &B11110111
       Waitms 2
       Portc = &B11111111
                                              'wygaszanie wyswietlacza odpowiedzialnego za minus/plus


    '============= wyswietlacz dziesiatek======================
                                                     'aktywuje wyswietlacz odpowiedzialny za dziesiatki
          Select Case D
            Case 0 : Portd = &B00000000
            Case 1 : Portd = &B00000110
            Case 2 : Portd = &B01011011
            Case 3 : Portd = &B01001111
            Case 4 : Portd = &B01100110
            Case 5 : Portd = &B01101101
            Case 6 : Portd = &B01111101
            Case 7 : Portd = &B00000111
            Case 8 : Portd = &B01111111
            Case 9 : Portd = &B01101111
          End Select
       Portc = &B11111011
       Waitms 2
       Portc = &B11111111
                                                    'wygaszenie wyswietlacza odpowiedzialnego za dziesiatki

    '============= wyswietlacz jednosci=========================

                                                     'aktywuje wyswietlacz odpowiedzialny za jednosci
          Select Case J
            Case 0 : Portd = &B10111111
            Case 1 : Portd = &B10000110
            Case 2 : Portd = &B11011011
            Case 3 : Portd = &B11001111
            Case 4 : Portd = &B11100110
            Case 5 : Portd = &B11101101
            Case 6 : Portd = &B11111101
            Case 7 : Portd = &B10000111
            Case 8 : Portd = &B11111111
            Case 9 : Portd = &B11101111
          End Select
          Portc = &B11111101
         Waitms 2
         Portc = &B11111111
                                            'wygaszenie wyswietlacza odpowiedzialnego za jednosci

    '=========== wyswietlacz cyfry dziesiętnej ==================

                                                     'aktywuje wyswietlacz odpowiedzialny za cyfry po przecinu
          Select Case U
            Case 0 : Portd = &B00111111
            Case 1 : Portd = &B00000110
            Case 2 : Portd = &B01011011
            Case 3 : Portd = &B01001111
            Case 4 : Portd = &B01100110
            Case 5 : Portd = &B01101101
            Case 6 : Portd = &B01111101
            Case 7 : Portd = &B00000111
            Case 8 : Portd = &B01111111
            Case 9 : Portd = &B01101111
          End Select
       Portc = &B11111110
       Waitms 2
       Portc = &B11111111
                                                    'wygaszenie wyswietlacza odpowiedzialnego za cyfry po przecinu
    Loop

    Odczytaj_nowe:
       Temp = Portc
       Portc = &B11111111
       Spiin M , 1
       Spiin D , 1
       Spiin J , 1
       Spiin U , 1
       Portc = Temp
    Return


    Master:
    Code:
    $regfile = "m8def.DAT"
    
    $crystal = 8000000
    $sim


    $baud = 19200

    Config Portd.7 = Output
    Config Portb.0 = Output
    Config Portb.1 = Output
    Config Portc.1 = Output
    Config Portb.2 = Output
    Portd.7 = 1
    Portb.0 = 1
    Portb.1 = 1
    Portb.2 = 1

    Config Portb.4 = Input
    Config Portb.3 = Output
    Config Portb.5 = Output


    Config Spi = Hard , Master = Yes , Noss = 1 , Interrupt = Off , Data Order = Msb , Polarity = Low , Clockrate = 128

    Config 1wire = Portc.0

    Dim M As Byte
    Dim D As Byte
    Dim J As Byte
    Dim U As Byte
    Dim Temp As Byte

    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    Dim Dsid3(8) As Byte
    Dim Dsid4(8) As Byte


    Dim I1 As Integer
    Dim I2 As Integer
    Dim I3 As Integer
    Dim I4 As Integer
    Dim Tymczasowo As Integer
    Dim Tymczasowo2 As Integer
    Dim Tymczasowo3 As Integer
    Dim Tymczasowo4 As Integer
    Tymczasowo = 100
    Tymczasowo2 = 200
    Tymczasowo3 = 300
    Tymczasowo4 = 400


    Dim Tempstring1 As String * 6
    Dim Tempstring2 As String * 6
    Dim Tempstring3 As String * 6
    Dim Tempstring4 As String * 6
    Dim Strtemp As String * 1

    Wait 1

    Spiinit

    Wait 1

    M = 0
    D = 0
    J = 0
    U = 0

    Temp = 0



    Dsid1(1) = 1wsearchfirst()
    Dsid2(1) = 1wsearchnext()
    Dsid3(1) = 1wsearchnext()
    Dsid4(1) = 1wsearchnext()

    Wait 1

    Print "s"

    Do



       1wreset
       1wwrite &HCC
       1wwrite &H44
    Waitms 1500


       1wreset
       1wwrite &H55
       1wverify Dsid1(1)
       1wwrite &HBE
       I1 = 1wread(2)

       1wreset
       1wwrite &H55
       1wverify Dsid2(1)
       1wwrite &HBE
       I2 = 1wread(2)

       1wreset
       1wwrite &H55
       1wverify Dsid3(1)
       1wwrite &HBE
       I3 = 1wread(2)

       1wreset
       1wwrite &H55
       1wverify Dsid4(1)
       1wwrite &HBE
       I4 = 1wread(2)



    I1 = I1 * 10
    I1 = I1 / 16

    I2 = I2 * 10
    I2 = I2 / 16

    I3 = I3 * 10
    I3 = I3 / 16

    I4 = I4 * 10
    I4 = I4 / 16



    Tempstring1 = Str(i1)
    Tempstring2 = Str(i2)
    Tempstring3 = Str(i3)
    Tempstring4 = Str(i4)


    If I1 < 0 Then
       If I1 < -9 Then
          If I1 < -99 Then
             M = 1
             Strtemp = Mid(tempstring1 , 2 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring1 , 3 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring1 , 4 , 1)
             U = Val(strtemp)
          Else
             M = 1
             D = 0
             Strtemp = Mid(tempstring1 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring1 , 3 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 1
          D = 0
          J = 0
          Strtemp = Mid(tempstring1 , 2 , 1)
          U = Val(strtemp)
       End If
    Else
       If I1 > 9 Then
          If I1 > 99 Then
             M = 0
             Strtemp = Mid(tempstring1 , 1 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring1 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring1 , 3 , 1)
             U = Val(strtemp)
          Else
             M = 0
             D = 0
             Strtemp = Mid(tempstring1 , 1 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring1 , 2 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 0
          D = 0
          J = 0
          U = I1
       End If
    End If

    Portd.7 = 0
    Spiout Temp , 1
    Spiout M , 1
    Spiout D , 1
    Spiout J , 1
    Spiout U , 1
    Portd.7 = 1

    Print "A"
    'Print I1
    Print Tymczasowo

    If I2 < 0 Then
       If I2 < -9 Then
          If I2 < -99 Then
             M = 1
             Strtemp = Mid(tempstring2 , 2 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring2 , 3 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring2 , 4 , 1)
             U = Val(strtemp)
          Else
             M = 1
             D = 0
             Strtemp = Mid(tempstring2 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring2 , 3 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 1
          D = 0
          J = 0
          Strtemp = Mid(tempstring2 , 2 , 1)
          U = Val(strtemp)
       End If
    Else
       If I2 > 9 Then
          If I2 > 99 Then
             M = 0
             Strtemp = Mid(tempstring2 , 1 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring2 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring2 , 3 , 1)
             U = Val(strtemp)
          Else
             M = 0
             D = 0
             Strtemp = Mid(tempstring2 , 1 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring2 , 2 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 0
          D = 0
          J = 0
          U = I2
       End If
    End If

    Portc.1 = 0
    Spiout Temp , 1
    Spiout M , 1
    Spiout D , 1
    Spiout J , 1
    Spiout U , 1
    Portc.1 = 1

    Print Tymczasowo2


    If I3 < 0 Then
       If I3 < -9 Then
          If I3 < -99 Then
             M = 1
             Strtemp = Mid(tempstring3 , 2 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring3 , 3 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring3 , 4 , 1)
             U = Val(strtemp)
          Else
             M = 1
             D = 0
             Strtemp = Mid(tempstring3 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring3 , 3 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 1
          D = 0
          J = 0
          Strtemp = Mid(tempstring3 , 2 , 1)
          U = Val(strtemp)
       End If
    Else
       If I3 > 9 Then
          If I3 > 99 Then
             M = 0
             Strtemp = Mid(tempstring3 , 1 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring3 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring3 , 3 , 1)
             U = Val(strtemp)
          Else
             M = 0
             D = 0
             Strtemp = Mid(tempstring3 , 1 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring3 , 2 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 0
          D = 0
          J = 0
          U = I3
       End If
    End If

    Portb.0 = 0
    Spiout Temp , 1
    Spiout M , 1
    Spiout D , 1
    Spiout J , 1
    Spiout U , 1
    Portb.0 = 1

    Print Tymczasowo3


    If I4 < 0 Then
       If I4 < -9 Then
          If I4 < -99 Then
             M = 1
             Strtemp = Mid(tempstring4 , 2 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring4 , 3 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring4 , 4 , 1)
             U = Val(strtemp)
          Else
             M = 1
             D = 0
             Strtemp = Mid(tempstring4 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring4 , 3 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 1
          D = 0
          J = 0
          Strtemp = Mid(tempstring4 , 2 , 1)
          U = Val(strtemp)
       End If
    Else
       If I4 > 9 Then
          If I4 > 99 Then
             M = 0
             Strtemp = Mid(tempstring4 , 1 , 1)
             D = Val(strtemp)
             Strtemp = Mid(tempstring4 , 2 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring4 , 3 , 1)
             U = Val(strtemp)
          Else
             M = 0
             D = 0
             Strtemp = Mid(tempstring4 , 1 , 1)
             J = Val(strtemp)
             Strtemp = Mid(tempstring4 , 2 , 1)
             U = Val(strtemp)
          End If
       Else
          M = 0
          D = 0
          J = 0
          U = I4
       End If
    End If

    Portb.1 = 0
    Spiout Temp , 1
    Spiout M , 1
    Spiout D , 1
    Spiout J , 1
    Spiout U , 1
    Portb.1 = 1

    Print Tymczasowo4


    Tymczasowo = Tymczasowo + 1
    Tymczasowo2 = Tymczasowo2 + 1
    Tymczasowo3 = Tymczasowo3 + 1
    Tymczasowo4 = Tymczasowo4 + 1
    Loop


    Przy czym master zajmuje się jeszcze wysyłaniem danych po Uarcie. Zmienne Tymczasowo..Tymczaosowo4 stworzone zostały jedynie w po to abym mógł symulować działanie atmegi i wysyłać dane (nie zerowe co występowało w przypadku zmiennych czujników) za pomocą UART na wirtualnie połączony z innym port COM. Zostało stworzone jeszcze oprogramowanie na PC odbierające te dane i wysyłające na serwer mysql.
    Mam nadzieję, że pomogłem komuś kto miał ten sam problem.

    Temat zamykam. W razie pytań zapraszam na PW.