Forum: Mikrocontroller und Digitale Elektronik PIC18F/ MPLAB X IDE und ADC Interrupt´s


von Daniel E. (everyday_fun69)


Lesenswert?

Grüße in die Runde,

gibt es hier Leute, die sich "sehr gut" mit dem PIC18F/ MPLAB X IDE und 
ADC Interrupt´s auskennen?

Pic's werden ja nicht gerade oft hier behandelt :-(

Danke schon mal.

von Jens P. (picler)


Lesenswert?

Es geht so. Also JA.

Das war aber bestimmt nicht deine Frage...

von Daniel E. (everyday_fun69)


Lesenswert?

Grüße, mal sehen ob ich mit meinem Problem / Verständnis weiter komme.

Ich habe den ADC als Interrupt im MCC aktiviert und im automatisch 
generierten File taucht neben Timer ISR auch der ADC ISR auf.

interrupt_manager.c

    else if(PIE1bits.ADIE == 1 && PIR1bits.ADIF == 1)
    {
        ADC_ISR();
    }

Nun habe ich meine eigene ADC ISR im main.c definiert (genauso wie für 
TMR0-3).

void My_ADC_ISR(void);                      //ADC ISR
ADC_SetInterruptHandler (My_ADC_ISR);       //Register the interrupt 
Handler

Im Programm habe ich eine Variable definiert, welche mir bei Erreichen 
des jeweiligen Channel die Variable anpasst, damit, wenn der ISR 
auslöst, ich weiß, welcher Channel den Wert bringt.

ADC_StartConversion(BatterySignal);                     //AN4
No_ADC = 4;


In der ADC ISR wird folgendes gemacht.

void My_ADC_ISR (void){                //ADC ISR

    if (No_ADC == 0)
        {
        ThrottleSignalValue = ADC_GetConversion(ThrottleSignal);
        }

    if (No_ADC == 1)
        {
        LDRSignalValue = ADC_GetConversion(LDRSignal);
        }

    if (No_ADC == 2)
        {
        CurrentSignalValue = ADC_GetConversion(CurrentSignal);
        }

    if (No_ADC == 4)
        {
        BatterySignalValue = ADC_GetConversion(BatterySignal);
        }
    //LED_Toggle();
    }

Leider wurde mit Einfügen des ADC Interrupt irgendwas bewirkt, dass 
jetzt sogar ein LCD Text vor der while (1) Schleife nicht mehr angezeigt 
wird.

Gern kann ich auch den gesamten Code posten, falls gewünscht.

Wo liegt mein Fehler?

Danke.

von deutschleera (Gast)


Lesenswert?

Daniel E. schrieb:
> ADC Interrupt´s

Daniel E. schrieb:
> Pic's werden ja nicht gerade oft hier behandelt

Dafür werden Deppenapostrophen hier gerne "behandelt".
Bitte keine solchen.

http://www.deppenapostroph.info

von Max M. (Gast)


Lesenswert?

Daniel E. schrieb:
> ThrottleSignalValue = ADC_GetConversion(ThrottleSignal);

Heißt das nicht 'ADC_GetConversionResult();'?

Ich vermute Du hängst in einer ADC IRQ Endlosschleife, weil Du den ADC 
Wert nie abholst und der IRQ deshalb weiter ansteht.
Deshalb immer den ADC lesen und dann entscheiden was damit zu tun ist.
In Deiner Konstruktion landest Du im endlos IRQ sobald kein Vergleich 
triggert.

Um sowas zu checken setze ich einen 'idle' Debug Pin in der Main, das in 
jeder IRQ Routine rückgesetzt wird.
So sehe ich auf dem Oszi wie viel freie zeit die MCU noch hat und wenn 
der dauernd Low wird, komme ich aus einem IRQ nicht mehr raus.

Warum eigentlich das?
> ADC_StartConversion(BatterySignal);                     //AN4
> No_ADC = 4;
Du definierst eine extra Variable um herauszufinden auf welchem Channel 
der ADC steht?
Das steht doch im channel selection register.

Bist Du Dir mit der Syntax sicher?
In meiner Erinnerung wird der channel gesetzt, dann der ADC gestartet, 
dann auf ADC fertig gewartet und dann wird gelesen.
Das ADC start UND channel selection in einem Aufruf geschieht, daran 
kann ich mich nicht erinnern.

von Daniel E. (everyday_fun69)


Angehängte Dateien:

Lesenswert?

Grüße in die Runde und Danke.

Ich habe mich hier orientiert:
https://microchipdeveloper.com/projects:mcu1101-project-3

anderseits wird in dem Video hier dein Begriff 
"ADC_GetConversionResult();"
https://www.youtube.com/watch?v=4WaB_Lj8FnY
verwendet.

Ich hab mal das mcc file vom ADC angehangen. Lassen wir mal den Begriff 
erstmal außen vor....

Woher weiß ich, wenn ich aus der Main raus springe in die ADC ISR, 
welcher channel grad dran ist und wie bekomme ich deiner/eurer Meinung 
nach den richtigen Wert in die entsprechende Variable ?

Irgendwie steh ich da auf dem Schlauch....

Danke.

von Max M. (Gast)


Lesenswert?

Daniel E. schrieb:
> Irgendwie steh ich da auf dem Schlauch....

Lös Dich mal von den ADC LIB Funktionsaufrufen und schau Dir die ADC 
Register an.
Du schreibst da rein auf welchem Channel der messen soll und das steht 
da auch noch drin bis du was anderes reinschreibst.
Und was da drinsteht kannst Du auch wieder lesen.

Diese Lib Funktionen machen mit viel gechecke und rumgedödel ganz simple 
Sachen mit der Hardware.
Ich finde das meist leichter direkt mit den Registern zu arbeiten.

Das Problem an all dieses schicken GUI Hilfen ist für Dich gerade das Du 
so weit weg von der HW bist, das Du nur Checkboxen und Funktionsaufrufe 
siehst.
Dahinter sind aber ganz langweilige Bits in irgendwelchen Registern und 
dieses ganze Bling Bling hält Dich davon ab auch mal ins DB und Family 
reference Datasheet zu sehen, wo die HW ganz exakt beschrieben ist die 
Du gerade hardwarenah betüterst.

von Daniel E. (everyday_fun69)


Lesenswert?

Grüße und Danke.

Mit deinem ADC_GetConversionResult(); liegts Du richtig.

void ADC_StartConversion(adc_channel_t channel) mit der Funktion wird ja 
schon der Kanal und ADC eingeschaltet und die Wandlung gestartet.

Damit brauch ich nur noch das Ergebnis abzuholen.

adc_result_t ADC_GetConversionResult(void)
{
    // Conversion finished, return the result
    return ((adc_result_t)((ADRESH << 8) + ADRESL));
}

Mir ist noch nicht klar, unabhängig der noch anderen unklaren Punkte, 
warum

Ich vermute Du hängst in einer ADC IRQ Endlosschleife, weil Du den ADC
Wert nie abholst und der IRQ deshalb weiter ansteht.

Selbst wenn ich den Wert nicht abhole, setzt doch die ADC ISR das Flag 
zurück bis es vom nächsten Event wieder aktiviert wird oder ?

void ADC_ISR(void)
{
    // Clear the ADC interrupt flag
    PIR1bits.ADIF = 0;

  if(ADC_InterruptHandler)
    {
        ADC_InterruptHandler();
    }
}

void ADC_SetInterruptHandler(void (* InterruptHandler)(void)){
    ADC_InterruptHandler = InterruptHandler;
}

In der Main starte ich den ADC wie folgt

ADC_StartConversion(LDRSignal);                         //AN1

wäre dies der nun der richtiges ADC ISR Inhalt ?

if(channel == LDRSignal)
{
LDRSignalValue = ADC_GetConversionResult;
}

Falls ich falsch liege, gern auch bitte ein Codebeispiel, damit wird 
evtl.  das Problem eher gelöst ;-)

Danke.

von Tobias S. (herrgesangsverein)


Lesenswert?

Ich rate dir, den Microchip Code Configurator MCC zu installieren und 
zum Testen zu nutzen. Dort kannst Du die ADC Funktionalität aktivieren 
und der Configurator erzeugt dir Code. Zugegeben, er generiert einen 
A...-voll Overhead, aber ich habe noch nie erlebt, dass er nicht 
funktioniert.
Dort kannst Du Dir anschauen wie es gemacht wird. Dann kannst Du den 
Code optimieren, d. h. den ganzen überflüssigen Rotz rausschmeißen.

Ich benutze den ganz gerne gerade für die grundlegende Konfiguration 
(Oszillator, etc.) und wenn der PIC Reserven hat, fass ich den 
generierten Code auch nicht an.

Zusätzlich unbedingt das Datenblatt konsultieren und verstehen. Gerade 
die ADC haben ein bestimmtes Timing.

von Tobias S. (herrgesangsverein)


Lesenswert?

Hey Runtervoter,
kannst Du mal begründen, was an meinem Beitrag auszusetzen ist?

von Teo D. (teoderix)


Lesenswert?

Du hast den Thread nich gelesen!
Dein Beitrag ist vollkommen unnötig, überflüssig..... Hier einfach des 
Lesens nicht wert.

von Max M. (Gast)


Lesenswert?

Daniel E. schrieb:
> Selbst wenn ich den Wert nicht abhole, setzt doch die ADC ISR das Flag
> zurück bis es vom nächsten Event wieder aktiviert wird oder ?

Was sagt das DB dazu?
Hör auf zu vermuten. Fang an zu lesen!

Einige Flags werden gelöscht wenn man die Buffer-Register betütert, 
andere muss man selber löschen.
Tut man beides nicht ist man eben in einer Endlosschleife.

Nochmal:
Du bist bare metal unterwegs.
Keine Lib, kein geheimer Zauber macht hier was für Dich, wenn Du selber 
es nicht tust.
Und wenn man Hardwarenah programmieren will MUSS man die Hardware auch 
kennen.
Also fang doch mal an die kennenzulernen.

von Daniel (Gast)


Lesenswert?

Danke an ein Paar Posts für nichts!

Meine Anfangsfrage war, kennt sich jemand mit dem PIC aus und nicht, wo 
kann ich was nachlesen.

Trotzdem Danke!

von Max M. (Gast)


Lesenswert?

Daniel schrieb:
> Meine Anfangsfrage war, kennt sich jemand mit dem PIC aus und nicht, wo
> kann ich was nachlesen.

Mal ehrlich: Du bleibst besser beim Arduino und lässt Dir von den Libs 
den Hintern nachtragen.
Hardwarenah programmieren wollen aber vollkommen unwillig die 
Beschreibung der Hardware zu lesen passt so garnicht zusammen.

Was erwartest Du?
Das wir für Dich das DB zu diesem speziellen PIC lesen und Dich an die 
Hand nehmen?
Klar kenne ich PICs.
Meinst Du ich muss nicht ganz oft ins DB sehen?

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.