Forum: Mikrocontroller und Digitale Elektronik AVR USART synchron


von Maxim B. (max182)


Lesenswert?

Guten Tag!
AVR hat USART. Ich lese aber überall nur, wie man USART asynchron 
verwendet. Für mich wäre es aber interessant, USART synchron zu 
betreiben, da schnellere Datenübertragung möglich wird und auch braucht 
dann Slave nicht unbedingt mit Quarz getaktet zu sein.

Die Frage nun: wie kann man am besten mehrere AVR miteinander verbinden? 
Master wird inner nur einer. Und so etwa von 10 bis 20 Slave. Wie kann 
man aber viele Slave adressieren? Mit Hilfe von 74HC138 für jeden 
separate Takt erzeugen oder kann man das besser machen? Mein Ziel ist, 
innerhalb von 1-2 ms 512-Block zu schicken. Ich nehme an, für I2C ist 
das schon zu viel?

SPI kommt leider nur schwer in Frage, da ich MK auf der Platte 
programmieren möchte. So kann ich SPI nur mit zusätzlichen Schalter 
zusammenführen, das sieht nicht schön aus.

Vielen Dank im voraus für Erklärung!

von Falk B. (falk)


Lesenswert?

@Maxim B. (max182)

>Die Frage nun: wie kann man am besten mehrere AVR miteinander verbinden?
>Master wird inner nur einer. Und so etwa von 10 bis 20 Slave.

Ganz schöne viele.

>Wie kann
>man aber viele Slave adressieren?

Bei SPI braucht man für jeden Slave ein chip select Signal.

>Mit Hilfe von 74HC138 für jeden
>separate Takt erzeugen

Sicher nicht, eher das chip select erzeugen.

> oder kann man das besser machen? Mein Ziel ist,
>innerhalb von 1-2 ms 512-Block zu schicken.

512 was? Äpfel, Birnen oder gar Melonen?
Bits oder Bytes?

>Ich nehme an, für I2C ist das schon zu viel?

Rechnung?

512 Bytes/MS = 512kB/s ~ 4Mbit/s

Das kann I2C nicht mehr, da braucht man SPI.

>SPI kommt leider nur schwer in Frage, da ich MK auf der Platte
>programmieren möchte.

MK?
Makulatur?

>So kann ich SPI nur mit zusätzlichen Schalter
>zusammenführen, das sieht nicht schön aus.

Wie meinen? SPI kann man problemlos nutzen, auch wenn man die AVRs per 
ISP programmieren will. Dazu braucht es keine Schalter, "nur" Knoff 
Hoff.

https://www.mikrocontroller.net/articles/AVR_In_System_Programmer#ISP-Pins_am_AVR_auch_f.C3.BCr_andere_Zwecke_nutzen

Warum willst du 10-20 Mikrocontroller vernetzen?

von Harry L. (mysth)


Lesenswert?

Maxim B. schrieb:
> SPI kommt leider nur schwer in Frage, da ich MK auf der Platte
> programmieren möchte. So kann ich SPI nur mit zusätzlichen Schalter
> zusammenführen, das sieht nicht schön aus.

Dann hast du SPI nicht verstanden...

von Oliver S. (oliverso)


Lesenswert?

Die AVR Usart hat einen Multi-Processor Communication Mode.
Guggst du ins Datenblatt...

Oliver

von georg (Gast)


Lesenswert?

Maxim B. schrieb:
> Für mich wäre es aber interessant, USART synchron zu
> betreiben, da schnellere Datenübertragung möglich wird und auch braucht
> dann Slave nicht unbedingt mit Quarz getaktet zu sein

Das ist wohl beides ein Irrtum, dafür wird die Sache wesentlich 
komplizierter - es hat schon seinen Grund, warum synchrone Protokolle 
nahezu ausgestorben sind.

Für ein Byte werden zwar nur 8 bit statt 10 gebruacht, aber ein 
wesentlicher Unterschied ist das ja nicht, und ausserdem kommt vor dem 
Datenblock noch eine Einleitung aus mehreren Bytes dazu. Und der Takt 
muss ABSOLUT synchron sein, also wird er mitübertragen oder aus den 
Daten regeneriert, die Anfordungen sind wesentlich höher als bei 
asynchron, ein Quarztakt genügt dafür nicht.

Maxim B. schrieb:
> Wie kann
> man aber viele Slave adressieren?

Genauso wie asynchron: indem man sich ein eigenes Protokoll schreibt und 
einen Bus verwendet anstatt eine Direktverbindung.

Nicht zuletzt ist es eine erhebliche Einschränkung, wenn man nur 
Controller mit synchronen Modi verwenden kann.

Georg


Georg

von Maxim B. (max182)


Lesenswert?

Falk B. schrieb:
> SPI kann man problemlos nutzen, auch wenn man die AVRs per
> ISP programmieren will. Dazu braucht es keine Schalter, "nur" Knoff

Das kann ich mir schlecht vorstellen. Wenn auf der Platte z.B. 8 AVR 
stehen und SCK, MISO und MOSI zusammen geschaltet sind, wie unterscheide 
ich, welche Kontroller gerade programmiert wird? Beim Programmieren gibt 
es ja kein SS!

Einziges, was in Kopf kommt: bei jedem AVR zusätzlich noch ein 
Dip-Schalter einlöten und somit diese Linien beim Programmieren 
voneinander trennen. Schön ist das aber nicht.

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

Maxim B. schrieb:
> Wenn auf der Platte z.B. 8 AVR
> stehen und SCK, MISO und MOSI zusammen geschaltet sind

...ist das Ganze bereits "broken by Design"

von Maxim B. (max182)


Lesenswert?

georg schrieb:
> Nicht zuletzt ist es eine erhebliche Einschränkung, wenn man nur
> Controller mit synchronen Modi verwenden kann.

Ich möchte ATMEGA644PA und ATMEGA1284P verwenden. Die haben zwei USART, 
beide haben XCK-Pin.

von Maxim B. (max182)


Lesenswert?

Falk B. schrieb:
> Warum willst du 10-20 Mikrocontroller vernetzen?

Weil ich mit STM32 noch nicht vertraut bin. Ich möchte Möglichkeit 
haben, die Fehler mit Simulator zu überprüfen. Geschwindigkeit von AVR 
reicht nur, wenn die Aufgabe auf mehrere geteilt wird.
Grob gesagt, ich muß jede 20 us 800 Befehle ausführen können. Dazu muß 
noch genug Zeit übrig bleiben, mindestens 50% frei. Sonst kann AVR 
nichts mehr, nicht einmal Befehle empfangen.

> Wie meinen? SPI kann man problemlos nutzen, auch wenn man die AVRs per
> ISP programmieren will. Dazu braucht es keine Schalter, "nur" Knoff
> Hoff.

> https://www.mikrocontroller.net/articles/AVR_In_Sy...

Dort ist leider nur beschrieben, wie man AVR mit anderen IC verwenden 
kann. Dort  steht aber nicht, wie man per SPI mehrere AVR verbinden kann 
und sie dabei noch programmieren. Die werden einander stören.

Das kann nur bei AVR funktionieren, wo SPI und ISP verschiedene Pins 
haben, so wie bei ATMEGA128.

: Bearbeitet durch User
von georg (Gast)


Lesenswert?

Maxim B. schrieb:
> Die haben zwei USART,
> beide haben XCK-Pin.

Das ändert doch an der Aussage garnichts. Aber wenn du unbedingt deinen 
Kopf durchsetzen und synchron senden/empfangen willst, studiere 
Protokolle wie SDLC oder HDLC, sowas brauchst du. Meiner Erinnerung nach 
hat Datev das verwendet, vor der Internetzeit.

Georg

von Falk B. (falk)


Lesenswert?

@Maxim B. (max182)

>Grob gesagt, ich muß jede 20 us 800 Befehle ausführen können. Dazu muß
>noch genug Zeit übrig bleiben, mindestens 50% frei. Sonst kann AVR
>nichts mehr, nicht einmal Befehle empfangen.

Das ist nicht wirklich, wonach ich gefragt habe.

Was willst du INSGESAMT machen? Soviele uC klingt mal wieder nach 
LED-Ansteuerung etc.

von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Ich möchte eine Orgel mit 8 gleichzeitig klingenden Stimmen (für Pedal 
reicht zwei) bauen.
Ich habe eine Ahlborn aus 70-n, ich muß dort sowieso etwas ändern. ich 
überlege: wenn sowieso Umbau notwendig, dann mache ich vielleicht ganze 
Klangerzeugung neu.

