Strona 1 z 1

[+]C/Python - Problem z komunikacją SPI RPi - AVR

: 11 września 2019, 21:23
autor: poganin
Dzień Dobry Forumowicze!

Problem wygląda 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.

C (Atmega64, slave)

Kod: Zaznacz cały

#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);
}


Python (RPi, Master):

Kod: Zaznacz cały

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.

Re: C/Python - Problem z komunikacją SPI RPi - AVR

: 12 września 2019, 07:00
autor: LordRuthwen
Spróbuj raczej tu: https://majsterkowo.pl/forum/

Re: C/Python - Problem z komunikacją SPI RPi - AVR

: 12 września 2019, 08:32
autor: pawkrol
A może ominąć problem np. układem ULN2803. Podajesz 1 na wej układu, a na wyjściu masz 0

Re: C/Python - Problem z komunikacją SPI RPi - AVR

: 12 września 2019, 10:16
autor: poganin
pawkrol pisze: 12 września 2019, 08:32 A może ominąć problem np. układem ULN2803. Podajesz 1 na wej układu, a na wyjściu masz 0
Od strony elektronicznej ominąć ten problem można na bardzo wiele sposobów - choćby w oparciu o pojedynczy tranzystor. Rzecz w tym, że płytka jest dość rozbudowana, ma wiele elementów i wykonanie nowej byłoby dość kosztowne ze względu na część z nich - biorę to rozwiązanie pod uwagę, jednak jest ono dla mnie ostatecznością. Mimo wszystko dzięki za odpowiedź i sugestię :)

Re: C/Python - Problem z komunikacją SPI RPi - AVR

: 12 września 2019, 20:31
autor: poganin
Dla potomnych:

Kod: Zaznacz cały

sudo rmmod spi_bcm2835
sudo modprobe spi_bcm2835
W celu rozwiązania problemu, należy po każdym wgraniu programu z użyciem AVRDUDE przeładować moduł SPI. Dzięki za pomoc :)