Tinyn har ju USI och jag har ställt in den att agera SPI enligt koden nedan. Det verkar funka men resultatet är lite stokastiskt. Det smyger sig in en massa skräptecken mellan de tecken jag skickar. I nuläget skickar jag först 0xCC från Megan tills den får 0xAA tillbaka, sen skickar Megan tio 0xFF och skriver ut de tio tecken den får tillbaka.
Jag vill i slutändan kunna föra över valfri struct byte för byte mellan processorerna.
Atmega@4MHz, Attiny@8MHz. De sitter ihopkopplade via en flatkabel på 10cm. SPI-frekvensen är 4MHz/4/64/128, samma resultat med alla. En (dålig) bild på SS- och SCK-linorna finns längst ner.
Resultatet visar jag i ett terminalfönster via UART. Det kan se ut så här:
Kod: Markera allt
command 0xCC, 0, 00AA
Data return: 0, 204
Data return: 1, 255
Data return: 2, 0
Data return: 3, 10
Data return: 4, 255
Data return: 5, 255
Data return: 6, 255
Data return: 7, 255
Data return: 8, 255
Data return: 9, 255
Testar SPI: 255
Knapp 1
command 0xCC, 0, 00AA
Data return: 0, 204
Data return: 1, 0
Data return: 2, 255
Data return: 3, 255
Data return: 4, 10
Data return: 5, 255
Data return: 6, 255
Data return: 7, 20
Data return: 8, 255
Data return: 9, 255
Testar SPI: 255
På nåt sätt hänger inte Tinyn med i svängarna verkar det som men det är ju skumt. Atmegan ska ju skriva ut saker via UART mellan varje byte så det blir ju en liten paus där och sen är ju Tinyn snabbare än Megan.
Det kanske är enkelt men jag lyckas inte komma på det. Ska man använda en buffert på något sätt? Har jag gjort nån enkel blunder i koden?
###### Nedan är koden ######
Här är koden på Atmegan. Den skickar först 0xCC tills den får 0xAA till svar. Sen skickar den 0xFF 10 gånger för att ta emot tio byte
Kod: Markera allt
u08 batteryGetStatus(BatteryStatusType* battery_status) {
u08 i;
u08 data; // Byt mot battery_status och fixa pekare0
// Set SS low
cbi(BATTMON_PORT, BATTMON_SS);
asm("nop"); //Wait for slave to initiate
asm("nop");
// Send command byte, command to recieve data, wait for 0xAA = ready to send
for (i=0;i<10;i++) {
data = spiTransferByte(0xCC);
rprintf("command 0xCC, %d, %x\r\n", i, data);
if (data==0xAA) break;
}
// If answer is AA = "ready to send"
if (data==0xAA) {
for (i=0;i<10;i++) {
data = spiTransferByte(0xFF);
rprintf("Data, %d, %x\r\n", i, data);
}
sbi(BATTMON_PORT, BATTMON_SS); // Set SS high
return data;
}
else {
sbi(BATTMON_PORT, BATTMON_SS); // Set SS high
return 0;
}
}
satan
Kod: Markera allt
//! Initiate SPI slave mode
void spiInit(void) {
// setup SPI I/O pins
cbi(SPI_DDR, SPI_SCK); // set USCK as input
sbi(SPI_PORT, SPI_SCK); // set SCK internal pullup
cbi(SPI_DDR, SPI_MOSI); // set DI as input
sbi(SPI_PORT, SPI_MOSI); // set DI internal pullup
sbi(SPI_DDR, SPI_MISO); // set DO as output
cbi(SPI_DDR, SPI_SS); // SS is input for slave operation
sbi(SPI_PORT, SPI_SS); // set SS internal pullup
// Set three-wire mode and external clock in USI Control Register
USICR = (1<<USIOIE)|(1<<USIWM0)|(1<<USICS1);
USISR |= (1<<USIOIF); //Clear counter overflow flag
}
//! Transfer one byte through SPI
u08 spiTransferByte(u08 data) {
USIDR = data; // move data to transfer register
while(!(USISR&(1<<USIOIF)) && SS); // wait for transfer to complete, if SS goes high abort
return USIDR; // return the received data
}
ISR(USI_OVF_vect) {
USISR |= (1<<USIOIF); // Clear overflow flag
}
Kod: Markera allt
int main(void) {
u08 i;
u08 spi_get;
sei();
spiInit(); // Init SPI
sbi(DDRB, PB5); // PP5 as output for blinking LED
sbi(PORTB, PB5); // Turn off LED
while(1)
{
// If SS pin is low do SPI-transfer
if(SS) {
cbi(PORTB, PB5); //Light LED
//spi_get = spiTransferByte(0x00); // Send dummy byte to initiate transfer
spi_get = spiTransferByte(0xAA); // Send 0xAA = ready to send
for (i=0;i<10;i++) {
spi_get = spiTransferByte(i*10); // Send echo
}
sbi(PORTB, PB5); //LED off
}
}
return 0;
}
