Atmel AVR, SPI a C

Vývojová prostředí, aplikace, skripty, http://www... síťové programy, internet, sdílení...
Odpovědět
dohnalik
Středně pokročilý
Středně pokročilý
Uživatelský avatar
Registrován: 16. říj 2009
Bydliště: Brno

Atmel AVR, SPI a C

Příspěvek 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.
OndraSter
Středně pokročilý
Středně pokročilý
Uživatelský avatar
Registrován: 22. úno 2006
Bydliště: Praha / ČVUT FIT
Kontaktovat uživatele:

Re: Atmel AVR, SPI a C

Příspěvek 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?
PC: i5-2500k 4.5GHz/24GB RAM/GTX560 Ti 1GB/>5TB - W7 Prof x64; Microsoft SideWinder X3 notebook: HP 6715b (4GB RAM) - W7 Prof x64;
mobil: Nokia Lumia 800 Cyan, 16GB; tablet: Toshiba Portege M200 (2GB, 64GB SSD, GeForce FX5200) - W7 Prof x32


Nahraďte Arduino výkonnější variantou!
Vývojová prostředí a nástroje | Webové prohlížeče | Seznam freehostingů
Ollie
Začátečník
Začátečník
Registrován: 07. kvě 2007
Bydliště: Rožnov p.R., Loukov
Kontaktovat uživatele:

Re: Atmel AVR, SPI a C

Příspěvek 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;
}
Obrázek
dohnalik
Středně pokročilý
Středně pokročilý
Uživatelský avatar
Registrován: 16. říj 2009
Bydliště: Brno

Re: Atmel AVR, SPI a C

Příspěvek 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.
Odpovědět

Zpět na „Programování a web“