Elektroda.pl
Elektroda.pl
X
Arrow Multisolution Day
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

SPI Bascom AVR - prośba o wyjaśnienie

splawik00 05 Maj 2013 22:08 11031 71
  • #1 05 Maj 2013 22:08
    splawik00
    Poziom 23  

    Witam.
    Mam kłopot w okiełznaniu magistrali SPI w Bascomie. Podobno SPI jest tak samo łatwe jak I2C, jednak I2C już od dawna rozumiem na tyle, że umożliwia mi to korzystanie z tej magistrali. SPI to dla mnie czarna magia. Kompletnie nie rozumiem o co tu chodzi. I2C jest proste, a SPI w mojej opinii o wiele bardziej zagmatwane. Chciałem skomunikować ze sobą dwie sztuki Atmega8 poprzez SPI. Master odbiera od slave'a bajt i wyświetla na LCD. Niby banalne, ale nie działa.

    SPI Bascom AVR - prośba o wyjaśnienie

    Kod dla SLAVE'a:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Kod dla MASTER'a:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Bardzo proszę o wytłumaczenie co jest źle w kodzie, że nie działa
    Jaka jest różnica w poleceniach SPIIN, SPIOUT a SPIMOVE. Według help'a dwa pierwsze wysyłają i odbierają, i trzecie też wysyła i odbiera. To jaka jest różnica?
    Czy polecenie SPIOUT czeka na odbiór danych przez drugi procesor, czy wysyła je od razu i gdy drugi procesor tych danych nie odbierze to są tracone?

    0 29
  • Arrow Multisolution Day
  • #2 06 Maj 2013 09:21
    fuse
    Poziom 15  

    Na wstępie zaznaczę, że nie łączyłem tak mikroprocesorów, a tylko obsługiwałem układy peryferyjne.

    Zacząłbym od przykładów, które są dołączone do kompilatora:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    W Twoim przykładzie użyłeś w konfiguracji Clockrate = 4 i to jest dobrze, ponieważ Master musi mieć taktowanie szyny ustawione ma 1/4 zegara Slava.
    Clockrate w konfiguracji Slava nie ma znaczenia.
    Noss ustawiłeś na 2 ?, z tego co wiem można włączyć lub wyłączyć, czyli 1 lub 0.
    W kodzie Slava skonfigurowałeś MOSI jako wyjście (Config Portb.3 = Output) ?, z dokumentacji Bascoma wynika, że masz skonfigurować tylko MISO jako wyjście, ponieważ MOSI jest ustawione na stałe jako wejście.

    Pin Direction Overrides - Master SPI Mode Direction Overrides
    MOSI: User Defined
    MISO: Input
    SCK: User Defined
    SS: User Defined

    Pin Direction Overrides - Slave SPI Modes:
    MOSI: Input
    MISO: User Defined
    SCK: Input
    SS:Input

    W pomocy do Bascoma można wyczytać, że procedury dla SPI są tylko dla Mastera ("All SPI routines are SPI-master routines") i jak rozumiem nie jest całkiem prostą rzeczą obsługa Slava.

    Za pomocą SpiMove możesz jednocześnie wysłać dane do Slava, i odebrać odpowiedź, przykład powyżej powinien to umożliwić (tzn. o ile dobrze go zrozumiałem Slave odpowie Ci po odebraniu danych), a to pozwoli Ci kontrolować ilość wysłanych danych.

    Napisałem to jako czystą teorię, jako że sam tego nie testowałem, ale ciekawy jestem czy uda Ci się rozwiązać problem.

    0
  • #3 06 Maj 2013 10:09
    splawik00
    Poziom 23  

    Z tego co ja widzę to dla slave mam tylko MISO jako output, to chyba dobrze?
    Z kolegi kodu nie rozumiem za bardzo na czym polega procedura Spi_isr i co ma ustawić bit Rbit, żeby wynik pojawił się na wyświetlaczu?
    Skąd slave ma wiedzieć kiedy ma wysłać dane do mastera?
    Oraz jak to w ogóle możliwe, skoro teoretycznie dane przechodzą w takt mastera, czyli to master wysyła dane ze slave'a, a nie slave, czyli kiedy są te dane wysyłane, jak chce slave, czy jak chce master? :D :D

    0
  • Arrow Multisolution Day
  • #4 06 Maj 2013 21:08
    fuse
    Poziom 15  

    Trochę się "zakręciłem" - przyjąłem Twój pierwszy kod za kod MASTER, chociaż wyraźnie go opisałeś jako SLAVE, chyba zasugerowałem się poleceniem Spiout.

    Ale i tak nie bardzo rozumiem jak SLAVE ma wysłać dane do MASTERA, to MASTER musi zainicjować połączenie, czyli powinieneś użyć w kodzie MASTERA SPIMOVE.

    Co do procedury Spi_isr to nie jest ona moim pomysłem tylko przepisałem ją z oryginalnych przykładów dołączonych do kompilatora BASCOM, zakładam, że powinna działać :)

    Ponieważ pokręciłem kod mastera ze slavem, to należałoby usunąć obsługę wyświetlacza oraz:
    Zmienna_send = Zmienna_send + 1.

    Zerknij do pomocy BASCOMa pod hasło SPISLAVE, pierwszy przykład jest dla programowego SPI, a drugi dla sprzętowego.

    0
  • #5 06 Maj 2013 21:24
    splawik00
    Poziom 23  

    Czyli jednak master odbiera dane od slave, a nie slave je wysyła. To już coś wiadomo :D
    Nie rozumiem jednak jak. Na chłopski rozum slave powinien zapisać to, co master chce odebrać, do rejestru przesuwnego SPI, po czym master to przesuwa i ma u siebie. Ale jak slave ma to wpisać do tego rejestru o ile dobrze to wymyśliłem?

    0
  • #6 06 Maj 2013 21:36
    tmf
    Moderator Mikrokontrolery Projektowanie

    Tak, slave ma wpisać dane do SPDR zanim master ich zażąda. Żądanie mastera polega na tym, że zaczyna on zmieniać stan linii SCK, co powoduje wysuwanie kolejnych bitów danych. Popatrz na SPI jak na dwa połączone szeregowo i zapętlone rejestry przesuwne, przy czym tylko urządzenie master może generować zegar przesuwający ich zawartość.

    0
  • #8 07 Maj 2013 07:19
    fuse
    Poziom 15  

    splawik00 napisał:
    A jak slave ma wpisać tę wartość do rejestru? Jakim poleceniem?


    Spdr = Zmienna_send 'oczywiście przed odczytem.
    Tak jak napisał tmf całość działa w pętli, czyli MASTER zacznie przesyłać dane, ale jednocześnie bity z rejestru będą "przepychane" do niego.
    W kodzie mastera używasz SPIMOVE i dzięki temu wysyłasz (cokolwiek) do SLAVEa i odbierasz od niego kolejne bity z rejestru Spdr, po pełnym cyklu Spdr będzie zawierał to co wysłałeś z MASTERA.
    Przed ponową transmisją wpisujesz do Spdr to co chcesz wysłać.

    0
  • #10 07 Maj 2013 14:19
    fuse
    Poziom 15  

    Nie będzie działać, ponieważ w kodzie SLAVE nie ma wstawki asemblerowej do obsługi SPI. Bascom nie obsługuje układu ustawionego na SLAVE, więc musi być wstawka w asemblerze wywoływana przerywaniami.

    0
  • #11 07 Maj 2013 14:41
    splawik00
    Poziom 23  

    Chodzi o to co kolega wstawił w drugim poście?
    Czy mógłby to kolega podstawić do mojego przykładu, żeby działało tak jak powinno?
    Nie chodzi o to, że mi się nie chce, tylko nie rozumiem za bardzo tego kodu.
    Gdybym miał przykład działający na podstawie mojego kodu to mógłbym go przeanalizować. Sam sobie nie poradzę, gdyż nie znam Asemblera. :cry:

    0
  • #12 07 Maj 2013 19:17
    fuse
    Poziom 15  

    Bardzo ważna jest zawartość pliku m8def.dat, musi posiadać wszystkie wymagane wpisy dla obsługi SPI.

    Moim zdaniem kod Slava powinien wyglądać tak (opieram to oficjalnym przykładzie dołączonym do kompilatora):

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • #14 07 Maj 2013 21:29
    MArSTER_1
    Poziom 18  

    Dla Mastera instrukcja :"Config Portb.2 = Input" jest błędna. Powinno być
    Config Portb.2 = Output.

    Generalnie to jeśli chcesz coś wysłać ze Slave do Master to musisz uruchomić Mastera. Dlaczego? Bo to on taktuje magistralę. Musisz więc wymyślić sposób na
    poinformowanie Mastera, że Slave coś przygotował do odczytania. W Slave wystarczy to co chcesz wysłać wpisać do rejestru Spdr. Bascom obsługuje bezpośrednie wpisy do rejestrów więc nie ma problemu.

    0
  • #15 07 Maj 2013 21:50
    splawik00
    Poziom 23  

    A czy taka sama sytuacja tylko w języku C byłaby tak samo trudna do zrealizowania? Przerzucam się powoli z Bascoma na C, ale jeszcze daleka droga przede mną. Pytam z ciekawości.
    Co do kodu mastera; po zmianie na wyjście pinb.2 nadal nie działa.
    Czy wpisywanie do swojego rejestru slave ma wykonywać w tym samym czasie co master polecenie spimove? Czy najpierw może wpisać, a master odbiera kiedy chce, tak jak mam teraz?

    0
  • #16 07 Maj 2013 22:02
    MArSTER_1
    Poziom 18  

    Wpisać musisz do rejestru w Slave PRZED wykonaniem instrukcji przez Mastera. Po prostu Master wykonujac instrukcje na przykład SPIOUT wysyła osiem taktów zegara na magistrale i jednoczesnie wysyła osiem bitów ze swojego rejestru SPDR. Te osiem bitów z jego rejestru trafia do rejestru SPDR w Slave a w tym samym czasie osiem bitów z rejestru SPDR ze Slave trafia do rejestru SPDR w Master. Po prostu w ciągu tych osmiu taktów procesory wymieniają sie bajtami. Po wysłaniu (wymianie bajtów) Master zatrzymuje zegar. Oba procesory moga odczytac z rejestrów SPDR nowe bajty. Spróbuj z instrukcją SPIOUT.
    Wpisz w Slave
    SPDR= 123
    później wejdź w pętle
    Do
    Loop

    A w Master w pewnym momencie zrób

    Dat = 111 'Zmienna bajtowa DAT
    Spiout Dat , 1
    DAT = SPDR

    I wyswietl zmienną DAT.

    0
  • #17 07 Maj 2013 22:44
    splawik00
    Poziom 23  

    Masakra, dalej nie działa, no chyba że coś źle zrobiłem. Czy włączenie przerwać jest konieczne dla obu procków?

    SLAVE:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    MASTER:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    SPI Bascom AVR - prośba o wyjaśnienie

    1
  • #18 08 Maj 2013 07:23
    fuse
    Poziom 15  

    Jak zrezygnujesz z obsługi przerywań w Slave to nie będziesz wiedział, że Master zakończył transmisję i możesz wpisać nową wartość do rejestru Spdr.

    Co do spiout to będzie taki efekt jak spimove tylko Slave nie dostanie danych, które mu możesz przesłać, a które mogą Ci się przydać.

    Spiuot i Spiin używa się w kodzie Mastera w sytuacji obsługi jednokierunkowych urządzeń peryferyjnych np przetworników A/D (Spiout) lub czujników, które tylko wysyłają dane (Spiin).

    W kwestii informowania Mastera, że Slave ma coś do wysłania, to możesz użyć dowolnej końcówki dowolnego portu, najlepiej jakiegoś przerywania (tylko nie SS) i w Masterze ustawić na wejście.
    Przywierasz do masy Slavem tę linię i Master może rozpocząć transmisję.

    Edit: Może spróbuj jeszcze dokładnie tak jak jest w przykładzie dołączonym do BASCOMA

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    i zmień w Masterze Polarity na Low (żeby dokładnie było tak jak w przykładzie).

    Różnica pomiędzy Twoim kodem, a tym z przykładu to:
    1. Config Pinb.4 = Output przed Config Spi (nie jestem pewien czy to ma znaczenie)
    2. W Config Spi dopisane Interrupt = On (to może mieć znaczenie)
    3. W Config Spi ustawione Polarity = Low (chociaż jak w Masterze i Slavie będzie HIGH to moim zdaniem też powinno działać)

    0
  • #20 08 Maj 2013 14:30
    MArSTER_1
    Poziom 18  

    Przerwania nie sa konieczne. Nie uruchamiaj ich. Na początek trzeba znaleźć przyczynę braku przekazywania danej ze Slave do Mastera. Czy to że napisałeś, że dalej nie działa (po zastosowaniu mojej sugestii aczkolwiek z przerwaniami) to znaczyło, że nadal wyswietla się 255?
    Czy w płytce Slave masz jakąś diodę, żeby móc zbadac czy dane z Mastera przechodza do Slave? Chodzi o badanie stanu rejestru SPDR w Slave. Jeśli dajmy na to wyślemy 111 to dioda powinna się zaświecić.

    0
  • #21 08 Maj 2013 16:31
    splawik00
    Poziom 23  

    Wszystkie próby oprócz tej teraz ostatniej były z wynikiem 255.
    Próby robię w symulatorze Proteus. Poniżej przebieg na oscyloskopie. MISO jest ciągle na poziomie 5V, natomiast master nadaje rzeczywiście zmienną. Tu może tego nie widać, bo zmienna = 0, ale jak dam jakąś inną wartość to przebieg się ładnie zmienia na MOSI.

    MASTER:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    SLAVE:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    SPI Bascom AVR - prośba o wyjaśnienie

    0
  • #22 08 Maj 2013 20:18
    MArSTER_1
    Poziom 18  

    Na poczatek z kodu Mastera i Slave usuń uruchomienie przerwań (enable interrupts po SPIINIT). Po drugie skoro masz symulator to najpierw podłącz LCD do Slave.
    Po trzecie w pętli Do Loop Slave wpisz cykliczne odczytywanie wartości rejestru SPDR i wyswietlanie tej wartości.. Na przykład co 100ms :

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    A w kodzie Master:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod



    Te dwa kody powinny uruchomić cykliczne nadawanie z Master i cykliczne wyświetlanie stanu rejestru w Slave.
    [/code][/quote]

    0
  • #23 08 Maj 2013 20:42
    splawik00
    Poziom 23  

    Slave nie wpisuje do SPDR wartości. Wyłączyłem nadawanie mastera i w slave zrobiłem:

    SPDR = 123
    lcd SPDR

    i pokazuje na LCD slave'a wartość "0". Również:

    SPDR = 123
    zmienna = SPDR
    lcd zmienna

    daje na LCD "0", no ale to w końcu to samo co wyżej, tylko inaczej zapisane.

    Poza tym slave nie odbiera w ogóle zmiennej przesłanej przez mastera :|

    0
  • #24 08 Maj 2013 21:36
    MArSTER_1
    Poziom 18  

    Rozumiem. A czy próbowałes uruchomić te kody, które podałem? W kodzie konfigurującym SPI w Master jest błąd (dwa przecinki po słowie Hard). Popraw to, uruchom te dwa kody i napisz o wyniku.


    Jeśli to nie pomoże, to spróbuj w kodzie Slave usunąć instrukcję SPIINIT.

    0
  • #26 08 Maj 2013 21:49
    MArSTER_1
    Poziom 18  

    Spróbuj w kodzie Slave usunąć instrukcję SPIINIT.

    0
  • #28 09 Maj 2013 07:03
    fuse
    Poziom 15  

    MArSTER_1 napisał:
    Spróbuj w kodzie Slave usunąć instrukcję SPIINIT.


    No to już jest jakaś wiedza szamańska ;)

    Co do usunięcia przerywań w kodzie Slava, jak rozumiem liczysz na to, że Slave w końcu sobie "trafi" z odczytem, ponieważ nie będzie mógł odczytać rejestru podczas transmisji, a to powoduje konieczność wydłużenia opóźnienia w kodzie Mastera.
    Taka metoda nie jest zbyt elegancka, zdecydowanie lepiej odczytać rejestr po otrzymaniu przerywania informującego o zakończeniu transmisji.
    W kodzie Slava zapomniałeś dodać konfiguracji wyświetlacza.

    Ponieważ całość odbywa się na symulatorze, to wykorzystałbym w pierwszej kolejności przykłady z Bascoma, łącznie z użytym tam procesorem i bez obsługi wyświetlacza, a sprawdzając na początek tylko przebiegi.

    0
  • #30 09 Maj 2013 13:10
    fuse
    Poziom 15  

    Myślałem o wykorzystaniu tych przykładów (z drobnymi modyfikacjami), w których konfiguracja procesora jest następująca:

    $regfile = "m88def.dat"
    $crystal = 8000000
    $baud = 19200
    $framesize = 128
    $hwstack = 40
    $swstack = 40

    Dodatkowo dla mastera:
    Config Spi = Hard , Interrupt = Off - i dalej tak jak już miałeś

    dla Slava tak jak masz czyli Interrupt = On

    Nie próbowałem na "żywym organizmie", ale symulator w BASCOMIE bez problemu zapisuje i odczytuje rejestr SPDR, a pisałeś, że nawet z tym masz problem.
    Może czas sprawdzić to na realnych mikroprocesorach ?

    Osobiście miałem czasem problem przy kompilacji programu obsługującego przetwornik D/A, program po wejściu w procedurę wysyłania danych po SPI zawieszał się i musiałem przełączyć opcje w konfiguracji BASCOMA Compiler -> Output -> Optimize code.

    Po kilku kompilacjach, nawet jak nic nie zmieniałem w kodzie znowu pojawiał się ten problem, ale po ponownym przełączeniu Optimize code zaczynało wszystko na powrót działać (korzystam z ATmega128)

    EDIT: na ostatnim diagramie nie podłączyłeś końcówki SS Mastera do + zasilania, a to bardzo ważne.
    teraz doczytałem, że tylko jak pin SS Mastera skonfigurowany jest jako wejście, a można go tak skonfigurować.

    Jeszcze jedno:
    "Slave wyświetla tylko "start" i nie wysyła danych do mastera."

    Użyłeś w kodzie Mastera Spiuot, a nie Spiin lub Spimove

    0