- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: RN-Control: Tasten abfragen per Interrupt

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    15.11.2010
    Ort
    Oberbayern
    Alter
    38
    Beiträge
    38

    RN-Control: Tasten abfragen per Interrupt

    Anzeige

    Praxistest und DIY Projekte
    Guten Morgen RN-Community,

    ich möchte gerne die Tasten meines RN-Control per Interrupt abfragen, um den Ablauf des Hauptprogramms nicht zu stören. Habe mich dazu dumm und dämlich gesucht, aber außer dieser wohlbekannten Seite nichts Verwertbares gefunden:

    http://halvar.at/elektronik/kleiner_...rs/interrupts/


    Vorraussetzung ist hierbei jedoch, dass die Taster direkt an INT0 oder INT1 angeschlossen sind. Das ist aber beim RN-Control nicht der Fall, dort liegen sie doch über einen Spannungsteiler an PINA.7 (ADC7). Wie ich die Tasten abfrage, ist mir bekannt.

    Wie kombiniere ich jetzt den Tasteraufbau des RN-Control mit den Interrupt-Pins? Muss ich nicht das Signal der Taster irgendwie auf einen INT-Pin umbiegen? Warum finde ich dazu nichts im RN, über diese Aufgabenstellung müssten doch schon viele in Verbindung mit dem RN-Control gestolpert sein.

    Hier mein bestehender Code:

    Code:
    $regfile = "m32def.dat"
    $framesize = 32
    $swstack = 32
    $hwstack = 32
    $crystal = 16000000
    $baud = 9600
    
    
    Declare Function GetButton() As Byte
    
    Config Adc = Single , Prescaler = Auto
    Config Pina.7 = Input
    Porta.7 = 1
    
    Dim bButton As Byte
    
    
    Do
       'Irgendein weiterer Programmablauf.
    
    
       bButton = GetButton()
    Loop
    
    Function GetButton() As Byte
        Local Ws As Word
    
        GetButton = 0
    
        Start Adc
        Ws = Getadc(7)
        Print Ws
    
        If Ws < 1023 Then
          Select Case Ws
             Case 390 To 400
                GetButton = 1
             Case 320 To 330
                GetButton = 2
             Case 250 To 260
                GetButton = 3
             Case 175 To 185
                GetButton = 4
             Case 95 To 105
                GetButton = 5
          End Select
        End If
    
        Print GetButton
    
        Waitms 10
    End Function

    Danke für's Lesen.

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Du könntest deine Funktion GetButton() in einem Timer IRQ z.B. alle 50 ms aufrufen aber nur
    Code:
    Function GetButton() As Byte
        Local Ws As Word
    
        GetButton = 0
    
        Start Adc
        Ws = Getadc(7)
        Print Ws
    und
    Code:
    If Ws < 1023 Then
          Select Case Ws
             Case 390 To 400
                GetButton = 1
             Case 320 To 330
                GetButton = 2
             Case 250 To 260
                GetButton = 3
             Case 175 To 185
                GetButton = 4
             Case 95 To 105
                GetButton = 5
          End Select
        End If
    in der Hauptschleife auswerten. Noch besser den ADC beim Programmstart initialisieren/freigeben und im IRQ nur Ws = Getadc(7) aufrufen.Dann ws aber als Global deklarieren!

    Gruß Richard

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Hallo,
    der ADC kann über INT0 automatisch getriggert werden.

    Ich würd also folgendes versuchen: PA7 mit PD2 (INT0) mit einem Draht verbinden. Vorsicht beide Pins als INPUT konfigurieren, damit kein hoher Stom über die Portpins fließen kann.

    INT0 auf falling und rising edge konfigurieren.

    Interrupt Enable für ADC - damit bei Ende der Messung ein ADC Interrupt ausgelöst wird.

    ON ADC ISR_hole_ergebnis_ab

    in der ISR_hole_ergebnis_ab die ADCL und ADCH Register "manuell" (nicht mit GETADC) auslesen.

    Ob wegen des Spannungsteilers immer sicher bei allen Tasten ein INT0 ausgelöst wird müßte man ausprobieren.


    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Zitat Zitat von Searcher Beitrag anzeigen
    Hallo,
    der ADC kann über INT0 automatisch getriggert werden.
    Das ist natürlich die sauberste Lösung, wenn das mit dem IRQ klappt.

    Gruß Richard

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    15.11.2010
    Ort
    Oberbayern
    Alter
    38
    Beiträge
    38
    Zitat Zitat von Richard Beitrag anzeigen
    Du könntest deine Funktion GetButton() in einem Timer IRQ z.B. alle 50 ms aufrufen aber nur
    Code:
    Function GetButton() As Byte
        Local Ws As Word
    
        GetButton = 0
    
        Start Adc
        Ws = Getadc(7)
        Print Ws
    und
    Code:
    If Ws < 1023 Then
          Select Case Ws
             Case 390 To 400
                GetButton = 1
             Case 320 To 330
                GetButton = 2
             Case 250 To 260
                GetButton = 3
             Case 175 To 185
                GetButton = 4
             Case 95 To 105
                GetButton = 5
          End Select
        End If
    in der Hauptschleife auswerten. Noch besser den ADC beim Programmstart initialisieren/freigeben und im IRQ nur Ws = Getadc(7) aufrufen.Dann ws aber als Global deklarieren!

    Gruß Richard
    Hmm, interessant. Klingt zunächst wie die einfachere Möglichkeit. Allerdings wartet meine Hauptschleife auf eine Eingabe von der Konsole (UART). Somit würde die Auswertung von Ws dann unter Umständen aufgrund einer wartenden Input-Funktion nicht ausgeführt werden. Wäre die Auswertung in der ISR zu lang?

    Zur Info: Ich warte in der Hauptschleife auf Textinput aus der Konsole, um diesen Text dann mittels I2C-Bus über einen Portexpander PCF8574 an ein LCD-Display zu senden.



    Zitat Zitat von Searcher Beitrag anzeigen
    Hallo,
    der ADC kann über INT0 automatisch getriggert werden.

    Ich würd also folgendes versuchen: PA7 mit PD2 (INT0) mit einem Draht verbinden. Vorsicht beide Pins als INPUT konfigurieren, damit kein hoher Stom über die Portpins fließen kann.

    INT0 auf falling und rising edge konfigurieren.

    Interrupt Enable für ADC - damit bei Ende der Messung ein ADC Interrupt ausgelöst wird.

    ON ADC ISR_hole_ergebnis_ab

    in der ISR_hole_ergebnis_ab die ADCL und ADCH Register "manuell" (nicht mit GETADC) auslesen.

    Ob wegen des Spannungsteilers immer sicher bei allen Tasten ein INT0 ausgelöst wird müßte man ausprobieren.


    Gruß
    Searcher

    Ui, das klingt kompliziert. Was meinst Du mit "ADCL und ADCH Register manuell (nicht mit GETADC) auslesen"? Warum nicht mit GetAdc auslesen und wie funktioniert dieses manuelle Auslesen? Wäre für ein Beispiel dankbar.



    Danke Euch vielmals.
    Geändert von dariegel (25.06.2011 um 16:59 Uhr)

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Input ist nicht gerade brauchbar, aus dem von Dir genannten Grund. Inkay wartet nicht, holt aber nur einzelne Zeichen. Da muss man halt ein Textende Zeichen z.B, # mit senden. Man kann auch per IRQ Text empfangen, da musst Du aber die Bascom Hilfe bemühen (habe ich noch nicht probiert). ADCL ADCH sind Register in denen nach einer Wandlung der ADC Wert als Lo Byte und H Byte abgelegt ist. Es gibt einen Bascom Befehl der daraus wieder ein "Word" macht, steht auch irgendwo in der Hilfe.

    Gruß Richard

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Hi,
    weil mir mein eigener Vorschlag nicht ganz geheuer war, habe ich das mal mit ATtiny45 und nachgebauter Eingangsschaltung des RN-Control auf Steckbrett ausprobiert. Funktioniert! Allerdings gibt es Probleme bei mir mit Prellen der Tasten und hab da kein wirksames Gegenmittel. Könntest mal ausprobieren und beurteilen, ob das akzeptabel ist - Es werden manchmal die Tastenwerte nicht korrekt bzw. schwankend gemessen, so daß es selten zu Fehlerkennungen kommen kann.

    Der Code ist ein Auszug mit den wichtigen Teilen. Hab versucht die Mega32 Unterschiede laut Datenblatt zu kommentieren.

    Nicht vergessen die Brücke zwischen PA7 (ADC7) und PD2 (INT0) auf Mega32

    OHNE GEWÄHR

    Code:
    FÜR ATTINY45 !!!
    
    $hwstack = 48                           'hwstack reichlich wg Interruptroutine
    
    Dim Adc_low As Byte         
    Dim Adc_high As Byte
    Dim Adc_result As Word At Adc_low Overlay
    
    
    Config Adc = Free , Prescaler = Auto
    Adcsrb = Adcsrb Or &B00000010           'ADC von free running nach INT0 trigger wechseln
                                                     'SFIOR = SFIOR or &B01000000 auf Mega32
    
    Admux = Admux Or &B00000011            'channel ADC3 (PB3) selected
                                                     'Admux = Admux Or &B00000111 - channel 7 auf Mega32
    
    
    On Adc ISR_ADC_Result_Evaluation        'Wenn Messung fertig -> Interrupt zur Auswertung 
    
    Config Int0 = Falling            'INT0 auslösen bei fallender Flanke
    
    Config Portb.2 = Input            'PB2 (INT0) als INPUT (anpassen auf Mega32)
    Config Portb.3 = Input            'PB3 (ADC3) als INPUT (anpassen auf Mega32)
    Portb.2 = 1                          'Pullup an PB2(INT0) einschalten (anpassen auf Mega32)
    
    
    Enable Adc                              'enable adc interrupt
    Enable Interrupts
    
    
    
    DO
    'Hauptprogramm
    LOOP
    
    
    
    ISR_ADC_Result_Eavluation:
          Adc_low = Adcl
          Adc_high = Adch
    
          Adc_result             'Durch Overlay steht 10bit Meßwert in ADC_result zur Verfügung
    
          Waitms 100            'Entprellung??? Etwas besser aber nicht das Gelbe vom Ei. Geht auch ohne wait
          Gifr.intf0 = 1                    'clear INT0 flag da nicht durch INT0 ISR gelöscht wird
    Return

    PS
    Warum nicht mit GetAdc auslesen
    Hatte selbst mal versucht GETADC im Interrupt zu nutzen und bin damit nicht klargekommen. Bin der Sache aber nicht auf den Grund gegangen und mache das jetzt so wie im Code gezeigt über die ADCH, ADCL register.

    Gruß
    Searcher
    Geändert von Searcher (25.06.2011 um 18:50 Uhr)
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    15.11.2010
    Ort
    Oberbayern
    Alter
    38
    Beiträge
    38
    Ok, danke für Eure Mühe, habe mich nun mal an Searchers Methode gewagt, die Brücke auf dem RN-Control gesetzt und den Code angepasst. Da ich aber selbst noch lange nicht so tief in den Registerinterna des ATmega32 drin bin, einige Fragen:

    Code:
     
    Adcsrb = Adcsrb Or &B00000010
    SFIOR = SFIOR or &B01000000

    Code:
    Admux = Admux Or &B00000011
    Admux = Admux Or &B00000111

    Die zweite Zeile der beiden Codesegemente ersetzt jeweils die erste Zeile beim ATmega32, oder?
    In der Zeile mit Adcsrb meckert der Compiler über Invalid datatype. Muss ich da was beachten oder gilt die Zeile nur für Deinen ATtiny45 und fliegt somit raus?


    Bei Adc_result sagt der Compiler Unknown statement, hast Du da etwas vergessen?

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Hallo dariegel,
    um zu verstehen, wie das Programm funktioniert, solltest Du unbedingt das Datenblatt zu deinem µC lesen und verstehen.

    Ich habe dieses für den Mega32 benutzt: http://www.atmel.com/dyn/resources/p...ts/doc2503.pdf

    Dort gibt es das Register ADCSRB für Mega32 nicht - deshalb der Compiler Fehler. In meinem Code wird mit Adcsrb = Adcsrb Or &B00000010 für ATtiny45 der ADC auf Start der Messung durch INT0 eingestellt. Im ATmega32 wird das im SFIOR Register gemacht. Also die Zeile mit ADCSRB raus und die Zeile mit der SIFOR Zuweisung rein.

    Zeile ADMUX: Du mußt für Dein RN-Control Board den ADC-Kanal 7, an dem die Tasten angeschlossen sind, an den ADC "anschließen". Das macht Admux = Admux Or &B00000111 auf dem Mega32. Auf meinem ATtiny habe ich einen anderen Kanal genutzt und deshalb sieht das bei mir etwas anders aus.

    Noch etwas zum GETADC. Das ist laut Bascom Hilfe zum Ausführen einer Einzelmessung da. Einzelmessung wird in meinem Code nicht genutzt. Der ADC wird auf Start der Messung durch Setzen des INT0 Flags eingestellt. Damit ist GETADC durch den Aufbau des Programms gar nicht sinnvoll und der Meßkanal, der in GETADC übergeben werden muß, muß "manuell" eingestellt werden. Im Simulator kann man nachvollziehen, welche Register im µC durch die entsprechenden Befehle zB CONFIGADC wie gesetzt werden.

    Das Programm funktioniert also grob so, daß bei Drücken einer Taste das INT0 Flag gesetzt wird (Signal kommt über die Brücke zu dem entsprechenden µC Pin (PD2) ) Dadurch wird eine ADC Messung getriggert und bei Beendigung der Messung erzeugt der ADC einen Interrupt. In der zugehörigen ISR wird dann der Messwert aus den ADC Registern ausgelesen und steht zur weiteren Auswertung in den entsprechenden Variablen bereit. Weil keine INT0 Interrupt Routine ausgeführt wird, bleibt das INT0 Flag stehen und muß deshalb noch durch Schreiben einer 1 gelöscht werden damit es beim nächsten Tastendruck wieder gesetzt werden kann um die nächste Messung triggern zu können.

    Ich möchte nochmal drauf hinweisen, daß das Programm funktioniert aber nicht perfekt ist. Eben nur eine Idee. Liegt an Dir was Du daraus machst oder doch eine andere Lösung verwirklichst.

    Bei Adc_result sagt der Compiler Unknown statement, hast Du da etwas vergessen?
    Nein, nichts vergessen, sondern da gehört das rein, was auch immer Du mit dem Meßergebnis anfangen möchtest - vielleicht auch gar nichts in der ISR und wertest ADC_result zwische DO und LOOP aus.

    Ebenso ist der Header mit $HWSTACK nicht vollständig. Die hatte ich nur eingefügt um Dir zu zeigen, das der Wert mit 32 in Deinem Programm zu klein ist.

    PS in meinem Code ist Portb.2 und Portb.3 natürlich auch nur für mich zutreffend. Die mußt Du bei Dir auch entsprechend anpassen

    Gruß
    Searcher
    Geändert von Searcher (27.06.2011 um 08:37 Uhr)
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    15.11.2010
    Ort
    Oberbayern
    Alter
    38
    Beiträge
    38
    Ok, jetzt habe ich es verstanden. Werde sehen, ob ich's zum Laufen kriege.


    Danke.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Dreh-Encoder und Tasten gleichzeitig abfragen
    Von DerSchatten im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 13.05.2011, 20:16
  2. PWM Frage und Interrupt mit Tasten?
    Von Enterprise im Forum C - Programmierung (GCC u.a.)
    Antworten: 24
    Letzter Beitrag: 31.03.2008, 17:16
  3. Pin change Interrupt und Tasten entprellen
    Von Razer im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 16.05.2006, 10:35
  4. Tasten bei RN-control abfragen
    Von christian87 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 26.01.2005, 22:09
  5. Tasten am Rn-Control wie abfragen
    Von FHarry im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 1
    Letzter Beitrag: 30.12.2004, 09:17

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress