Komunikace SPI - MISO - jak provést příjem dat?

Potřeboval bych radu s komunikací po SPI u AVR(konkrétně mám ATmega128). AVR mám jako Master a paměť EEPROM jako Slave. Zápis je mi jasný, nakonfiguruji kanál SPI a pak stačí zapsat do datového registru, data se mi pak začnou posílat automaticky. Pak už jen čekám na nastavení SPIF.

Ale jak provést příjem dat? V datasheetu je jen příklad pro slave. A já potřebuji aby AVR generoval hodiny a přijímal data. A z popisu od Atmelu nějak vůbec netuším jak na to.

:arrow_right: administrator: přejmenováno z "komunikace SPI - MISO"

Podle mne by měl být postup shodný jako u slave.
Jediný rozdíl je v nastavení stavového registru.
Zbytek si procesor obslouží sám.
(Chápej… buď tvou snahu bude ignorovat nebo ti v tom lepším případě vynadá [WCOL]) :slight_smile:

Vysielaj 0xff a to co nacitas z registra (do ktoreho si predtym vlozil 0xff) je to, co ti pamat poslala. Pozri si blokovu schemu SPI v datasheete k procesoru.

Dík martine, zdá se že to funguje. Přečtu to co pošle slave(zatímco vysílám 0xff ale koneckonců můžu vysílat i něco jiného).

Objevil se ale další problém. Pokud nic nevysílám přes MOSI, pak je na tomto pinu log 1 i když mám odpovídající pin DDRB na log 1 a PORTB na log 0. A to jak se zdá poněkud hatí mé plány na komunikaci s 93C66.

Dá se nějak vnutit v době nečinnosti log 0?

Ještě jednou dík.

Tak, ze zdeaktivujes SPI. Potom si s pinmi rob co chces. Preco by pri aktivacii periferie mal byt brany ohlad na binarne nastavenie prislusnych pinov? To je nezmysel. Bud plati nastavenie DDRx/PORTx , alebo periferia.

Preco chces mat vystupny pin SPI s pamatou 93cxx na log.0? Aky to ma zmysel? Normalny stav pri seriovych komunikaciach (I2C, SPI, UART) je mat linku v log.1. To akurat Presto mal volakedy tak nedotiahnuty sw, ze na SPI rozhrani musela byt v kludovom stave log.0, co je pre bezne SPI rozhranie neprirodzeny stav. Ale velmi promptne to dali do poriadku, takze s touto firmou mam dobre skusenosti.

Podle datasheetu začne instrukce log “1” na vývodu CS za současného start bitu v log “1”.

na začátku je tedy 1 start bit a 2 bity kódu.

Abych si to zjednodušil tak vysílám na začátku 8 bitů z nichž nejnižší 3 jsou star bit a kód instrukce. Vyšší bity jsou v log “0”. Zde je daný kód

#define F_CPU 16E6

#define MISO 3
#define MOSI 2
#define SCK 1
#define SS 0

#include <avr/io.h>
#include <util/delay.h>
#include “bitove_operace.h”

void SPI_MasterInit(void)
{
/* Nastaví MOSI, SCK a SS jako výstupní piny, ostatní na portu B jsou jako vstupní */
sbi(DDRB,MOSI);
sbi(DDRB,SCK);
sbi(DDRB,SS);
cbi(DDRB,MISO);

/* Zapnutí SPI, nastaví AVR jako Master, hodinový kmitočet je fck/128 /
/
tedy 125kHz */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1)|(0<CPOL)|(0<CPHA);
}

