Forum: Mikrocontroller und Digitale Elektronik avr MSPIM usart spi


von grundschüler (Gast)


Lesenswert?

ein Atmega 328 schafft bei 8 MHz per hw-spi rund 220 kbyte/sec. Mit 
usart spi geht es hoch auf 407 kbyte/s - jewels gemessen an einem 
spi-tft. Der Code:
1
int init_usart_spi(void)
2
{
3
4
 DDRD &=~(1<<PD0);//rx-miso
5
 DDRD |= (1<<PD1);//tx-mosi
6
// 1. Set baud Rate Register to 0
7
 UBRR0 = 0x0000;
8
// 2. Set XCK line to output mode
9
// DDRB = (1<<PB0);  // XCK0 ATMega644
10
 DDRD |= (1<<PD4);  // XCK0 ATMega328
11
// 3. Select Master SPI Mode (UMSELn1:0 = 11)
12
 UCSR0C = (1<<UMSEL01) | (1<<UMSEL00);// | (1<<UCSZ01) | (1<<UCSZ00);
13
// 4. Set UCPOLn and UCPHAn to required SPI mode
14
 UCSR0C |=(1<<UCPHA0)|(1<<UCPOL0);
15
//5. Enable Transmitter and Receiver
16
 UCSR0B = (1<<RXEN0) | (1<<TXEN0);
17
//6. Set Baud Rate Register to required value
18
 UBRR0 = 0x0000;   // 8Mbps       @16Mhz F_CPU
19
// UBRR1 = 0x0001;   // 4Mbps
20
// UBRR1 = 0x0002;   // 2.66Mbps
21
// UBRR1 = 0x0003;   // 2Mbps
22
// UBRR0 = 0x0007;   // 1Mbps
23
}
24
25
/*atme avr317
26
// 1. UDR empty?
27
while ( !( UCSR0A & (1<<UDRE0)) );
28
// 2. Copy value to UDR
29
UDR0 = dat;
30
// 3. Transmit Complete?
31
while ( !(UCSR0A & (1<<RXC0)) );//15,6
32
// 4. Return value from UDR
33
return UDR0;
34
*/
35
36
37
write_usart_spi(u8 dat){
38
//while ( !( UCSR0A & (1<<UDRE0)) );
39
UDR0 = dat;
40
while ( !(UCSR0A & (1<<RXC0)) );//15,6
41
UDR0;//rx_buffer leeren
42
}
43
44
45
....
46
#if (zucAVR  && use_usart_spi==0) || lcd_bitbang==1 
47
48
  for( index = 0; index < ((uint32_t)lcd_max_width*lcd_min_width); index++ )  {
49
    lcd_write_2x8bit_only(Color);
50
  }
51
#endif
52
53
#if zucAVR  && use_usart_spi==1 && lcd_bitbang==0
54
for( index = 0; index < ((uint32_t)lcd_max_width*lcd_min_width); index++ )  {
55
 UDR0 = Color>>8;
56
 while ( !(UCSR0A & (1<<UDRE0)) );//15,6
57
 UDR0;//rx_buffer leeren
58
 UDR0 = Color;
59
 while ( !(UCSR0A & (1<<UDRE0)) );//15,6
60
 UDR0;//rx_buffer leeren
61
    } 
62
UDR0;  //<==?????????  
63
lcd_cs_high;
64
65
#endif

Das ganze funktioniert, aber die Flag-Abfrage scheint mir noch nicht 
optimal zu sein. Was ich nicht verstehe ist, warum nach der for-Schleife 
noch einmal der rx-buffer mit UDR0 geleert werden muss. Lässt man dies 
weg, ist danach keine Anzeige auf dem TFT mehr möglich.  Warum?

von S. Landolt (Gast)


Lesenswert?

> UDR0 = Color>>8;
> while ( !(UCSR0A & (1<<UDRE0)) );//15,6
> UDR0;//rx_buffer leeren

Beim ersten Mal ist UDRE0 sofort gesetzt, also greift das erste "UDR0;" 
ins Leere - muss folglich am Ende nachgeholt werden.

von grundschüler (Gast)


Lesenswert?

S. Landolt schrieb:
danke für Beitrag und Interesse.

Ich habe das multiwrite jetzt als Funktion ausgelagert. Es werden jetzt 
für einenb 8 MHz-AVR gewaltige 498 kbytes/sec geschrieben:
1
void write_usart_spi_multi (
2
  const u8 *buff,  // Pointer to the data
3
  u32 anz2Bytes  // Number of bytes to send (even number)
4
){
5
do {
6
7
UDR0=(*buff);
8
 while ( !(UCSR0A & (1<<UDRE0)) );
9
 UDR0;//rx_buffer leeren
10
UDR0=*(buff+1);
11
 while ( !(UCSR0A & (1<<UDRE0)) );
12
 UDR0;//rx_buffer leeren
13
 anz2Bytes--;
14
  } while (anz2Bytes);
15
//  } while (anz2Bytes--);//<<<<<!!!!!!!!!!!
16
17
while ( !(UCSR0A & (1<<UDRE0)) );
18
UDR0;
19
return;    
20
}

Für mich erstaunlich ist, dass >while (anz2Bytes--);< die Funktion 
ausbremst (430kbyte/sec). Sieht jemand noch weitere 
Optimierungsmöglichkeiten für schnelles spi?

von S. Landolt (Gast)


Lesenswert?

> Sieht jemand noch weitere Optimierungsmöglichkeiten
> für schnelles spi?
?
Ich denke, Sie sind am theoretischen Maximum.

Falls Sie eine Herausforderung fürs lange Wochenende möchten: den Inhalt 
zweier SDCards vergleichen, mit 1.25 MB/s; d.h. also mit 20 MHz 
Systemtakt, so Sie die lästige Hardware nicht scheuen.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

grundschüler schrieb:
> Für mich erstaunlich ist, dass >while (anz2Bytes--);< die Funktion
> ausbremst (430kbyte/sec).

Wie siehts mit --anz2Bytes aus? Pos-de/inc ist meistens langsamer

von grundschüler (Gast)


Lesenswert?

N. G. schrieb:
> Wie siehts mit --anz2Bytes aus?

Du hast recht,
} while (--anz);
ergibt auch 498 kbyte/sec.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.