Verwendung des ADC eines ATMega8 mit C++

#3859162
Lesenswert?

Hallo,

ich arbeite gerade an einem kleinen Projekt mit dem ATMega8 und brauche 
dringend Hilfe mit der Programmierung in C++.
Ich habe bisher nur wenig Erfahrungen mit der µC-Welt an sich, aber auch 
mit der C++ Programmierung. Für das Programmieren benutze ich das 
Programm "SiSy" (myAVR), welches jede menge vorgefertigte Klassen 
bereitstellt. Diese vereinfachen das Programmieren ungemein, aber ich 
stoße damit gerade an Grenzen. (vor allem deshalb, weil die 
Beschreibungen in der Hilfe leider nur sehr dürftig ausfallen)
Für die Programmierung mit C findet man zwar ein haufen Beispiele, 
allerdings kann ich diese anscheinend nicht korrekt auf C++ 
übertragen...

Zum Problem:
Der µC soll von mittels dem ADC die Spannungswerte von zwei 
Potentiometern ermitteln (zwei Kanäle). (Danach sollen die gemessenen 
Werte entsprechend interpretiert und an irgendeinem Port ausgegeben 
werden.)
-> Kann mir jemand vielleicht ein einfaches Codebeispiel zum 
Konfigurieren der entsprechenden Register (ADCSRA, ADMUX) und Auswerten 
eines Messwertes für eine kontinuierliche Messung (Referenzsp. AVCC) 
zeigen? (MUSS dabei mit Interupts gearbeitet werden?)
-> Oder kennt sich jemand mit der Verwendung der Klasse 
"AdcMultiChannel" im Programm "SiSy" aus?

Vielen schonmal!
Chris
Gast #3859177
Lesenswert?

>an irgendeinem Port ausgegeben
werden.

Willst du die Byte´s Parallel ausgeben?? weil ein PORT PIN kann nur 0V 
oder 5V.

Ausser der Beispiele im Netz nimm noch Datenblatt zu rate, erhlich 
gesagt der Atmega8 ist mist, da weder DebugWire noch JTAG um das ding 
mit JTAGICE oder DRAGON anzuhalten bzw. debuggen ;-)))
Gast #3859179
Lesenswert?

Ich empfehle auch dir AVR Studio 6.2 ohne vorgefertigtem scheiß zu 
nehmen und damit sich ruhig an dein Problem rantasten, und besorg dir 
ein JTAGICE3 und Atmega168 oder 328 für diese Problemstellung.

;-)))
Gast #3859180
Lesenswert?

jetzt übertreibt mal nicht. Wie habe es nur die Leute geschafft ohne 
Debuggen die alten µC zu programmieren?

Für etwas ADC auslesen reicht das Datenblatt, spätestens nach den 3. 
Versucht läuft der Code. So mal man auch den Simulator hat.
Gast #3859480
Lesenswert?

hier mal die Variante im kleinen Programm
1
class Application : public Controller
2
{
3
    // Bausteine und Attribute .........................................
4
    protected: AdcMultiChannel analog;
5
    protected: Uart console;
6
    // Funktionen ......................................................
7
    public: void onStart()
8
    {
9
        // hier Initialisierungen durchführen
10
        
11
        console.config(9600);
12
        analog.config();           // Basiskonfiguration
13
        analog.addChannel(0);      // Chanel hinzufügen
14
        analog.addChannel(1);
15
        analog.configInt(enable);  // Abholen und zwischenspeichern der Werte starten
16
    }
17
    public: void onWork()
18
    {
19
        uint8_t wert1,wert2;
20
        wert1=analog.getValue8(0);
21
        wert2=analog.getValue8(1);
22
        console.sendByte(wert1);
23
        console.sendByte(wert2);
24
        waitMs(10);
25
        
26
    }
27
} app;
#3859554
Lesenswert?

Peter II schrieb:
> die kannst du 1:1 übernehmen. Du musst überhaupt nichts umwandeln.

Oh, danke für den Hinweis! Mir war so, als wenn Ausdrücke wie z.B.
1
ADCSRA = (1<<ADPS1) | (1<<ADPS0);
nicht funktionieren würden. Hab ich anscheinend aber noch nie 
ausprobiert.. ;-)

