Stránka 1 z 1

Atmel AVR, SPI a C

Napsal: ned 22. dub 2012, 13:05
od dohnalik
Zdravím. Mám takový dotaz na programování rozhraní SPI pro AVR v jazyce C.

Kód: Vybrat vše

unsigned char SPI_Write(unsigned char dataout)
{
  SPDR = dataout; //zapis do prenosoveho registru

  while(!(SPSR & (1<<SPIF))); //cekani na dokonceni prenaseni
  
  PORTB = (1<<PB2); //SS pin log 0
  _delay_us(1);          //zpozdeni 1us  

  PORTB = ~(1<<PB2); //SS pin log 1

}
V kódu výše je jednoduchá metoda zápisu přes SPI do slave zařízení (samotné nastavení SPI registrů řeším v metodě main).

A teď mám pár otázek. PB2 je pin slave select, čili když chci zapisovat musím jej nastavit na log 0. Proč se toto děje až po zápisu do přenosového registru SPDR? Proč mi nefunguje, když PB2 nastavím na log 0 již před samotným zápisem do registru? Dále proč je tam to zpoždění 1us a proč to bez něj někdy funguje a někdy ne? Je to tak, že SPDR registr funguje jako nějaká cache do zařízení se data odešlou až po nastavení SS na log0? Za každou odpověď díky.

Re: Atmel AVR, SPI a C

Napsal: ned 22. dub 2012, 13:14
od OndraSter
Ta at(x)mega je Master nebo Slave? Pokud master, tak SS pin NEMÍ být vstup - jakmile je vstup a dostane se do log 0, tak se přepne SPI na slave automaticky.

SPDR je odchozí a příchozí datový registr. (Zápis = odchozí, čtení = příchozí.)

Odkud si ten kód vzal?

Re: Atmel AVR, SPI a C

Napsal: ned 22. dub 2012, 13:23
od Ollie
Především, pin /SS je určený k použití AVRka jako slave, pokud je to master, a na druhým konci je jen jeden slave, pak zapojení neřešíš, a aktivační pin (SS-slave select, CS-chip select, CE-chip enable) u slavu můžeš zapojit natvrdo na GND ne? Aspoň displej z Nokie 3310 takto běžně používám... Pokud máš více než 1 slave, nastavíš před začátkem komunikace příslušný SS pin na log. 0, po skončení komunikace na log. 1.

Kód: Vybrat vše

static void LcdSend ( byte data )
{
    //  Enable display controller (active low).
    PORTB &= ~LCD_CE_PIN;

    //  Send data to display controller.
    SPDR = data;

    //  Wait until Tx register empty.
    while ( (SPSR & 0x80) != 0x80 );

    //  Disable display controller.
    PORTB |= LCD_CE_PIN;
}

Re: Atmel AVR, SPI a C

Napsal: ned 22. dub 2012, 13:46
od dohnalik
Je to samozřejmě master. !SS pin slave zařízení jsem přímo na zem zkusil připojit, ale nefungovalo mi to, nechtělo to přijímat data synchronizovaně, či co, prostě to dělalo šílený bordel. PB2 je nastavený jako výstup. Vím, co je SPDR.
Když jsem to napsal jako Ollie, tak mi to nefungovalo, čert ví proč, prostě mi to nefungovalo. Kód jsem vyhrabal někde na internetu. Jinak je dost zjednodušený, ale pro vysvětlení mého problému to stačí. Jen mám ještě jednu takovou blbou otázku, co je to vlastně unsigned char? předpokládám, že je to určení datového typu, ale na co přesně?

Přiložím celý kód

Kód: Vybrat vše

#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>

unsigned char SPI_WriteRead(unsigned char dataout)
{
  unsigned char datain;
  
  SPDR = dataout;

  while(!(SPSR & (1<<SPIF)));
  
  datain = SPDR;

  PORTB = (1<<PB2);
  _delay_us(1);            

  PORTB = ~(1<<PB2);
  
  return datain;
}
int main(void)
{
  DDRB = (1<<PB3)|(1<<PB5)|(1<<PB2);
  DDRD = (1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6);
  PORTB &= ~(1<<PB2);
  SPCR = (1<<SPE)|(1<<MSTR);
  
  .............
  xx
  .............
  return 0;
}
Tak mi to nakonec bylo vysvětleno jinde, kdyby to někoho zajímalo, tak sem.