Forum: Mikrocontroller und Digitale Elektronik ADC Conversion Resultat in Hex umwandeln


von F C (Gast)


Lesenswert?

Hallo Leute!

Bin noch nicht so geübt im 'Microcontrolling' und hab jetzt mal eine
Frage. Und zwar hab ich einen ATMega 16 und will dort mittels eine ADC
Conversion machen. Das Resultat soll das mittels Display Multiplexing
auf 3 DIGITS in Hexadezimalwert ausgegeben werden.
Meine Probleme:
Erstens, wie kann ich EIN Ergebnis auslesen, wenn das in zwei Registern
liegt (ADCH und ADCL).
Zweitens, wie kann ich dann wenn ich EIN Ergebnis habe, dieses
(möglichst einfach)in einen Hexwert umwandeln?

Wäre für jede Hilfe dankbar

mfg
FC

von Hannes L. (hannes)


Lesenswert?

> Erstens, wie kann ich EIN Ergebnis auslesen, wenn das in zwei
> Registern liegt (ADCH und ADCL).

Das Ergebnis liegt in zwei I/O-Registern. Man kann es in zwei
Arbeitsregister (r0..r31) einlesen und diese beiden Register als eine
16-Bit-Zahl betrachten.

> Zweitens, wie kann ich dann wenn ich EIN Ergebnis habe, dieses
> (möglichst einfach)in einen Hexwert umwandeln?

Nehmen wir an, du hast ADCL nach r16 eingelesen und ADCH nach r17.
Das entspräche dem ASM-Code:
 in r16,adcl
 in r17,adch

Nun willst du den Wert an einem dreistelligen 7-Segment-Display (LEDs)
in HEX-Schreibweise per Multiplex anzeigen.
In r16 liegen die unteren zwei Nibbles, in r17 das obere Nibble und ein
unbenutztes Dummy-Nibble. Du musst also erstmal die drei benötigten
Nibbles isolieren (andi, swap) und in 3 Registern oder RAM-Zellen
ablegen.
Dann musst du dir im Flash eine Tabelle mit 16 Einträgen anlegen, in
der für jede Hex-Ziffer das Bitmuster der Segment-LEDs eingetragen ist.
Der genaue Inhalt der Tabelle richtet sich danach, wie das Display an
den AVR angeschlossen ist, ob mit gemeinsamer Anode je Digit oder mit
gemeinsamer Kathode. Dann spielt auch noch die Zuordnung Segment zu
Portpin eine Rolle.

Um die Zahlenwerte nun kontinuierlich anzuzeigen, richtest du dir einen
Timer ein, der alle etwa 1..3ms einen Interrupt auslöst. In dieser ISR
(Interrupt-Service-Routine) zählst du einen Merker hoch, der dir sagt,
welches Digit gerade angezeigt wird. Dann
- deaktivierst du erstmal alle Digit-Treiber (es war nur einer
  aktiv),
- setzt du den Z-Pointer auf die Bitmustertabelle,
- addierst den Wert des anzuzeigenden Nibbles dazu,
- holst mittels LPM das Bitmuster aus der Tabelle,
- um es dann an den Segment-Port auszugeben.
- Nun aktivierst du den entsprechenden Digit-Treiber, um diese eine
  Anzeigestelle (Digit) leuchten zu lassen.

...

von günther (Gast)


Lesenswert?

Die beiden 8Bit Werte in einen 16Bit Wert packen kannst du so:
uint16_t x;
x=((uint16_t)ADCH<<8)|ADCL;
Aber wenn du die doch sowieso als hex ausgeben willst, wäre es doch
vielleicht geschickter, sich den Aufwand zu sparen.
Schreib dir doch einfach eine Funktion, die vier Bit entgegennimmt und
dann das entsprechende Hex-Zeichen auf dem Display ausgibt.

void printHex(uint8_t i) {
 switch(i) {
  case 0: print('0');
  .
  .
  .
  case 15: print('F');
 }
}

und jetzt die ganze Geschichte so aufrufen:
printHex(ADCH>>4);
printHex(ADCH&0xF);
printHex(ADCL>>4);
printHex(ADCL&0xF);

Der erste Aufruf schiebt ADCH erst um vier Bit nach rechts, der zweite
Auruf maskiert die oberen vier Bit aus, betrachtet also nur die vier
unteren Bit. Mit ADCL verfährst du genauso.
Hoffe geholfen zu haben...
print() musst du dir selber überlegen, wie dein Display funktioniert,
weiss ich nicht...

von Schoasch (Gast)


Lesenswert?

Hi

Welche Programmiersprache verwendest du? Hast du die Routine für das
Display schon? Welche Werte kannst du denn Übergeben?
Ich würde glaube ich gar nicht die 2 8Bit Zahlen zu einer 16Bit zahl
zusammenfassen!
Grund dafür ist:
int erste_stelle,zweite_stelle,dritte_stelle;

erste_stelle = ADCH;        // vl auch noch & 0x0F anhängen
zweite_stelle= (ADCL >> 4); // vl auch noch & 0x0F anhängen
dritte_stelle= ADCL & 0x0F;

So hättest du halt mal alle dein Hexstellen.

Weiters würde ich einfach eine Tabelle bzw Arry anlegen, wo du dann die
jeweiligen Zeichen angibts.

Also mach ein Array:
int LCD_Hex_zeichen[17]={ Hier tragst du die Zahlen ein, welche du ans
LCD schicken musst, wenn das jeweilige Array ansprichst};

Also wenn zb in der Variable erste_stelle 10(dezimal) drin steht, dann
sollte die Segmente aktiviert sein die für A(hex) steht usw.
Weist du was ich meine?

Entschuldige mein schlechte Erklärung... ich hoffe du kannst ungefähr
meinen Gedankengängen folgen.

mfg Schoasch

PS.: Habe noch nie einen AVR programmiert ;-)

von F C (Gast)


Lesenswert?

Vielen Dank für die rasche Hilfe. Werd jetzt mal herumprobieren und
hoffe, dass es so funktioniert.
Danke nochmals

mfG FC

von Hannes L. (hannes)


Lesenswert?

> Werd jetzt mal herumprobieren

Mit "herumprobieren" wird da wohl nicht viel bei herauskommen.

Beser, du beschäftigst dich gründlich mit dem Datenblatt und dem
Befehlssatz der (immer noch nicht genannten) Programmiersprache.

Es bringt dem Anfänger vermutlich auch eine ganze Menge, erstmal hier
im Forum etwas herumzustöbern und sich die reichlich vorhandenen
Quelltexte (die in den verschiedenen Programmiersprachen vorhanden
sind) anzuschauen und zu analysieren. Ich gehe mal davon aus, dass du
das AVR-Tutorial auf dieser Seite bereits durchgearbeitet hast. -
Oder?

Viel Erfolg...

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.