Wie ist diese Beispielzeile überhaupt zu verstehen? Ich interpretiere es 
so: "Es wird eine '1' an die entsprechende Stelle im ADCSRA-Register 
'geschoben'". Stimmt das? Was bezweckt das '|' (ODER) zwischen den 
Ausdrücken?
#3860060
Lesenswert?

Chris K. schrieb:
> Wie ist diese Beispielzeile überhaupt zu verstehen? Ich interpretiere es
> so: "Es wird eine '1' an die entsprechende Stelle im ADCSRA-Register
> 'geschoben'". Stimmt das? Was bezweckt das '|' (ODER) zwischen den
> Ausdrücken?

Die Frage meinst du ernst? Das sind eigentlich Grundlagen C.
OK, links neben dem Oder steht da "schiebe eine 1 um eine Stelle nach 
links" (ADPS1 hat den Wert 1, siehe auch avr/io.h), rechts vom Oder 
steht "schiebe eine 1 um null Stellen nach links" (ADPS0 hat den Wert 
0). Man könnten also auch schreiben:
1
ADCSRA = (1<<1) | (1<<0);

Dröseln wir die Schiebeoperationen auf steht da:
1
ADCSRA = 0b10 | 0b01;

Und jetzt noch das Oder auflösen:
1
ADCSRA = 0b11;

Also eigentlich ganz einfach.
Man schreibt halt nur
1
ADCSRA = (1<<ADPS1) | (1<<ADPS0);

damit man auch nach 8 Monaten noch weiß warum man ADCSRA den Wert 3 
zugewiesen hat falls man noch mal in den Quellcode rein schaut. ;)
#3861066
Lesenswert?

Schiebeoperationen sind mir nicht unbekannt, allerdings nur so:
1
test = test >> 3;
Du meinst also, dass die Werte von ADPS0, ADPS1,... einen 
voreingestellten Wert haben, der in der h-Datei "hinterlegt" ist?!
Ich arbeite bisher wie gesagt ohne die manuelle Einbindung von Dateien 
usw., verzeih mir also, dass ich mit den Ausdrücken nicht 
zurechtgekommen bin ;-)
Die Sache mit dem ODER hätte ich eigentlich selbst erkennen müssen...
#3861169
Lesenswert?

Chris K. schrieb:
> Schiebeoperationen sind mir nicht unbekannt, allerdings nur so:
>
1
test = test >> 3;

Wobei das, wenn es sich bei 'test' um etwas handelt, was logischweise 
eine Zahl darstellt, wie zb die Anzahl an Gummibärchen, besser als
1
  uint16_t AnzahlGummibärchen;
2

3
  AnzahlGummibärchen = AnzahlGummibärchen / 8;
4
// oder
5
  AnzahlGummibärchen /= 8;
geschrieben wird.
COmpiler sind nicht doof. Wenn eine derartige Division durch eine 
Schiebeoperation ersetzt werden kann, dann macht das der Compiler schon.

> Du meinst also, dass die Werte von ADPS0, ADPS1,... einen
> voreingestellten Wert haben, der in der h-Datei "hinterlegt" ist?!

Was soll das heißen "Du meinst"?
Das ist so! Genau das ist der Zweck von
1
#include <avr/io.h>
dass es für jeden im Datenblatt vorkommenden Registernamen, jeden im 
Datenblatt vorkommenden Bitnamen ein entsprechendes #define gibt, damit 
man sich eben nicht mit so Banalotäten wie Bitnummern rumschlagen muss.
Das einzige was nicht abgedeckt ist, ist das man einen Bitnamen auf ein 
falsches Register anwenden kann. Nichts und niemand hindert einen
1
  ADCSR |= ( 1 << TOIE0 );
zu schreiben, obwohl das Overflow Interrupt Enable Bit nicht im Register 
ADCSR beheimatet ist. D.h. durch die Verwendung von Register bzw. 
Bitnamen wird einem zwar das mitdenken nicht abgenommen, aber es ist 
zumindest insofern einfacher, dass man nicht erst mal in
1
  ADCSRA |= 0x56;
erst mal langatmig anhand der Bits aufdröseln muss, welche Bits da 
gesetzt werden und wie die heissen, damit man dann im Datenblatt die 
Beschreibung für diese Bits lesen kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren