Forum: Mikrocontroller und Digitale Elektronik Wie programmier ich das elegant in C


von Zerspannungsmechaniker (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe hier diesen Schaltplan gemacht.
Ich nenne das mal einen Bus-Koppler bis mir ein besserer Name einfält.
Mit dem 74HC245 kann ich ein Byte vom ATmega8 auf den rechten Bus 
transportieren. (Write_Bus)
Mit dem 74HC574 kann ich von dem rechten Bus ein Byte zum ATmega8 
transportieren. (Read_Bus)
Die CPU auf dem rechten Bus ist der Master, er steuert alle Funktionen.
Der ATmega8 ist nur der Slave.

Ich brauche von dem ATmega8 PD0(RxD) und PD1(TxD) für eine RS232 
Schnittstelle. PB6 und PB7 brauche ich für den Quarz.
Deshalb sind die Bits der Bytes schön auf Port B, C und D verteilt.
Im Platinen-Layout sieht das aber ganz gut aus ;-)

Wie kann ich in C die beiden Funktionen
1
unsigned char Read_Bus(void);
2
void         Write_Bus(unsigned char);
ohne viel Bitpopelei elegant schreiben?

von Huch (Gast)


Lesenswert?

> ... ohne viel Bitpopelei elegant schreiben?

Ich sags mal so: In dem Du weniger als viel Bitpopelei verwendest aber 
gerade soviel das es reicht. :-)

von Huch (Gast)


Lesenswert?

Eine andere Antwort: Nimm Dir als erstes nicht Eleganz zum Ziel sondern 
die Funktion. Hauptsache Du verstehst wie es funktioniert und es geht. 
Die "Eleganz", wie immer man das definiert, kommt dann mit den Jahren.

von Zerspannungsmechaniker (Gast)


Lesenswert?

Huch schrieb:
> Nimm Dir als erstes nicht Eleganz zum Ziel sondern
> die Funktion.

Um die Wahrheit zu sagen, ich kriege die Bitpopelei überhaupt nicht hin.
Ich geh jetzt und sauf mich zu!

von doch Gast (Gast)


Lesenswert?

Huch schrieb:
> Eine andere Antwort: Nimm Dir als erstes nicht Eleganz zum Ziel sondern
> die Funktion. Hauptsache Du verstehst wie es funktioniert und es geht.
> Die "Eleganz", wie immer man das definiert, kommt dann mit den Jahren.
Sehr richtig, zumal C gerade für "Bitpopeleien" sehr gut geeignet ist.

(Das heisst aber nicht dass C nur für solche Sachen gut ist! (Nur 
dass jetzt keiner ankommt...))

von ... (Gast)


Lesenswert?

Ja dann: Prost!

von doch Gast (Gast)


Lesenswert?

Ahh, jetzt hab ich kapiert. Da will mal wieder jemand dass wir die 
Arbeit machen. So geht's natürlich auch.

von Thomas E. (thomase)


Lesenswert?

Warum du die Daten nicht einfach in den USART deines Host-Controllers 
schreibst, will ich jetzt gar nicht wissen.

Aber das, was du da bauen willst, wird so nie funktionieren. Denn woher 
soll der Client wissen, daß gültige Daten am Port anliegen?
Woher soll der Host wissen, daß der Client Daten für ihn hat?

Ein Bus benötigt immer Steuerleitungen. In deinem Fall Strobe und 
Busy/Acknowledge für jeweils beide Busse.

Um nochmal auf meinen ersten Satz zurückzukommen: Lass' den Quatsch und 
nimm den USART vom Host. Ist wesentlich weniger aufwendig und schneller.

mfg.

von Peter D. (peda)


Lesenswert?

So geht das nicht.
Schau Dir mal den 74HC646 an, der ist dafür gedacht.

Ich würde allerdings keine 2 MCs so koppeln. Reichen denn die 4 UARTs 
des ATmega2560 nicht?


Peter

von Achim M. (minifloat)


Lesenswert?

Warum nicht mit Port C und B direkt auf den Bus gehen?
Oder einer sonstigen Kombination aus den Ports, um dann INT0 und INT1 
freizuhalten, welche dann als ¬READ und ¬WRITE fungieren.
Oder einen Mega48/88/168 hernehmen, der beherrscht Pinchange-Interrupts 
auf allen Pins. Oder sind 20MHz bzw. die entsprechenden Zeiten, um in 
die Interruptroutine zu springen, zu langsam?

Fragen nebenher:
Wieviele Takte braucht man zum Program Counter ablegen und Sprung?
Nach wievielen Takten bin ich in der Routine drin?

mfg mf

PS: Bitpopelei sehr gut im AVR-GCC-Tutorial beschrieben.

von Zerspannungsmechaniker (Gast)


Lesenswert?

[IRONIE]
Danke für die Hilfe.
[/IRONIE]

