Hallo. Ich wollte gerne interrupt-gesteuert eine LED an PortA zum leuchten bringen, genauer gesagt mit Hilfe des Analog Komarators. Ich benutze den MEGA32 und ich programmier in C, bzw. ich will mal gern in C programmieren können ... Der Code Wizzard in Codevision spuckt mir schon mal folgende Zeilen hierfür aus: #include <mega32.h> // Analog Comparator interrupt service routine interrupt [ANA_COMP] void ana_comp_isr(void) { // Place your code here } void main(void){ PORTA=0x00; DDRA =0xFF; . . . // Analog Comparator initialization // Analog Comparator: On // Interrupt on Falling Output Edge // Analog Comparator Input Capture by Timer/Counter 1: Off // Analog Comparator Output: On ACSR=0x0A; SFIOR=0x00; #asm("sei") while (1) { //Place your code here }; } Ich lege also eine feste Spannung an AIN0 an, und wenn die sich veränderende Spannung an AIN1 kleiner ist als das Potential an AIN0, dann ist der "Analog Comparator Output" gesetzt und der Interrupt setzt ein. Was muss ich nun bei den beiden "Place your code here" Feldern bei der Interrupt Funktion und bei der main Schleife eingeben, damit die LED leuchtet, wenn der Interrupt ausgelöst wird ? Danke schon im Vorraus für die Bemühungen. Helge
bei main muss nicht zwangsläufig was rein, das ist das Hauptprogramm in einer Endlosschleife, in deinem Fall tut es eben nichts ausser endlos im Kreis zu laufen :-) In die Interruptroutine schreibst du das, was der Interrupt tun soll. In deinem Fall wäre das sowas wie: PORTA.0=1; //LED an Das ist nicht ganz C-conform, geht, soweit ich weiss, nur bei CV, ist aber sehr angenehm. Besser lesbar: #define LED1_out PORTA.0 . . . LED1_out=1; Das Programm macht dann aber nichts weiter, als beim 1. Komperator-Interupt die LED einzuschalten, und nichts anderes, wahrscheinlich nicht sehr sinnvoll für einen Mega32 :-)
Hallo. Danke erstmal für die schnelle Antwort. Natürlich will ich auf höheres hinaus, das soll erstmal der Anfang sein. Ziel ist es ein Signal von ein entsprechend geleveltes Signal von einem NTC aufzunehmen (also eigentlich von 16 NTC's, aber halt gemultiplext) und dann auf 16 LED's auszugeben. Es soll also eine Endlosschleife 16 mal durchlaufen werden und wenn der Wert an den Komparator einen Schwellenwert erreicht, soll die entsprechende LED leuchten. In der Schleife müsste also eine Variable bis 16 hochgezählt werden um den externen MUX anzusteuern. Schaltet der MUX den ersten von den 16 NTC's durch soll bei einen Interrupt dann die erste LED entsprechend leuchten und so weiter. Das soll dann bei später erhöhter Anzahl non NTC's so eine Art niedrig pixelige Wärmebildkamera werden. Ich kenne mich nur noch nicht so gut aus um diese Schleife zu programmieren, aber müsste ja eigentlich nicht so schwer sein, bin halt noch blutiger Anfänger. Die Schleife müsste ich dann in das "Place your Code here"-Feld bei der Interruptfunktion schreiben, oder ?
Bitte besorge Dir erst mal ein C-Buch und lies Dir das AVR-GCC-Tutorial auf dieser Seite durch. Letzteres bezieht sich zwar nicht auf CodeVision, aber die µC-Programmierung in C ist dort recht ausführlich beschrieben. CodeVision hat zwar einige Erweiterungen ggü. ANSI-C, die der GCC-C-Compiler nicht bietet (z.B. Bitvariablen und Bitaddressierung) und ist in der Syntax z.B. bei der Deklaration von Interrupt-Handlern anders, aber der Code lässt sich i.A. mit einigen kleinen Änderungen relativ leicht portieren. Und es ist einfacher, GCC-C-Code nach CodeVision zu portieren als umgekehrt, da CodeVision auch die ANSI-konformen Bitmanipulationen versteht, GCC-C aber nicht die vereinfachten Schreibweisen von CodeVision. Zu Deiner eigentlichen Frage: Interrupt Handler sollten grundsätzlich nur so viel Code enthalten, wie unbedingt nötig. Dort sollten wirklich nur die zeitkritischsten Aktionen ausgeführt werden und vor allem keine Schleifen (BTW: Eine Schleife, die 16 mal durchlaufen wird, würde ich nicht als Endlosschleife bezeichnen, es sei denn, Du hast sehr pessimistische Vorstellungen von der Ewigkeit...;-), da während der Ausführung des Interrupt Handlers das komplette System blockiert ist. Und das Programm soll ja vielleicht noch erweitert werden... Die übliche Vorgehensweise ist, im Interrupt Handler ein Flag (also eine Variable oder ein Bit in einer Variablen) zu setzen und dieses im Hauptprogramm abzufragen. Auf die Weise gibts i.d.R. keine Aufhänger oder Verluste. Das Setzen des Flags käme dann an die Stelle im Interrupt Handler, wo steht 'Place your code here'. Aber wie gesagt, erst die Grundlagen und Schritt für Schritt heranarbeiten. Gruß Johnny
Hallo. Danke für die ausführliche Antwort. Das mit den C-Lehrbuch wäre sicherlich sinnvoll für mich. Kannst du mir vielleicht eins empfehlen ? Ich werd aus den Lehrbüchern, die ich bis jetzt so durchforstet habe nich schlau. Das Tutorial ist ja super ausführlich, aber ich hatte da halt immer Probleme mit der Anwendung der Codes in Codevision, weil ja die öfter mal etwas anders sind, und ich nicht weiß warum das dann nicht geht. Zu der Schleife: Die soll halt intern bis 16 zählen, und dann wieder von Vorne beginnen. Die Fachsprache ist mir noch ziemlich fremd. Ich weiß auch gar nicht, wie nan das am einfachsten macht. Da kommt also ein Interrupt; dieser darf aber nicht irgendeine xy LED zu leuchten bringen, sondern nur die, die dem xy NTC-Sensor entspricht, der wiederrum vom externen Multiplexer angesteuert wird. Ich bräuchte also noch so eine Art Bedingung die da heißt: Falls ein Interrupt vorliegt UND der entsprechende NTC-Sensor gerade vom Multiplexer angesteuert wird, dann darf die LED leuchten. Mein Ziel ist es erstmal 16 LED's, denen 16 NTC-Sensoren gegenüberliegen, zum leuchten zu bringen, wenn der entsprechende Sensor warm wird. Ich bräuchte also dann eine Schleife in main, die die ganze Zeit nacheinander die Aufmerksamkeit auf die jeweilige LED lenkt, und dann, falls ein Interrupt eintritt UND der entsprechende Sensor gerade angesteuert wird, die LED zum leuchten bringt. Denke ich da richtig ? Aber wie setzte ich das Softwaremässig um ? Da hab ich halt noch keine Ahnung. Vielleicht weiß jemand schon mal was von einen ähnlichen Projekt ? mfG Helge
Hmm, so wie Du das jetzt beschreibst, wäre das meiner Meinung nach eher ein Fall für den A/D-Wandler im AVR. Das geht soweit ich weiß allerdings nicht mit 16 Kanälen. Die Bausteine, die ich kenne, haben 8-Kanal-ADCs drin, oder gibts da schon neuere Typen mit mehr Kanälen? Wenn Du den ADC benutztest, könntest Du Dir die Sache mit den Interrupts sparen. Einfach die NTCs, als Spannungsteiler geschaltet, an den ADC hängen. Im Hauptprogramm reihum den ADC abfragen und bei Erreichen oder Überschreiten des Schwellenwerts die LED anmachen... Greetz kmt
Wenn es nur um eine Schwellwert-Erkennung geht (Ja-Nein-Entscheidung), wovon ich bei einer (binären) Darstellung durch einzelne LEDs mal ausgehe, braucht man den ADC eigentlich nicht. Aber wenn mans mit dem Komparator macht, würde ich es auch nicht mit dem Interrupt lösen, sonder den Komparator-Ausgang in der Zählschleife direkt abfragen. #include <io.h> #include <delay.h> //...bla... #define ACO ACSR.5 //...blabla... void main(void) { unsigned char ntc_mux; //Zählvariable f. ext. Mux //Initialisierung //...blablabla... while(1) { for(ntc_mux = 0; ntc_mux < 16; ntc_mux++) { PORTB &= 0xf0; //Mux Kanal setzen PORTB |= ntc_mux & 0x0f; delay_us(100); //kurz warten if(ntc_mux < 8) { if(ACO) //Wenn Komparator-Ausgang 1 PORTD &= ~(1 << ntc_mux); //LED ein else //Komparator-Ausgang 0 PORTD |= 1 << ntc_mux; //LED aus } else { if(ACO) //Kommentar siehe oben PORTC &= ~(1 << (ntc_mux - 8)); else PORTC |= 1 << (ntc_mux - 8); } } } } Dabei ist der Mux an die 4 LSB von PortB angeschlossen. Die LEDs sind an PortD (für Kanal 0 bis 7) und PortC (Kanal 8 bis 15) angeschlossen, und zwar High-Side (mit Vorwiderstand gegen VCC; wenn Du die LEDs andersrum anschließen willst, dann die Operationen zum Setzen und Löschen vertauschen). Das Codeschnipselchen nur als Denkanstoß. Gibt sicherlich viele andere Lösungsmöglichkeiten für das Problem. Viel Spaß noch beim basteln. Gruß Johnny
Hallo. Vielen Dank für den Code. Ich probier das so schnell es geht mal aus. Gruß Helge
Hallo. Wie verhält es ich eigentlich im Programmbeispiel mit der for-Schleife; die Variable ntc_mux zählt bis 16 und dann ? Wie funktioniert das, dass die Variable wieder auf Null zurückgesetzt wird und wieder von Vorne die Schleife wieder und wieder durchläuft ? Gruß Helge
Die Initialisierung 'ntc_mux = 0' steht doch in der Schleifenanweisung... Und da die for-Schleife in einer Endlosschleife immer wieder aufgerufen wird, wird ntc_mux auch bei jedem Durchlauf neu initialisiert
Hallo. Kann es sein, dass der Codevision Compiler die Operatorenschreibweise mit |= und &= (Bitoperatoren, oder ?) nicht verarbeiten kann ? Irgendwie funktioniert das Programm nämlich überhaupt nicht. Ich wollte mit folgenden Codeabschnitt nur mal auf PORTB ein Rechtecksignal anliegen lassen, aber auf meinem Oszi erscheint nur Gleichspannung. Oder kann es irgendwie sein, dass mein uralt-Oszi das gar nicht mehr darstellen kann ? #include <mega32.h> #include <delay.h> #define ACO ACSR.5 unsigned char ntc_mux; //Zählvariable f. ext. Mux void main(void) { while(1) { for (ntc_mux=0; ntc_mux<16; ntc_mux++) { PORTB &=0xF0; PORTB |= ntc_mux & 0xF0; delay_us(100); } } }
O.K. Hat sich erledigt, ist wohl eher ein Problem meiner Verpeiltheit.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.