Forum: Mikrocontroller und Digitale Elektronik Probleme bei C Programmierung


von Daniel S. (stoegi)


Lesenswert?

Hallo,
folgendes Problem:

Wenn ich dieses Programm ausführe funktioniert alles einwandfrei.
Der Binärwert Y wird zum Test als Dezimalzahl (255) auf dem LCD
angezeigt.

#include "lcd_routine.h"

void main()
{
  lcd_ini();

  uint16_t Y = 0b11111111; // Dezimal 255

  while(1)                // Endlosschleife
    {
        lcd_gotopos(1,1);   // Position der Zahl
        ZalString(Y);       // Zahl ausgeben
        delay(5000);        // 0,5s abwarten
    }

}
--------------------------------------------------------------------
(ZalString ist in der LCD Routine beigefügt und wandelt die Zahl.)

So, jetzt habe ich meinen ADC Wert in der Variable "x" gespeichert
aus diesem Programm, welches eigenständig auch ohne Probleme läuft:

  int x = 0;
  // Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz
  ADCSRA = _BV(ADEN) | _BV(ADPS2);
  for (;;) {
    // Select pin ADC0 using MUX
    ADMUX = 0;

    //Start conversion
    ADCSRA |= _BV(ADSC);

    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}

    // get converted value
    x = ADCW;
  }
---------------------------------------------------------------------
Und mein Problem ist es, diese beiden Programme zusammenzufügen und
jetzt den Binärwert von "x" aufs Display zu kriegen mit ZalString(x),
statt dem Test mit dem Fixwert "Y".

Wie füge ich jetzt den ADC Teil in das Restliche Programm oben ein,
dass das funktioniert. Vielen Dank

von Yagan Ζ. D. (yagan)


Lesenswert?

daniel,

das müsste etwa so aussehen:

#include "lcd_routine.h"

void main()
{
  lcd_ini();

  uint16_t Y = 0b11111111; // Dezimal 255
  int x = 0;

  // Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz
  ADCSRA = _BV(ADEN) | _BV(ADPS2);

  while (1)                // Endlosschleife
    {
    // Select pin ADC0 using MUX
    ADMUX = 0;

    //Start conversion
    ADCSRA |= _BV(ADSC);

    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}

    // get converted value
    x = ADCW;

    Y = (uint16_t)x;
    lcd_gotopos(1,1);   // Position der Zahl
    ZalString(Y);       // Zahl ausgeben
    delay(5000);        // 0,5s abwarten
    }

}

Also Initialisierungen vor die Endlosschleife und Aktionen in die
Schleife.
while(1) {} ist übrigens äquivalent zu for (;;) {}

Ciao, Yagan

von Daniel S. (stoegi)


Lesenswert?

VIELEN DANK,
funktioniert einwandfrei :D
Danke

von Gast ein Anderer (Gast)


Lesenswert?

uint16_t Y = 0b11111111; // Dezimal 255 wiso uint16_t ?
Wenn du Messwerte in Zahlen darstellen willst solltest du dir
itoa()
mal anschauen.
Gruß

von karl-heinz (Gast)


Lesenswert?

uint16_t Y = 0b11111111; // Dezimal 255.....

binäre werte werden in winavr-c nicht erkannt.
werden nur als deci.

von karl-heinz (Gast)


Lesenswert?

erkannt zb 11.111.111 > 11million.....

von Daniel S. (stoegi)


Lesenswert?

Habe noch eine Frage:

hier ein Ausschnitt:

// get converted value
    x = (uint16_t)ADCW;

  double y = x*5/1023;

  int z = y;

    lcd_gotopos(1,10);  // Position der Zahl
    ZalString(z);       // Zahl ausgeben
    delay(5000);        // 0,5s abwarten

Jetzt krieg ich die Ganzen Volt von 0-5 aufs display.. logisch
Wie schreibe ich jetzt das Programm dass ich noch 2 Kommastellen
kriege, oder zum Anfang mal 1 Kommastelle.

Danke

von Xenu (Gast)


Lesenswert?

>binäre werte werden in winavr-c nicht erkannt

Bei mir schon. Vielleicht solltest Du mal ne neuere Version
installieren.

von Yagan Ζ. D. (yagan)


Lesenswert?

daniel,

am einfachsten geht das mit der Funktion sprintf(), z.B. so:

char sAnzeige[10];

long lMesswert = x*5000L/1023L; // 0...1023 normieren auf 0-5000 =
5,000 V.

sprintf(sAnzeige, "%ld,%03ld V", lMesswert/1000L,abs(lMesswert%1000L)
);
// erzeugt in sAnzeige die Anzeigewerte 0,000 V bis 5,000 V.
OutString(sAnzeige);

OutString gibt einen String auf das LCD. Möglicherweise heisst diese
Funktion bei Dir anders.

Ciao, Yagan

von Yagan Ζ. D. (yagan)


Lesenswert?

Ach so, Du wolltest nur 2 Kommastellen, dann so:

char sAnzeige[10];

long lMesswert = ((long)x*500L)/1023L; // 0...1023 normieren auf 0-500
= 5,00 V.

sprintf(sAnzeige, "%ld,%02ld V",
lMesswert/100L,abs(lMesswert%100L));
// erzeugt in sAnzeige die Anzeigewerte 0,00 V bis 5,00 V.
OutString(sAnzeige);

Du siehst, das lässt sich einfach auf beliebige Stellen anpassen.

Ciao, Yagan

von Gast ein Anderer (Gast)


Lesenswert?

Man könnte…

1. TFM lesen ;-)

2. z.B. hier ein Buch für wenig Geld kaufen das man dann allerdings
auch lesen müsste ;-(
http://www.buecherbillig.de/category/Programmierung_C+plus+plus.html

3. Die Grundlagen, Variabeltypen, Typenumwandlung etc. auch kostenlos
im net anschauen  z.B. Hier:
http://www.goblack.de/desy/sc12chip/sprachen/index.html Was man dann
allerdings auch lesen müsste ;-(

Mal im ernst: die Grundlagen solltest du schon mal durchlesen, dann
fallen dir vielleicht auch schnell verschiedene Lösungsmöglichkeiten
ein und das ist ja das was am meisten Spaß daran macht.
Nur ein Tipp: auch wenn es Variablen  gibt die Kommazahlen darstellen
ist  Yagans Vorschlag Long (Bzw. unsigned Long) zu verwenden eleganter
(Fließkomma Funktionen brauchen sehr viel Resourcen ). In so einem Long
kannst du dann ja auch gleich mehrere Messwerte aufaddieren
(anschließend natürlich entsprechen weniger teilen) damit hast du dann
schon eine simple Art von Mittelwertbildung (die Nachkomma Anzeige wird
ruhiger)
Gruß

von Daniel S. (stoegi)


Lesenswert?

Hey Yagan,
erst mal danke fürs Prog.
Aber, es zeigt mir nicht das korrekte Ergebnis an, und vorallem auf 8
kommastellen statt 2. hm komisch

danke

von Yagan Ζ. D. (yagan)


Lesenswert?

Müsste eigentlich gehen, daniel.
Vielleicht ist die Übertragung auf das LCD nicht korrekt.
Hast Du mal im Debugger nachgeschaut, was im String 'sAnzeige'
steht?

Ciao, Yagan

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.