Skocz do zawartości

[C/Python] Komunikacja RPi - Atmega64 (SPI)


3_Harmoniczna

Pomocna odpowiedź

Dzień Dobry Forumowicze!

Problem dotyczy zarówno mikrokontrolera, jak i RPi, więc mam nadzieje że nie będzie problemu związanego z nieodpowiednim działem. Od kilku dni borykam się bezskutecznie z pewnym problemem, a prezentuje się on następująco:

Potrzebuję wymienić dane poprzez SPI między Raspberry Pi Zero W (Master), a Atmegą64(Slave). Atmega zasilana przez 5V na własnoręcznie zaprojektowanej płytce (z konwerterem poziomów logicznych 3,3V-5V na MOSFET'ach). Generalnie elektrycznie wszystko jest sprawne i sprawdzone kilkukrotnie, więc to odpada.

Jestem w stanie zaprogramować AVR'a przez RPi za pośrednictwem SPI właśnie (na RPi Rasbian w wersji 9), z wykorzystaniem AVRDUDE. Problem jaki się pojawia, to przy próbie wymiany danych między nimi. AVR'a programuje w C, natomiast RPi w Pythonie (kody programów niżej). Polega on na tym, że biblioteka Python'a SpiDev, jako sygnał ChipSelect podaje stan wysoki, podczas gdy ATMEGA wymaga podczas tej komunikacji stanu niskiego. Atmega nie posiada możliwości zmiany trybu na taki, aby czytała stan wysoki, a biblioteka SpiDev z kolei, nie ma funkcjonalności podania stanu niskiego. Chciałem to obejść poprzez podpięcie nóżki Atmegi pod zupełnie inną nóżkę RPi i ręcznego wysterowywania tej nóżki przed nadaniem paczki danych, jednak to nie działa - nie wiem jednak dlaczego. Nie używałem nigdy wcześniej SPI, więc finalnie nie jestem nawet pewien gdzie leży problem - czy w kodzie Slav'a, Mastera czy zupełnie gdzie indziej.

 

Slave (C, Amtega64):

#define F_CPU 1000000UL
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#define ustaw(bajt, nr_bitu) (bajt |=(1<<nr_bitu))
#define skasuj(bajt, nr_bitu) (bajt &=~(1<<nr_bitu))
#define sprawdz(bajt, nr_bitu) ((bajt &(1<<nr_bitu))&&1)
#define sleep(czas) for (int i=0; i<(czas); i++) _delay_ms(1)

int data=500;

void init_spi(void)
{
 DDRB=(1<<PB3);                           //MISO - output
 SPCR=(1<<SPE)|(1<<SPIE);       //SPI_ON & Interrupt
 SPDR=0;
}

uint8_t rec_spi(void)
{
 while (!(SPSR & (1<<SPIF))) ;  
 return SPDR;                   //return data register
}


int main(void)
{
        sei();
        init_spi();
        DDRC |=1<<PC3; //LED'y
        DDRC |=1<<PC4;
        DDRC |=1<<PC5;

        while (1)
        {
                ustaw(PORTC, PC4);
                sleep(data);
                skasuj(PORTC, PC4);
                sleep(data);
        }
}

ISR (SPI_STC_vect)
{
 data = rec_spi();
 ustaw(PORTC,PC5);
}

 

Master (Python, RPi):

import RPi.GPIO as GPIO
import spidev
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(7, GPIO.OUT)
GPIO.output(7, GPIO.HIGH)
spi = spidev.SpiDev()
spi.open(0, 0)
print('Open SPI')
#GPIO.output(7, GPIO.LOW)
data = 0xAA

try:
        while True:
                print('Sending..')
                GPIO.output(7, GPIO.LOW)
                spi.xfer([data], 50000, 100, 8)
#               spi.writebytes([250])
                GPIO.output(7, GPIO.HIGH)
                print('complete')
                time.sleep(2)
        #end while
except KeyboardInterrupt:
#       sleep(0.1)
        spi.close()
        GPIO.cleanup()

 

Na masterze (RPi) próbowałem ustawiać różne tryby (spi.mode), różne prędkości, próbowałem z spi.writebytes oraz z spi.xfer. Wszystko bez skutku.
Na Atmedze, mrugam diodą co pół sekundy. Próbowałem osiągnąć taki efekt, by wysłać liczbę 250 i ustawić ją jako czas mrugania, co zauważyłbym jako szybsze mruganie diody. Próbowałem też zapalić inną diodę w przerwaniu od SPI - wszystko bezskutecznie. SPI w FuseBitach jest aktywne. Połączenia elektryczne są poprawne, przy czym Atmegowski SS jest podłączony do 7 pinu RPi.

Byłbym bardzo wdzięczny za wszelką pomoc i sugestie.

Pozdrawiam.

Link do komentarza
Share on other sites

@3_Harmoniczna witam na naszym forum!

2 godziny temu, 3_Harmoniczna napisał:

Atmega nie posiada możliwości zmiany trybu na taki, aby czytała stan wysoki, a biblioteka SpiDev z kolei, nie ma funkcjonalności podania stanu niskiego.

A może spróbuj to poprawić elektronicznie? Na jednym tranzystorze NPN można zrobić negację. Sygnał na bazę poprzez rezystor, kolektor na 3V poprzez rezystor 4k7 i pomiędzy sygnał na konwerter.

Edytowano przez Gieneq
Link do komentarza
Share on other sites

(edytowany)
1 godzinę temu, Gieneq napisał:

@3_Harmoniczna witam na naszym forum!

A może spróbuj to poprawić elektronicznie? Na jednym tranzystorze NPN można zrobić negację. Sygnał na bazę poprzez rezystor, kolektor na 3V poprzez rezystor 4k7 i pomiędzy sygnał na konwerter.

To dla mnie ostateczność. Płytka jest dość rozbudowana (kilka ukłądów uC, dwie przetwornice i kilka innych układów) i stworzenie nowej było by dość kosztowne ze względu na same tylko elementy, nie wspominając o czasie. W związku z tym, szukam innych rozwiązań.

Edytowano przez 3_Harmoniczna
przesadziłem
Link do komentarza
Share on other sites

 

4 godziny temu, 3_Harmoniczna napisał:

Na masterze (RPi) próbowałem ustawiać różne tryby (spi.mode)

Jakie dokładnie?

Oprócz mode masz jeszcze cshigh, co pokazuje i co się stanie jak ustawisz?

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)
2 godziny temu, ethanak napisał:

 

Jakie dokładnie?

Oprócz mode masz jeszcze cshigh, co pokazuje i co się stanie jak ustawisz?

Cześć, dzięki za odpowiedź

Wszystkie 4 tryby testowałem, tyle że w ciemno (wiem tylko czego dotyczą, ale nie znalazłem informacji który jak działa dokładnie - ale też nie szukałem namiętnie). Co do cshigh, to z tego co pamiętam, to wyczytałem że ma zwracać stan tegoż pinu - toteż nawet nie sprawdzałem go. W jaki sposób miałbym go ustawić? Pokombinuje z pewnością z tym cshigh po powrocie do domu.

Edytowano przez 3_Harmoniczna
Link do komentarza
Share on other sites

 

13 minut temu, 3_Harmoniczna napisał:

Wszystkie 4 tryby testowałem, tyle że w ciemno (wiem tylko czego dotyczą, ale nie znalazłem informacji który jak działa dokładnie

A zajrzałeś w ogóle do dokumentacji spidev (nie python-spidev bo ta zakłada, że spidev już znasz)?

15 minut temu, 3_Harmoniczna napisał:

Co do cshigh, to z tego co pamiętam, to wyczytałem że ma zwracać stan tegoż pinu

Owszem ma zwracać ale nie stan pinu. Może jednak spróbuj takiego prostego kodu (możesz w konsoli pythona wpisać z palca):

import spidev
help(spidev.SpiDev())

Tam będzie co to mode, co to cshigh i jeszcze parę innych wielce przydatnych informacji.

  • Lubię! 1
Link do komentarza
Share on other sites

Dzięki za pomoc - znalazłem rozwiązanie mojego problemu. Okazało się, że po użyciu AVRDUDE, w celu poprawnego działania modułu SPI należy go przeładować:

sudo rmmod spi_bcm2835
sudo modprobe spi_bcm2835

Jeszcze raz dzięki za odpowiedzi 🙂

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.