void SPI_MasterTransmit(unsigned char cData)
{
/* Start transmission /
SPDR = cData;
/
Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
}

char SPI_MasterReceive(void)

{
SPDR = 0xff;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
return SPDR;

}

int main()
{

unsigned char dataHI,dataLO;

SPI_MasterInit();
while(1)
{
sbi(PORTB,SS);
_delay_us(5);
SPI_MasterTransmit(0b00000110); // budeme číst
SPI_MasterTransmit(10); // na adresu 10
dataHI=SPI_MasterReceive(); // mělo by to být číslo 0
dataLO=SPI_MasterReceive(); // mělo by to být číslo 5
cbi(PORTB,SS);
_delay_us(1);
PORTA=dataLO;

_delay_us(30);
};

}

sbi a cbi nastaví či vynulují daný bit.

Tahle nekonečná smyčka by měla číst adresu 10(organiyace po 16 bitech) a zobrazovat ji na portu A. Vždycky přečtě 0xFF ale snad jsem zapsal na tuto adresu číslo 5.

Je možné to udělat jak to tady je?

Neviem Ti v tomto poradit, skus si najst napr. na www,avrfreaks,net nejake hotove kody pre komunikaciu s touto pamatou. Ja pouzivam AT45DB161, 25Cxx, AD a DA prevodniky cez SPI, 74HC5956, 74HC165 a tam je to vsetko v logike typu /CS.

NA zaciatok skus predlzit casy aspon 10-100x. Miesto 1us tam daj 100us a skus osiloskopom odsledovat, ci ti tam vobec signaly idu ako maju.
Dobre je taketo veci odladovat pri omnoho nizsich rychlostiach, lebo i tam byvaju skryte problemy. A ked Ti to bezi na 100kHz, potom zvysuj prenosovu rychlost systemom “co to da”.

Druha vec je taka, neviem aku mas schemu, ale ak mas na SS pulldown odpor, tak SPI MASTER na ATmega ani nerozbehas. Je to popisane v datasheete, aj ked nie tak jednoznacne, aby z toho clovek hned pochopil, co sa deje.
Skratka, ak je SS vstupny a je na nom log.0, potom SPI do rezimu MASTER ani neprepnes, lebo SPI bude v rezime SLAVE. Nepomoze ani ak nastavis SS ako vystup, SPI ostane v rezime SLAVE. Ak vsak das na SS pullup, potom budes mat po starte na chvilu cipselektnutu EEPROMU. Nemusi to v principe vadit. S mojimi suciastkami je to vyhodne, ale 93C je v tomto uplne opacne.

V tvojom pripade ako CS pouzi iny pin a SS pouzivaj v suvislosti s SPI iba ak ho chces mat v rezime SLAVE. Po resete maj na SS vzdy pullup, napr. 4k7 a pouzivaj ho iba ako vystupny. Tak sa vyhnes vsetkym problemom s SPI a usetris si velmi vela (ale naozaj velmi vela) casu.

Ale ani ten chvilkovy CS v log. 1 na EEPROME po starte procesora nemusi byt skodlivy. Ved hned prepnes SS na vystup a potom do log.0. Data v EEPROMe sa nemozu modifikovat. Len je dolezite dat ten pull-up na SS, lebo inak sa s SPI ani nepohnes.

Tak jsem to nakonec vyřešil netradičně - přešel jsem na paměť 25LC640.

Díky za tuto radu :smiley:

Teď už se mi to podařilo rozeběhnout, přečtu co jsem zapsal.

Tady jsem nahrál průběhy během čtení

edisk.cz/stahni/58540/print_ … .35KB.html

(DO-CS,D1-SCK,D2-SI,D3-SO)
(čtu číslo 2 na adrese 10)

Mohly by být případné zákmity na SO(D3) ve stavu vysoké impedance nebezpečné pro spolehlivost přenosu?

:arrow_right: administrator: externí soubory přiloženy
prebehy_behem_cteni.png

Já mám také jeden dotaz ohledně SPI.
A to jak dlouhé vedené mohu použít mezi dvěma zařízeními?
Zatím nikde jsem na tuto informaci nenarazil.
Nevěděl by někdo?

Ake len chces :slight_smile:
vsetko je to iba o tom,

-aku rychlost chces - co najmensia kapacita vedenia - cim dlhsie, tym vacsia,
-ako vies linku vybudit
-SPI linku (na rozdiel I2C) mozes velmi jednoducho predlzit i cez prudove slucky do vzdialenosti desiatok kilometrov

hi lidi!
Chtěl jsem se zeptat proč je ve funkci SPI_MasterReceive(void)
SPDR = 0xff; ? Neměl by být SPDR vynulovaný ?
díky ahoj

nie :slight_smile:

to jsi mi to moc nevysvětlil

Špatně jsi to pochopil. (jak Martina tak funkci SPI) :confused:
V podstatě se v režimu MASTER zápisem LIBOVOLNÉ hodnoty do SPDR spustí generování CLK.
Pokud před tímto krokem něco náhodou přijde na vstup,
tak to procesor ostentativně ignoruje. (proč by se měl vzrušovat, on je tu přece MASTER) 8)

Dakujem :slight_smile:

Takže já při přijímání dat musím do SPDR vložit libovolnou hodnotu kromě nuly a poté budu příjmat do SPDR data od “slave”?A nebudu mít data v SPDR totožná , jako s těmi , co jsem tam vložil libovolně?

Ako uz bolo povedane, akonahle zapises data do registra, spusti sa ich odoslanie von (MOSI) a ich nahradenie datami z pinu MISO. Je jedno, co tam zapises.

Treba si len davat pozor, aby zariadenie, do ktoreho ide signal MOSI, tie data nejako zle nevyhodnotilo. Hodnota 0xff je “bezpecna” i v tom, ze mozes (su take suciastky) zapojit i rozhranie 3wire SPI (MISO/MOSI, CLK, SET) na rozdiel od klasickeho 4wire (MISO, MOSI, CLK, SET). MOSI prepojis s MISO cez diodu katodou obratenou k MOSI. Toto spojenie potom sluzi ako Data I/O pre 3wire SPI. Ak vysielas z SPI 0xff, nijako negativne neovplyvnis prijimane data. Dioda je zavreta. Samozrejme na MISO musi byt pullup odpor.

ok , díky moc
už je mi to jasnější :slight_smile: