Hallo Gerko,
wollte jetzt mal fragen ob du auch das RN-Mega8 hast? Ich habe mich vielleicht etwas unklar ausgedrückt, aber auf dem RN-Mega8 gibt es 5 Tasten die über ein Widerstandsnetzwerk an den ADC angeklemmt sind.
Also ich habe zwei Programme. Das erste Programm gibt den Wert der jeweiligen Taste auf dem UART aus. Es basiert auf dem ersten Programm:
Code:
.NOLIST ; List-Output unterdrücken
.INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp
;.include "C:\PROGRA~1\VMLAB\include\m8def.inc
.def temp = r16 ; allgemeines temp Register, zur krufristigen Verwendung
.def temp2 = r17 ; Register für 24 Bit Addition, Lowest Byte
.def temp3 = r18 ; Register für 24 Bit Addition, Middle Byte
.def temp4 = r19 ; Register für 24 Bit Addition, Highest Byte
.def adlow = r20 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh = r21 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def messungen = r22 ; Schleifenzähler für die Messungen
.def ztausend = r23 ; Zehntausenderstelle des ADC Wertes
.def tausend = r24 ; Tausenderstelle des ADC Wertes
.def hundert = r25 ; Hunderterstelle des ADC Wertes
.def zehner = r26 ; Zehnerstelle des ADC Wertes
.def zeichen = r27 ; Zeichen zur Ausgabe auf den UART
;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7273800 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate
; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate
.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher
;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000
rjmp Init ; Interruptvektoren überspringen
;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp
; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren
; ADC initialisieren: Single Conversion, Vorteiler 128
ldi temp, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
out ADMUX, temp
ldi temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp
; Pullup aktivieren
ldi temp,0x00
out DDRC,temp
ldi temp,0x01
out PORTC,temp
;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:
clr temp
clr temp2
clr temp3
clr temp4
ldi messungen, 0 ; 256 Schleifendurchläufe
; neuen ADC-Wert lesen (Schleife - 256 mal)
sample_adc:
sbi ADCSRA, ADSC ; den ADC starten
wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
rjmp wait_adc
; ADC mit 10 Bit einlesen:
in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte
; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden
add temp2, adlow ; addieren
adc temp3, adhigh ; addieren über Carry
adc temp4, temp ; addieren über Carry, temp enthält 0
dec messungen ; Schleifenzähler MINUS 1
brne sample_adc ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen
; Aus den 256 Werten den Mittelwert berechnen
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte
; (im Register temp2) fällt einfach weg
;
; allerdings wird der Wert noch gerundet
cpi temp2,128 ; "Kommastelle" kleiner als 128 ?
brlo no_round ; ist kleiner ==> Sprung
; Aufrunden
subi temp3, low(-1) ; addieren von 1
sbci temp4, high(-1) ; addieren des Carry
no_round:
; Ergebnis nach adlow und adhigh kopieren
; damit die temp Register frei werden
mov adlow, temp3
mov adhigh, temp4
;in ASCII umwandeln
ldi ztausend, -1 + '0' ; um binär-Wert in ASCII zu wandeln, auf den binär-Wert den
_a6ser: ; ASCII-Wert der Null addieren
inc ztausend
subi adlow, low(10000) ; -10,000
sbci adhigh, high(10000)
brcc _a6ser
ldi tausend, 10 + '0'
_a7ser:
dec tausend
subi adlow, low(-1000) ; +1000
sbci adhigh, high(-1000)
brcs _a7ser
ldi hundert, -1 + '0'
_a8ser:
inc hundert
subi adlow, low(100) ; -100
sbci adhigh, high(100)
brcc _a8ser
ldi zehner, 10 + '0'
_a9ser:
dec zehner
subi adlow, -10 ; +10
brcs _a9ser
subi adlow,-'0'
;an UART Senden
mov zeichen, ztausend ; Zehntausender Stelle
rcall transmit
mov zeichen, tausend ; Tausender Stelle ausgeben
rcall transmit
mov zeichen, hundert ; Hunderter Stelle ausgeben
rcall transmit
mov zeichen, zehner ; Zehner Stelle ausgeben
rcall transmit
mov zeichen, adlow ; Einer Stelle ausgeben
rcall transmit
ldi zeichen, 13 ; CR
rcall transmit
ldi zeichen, 10 ; LF
rcall transmit
rjmp Hauptschleife
;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------
transmit:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp transmit
out UDR, zeichen
ret
;------------------------------------------------------
; ENDE
;------------------------------------------------------
Ende:
rjmp Ende
Das zweite Programm gibt die jeweilige Nummer gedrückten Taste auf dem UART zurück. Das Programm ist natürlich nich nicht fertig, funktioniert aber schon.
Code:
; Programm zur Abfrage der Tsten auf dem RNMega8
; Schaltung überprüfen (am ADC mit Multimeter messen) hängt ADC in der Luft?
.NOLIST ; List-Output unterdrücken
; .INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp
.include "C:\PROGRA~1\VMLAB\include\m8def.inc"
.def temp = r16 ; allgemeines temp Register, zur krufristigen Verwendung
.def temp2 = r17 ; Register für 24 Bit Addition, Lowest Byte
.def temp3 = r18 ; Register für 24 Bit Addition, Middle Byte
.def temp4 = r19 ; Register für 24 Bit Addition, Highest Byte
.def adlow = r20 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def adhigh = r21 ; Ergebnis vom ADC / Mittelwert der 256 Messungen
.def messungen = r22 ; Schleifenzähler für die Messungen
.def ztausend = r23 ; Zehntausenderstelle des ADC Wertes
;.def Taste1 = r24 ; Tausenderstelle des ADC Wertes
;.def Taste2 = r25 ; Hunderterstelle des ADC Wertes
;.def Taste3 = r26 ; Zehnerstelle des ADC Wertes
.def zeichen = r27 ; Zeichen zur Ausgabe auf den UART
;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7273800 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate
; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate
.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher
;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000
rjmp Init ; Interruptvektoren überspringen
;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp
; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren
; ADC initialisieren: Single Conversion, Vorteiler 128
ldi temp, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
out ADMUX, temp
ldi temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp
;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:
clr temp
clr temp2
clr temp3
clr temp4
ldi messungen, 0 ; 256 Schleifendurchläufe
; neuen ADC-Wert lesen (Schleife - 256 mal)
sample_adc:
sbi ADCSRA, ADSC ; den ADC starten
wait_adc:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
rjmp wait_adc
; ADC mit 10 Bit einlesen:
in adlow, ADCL ; immer zuerst LOW Byte lesen
in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte
; alle 256 ADC-Werte addieren
; dazu wird mit den Registern temp4, temp3 und temp2 ein
; 24-Bit breites Akkumulationsregister gebildet, in dem
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden
add temp2, adlow ; addieren
adc temp3, adhigh ; addieren über Carry
adc temp4, temp ; addieren über Carry, temp enthält 0
dec messungen ; Schleifenzähler MINUS 1
brne sample_adc ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen
mov adlow, temp3
mov adhigh, temp4
Taste1:
subi adlow, low(70) ; -70
sbci adhigh, high(70)
brcc Taste2
ldi zeichen, '1' ; Taste1
rcall transmit
rjmp taste_gefunden
Taste2:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste3
ldi zeichen, '2' ; Taste2
rcall transmit
rjmp taste_gefunden
Taste3:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste4
ldi zeichen, '3' ; Taste3
rcall transmit
rjmp taste_gefunden
Taste4:
subi adlow, low(65) ; -65
sbci adhigh, high(65)
brcc Taste5
ldi zeichen, '4' ; Taste4
rcall transmit
rjmp taste_gefunden
Taste5:
ldi zeichen, '5' ; Taste5
rcall transmit
rjmp taste_gefunden
taste_gefunden:
rjmp Hauptschleife
;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------
transmit:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp transmit
out UDR, zeichen
ret
;------------------------------------------------------
; ENDE
;------------------------------------------------------
Ende:
rjmp Ende
Einfach mal anschauen...
Lesezeichen