In Moment favorisiere ich folgende Aufbau:
Alle Tastaturen MIDIfizieren (das erleichtert spätere Nachbesserungen).
Ein Zentralblock mit ATmega1284. Der bekommt MIDI-Befehle, sucht freie 
Kanal und falls vorhanden, schaltet den Ton ein.

So etwas habe ich schon im 2000 mit AT89C-Serie gemacht. Nun aber möchte 
ich Klangerzeugung nach Wellentabellen-Prinzip. Dabei scheint es mir von 
Vorteil, wenn nur zentrale CPU die ganzen Formen gespeichert hat und sie 
nach Bedarf an die Kanal-Erzeuger schickt.

Nach meinen Berechnungen kann ATMEGA844PA mit F_CPU=20MHz zwei Töne 
bedienen, mehr nicht. Dabei verzichte ich auf digitale Modulation: 
Amplitude wird mit Hilfe vom PWM und Vref bei DAC MCP4922 erzeugt. Auch 
2 Einheiten pro Chip, so paßt das gut zusammen.

Um Ton zu schalten, sollte zuerst Formtabelle übertragen werden, 480 
16bit-Worte (es reicht eigentlich, wenn das nur beim Umschalten von 
Register gemacht wird, nicht bei jedem Tastendruck. Aber sowieso: so 
schnell wie nur technisch möglich).

SPI ist schon sowieso mit DAC beschäftigt, ich brauche andere Interface.

Schema für 2 Töne so ungefähr wie auf dem Bild.

Noch zuletzt: ich bin ein Musiker. Ich weiß, was ich brauche. Ich weiß 
nur noch nicht genau, wie ich das mache.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Maxim B. (max182)

>Ich möchte eine Orgel mit 8 gleichzeitig klingenden Stimmen (für Pedal
>reicht zwei) bauen.

Dafür braucht man keine 20 AVRs. Bestenfalls 2.

>So etwas habe ich schon im 2000 mit AT89C-Serie gemacht. Nun aber möchte
>ich klangerzeugung nach Wellentabellen-Prinzip.

Gute Idee.

>Nach meinen Berechnungen kann ATMEGA844PA mit F_CPU=20MHz zwei Töne
>bedienen, mehr nicht.

Andere schaffen 6 und mehr.

http://elm-chan.org/works/mxb/report.html

>SPI ist schon sowieso mit DAC beschäftigt, ich brauche andere Interface.

Nö, bessere Konzepte.

von Maxim B. (max182)


Lesenswert?

Für mich ist eine gute Polyphonie am wichtigsten. Es ist nicht zulässig, 
wenn bei mehreren Stimmen immer "schmutziger" wird, wie normalerweise 
bei Keyboards. Deshalb möchte ich Töne maximal voneinander trennen.

