Hallo,
ich möchte eine 7-Segment Anzeige per ATmega32 ansteuern wobei die
Eingangssignale als Gray-Code definiert sind:
000 = A
001 = U
011 = E
010 = 1
110 = 2
111 = 3
101 = 4
Wenn die entsprechenden Signale an den jeweiligen Bits (PA0 - PA2)
anliegen sollen die entsprechenden Bits am PORT D auf High geschaltet
werden.
Ich hab mir das Tutorial durchgelesen und auch andere Beispiele
angeschaut und mal probiert ein Programm dazu zu schreiben.
Für Hilfe und Ratschläge wäre ich sehr dankbar.
mfg
Uff ! So vergleicht man eigentlich nicht. Das ist eine Zuweisung in
einem if.
Also wird hier PINA der Wert von PINA mit 1 und-verknüpft zugewiesen.
Weil aber in C jede Zuweisung auch einen Wert hat, gibt's dafür keinen
Mecker vom Compiler, sondern die Bedingung ist wahr, sobald PINA und 1
einen Wert ungleich null hat.
Du schreibst also auf PINA, das ist bei AVRs wie ein Schreiben auf
PORTA. Da die Pins wohl Eingänge sind, schaltest Du damit munter die
Pullups, falls sie global aktiviert sind. War vermutlich so nie gedacht.
Punkt 2 ist noch witziger, sobald das Bit 0 in PINA eins ist, ist die
Bedingung erfüllt. Also immer, wenn PA0 auf high ist.
Laut Deiner Tabelle also bei U, E, 3 und 4. Nicht wie geplant nur bei U.
Warum Du die Anzeige löschst, wenn der aktuell abgetestete Wert nicht
stimmt, bleibt wohl Dein Geheimnis. Würdest Du Dir das verkneifen,
könntest Du die delay auch einfach weg lassen.
Also normalerweise würdest Du ja auch sagen
- wenn U, zeige U an
- wenn E, zeige E an
... usw.
- wenn nix von alledem, lösche Anzeige
So was kann man als witzige if...else if...else if...else if...else
Kaskade schreiben. Oder man kann das wie dafür gemachte switch/case
benutzen.
Wenn Du es so umsetzt kannst Du auch volle Geschwindigkeit geben. Es
flackert dann nur, wenn der Eingangswert wackelt.
Max D. schrieb:> Mach dir eine code Tabelle und benutze deinen Code als Zeiger da rein.
So in etwa?
1
constunsignedcharGrayCode[7]={0x7E,//U
2
0x79,// E
3
0x06,//1
4
0x5B,//2
5
0x4F,//3
6
0x66,//4
7
0x77//A
8
};
Das wären die Zustände für die Pins an der 7-Segment Anzeige.
Abgefragt sollen folgende Zustände an den Eingangspins:
U = 0x01
E = 0x03
1 = 0x02
2 = 0x06
3 = 0x07
4 = 0x05
A = 0x00
Edit:
Ist das korrekt?
Max D. schrieb:> Du musst vorher den graycode in binär "umdenken"
denken vielleicht, programmieren muss man das nicht - es genügt ja eine
Tabelle Gray -> 7Segment.
Georg
Georg schrieb:> Max D. schrieb:>> Du musst vorher den graycode in binär "umdenken">> denken vielleicht, programmieren muss man das nicht - es genügt ja eine> Tabelle Gray -> 7Segment.>> Georg
Soll so sein wie im Anhang dargestellt. Das ganze mit gemeinsamer
Kathode der 7-Segment Anzeige
Du baust dir erstmal eine Tabelle die für deine 8 Zustände die Werte
enthält:
1
uint8_tkonverterTabelle[]={
2
0x77//A
3
0x7E//U
4
0x06//1
5
0x79//E
6
//hier noch die restlichen Codes
7
};
(größere Tabellen kann man auch in den flash legen (pgmspace.h) um Platz
im RAM zu sparen, bei 8 Einträgen lohnts aber ned)
Du kannst die dann ansprechen fast wie eine Funktion:
1
PORTD=konverterTabelle[PINA&0b00000111];
Wenn auf PORTD noch andere Funktionen liegen, dann musst du halt die
bits maskieren.
Ich würde es nicht umdenken nennen. Es ist eher ein Umsortieren. Du
brauchst aber 8 Plätze im Array, nicht 7, da es einen ungültigen Zustand
gibt.
0 = 000 = A
1 = 001 = U
2 = 010 = 1
3 = 011 = E
4 = 100 = -
5 = 101 = 4
6 = 110 = 2
7 = 111 = 3
fop schrieb:> #ifndef NEGATIVE_LOGIC> PORTD=(PORTD & ~CHR_8)|Gray2SevenCode[PINA & 7U];> #else> PORTD=(PORTD | CHR_8)& Gray2SevenCode[PINA & 7U];> #endif> [/c]
Vor dem ersten PORTD bekomm ich folgende Fehlermeldungen:
expected identifier or '(' before 'volatile'
expected ')' before '(' token
CHR_8 brauch ich ja nicht unbedingt
Jein, das CHR_8 nehme ich als Maske, für alle Bits, die zur Ausgabe an
die Anzeige dazu gehören. Nur für den Fall, dass der 8. Pin mal eine
andere Bedeutung bekommt.
Ich hatte das Beispiel getippt, ohne es durch den Compiler zu jagen.
Sollte aber so ähnlich funktionieren. Die letzte Zeile gehört natürlich
in die Schleife der main() Funktion.
Also nochmal probiert. Folgendes Compiliert durch :
fop schrieb:> Also nochmal probiert. Folgendes Compiliert durch
Zu umständlich. Ich würde den ganzen Schmonzes mit NEGATIVE_LOGIC
weglassen. Das verwirrt doch unseren TE bloß. Eher so:
1
...
2
3
constuint8_tGray2SevenCode[8]=
4
{CHR_A,CHR_U,CHR_1,CHR_E,
5
CHR__,CHR_4,CHR_2,CHR_3};
6
7
intmain(void)
8
{
9
/* Eingaenge definieren */
10
DDRA&=~(INMSK<<INLSB);/* Datenrichtung */
11
PORTA|=(INMSK<<INLSB);/* PullUps */
12
13
/* Ausgaenge definieren */
14
DDRD|=0xFF;/* Datenrichtung */
15
16
while(1)
17
{
18
PORTD=Gray2SevenCode[(PINA>>INLSB)&INMSK];
19
}
20
}
Falls er seine LED doch lieber mit L statt mit H einschalten will, dann
genügt es, eine einzige Zeile zu ändern:
1
PORTD=~Gray2SevenCode[(PINA>>INLSB)&INMSK];
Außerdem noch ein paar Anmerkungen:
1. es ist ziemlich verwirrend, eine entweder-oder Codevariante als
1
#ifndef BEDINGUNG
2
#else
3
#endif
zu schreiben. So ziemlich jeder erwartet den if Zweig zuerst. Also
einfach #ifdef BEDINGUNG und dann die beiden Blöcke tauschen.
2. wenn du ohnehin alle Bits setzen willst, dann brauchst du nicht mit
logischen Operatoren rumzumachen, sondern kannst den Wert direkt
zuweisen. Alle Anfänger, die deinen Code mal zu verstehen versuchen,
werden es dir danken.
3. es ist ungeschickt, CHR_8 als Maske zu nehmen. Denn es ist zwar mit
dieser Codierung gegeben, daß CHR_8 alle Bits gesetzt hat, aber das
muß ja nicht so bleiben (genau deswegen verwendet man ja ein #define,
damit man den Code verwenden kann ohne die Interna zu kennen). Wenn du
also explizit alle Bits setzen willst, dann schreib das auch so hin und
verlaß dich nicht auf Spezifika der gerade gewählten Codierung.
Stell dir dazu einfach vor, der TE wöllte das nächste Mal keine
7-Segment-Anzeige verwenden, sondern 7 einzelne LED, je eine für jeden
Zustand. Dann müßte er außer der Übersetzungstabelle noch eine ganz
andere Stelle im Code ändern.
Axel S. schrieb:> der TE wöllte das nächste Mal keine> 7-Segment-Anzeige verwenden, sondern 7 einzelne LED, je eine für jeden> Zustand.
Dann kann man das ja als HAL aufeinander aufbauen. Es gibt eine Routine
Setze_LED, und die Routine Setze_Display verwendet diese. Dann muss man
auch kein 8bit-Port für das Display verwenden, sondern kann beliebige
Pins nehmen. Die paar Befehle mehr sollten ja keine Rolle spielen.
Georg
Georg schrieb:> Axel S. schrieb:>> der TE wöllte das nächste Mal keine>> 7-Segment-Anzeige verwenden, sondern 7 einzelne LED, je eine für jeden>> Zustand.>> Dann kann man das ja als HAL aufeinander aufbauen.
Hast du eigentlich verstanden, worum es mir in Punkt 3 ging?
Kleiner Tip: das wesentliche hast du nicht zitiert.
Axel S. schrieb:> fop schrieb:>> Also nochmal probiert. Folgendes Compiliert durch>> Zu umständlich. Ich würde den ganzen Schmonzes mit NEGATIVE_LOGIC> weglassen. Das verwirrt doch unseren TE bloß. Eher so:
Ja, ist alles neu für mich in Sachen Mikrocontroller.
Im Grunde geht es um folgende Aufgabenstellung und Problem:
In einem Aufzug wird die Position über Initiatoren als Gray-Code
erfasst. Dabei entspricht die unterste Position dem Signal "001" (also
U). Es gibt 6 Etagen und wenn der Aufzug außer Betrieb ist wird die
Position "000" gesetzt und es erscheint die Anzeige "A".
Deswegen das ganze mit 7-Segment Anzeige und keine einzelnen LED.