Čaute,
snažím sa už pár dní rozchodiť SPI komunikáciu medzi dvoma procesormi atmega8. Nakonfiguroval som jedného ako master, druhého ako slave. Vysielanie realizujem tak, že hodím zariadeniu slave pin SS na nulu, v mastrovi naplním SPDR odosielanou info, a čakám na dokončenie prenosu. Od mastra so slave chodia data v poriadku… ibaže by som potreboval počas tejto transakcie aby slave zaradenie cez svoj shift register posielalo niečo ako mnou vytvorený status register velký 8bitov… skúšal som to tak, že som po prijatí dát cez SPI v prerušení po prečítaní prijatého byte skúšal SPDR = mojadata… s naivnou myslienkou, ze mi to z neho shiftom odošle počas ďalšieho prenosu. No komunikácia sa tým uplne rozhádzala. Viete prosim niekto poradit ako na to ? da sa to takto vobec?
Ono by to tak jaksi fungovat mělo .
Asi to bude chtít kus kódu.
Inicializacia Master:
DDRB = 0x68; // SPI Port inicializácia
// NC , CS, SCK MISO, MOSI, WP , PWM, RST
// PB7, PB6, PB5, PB4, PB3, PB2 , PB1, PB0
// I O O I O I I 1
// 0 1 1 0 1 0 0 0
SPCR = (0<<SPIE)|(1<<SPE)|(1<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(1<<SPR0)|(1<<SPR1);
Vysielanie master:
unsigned char zapis_cez_SPI(unsigned char data)
{
PORTC = 0x00; // CS nula
_delay_ms(5);
SPDR = data; //data do SPDR
while(!(SPSR & (1<<SPIF))); //cakam
data = SPSR; //pre pripad odstr. flagu chyby prenosu
poc = SPDR; // čítanie SPDR do globálnej premennej
_delay_ms(5);
PORTC = 0xFF;
return data;
}
Inicializacia Slave:
DDRB = 0x50; // SPI Port inicializácia
// NC , LED, SCK MISO, MOSI, SS , NC, NC
// PB7, PB6, PB5, PB4, PB3, PB2 , PB1, PB0
// I 0 I 0 I I I I
// 0 1 0 1 0 0 0 0
SPCR = (1<<SPIE)|(1<<SPE)|(1<<DORD)|(0<<MSTR)|(0<<CPOL)|(0<<CPHA);
Prijem byte pri preruseni:
ISR(SPI_STC_vect)
{
prenesene = SPDR;
SPDR = statusbyte;
}
no ked to takto spravim, a z mastera konstantne v časových intervaloch 1s vysielam akekolvek cislo, do slave stale mi chodi 0.
Akonahle zmazem riadok SPDR = statusbyte; tak mi slave zacina primat data v poriadku.
Z neznamych pricin bez zmeny v kode po dalsom prekompilovani a nahrati do čipu to žačalo fungovať. Vďaka za potvrdenie ze by to tak malo fungovat:) Pripadne ak si si vsimol v mojom kode nejake zbytocnosti, sem s kritikou, rad to zlepsim:)
Právě, že do toho koukám jak husa do flašky a krom pár neobratností tam nic vážnýho nevidim.
Když používáš shifty pro nastavování registrů(což je dobře), proč je nevyužíváš i u portů? Ušetřil by sis ty několikařádkové komentáře.
Předpokládám, že víš, že zápis (0<<x) ve spojení s OR nedělá nic a je zbytečný (nenuluje bit, nechává ho na původní hodnotě).
[code]masterInit()
{
PORTB |= 1<<PB2; // SS=1
DDRB |= (1<<PB5) | (1<<PB3) | (1<<PB2); // CLK, MOSI, SS out
SPCR |= (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0);
}
uchar masterWrite(uchar data)
{
PORTB &= ~(1<<PB2); // SS=0
SPDR = data;
while(!(SPSR & (1<<SPIF)));
PORTB |= (1<<PB2); // SS=1
return SPDR;
}
slaveInit()
{
DDRB |= (1<<PB4); // MISO out
SPCR |= (1<<SPIE) | (1<<SPE);
}
volatile uchar rxData, txData; // volatile nutne
slaveISR(…)
{
rxData = SPDR;
SPDR = txData;
}
[/code]
Shifty pouzivam odvtedy, ako si ma ich naucil pouzivat pri rieseni problemu vyrabania diktafonu pomocou atmegy a flash pamäti:)
Je to prehladnejšie a praktickejšie…len som už dlhšie skrz školu neprogamoval MC, a tak mi akosi nestihlo dopnut, ze by sa dali pouzit aj na nastavovanie samotnych portov, nielen registrov:) Tie OR spojené s priradením 0 som si tam väčšinou písal len aby som si uvedomil , že tam tú nulu chcem nechať(kedže som počítal, že ten register je vynulovany od spustenia MC).
Diky za radu, rozhodne to bude pohodlnejsie a prehladnejsie nastavovat aj porty pomocou shiftov.
A ještě lepší je mít je pojmenovaný .[code]#include <avr/io.h>
#define F_CPU 11059200UL
#include <util/delay.h>
#define SETBIT(ADDRESS, BIT) ((ADDRESS) |= (1<<(BIT)))
#define CLRBIT(ADDRESS, BIT) ((ADDRESS) &= ~(1<<(BIT)))
#define NEGBIT(ADDRESS, BIT) ((ADDRESS) ^= (1<<(BIT)))
#define TSTBIT(ADDRESS, BIT) ((ADDRESS) & (1<<(BIT)))
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED1 PB0
void main(void)
{
SETBIT(LED_DDR, LED1);
for(;
{
_delay_ms(500);
NEGBIT(LED_PORT, LED1);
}
}[/code](První program každýho procesoru, kterej dostanu do ruky )
Moc diky, so shiftami to bude ovelajednoduchsie. Daju sa vsak pouzit na testovanie obsahu unsigned char premennej? Ked chcem napriklad otestovat ci je v premennej data bit 3 nulovy alebo v log 1, da sa na to pouzit shift?
Dá.if(promenna & (1<<3)) ...
if(!(jina & (1<<3))) ...
Diky, moc pomohlo:)