Wie man hier noch 8 Töne schafft, verstehe ich schlecht.
Als Beispiel: DDS-Funktion:
1
while(1){
2
3
  
4
  if( FLAGG & (1<<F_PULS) ){
5
6
    unsigned int phase_index = 0;
7
    unsigned int a = 0;
8
    static __uint24 freq_zaehler_a = 0;
9
    static __uint24 freq_zaehler_b = 0;
10
    static unsigned int form_puffer_a = MCP4921_KANA | MCP4921_GA | MCP4921_SHDN | 0x0400;
11
    static unsigned int form_puffer_b = MCP4921_KANB | MCP4921_GA | MCP4921_SHDN | 0x0400;
12
13
    FLAGG &= ~(1<<F_PULS);
14
15
    /*** Kanal A ***/
16
17
  // Per SPI an DAC MSB senden
18
    
19
    PORT_CS0 &= ~(1<<CS0);
20
    SPDR = (unsigned char)(form_puffer_a >> 8);
21
22
  // DDS Phase berechnen
23
    freq_zaehler_a += tonfrequenz_a;
24
    if(freq_zaehler_a >= 0xf00000) freq_zaehler_a -= 0xf00000;
25
26
  // Per SPI an DAC LSB senden
27
    while(!(SPSR & (1<<SPIF)));
28
    SPDR = (unsigned char)form_puffer_a;
29
30
  // Adresse fuer Formtabelle berechnen
31
    phase_index = (unsigned int)(freq_zaehler_a >> 16);
32
    a = (unsigned int)freq_zaehler_a;
33
    phase_index = (phase_index << 1);
34
    if(a & 0x8000) phase_index |= 0x0001;
35
36
  // Signalform aus der Tabelle holen
37
    form_puffer_a = (unsigned int)(tonform[phase_index] + 2048) | MCP4921_KANA | MCP4921_GA | MCP4921_SHDN;
38
39
    while(!(SPSR & (1<<SPIF)));
40
    PORT_CS0 |= (1<<CS0);
41
42
43
    /*** Kanal B ***/
44
45
  // Per SPI an DAC MSB senden
46
    
47
    PORT_CS0 &= ~(1<<CS0);
48
    SPDR = (unsigned char)(form_puffer_b >> 8);
49
50
  // DDS Phase berechnen
51
    freq_zaehler_b += tonfrequenz_b;
52
    if(freq_zaehler_b >= 0xf00000) freq_zaehler_b -= 0xf00000;
53
54
  // Per SPI an DAC LSB senden
55
    while(!(SPSR & (1<<SPIF)));
56
    SPDR = (unsigned char)form_puffer_b;
57
58
  // Adresse fuer Formtabelle berechnen
59
    phase_index = (unsigned int)(freq_zaehler_b >> 16);
60
    a = (unsigned int)freq_zaehler_b;
61
    phase_index = (phase_index << 1);
62
    if(a & 0x8000) phase_index |= 0x0001;
63
64
  // Signalform aus der Tabelle holen
65
    form_puffer_b = (unsigned int)(tonform[phase_index] + 2048) | MCP4921_KANB | MCP4921_GA | MCP4921_SHDN;
66
67
    while(!(SPSR & (1<<SPIF)));
68
    PORT_CS0 |= (1<<CS0);
69
70
  }
71
}

Schon jetzt ist das so gemacht, daß während SPI beschäftigt ist, weiter 
gerechnet wird. Was kann man hier noch optimieren?

Interrupt:
1
ISR(TIMER0_COMPA_vect, ISR_NAKED){ // Timer 0 interrupt.
2
3
  MCP4921_LDAC_PORT &= ~(1<<MCP4921_LDAC); // Impuls LDAC
4
  FLAGG |= (1<<F_PULS);  // Flag fuer Puls einsetzen
5
  MCP4921_LDAC_PORT |= (1<<MCP4921_LDAC);
6
  
7
  reti(); // da ISR_NAKED
8
}
So ist schneller, als ohne ISR_NAKED ISR von Timer ist hier nur 
provisorisch, am Ende muß natürlich ISR von INT0 kommen, aber Prinzip 
ist gleich. Fd wird von AD9833 erzeugt (um 50, notfalls 40 kHz), so kann 
feine Abstimmung der Tonhöhe gemacht werden.

Schieben von Tabellenindex habe ich schon optimiert: sieht etwas komisch 
aus, kommt aber viel schneller, als gewöhnliche
1
phase_index = (unsigned int)(freq_zaehler_b >> 15);
Was noch?

Das ganze braucht etwa 179 Cycle. Es muß noch etwas anderes erledigt 
werden, CPU darf nicht 100% nur das machen...

Für Tabellen möchte ich einfach etwas von meinen Orgeln aufnehmen und so 
anpassen, daß bei beliebigen gleichzeitig geschalteten Register +2047 
und -2048 nicht überschritten werden.

Klar: hier fehlt noch Klangfarben-Anpassung nach Tonhöhe. Aber bei so 
einem einfachen Instrument kann man nicht alles haben. Es wird sowieso 
besser als jetzt. Es wäre schön, wenn auch repetierende Register 
gelingen. Dafür sehe ich nur eine Möglichkeit: Formtabelle während des 
Spiels aufladen und zwischen zwei umschalten. Aber das sollte schneller 
passieren, als eine wahrnehmbare Verzögerung. Eine pneumatische Jehmlich 
möchte ich nicht :)

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Noch ein bisschen kalkuliert: bei I2C 400 kHz, wenn folgende Schema 
benutzt wird:IC-Adresse - Befehl (- Daten), zuerst Daten nach Rx-Puffer, 
dann Schaltbefehl:
Formtabelle aus Puffer aufladen, ~500 us
Ton ausschalten ~= 60 us
Tonfrequenz, Amplitude -> Puffer und Schaltbefehl: 270 us
Data -> Rx_Puffer[960] ~= 28,9 ms für 960 bytes, das ist eindeutig zu 
viel.

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.