Ich baue für ein über 20 Jahre altes Gerät ein nicht mehr lieferbares 
Interface quasi nach.

Ich hatte gehofft, das man statt Bitpopelei da was in der Art
1
struct status {
2
  unsigned char b0:1;
3
  unsigned char b1:1;
4
  unsigned char b2:1;
5
  unsigned char b3:1;
6
  unsigned char b4:1;
7
  unsigned char b5:1;
8
  unsigned char b6:1;
9
  unsigned char b7:1;
10
};
mit einer struct machen könnte.

von Floh (Gast)


Lesenswert?

Zerspannungsmechaniker schrieb:
> Ich brauche von dem ATmega8 PD0(RxD) und PD1(TxD) für eine RS232
> Schnittstelle. PB6 und PB7 brauche ich für den Quarz.
> Deshalb sind die Bits der Bytes schön auf Port B, C und D verteilt.

Ja klar. Ein bisschen nachschauen was man eigentlich braucht und man 
würde z.B. einen mega16 nehmen. Der hat mehrere komplette (!) 
8-Bit-Ports. Das würde sich die ganze Bitschieberei auf Null reduzieren.

von doch Gast (Gast)


Lesenswert?

Wo ist das Problem???

Bitmanipulation in diesem Ausmaß ist selbst in Assembler Kinderkram.

uint8/16/32, ein paar Shifts, UND, ODER, ggf. noch XOR und NOT, fertig.

von Karl H. (kbuchegg)


Lesenswert?

Zerspannungsmechaniker schrieb:

> Ich hatte gehofft, das man statt Bitpopelei da was in der Art
>
1
> struct status {
2
>   unsigned char b0:1;
3
>   unsigned char b1:1;
4
>   unsigned char b2:1;
5
>   unsigned char b3:1;
6
>   unsigned char b4:1;
7
>   unsigned char b5:1;
8
>   unsigned char b6:1;
9
>   unsigned char b7:1;
10
> };
11
>
> mit einer struct machen könnte.

ist genauso Bitpopelei

Wo liegt den das Problem.

Schreib dir deine Ausgangslage hin

     PD3 PD2 PC5 PC4 PC3 PC2 PC1 PC0

und überleg dir welche Bitblöcke du beim Einlesen wie schieben musst, 
damit genau diese Bitfolge rauskommt. Ist doch kein wirkliches Problem.

Du liest von PIND ein, dann hast du

     PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0

interessiert (in Ergebnis nachsehen) bist du an PD3 und PD2. Also setzt 
du gezielt erst mal alle anderen Bits auf 0. Dann hast du

      0   0  0   0  PD3 PD2 0 0

Jetzt schaust du wieder aufs Ergebnis und vergleichst. Wenn du dein 
0-gesetztes Zwischenergebnis um 4 Stellen nach links schiebst, sind die 
beiden Bits dort wo sie sein sollen.

      PD3 PD2 0 0 0 0 0 0

und sind fertig um ins Ergebnis übernommen zu werden.

Und jetzt im ganzen C-Satz:


    uint8_t bitsD = PIND;

    bitsD &= ~( 1 << PD3 | 1 << PD2 );          // auf 0 setzen
    bitsD <<= 4;

fertig zum Zusammenführen mit den Bits vom C-Port.

Beim Schreiben genau anders rum. Du hast 8 Bit und musst du nach diesem 
Schema auf die Portbits verteilen. Auch da gibt es wieder Bitblöcke die 
gemeinsam behandelt werden können.

von Peter D. (peda)


Lesenswert?

Zerspannungsmechaniker schrieb:
> Ich baue für ein über 20 Jahre altes Gerät ein nicht mehr lieferbares
> Interface quasi nach.

Bevor Du anfängst zu programmieren, denke erstmal über das Timing nach.
Wenn der AVR memory mapped dran hängt, muß er ja die Lese- und 
Schreibzeiten einhalten können. Es könnte also ein CPLD oder FPGA 
notwendig werden.

Vermutlich brauchst Du auch noch einige Adreßleitungen, d.h. es wird 
knapp mit den Pins des ATmega8.


Peter

von Ästhet (Gast)


Lesenswert?

Nur, weil der Thread sowieso von 'Eleganz' handelt:

Dein Schaltplan wäre wesentlich eleganter, wenn du für die beiden HC574 
die Funktionen Rotate und Mirror benutzt hättest.

von Stephan H. (stephan-)


Lesenswert?

wäre ein Bidi Treiber 245 nicht besser geeignet.

von Tobi (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> bitsD &= ~( 1 << PD3 | 1 << PD2 );          // auf 0 setzen

Wenn die Bits PD3 und PD2 interessieren, dann sollte man die lieber 
nicht auf 0 setzen. Also ist das Komplement zu viel.
1
bitsD &= ((1 << PD3) | (1 << PD2));

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.