PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Analogport auslesen, und Wert ausgeben (seriell)



moonwalker99
09.02.2006, 22:20
Hallo allerseits,

habe gerade ein einfaches Programm entworfen, das das Analogsignal (wird über poti auf Pin C 0 [Atmega8 ADC0] 0-5V) eingelesen. Es soll nach beendigung der ADC-Conversion also nach auslösen des Interrupts, über die Serielle Schnittstelle ausgegeben werden. Leider kommt nur Gullasch am Hyperterminal an. Denke ich habe irgendeinen Denkfehler drin, da das Gullasch sich beim Drehen des Potis verändert.

Achtung: Das ich ADLAR gesetzt habe war nur ein Versuch, dachte mal schauen was passiert wenn er die bits auf die andere seite schiebt, das resultat war: Andere ASCII Zeichen am Hyperterminal die sich beim Drehen des Potis verändern.

Hier der Code meines Programms:



.include "m8def.inc"

// aus dem UARTprogramm
.def temp = r16
.equ CLOCK = 3686400
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1


// aus dem ADC-prog
.def ad_value = r17
.org 0x000

rjmp init ;1 POWER ON RESET
reti ;2 Int0-Interrupt
reti ;3 Int1-Interrupt
reti ;4 TC2 Compare Match
reti ;5 TC2 Overflow
reti ;6 TC1 Capture
reti ;7 TC1 Compare Match A
reti ;8 TC1 Compare Match B
reti ;9 TC1 Overflow
reti ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
rjmp ad_vector;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comparator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Store Program Memory Ready

init:
; Stackpointer initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp

; Baudrate einstellen
ldi temp, LOW(UBRRVAL)
out UBRRL, temp
ldi temp, HIGH(UBRRVAL)
out UBRRH, temp

; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp

sbi UCSRB,TXEN ;TX aktivieren


;ADC initailisieren

cbi ADMUX, MUX0
cbi ADMUX, MUX1
cbi ADMUX, MUX2
cbi ADMUX, MUX3
sbi ADMUX, ADLAR
cbi ADMUX, REFS0
cbi ADMUX, REFS1

;ADC interrupt anschalten

sbi ADCSR, ADIE

;Prescaler auf 16 setzen

cbi ADCSR,ADPS0
cbi ADCSR,ADPS1
cbi ADCSR,ADPS2

;AD Converter anschalten

sbi ADCSR,ADEN

;global interrupts aktivieren

sei

;erste Wandlung auslösen

sbi ADCSR, ADSC

;Hauptprogramm

main:
nop
nop
nop


rjmp main


ad_vector:

in temp,adch
sbi adcsr,adsc
sei
rjmp serout
ret



serout:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp serout
out UDR, temp
ret ; zurück zum Hauptprogramm

izaseba
09.02.2006, 22:31
O weh,
mal abgesehen, von der Art, wie Du Deine ADC_ready routine betrittst und verläßt und der Art, wie Du den ADC Wert ausließt fällt mir auf, daß Du den adch Wert direkt an den UART schickst( na ja über den temp)
Das geht aber nicht so, wenn Du die Werte im Terminal ablesen willst.
Du mußt den Wert ja noch irgendwie nach ASCII umrechnen, irgendwo habe ich schon Beispiele dafür hier gepostet, mal sehen, ob ich die noch finde.

Gruß Sebastian

Edit:

schau mal hier (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=15220&start=0) mein Post von 7 Uhr 17 alles was unter berechne: steht, wandelt Dir eine 16 Bit Zahl in ASCII Kodierte Zahlen um.

moonwalker99
10.02.2006, 05:39
Danke für die Tips, hab mir so was in der Art schon gedacht.
Wie meinst du das, mit der Routine und mit dem Übergeben, wie mach ich das besser? Bin noch total am Anfang und kann gute Tips immer brauchen.

izaseba
10.02.2006, 16:24
Naja,

1. Man soll beim betreten der ISR den SREG sichern.
2. Beim verlassen wiederherstellen, weißt Du überhaupt wann sie verlassen wird?
3. ADC Auslesen ADCL und ADCH sollen beide ausgelesen werden, auch wenn Du den Wert der in ADCL steht eventuell nicht brauchst.
4. Der Sprung aus der ISR nach serout:, das kann man irgendwie eleganter machen...
überleg mal, Du schaltest die Interrupts wieder ein, dann springst Du nach serout:, die Rücksprungadresse von dem Interrupt liegt aber noch auf dem Stack, je nachdem wie lange serout: braucht tritt eventuell ein neuer Interrupt, obwohl, der alte noch nicht abgearbeitet ist, also wieder Rücksprungadresse auf den Stack, und so weiter, irgendwann knallt es, und die Bits laufen aus dem AVR auf die Platine raus.

Schau Dir mein Programm an, ich will nicht sagen, daß ich es perfekt geschrieben habe, aber so ist es mal schöner, also im Interrupt, ein Flag setzen, daß die Wandlung fertig ist, in der Hauptschleife, regelmäßig den Flag überprüfen, und wenn gesetzt, dann Ausgabe über den UART(davor noch was umrechnen) und zum Schluß den Flag wieder löschen.

Hier in Forum haben wir mal ein riesen Thread gemacht hmmm, such mal nach Assembler für anfänger, oder so, da sind paar brauchbare Sachen drin.

wenn noch was unklar ist, dann einfach fragen.

Gruß Sebastian

moonwalker99
10.02.2006, 16:51
Das mit dem Serout ist mir klar, das kann man leicht besser lösen.
Ich habe jetzt mal, aus purer Faulheit heraus, anstatt mit Hyperterm mit diesem Programm gearbeitet:

HTerm 0.6.1 beta, das zeigt Binär, ASCII, HEX und Dezimal an, ist echt geschickt und man spart sich die Umwandlung, so lange man sie nicht braucht.

1. Man soll beim betreten der ISR den SREG sichern.
2. Beim verlassen wiederherstellen, weißt Du überhaupt wann sie verlassen wird?
3. ADC Auslesen ADCL und ADCH sollen beide ausgelesen werden, auch wenn Du den Wert der in ADCL steht eventuell nicht brauchst.

Zu 1 und 2, das kannst du mir gerne mal näher erleutern, davon habe ich keine Ahnung.
Zu 3. Hab mir mal gerade das Datenblatt zur Hand genommen, daraus bin ich jetzt nicht wirklich schlau geworden. :-s

izaseba
10.02.2006, 19:14
HTerm 0.6.1 beta, das zeigt Binär, ASCII, HEX und Dezimal an

Ja das ist natürlich die einfachste Lösung.


Zu 1 und 2, das kannst du mir gerne mal näher erleutern, davon habe ich keine Ahnung.

Was möchtest Du erklärt haben? Warum sichern, oder wie sichern, oder die Bedeutung von SREG ?

schau Dir diese (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=11488&postdays=0&postorder=asc&highlight=tutorial+assembler+anf%E4nger&start=110)
Seite an... da haben wir so das eine oder andere zu SREG geschrieben.


When an ADC conversion is complete, the result is found in these two registers. If differential
channels are used, the result is presented in two’s complement form.
When ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently,
if the result is left adjusted and no more than 8-bit precision is required, it is
sufficient to read ADCH. Otherwise, ADCL must be read first, then ADCH.


Das meinte ich, wobei bei ADLAR ist es wieder mal egal...

Gruß Sebastian

moonwalker99
11.02.2006, 16:25
Also ich lese davor einfach ADCL aus, ob ich das brauche oder nicht, scheint ja egal zu sein. Sollte es aber machen, da er sonst keine neue Wandlung startet.

Ich hab mal ne kleine frage: Wie kann ich realisieren das eine LED an einem bestimmtem Punkt an geht. bzw bei 100. Es gibt zwar größer kleiner befehle aber die beziehen sich meines erachtens nur auf die verschiedenen Flags, oder sehe ich das falsch?!...

izaseba
11.02.2006, 17:16
Ja Flags des SREG Registers.

z.B.

2 Register z.B. R16 R17

cp R17,R16
brcs machwas
sonst:
...
...
machwas:

Es wird nach machwas gesprungen, wenn Carrybit gesetzt ist, sonst wird weiter unter sonst: gemacht, Carry ist dann gesetzt, wenn R16 größer als R17 ist.

Ich empfehle Dir Avr Studio, und kleine Spielchen mit cp cpi cpc sub add inc dec, dabei den SREG beobachten...

Gruß Sebastian

moonwalker99
14.02.2006, 08:53
Danke, das hat mir geholfen. Jetzt hab ich die Befehle verstanden. Wusste net das das Bit immer im SREG gesetzt wird, dann ist das ganze natürlich logisch.

Wie lese ich die ADC-Ports am besten aus, wenn ich mehrere benutzen will?! .....

izaseba
14.02.2006, 22:36
Schonmal was von ADMUX Register gehört ?

Gruß Sebaastian