Forum: Mikrocontroller und Digitale Elektronik AVR-Tutorial: ADC


von Neuling (Gast)


Lesenswert?

Habe hier ein Mega88 und wollte mal das AVR-Tutorial: ADC abarbeiten.

Aber bei mir läuft das nicht so ganz

bei
1
    sbi     ADCSRA, ADSC        ; den ADC starten
2
 
3
wait_adc:
4
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht
5
    rjmp    wait_adc

kommen die Fehler beim übersetzen

Test.asm(153): error: Operand 1 out of range: 0x7a

WARUM das jetzt???

von Alter Fux (Gast)


Lesenswert?

kommentierer Zeile 42 aus!

von Neuling (Gast)


Lesenswert?

Hääääää ??????????????????

Zeile 42 wie wo was ???????????????????????

von spess53 (Gast)


Lesenswert?

Hi

>WARUM das jetzt???

Die Adressen der ADC-Register liegen ausserhalb des Adressbereichs von 
'sbi', 'sbic'. Da hilft nur Lesen des IO-Registers in ein Register. 
'in/out' gehen auch nicht.
1
   sbi     ADCSRA, ADSC
2
3
ersetzen durch z.B. :
4
5
   lds r16,ADCSRA
6
   sbr r16,1<<ADSC
7
   sts ADCSRA, r16
8
9
    sbic    ADCSRA, ADSC 
10
    rjmp    wait_adc
11
->
12
    lds r16,ADCSRA
13
    sbrs r16,ADSC
14
    rjmp    wait_adc

MfG Spess

von Neuling (Gast)


Lesenswert?

Und wieso Zeile 42 raus?

von Alter Fux (Gast)


Lesenswert?

42 ist die Antwort auf alle Fragen :-)

von spess53 (Gast)


Lesenswert?

Hi

>Und wieso Zeile 42 raus?

Vergiss es. Die haben keine Ahnung.

MfG Spess

von Justus S. (jussa)


Lesenswert?

Neuling schrieb:
> Und wieso Zeile 42 raus?

das sollte ein dezenter Hinweis sein, dass so Mini-Ausschnitte aus 
Programmen selten für die Fehlersuche sinnvoll sind

von Neuling (Gast)


Lesenswert?

spess53 schrieb:
> Die Adressen der ADC-Register liegen ausserhalb des Adressbereichs von
>
> 'sbi', 'sbic'. Da hilft nur Lesen des IO-Registers in ein Register.
>
> 'in/out' gehen auch nicht.
>     rjmp    wait_adc
> MfG Spess

Ist das langsamer als auf dem Mega8? Sind ja mehr Befehle?

Alter Fux schrieb:
> 42 ist die Antwort auf alle Fragen :-)

Sorry sollte ich jetzt einwenig hart sein. A...... klasse einen Anfänger 
zu verarschen hast es ja voll drauf. Hoffe du als Experte bekommst mal 
auf eine Frage auch so eine Irreführung.

von gerd (Gast)


Lesenswert?

Neuling schrieb:
> Und wieso Zeile 42 raus?

Siehe Netiquette - Äußere Form!

- gerd

von spess53 (Gast)


Lesenswert?

Hi

>das sollte ein dezenter Hinweis sein, dass so Mini-Ausschnitte aus
>Programmen selten für die Fehlersuche sinnvoll sind

In dem Fall war doch alles da: ATMega88, ADC-Register ,IO-Befehle und 
Fehlermeldung 'Operand 1 out of range: 0x7a'.

Gleich los Schreien statt Denken ist halt einfacher.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

>Ist das langsamer als auf dem Mega8? Sind ja mehr Befehle?

Ja. Geht aber nicht anders. Aber da du sowieso auf die Wandlung wartest, 
ist das vollkommen egal.

MfG Spess

von Neuling (Gast)


Lesenswert?

gerd schrieb:
> Neuling schrieb:
>
>> Und wieso Zeile 42 raus?
>
>
>
> Siehe Netiquette - Äußere Form!
>
>
>
> - gerd

Wo habe ich mit meiner Frage die Netiquette nicht eingehalten das ich so 
verarscht werde?

Ich glaube da sollte hier jemand anderes mal die Netiquette einhalten.

Es gibt aber auch User die NORMAL und echt Hilfsbereit sind

Danke spess53

von Neuling (Gast)


Lesenswert?

spess53 schrieb:
> Ja. Geht aber nicht anders. Aber da du sowieso auf die Wandlung wartest,
>
> ist das vollkommen egal.
>
>
>
> MfG Spess

Also lieber einen Mega8 als ein Mega88 ???

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Nicht unbedingt. Du braucht nur zusätzlich zum Tutorial das kostenlose 
PDF und den Willen zum Nachlesen der Unterschiede.

AVR094: Replacing ATmega8 by ATmega88 (PDF)
http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf

von Alter Fux (Gast)


Lesenswert?

Neuling schrieb:
> Sorry sollte ich jetzt einwenig hart sein. A......

Um es kurz zu machen, Zitat:
"
Klare Beschreibung des Problems. Besonders für Anfänger gilt: Gerade am 
Anfang ist es immer gut zu sagen, was man erreichen will und nicht so 
sehr Annahmen darüber zu treffen, wie man es erreichen könnte und dann 
das Wie zu hinterfragen. Oft ist der Denkfehler nämlich schon im Ansatz 
und man kann besser helfen, wenn man das Ziel des Fragenden kennt.Im 
Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...) Welcher 
Compiler in welcher Version (Z.B WINAVR 17032007, BASCOM-AVR 1.4; nicht: 
"neueste Version"!) Das Problem in Zahlen fassen! Nicht einfach 
schreiben "so schnell wie möglich", "so stromsparend wie möglich" etc, 
sondern mal ein paar Zahlen nennen. X MHz, Y ms, Z µA etc. Wenn man 
keine exakte Vorstellung davon hat, sollte wenigstens eine Größenordnung 
angegeben werden (1..5 MHz, <1mA etc.) Welcher IC in welchem Gehäuse. 
Wenn Datenblätter vorhanden sind diese ggf. anhängen oder als Link 
angeben. Daran denken, dass die Leute im Forum nicht neben einem sitzen 
und alles so vor sich sehen wie der Fragesteller Klare Fragen 
formulieren und nicht davon ausgehen, dass eine diffuse 
Zustandsbeschreibung als Frage interpretiert wird.
"

denke mal drüber nach.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Kompletter Code ist i.d.R besser und hier im Forum gewünscht. Aber keine 
Regel ohne Ausnahme. Für mich war die prägnante Anfangsfrage auch 
vollständig. Wenn alle Neulinge 2011 ihr Problem so auf den Punkt 
bringen, sehen wir einem rosigen Jahr entgegen :-)

von spess53 (Gast)


Lesenswert?

Hi

>Also lieber einen Mega8 als ein Mega88 ???

Blödsinn. Das merkst du überhaupt nicht. sbi/cbi/sbis/sbic kannst du 
auch beim ATMega8 nicht auf alle IO-Register anwenden. Also, warum 
diesen Dinosaurier verwenden?

MfG Spess

von gerd (Gast)


Lesenswert?

Neuling schrieb:
> Wo habe ich mit meiner Frage die Netiquette nicht eingehalten das ich so
> verarscht werde?
>
> Ich glaube da sollte hier jemand anderes mal die Netiquette einhalten.

Möglich! Ich wollte lediglich deine Frage beantworten, warum jemand nur 
"42" gepostet hat (ob das nun angebracht war oder nicht).

- gerd

von Neuling (Gast)


Lesenswert?

Alter Fux schrieb:
> Um es kurz zu machen, Zitat:
>
> "
> Klare Beschreibung des Problems. Besonders für Anfänger gilt: Gerade am
> Anfang ist es immer gut zu sagen, was man erreichen will und nicht so
> sehr Annahmen darüber zu treffen, wie man es erreichen könnte und dann
> das Wie zu hinterfragen. Oft ist der Denkfehler nämlich schon im Ansatz
> und man kann besser helfen, wenn man das Ziel des Fragenden kennt.Im
> Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...) Welcher
> Compiler in welcher Version (Z.B WINAVR 17032007, BASCOM-AVR 1.4; nicht:
> "neueste Version"!) Das Problem in Zahlen fassen! Nicht einfach
> schreiben "so schnell wie möglich", "so stromsparend wie möglich" etc,
> sondern mal ein paar Zahlen nennen. X MHz, Y ms, Z µA etc. Wenn man
> keine exakte Vorstellung davon hat, sollte wenigstens eine Größenordnung
> angegeben werden (1..5 MHz, <1mA etc.) Welcher IC in welchem Gehäuse.
> Wenn Datenblätter vorhanden sind diese ggf. anhängen oder als Link
> angeben. Daran denken, dass die Leute im Forum nicht neben einem sitzen
> und alles so vor sich sehen wie der Fragesteller Klare Fragen
> formulieren und nicht davon ausgehen, dass eine diffuse
> Zustandsbeschreibung als Frage interpretiert wird.
>
> denke mal drüber nach.

Da man mir ja hier auf anhieb helfen konnte denke ich habe ich alles 
gesagt zu meinem Problem was zu sagen war. Wo bitte habe ich was 
weggelassen was man hätte benötigt um das problem besser zu lösen.

Lerne bitte jemand richtig essen der kleckert und das im normalen Ton 
und nicht mit einer verarsche das jemand her geht und seine 
Programmzeilen abzählt und sich gedanken macht über die Antwort.

von Alter Fux (Gast)


Lesenswert?

Alter Fux schrieb:
> Sorry sollte ich jetzt einwenig hart sein. A......

etwa hier?

von Neuling (Gast)


Lesenswert?

Alter Fux schrieb:
> Alter Fux schrieb:
>
>> Sorry sollte ich jetzt einwenig hart sein. A......
>
>
>
> etwa hier?

Das war ja wohl lange nach deiner Verarsche und nicht der Grund deiner 
Verarschung.

von Karl H. (kbuchegg)


Lesenswert?

Jungs beruhigt euch

Wenn er im Eröffnungsposting noch die Zeile 153 aus der Fehlermeldung 
markiert hätte, wäre es eine perfekte Frage gewesen. 10 Punkte von 10 
möglichen.
Aber auch so war offensichtlich und gut erkennbar, was das Problem 
darstellt.

Im Vergleich, wie andere Fragen hier manchmal aussehen, ist das hier 
harmlos und schon fast vorbildlich.

von Neuling (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Jungs beruhigt euch
>
>
>
> Wenn er im Eröffnungsposting noch die Zeile 153 aus der Fehlermeldung
>
> markiert hätte, wäre es eine perfekte Frage gewesen. 10 Punkte von 10
>
> möglichen.
>
> Aber auch so war offensichtlich und gut erkennbar, was das Problem
>
> darstellt.
>
>
>
> Im Vergleich, wie andere Fragen hier manchmal aussehen, ist das hier
>
> harmlos und schon fast vorbildlich.

Danke und es zeigt mir auf das es sich doch eventuell lohnt sich hier 
anzumelden.

Eine Entschuldigung und die Einsicht wäre auch ok gewesen und ich hätte 
mich nicht so aufgeregt. Ich kann es halt nicht leiden mich hin zu 
setzen und zu denke das mir einer helfen möchte und nach 5 Minuten zu 
merken das ich GRUNDLOS verarscht wurde und die Zeit dahin ist.

von Neuling (Gast)


Lesenswert?

Aber mein Problem geht weiter.
1
; Stackpointer initialisieren
2
ldi Temp1, high(RAMEND) 
3
out SPH,Temp1           
4
ldi Temp1, low(RAMEND)
5
out SPL,Temp1
6
7
; Ports initialisieren
8
ldi  Temp1, 0b11111111
9
out DDRC,Temp1 ; Port-C Ausgang
10
ldi  Temp1, 0b11111110
11
out DDRD,Temp1 ; Port-D Ausgang PD0=Eingang RXD
12
out DDRB,Temp1 ; Port-B Ausgang PB0=Eingang ADC0
13
14
; Alle Port's auf Low
15
ldi Temp1,0b00000000
16
out PortB,Temp1 ; Port B alles auf Low
17
out PortC,Temp1 ; Port C alles auf Low
18
out PortD,Temp1 ; Port D alles auf Low
19
20
;Alle Interrups an
21
sei
22
23
; neuen ADC-Wert lesen
24
loop:
25
; den ADC starten
26
   lds Temp1,ADCSRA
27
   sbr Temp1,1<<ADSC
28
   sts ADCSRA, Temp1
29
   
30
 
31
wait_adc:
32
; wenn der ADC fertig ist, wird dieses Bit gelöscht
33
   lds  Temp1,ADCSRA
34
   sbrs Temp1,ADSC
35
   rjmp wait_adc
36
37
38
; Cursor auf die 5 Stelle in Zeile 4 setzen
39
   ldi Temp1, 0b11011000
40
   rcall lcd_command
41
42
; ADC einlesen:
43
   ldi  xl, ADCL    ; immer zuerst LOW Byte lesen
44
   ldi  xh, ADCH    ; danach das mittlerweile gesperrte High Byte
45
   
46
   rcall lcd_number_big
47
48
49
   rjmp loop

lcd_number_big ist eine Routine die mir auf dem Display die Zahl 
darstellt die in xh und xl steht. Die Routine geht auch. Ich bekomme 
aber immer den gleichen Wert angezeigt obwohl ich PC0 (ADC0) mit GND 
verbunden habe.

Sinn der Übung ist es mich in den ADC einzuarbeiten und ich wollte gerne 
mal die Werte sehen.

Habe ich was vergessen was zur lösung des Problemes führen kann?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Bei Verbindung GND zum abgefragten Eingangspin des ADC sollte ein 
gleichbleibender Wert (um die 0 :-) rauskommen. Was anderes wäre 
komisch.

Um eine Spannung zu messen, müsstest du auch eine Spannung auf den 
betreffenden ADC-Pin geben z.B. mit einem Potentiometer wie in 
AVR-Tutorial: ADC: Beschaltung des ADC-Eingangs

von Neuling (Gast)


Lesenswert?

Stefan B. schrieb:
> Bei Verbindung GND zum abgefragten Eingangspin des ADC sollte ein Wert
>
> um die 0 rauskommen. Was anderes wäre komisch :-)

Ja und weil es komisch ist das ich 31096 herraus bekomme suche ich 
gerade nache dem Fehler den ich gemacht habe.

von spess53 (Gast)


Lesenswert?

Hi

>Habe ich was vergessen was zur lösung des Problemes führen kann?

Vielleicht solltest du mal den ADC initialisieren.

MfG Spess

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Neuling schrieb:

> Ja und weil es komisch ist das ich 31096 herraus bekomme suche ich
> gerade nache dem Fehler den ich gemacht habe.

Ah sorry, ich dachte du gehst nach Code im Tutorial vor.

von Neuling (Gast)


Lesenswert?

Sorry vor dem sei mach ich natürlich
1
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128
2
ldi Dummy1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
3
sts ADMUX, Temp1
4
ldi Temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
5
sts ADCSRA, Temp1

somit sieht das ganze so aus
1
; Stackpointer initialisieren
2
ldi Temp1, high(RAMEND) 
3
out SPH,Temp1           
4
ldi Temp1, low(RAMEND)
5
out SPL,Temp1
6
7
; Ports initialisieren
8
ldi  Temp1, 0b11111111
9
out DDRC,Temp1 ; Port-C Ausgang
10
ldi  Temp1, 0b11111110
11
out DDRD,Temp1 ; Port-D Ausgang PD0=Eingang RXD
12
out DDRB,Temp1 ; Port-B Ausgang PB0=Eingang ADC0
13
14
; Alle Port's auf Low
15
ldi Temp1,0b00000000
16
out PortB,Temp1 ; Port B alles auf Low
17
out PortC,Temp1 ; Port C alles auf Low
18
out PortD,Temp1 ; Port D alles auf Low
19
20
21
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128
22
ldi Dummy1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
23
sts ADMUX, Temp1
24
ldi Temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
25
sts ADCSRA, Temp1
26
27
;Alle Interrups an
28
sei
29
30
; neuen ADC-Wert lesen
31
loop:
32
; den ADC starten
33
   lds Temp1,ADCSRA
34
   sbr Temp1,1<<ADSC
35
   sts ADCSRA, Temp1
36
   
37
 
38
wait_adc:
39
; wenn der ADC fertig ist, wird dieses Bit gelöscht
40
   lds  Temp1,ADCSRA
41
   sbrs Temp1,ADSC
42
   rjmp wait_adc
43
44
45
; Cursor auf die 5 Stelle in Zeile 4 setzen
46
   ldi Temp1, 0b11011000
47
   rcall lcd_command
48
49
; ADC einlesen:
50
   ldi  xl, ADCL    ; immer zuerst LOW Byte lesen
51
   ldi  xh, ADCH    ; danach das mittlerweile gesperrte High Byte
52
   
53
   rcall lcd_number_big
54
55
56
   rjmp loop

von spess53 (Gast)


Lesenswert?

Hi

>ldi Dummy1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
>sts ADMUX, Temp1

Fällt dir etwas auf?

Ich weiss schon, warum ich dieses .def-Geraffel nicht benutze.

MfG Spess

von Neuling (Gast)


Lesenswert?

Ich habe bei mir
1
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128
2
ldi Temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
3
sts ADMUX, Temp1
4
ldi Temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
5
sts ADCSRA, Temp1

stehen das mit dem Dummy1 habe ich hier aus einem anderen Thread 
übernommen war aber nicht richtig nur noch bei mir in der 
Zwischenablage. In meinem Programm ist es Temp1

von Karl H. (kbuchegg)


Lesenswert?

Müsste es hier

wait_adc:
; wenn der ADC fertig ist, wird dieses Bit gelöscht
   lds  Temp1,ADCSRA
   sbrs Temp1,ADSC
   rjmp wait_adc


nicht SBRC anstelle von SBRS heißen?

von spess53 (Gast)


Lesenswert?

Hi

>   sbrs Temp1,ADSC  <-----
>   rjmp wait_adc

   sbrc Temp1,ADSC   <-----
   rjmp wait_adc

ADSC ist während der Wandlung H.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> Hi
>
>>   sbrs Temp1,ADSC  <-----
>>   rjmp wait_adc
>
>    sbrc Temp1,ADSC   <-----
>    rjmp wait_adc
>
> ADSC ist während der Wandlung H.

Hab ich mir auch überlegt. Allerdings müsste irgendwann das ADC Ergebnis 
auch so fertig werden und korrekt sein. D.h. seine hohen Zahlen erklärt 
das nicht, weil er ja in einer Schleife läuft.

Die sind überhaupt seltsam. Ich wüsste nicht, wie es zu einem 
Messergebnis von 31096 kommen kann. Von daher tendiere ich sogar eher zu 
einem Fehler in den Ausgabefunktionen.

von spess53 (Gast)


Lesenswert?

Hi

>Allerdings müsste irgendwann das ADC Ergebnis
>auch so fertig werden und korrekt sein.

Nein. Das Ende der Wandlung wird überhaupt nicht abgewartet.

>Ich wüsste nicht, wie es zu einem
>Messergebnis von 31096 kommen kann. Von daher tendiere ich sogar eher zu
>einem Fehler in den Ausgabefunktionen.

Der Wert kann nicht >1023 werden.

MfG Spess

von Neuling (Gast)


Lesenswert?

Trage ich hier xl mit 255 und xh mit 1 ein:
1
; ADC einlesen:
2
   ldi  xl, 255    ; immer zuerst LOW Byte lesen
3
   ldi  xh, 1      ; danach das mittlerweile gesperrte High Byte
4
   
5
   rcall lcd_number_big
6
7
8
   rjmp loop

wird richtig 00511 auf dem Display angezeigt.

Ein xl mit 255 und ein xh 255 zeigt auch 65535 an also auch OK
Ein xl mit 0 und ein xh mit 0 liefert mir 00000 wie es sich gehört.

So glaube ich nicht das es an der ausgabenroutine liegt.

Diese sieht so aus ( angelhnt aus dem Tutorial )
1
 ; Eine Zahl aus dem Register xh(high) und xl(low) dezimal ausgeben
2
3
lcd_number_big:
4
  push  xl
5
  push  xh
6
7
; Division durch mehrfache Subtraktion
8
 
9
    ldi     Temp1,'0'-1     ; Ziffernzähler direkt als ASCII Code
10
    ; bzgl. '0'-1 siehe http://www.mikrocontroller.net/topic/198681
11
Z_ztausend:
12
    inc     Temp1
13
    subi    xl, low(10000)   ; -10,000
14
    sbci    xh, high(10000) ; 16 Bit
15
    brcc    Z_ztausend
16
                                    
17
    rcall   lcd_data
18
    subi    xl, low(-10000)  ; nach Unterlauf wieder einmal addieren
19
    sbci    xh, high(-10000); +10,000
20
 
21
    ldi     Temp1, '0'-1      ; Ziffernzähler direkt als ASCII Code
22
Z_tausend:
23
    inc     Temp1
24
    subi    xl, low(1000)    ; -1,000
25
    sbci    xh, high(1000)  ; 16 Bit
26
    brcc    Z_tausend
27
                                    
28
    rcall   lcd_data
29
    subi    xl, low(-1000)   ; nach Unterlauf wieder einmal addieren
30
    sbci    xh, high(-1000) ; +1,000
31
 
32
    ldi     Temp1, '0'-1      ; Ziffernzähler direkt als ASCII Code
33
Z_hundert:
34
    inc     Temp1
35
    subi    xl, low(100)     ; -100
36
    sbci    xh, high(100)   ; 16 Bit
37
    brcc    Z_hundert
38
                                    
39
    rcall   lcd_data
40
    subi    xl, low(-100)    ; nach Unterlauf wieder einmal addieren
41
    sbci    xh, high(-100)  ; +100
42
 
43
    ldi     Temp1, '0'-1       ; Ziffernzähler direkt als ASCII Code
44
Z_zehner:
45
    inc     Temp1
46
    subi    xl, low(10)      ; -10
47
    sbci    xh, high(10)    ; 16 Bit
48
    brcc    Z_zehner
49
                                    
50
    rcall   lcd_data
51
    subi    xl, low(-10)     ; nach Unterlauf wieder einmal addieren
52
    sbci    xh, high(-10)   ; +10
53
 
54
    subi    xl, -'0'         ; adlow enthält die Einer, Umwandlung in ASCII
55
    mov     Temp1,xl
56
    rcall   lcd_data
57
58
    pop   xh
59
    pop   xl
60
    ret

von Neuling (Gast)


Lesenswert?

Der Code zu dem Programm:
1
.INCLUDE "m88def.inc"
2
3
.def Temp1    = r16
4
5
.equ F_CPU = 8000000                            ; Systemtakt in Hz
6
.equ BAUD  = 38400                              ; Baudrate
7
8
; Berechnungen
9
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
10
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
11
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
12
 
13
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
14
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
15
.endif 
16
17
.org 0x000     ; kommt ganz an den Anfang des Speichers
18
  rjmp RESET ; Interruptvektoren überspringen und zum Hauptprogramm
19
20
reti           ; $001 External Interrupt Request 0
21
reti           ; $002 External Interrupt Request 1
22
reti           ; $003 Pin Change Interrupt Request 0
23
reti           ; $004 Pin Change Interrupt Request 0
24
reti           ; $005 Pin Change Interrupt Request 1
25
reti           ; $006 Watchdog Time-out Interrupt
26
reti           ; $007 Timer/Counter2 Compare Match A
27
reti           ; $008 Timer/Counter2 Compare Match A
28
reti           ; $009 Timer/Counter2 Overflow
29
reti           ; $00A Timer/Counter1 Capture Event
30
reti           ; $00B Timer/Counter1 Compare Match A
31
reti           ; $00C Timer/Counter1 Compare Match B
32
reti           ; $00D Timer/Counter1 Overflow
33
reti           ; $00E TimerCounter0 Compare Match A
34
reti           ; $00F TimerCounter0 Compare Match B
35
reti           ; $010 Timer/Couner0 Overflow
36
reti           ; $011 SPI Serial Transfer Complete
37
rjmp InRS232   ; $012 USART Rx Complete
38
reti           ; $013 USART, Data Register Empty
39
reti           ; $014 USART Tx Complete
40
reti           ; $015 ADC Conversion Complete
41
reti           ; $016 EEPROM Ready
42
reti           ; $017 Analog Comparator
43
reti           ; $018 Two-wire Serial Interface
44
reti           ; $019 Store Program Memory Read
45
46
RESET:         ; Hier beginnt das Hauptprogramm 
47
48
49
; Stackpointer initialisieren
50
ldi Temp1, high(RAMEND) 
51
out SPH,Temp1           
52
ldi Temp1, low(RAMEND)
53
out SPL,Temp1
54
55
; Ports initialisieren
56
ldi  Temp1, 0b11111111
57
out DDRC,Temp1 ; Port-C Ausgang
58
ldi  Temp1, 0b11111110
59
out DDRD,Temp1 ; Port-D Ausgang PD0=Eingang RXD
60
out DDRB,Temp1 ; Port-B Ausgang PB0=Eingang ADC0
61
62
63
; Baudrate einstellen
64
ldi Temp1, HIGH(UBRR_VAL)
65
sts UBRR0H, Temp1
66
ldi Temp1, LOW(UBRR_VAL)
67
sts UBRR0L, Temp1
68
69
; RS232 Frame-Format: 8 Bit 
70
ldi Temp1, (1<<RXEN0)|(1<<RXCIE0)|(1<<TXEN0) ; TX aktivieren Interrupt bei Empfang RX (Empfang) aktivieren
71
sts UCSR0B, Temp1
72
73
ldi Temp1, (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00) ; 8 Bit Daten kein Paraty, 1 Stopbit
74
sts UCSR0C, Temp1 
75
76
77
; Alle Port's auf Low
78
ldi Temp1,0b00000000
79
out PortB,Temp1 ; Port B alles auf Low
80
out PortC,Temp1 ; Port C alles auf Low
81
out PortD,Temp1 ; Port D alles auf Low
82
83
84
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128
85
 
86
ldi Temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
87
sts ADMUX, Temp1
88
ldi Temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
89
sts ADCSRA, Temp1
90
91
92
93
rcall FirmOut       ; Meldung auf RS232 ausgeben
94
rcall Ton           ; Tonfolge ausgeben
95
rcall StartDisplay  ; Startbildschirm aufbauen und Display Init
96
97
98
;Alle Interrups an
99
sei
100
101
102
103
; neuen ADC-Wert lesen
104
loop:
105
; den ADC starten
106
   lds Temp1,ADCSRA
107
   sbr Temp1,1<<ADSC
108
   sts ADCSRA, Temp1
109
   
110
 
111
wait_adc:
112
; wenn der ADC fertig ist, wird dieses Bit gelöscht
113
   lds  Temp1,ADCSRA
114
   sbrs Temp1,ADSC
115
   rjmp wait_adc
116
117
118
; Cursor auf die 5 Stelle in Zeile 4 setzen
119
   ldi Temp1, 0b11011000
120
   rcall lcd_command
121
122
; ADC einlesen:
123
   ldi  xl, ADCL    ; immer zuerst LOW Byte lesen
124
   ldi  xh, ADCH    ; danach das mittlerweile gesperrte High Byte
125
   
126
   rcall lcd_number_big
127
128
129
   rjmp loop
130
131
          
132
.include "lcd-routines.asm"            ; LCD Funktionen 
133
.include "ton.asm"                     ; Ton Funktionen 
134
.include "rs232.asm"                   ; RS232 Funktionen
135
.include "StartDisplay.asm"            ; Display Funktionen

Das ganze geht schon fein und das gerüsst benutze ich zum lernen immer.

Nur den Teil zwischen Loop benutze ich um weiter zu lernen und neue 
Funktionen zu erkunden.

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Allerdings müsste irgendwann das ADC Ergebnis
>>auch so fertig werden und korrekt sein.
>
> Nein. Das Ende der Wandlung wird überhaupt nicht abgewartet.

Schon.
Aber im nächsten Schleifendurchlauf ist es dann in den ADC Registern 
vorliegend und er würde es sich holen, während der ADC schon wieder 
arbeitet. Ich weiß allerdings nicht auswendig ob es zulässig ist, 
während der Wandlung auf ADCH/ADCL zuzugreifen. Muss es aber wohl, sonst 
würde der Free-Running Mode keinen Sinn ergeben.

von Karl H. (kbuchegg)


Lesenswert?

Ähm,


   ldi  xl, ADCL    ; immer zuerst LOW Byte lesen
   ldi  xh, ADCH    ; danach das mittlerweile gesperrte High Byte


LDI ist hier der falsche Befehl. Du lädst die Adressen von ADCL und ADCH 
und gibst sie aus.
Das müssen IMHO LDS sein.

(Und natürlich SBRC anstelle von SBSR. Aber das hatten wir schon)

von Neuling (Gast)


Lesenswert?

1000 Dank as war es. Jetzt wo es so aussieht:
1
; neuen ADC-Wert lesen
2
loop:
3
; den ADC starten
4
   lds Temp1,ADCSRA
5
   sbr Temp1,1<<ADSC
6
   sts ADCSRA, Temp1
7
   
8
 
9
wait_adc:
10
; wenn der ADC fertig ist, wird dieses Bit gelöscht
11
   lds  Temp1,ADCSRA
12
   sbrc Temp1,ADSC
13
   rjmp wait_adc
14
15
16
; Cursor auf die 5 Stelle in Zeile 4 setzen
17
   ldi Temp1, 0b11011000
18
   rcall lcd_command
19
20
; ADC einlesen:
21
   lds  xl, ADCL    ; immer zuerst LOW Byte lesen
22
   lds  xh, ADCH    ; danach das mittlerweile gesperrte High Byte
23
   
24
   rcall lcd_number_big
25
26
27
   rjmp loop

bekomme ich gegen GND 00000
und gegen VCC 01019

warum nicht 1023? aber das ist wohl eine andere geschichte

von Thomas E. (thomase)


Lesenswert?

Neuling schrieb:
> Eine Entschuldigung und die Einsicht wäre auch ok gewesen und ich hätte
>
> mich nicht so aufgeregt. Ich kann es halt nicht leiden mich hin zu
>
> setzen und zu denke das mir einer helfen möchte und nach 5 Minuten zu
>
> merken das ich GRUNDLOS verarscht wurde und die Zeit dahin ist.

Wenn man "42" liest und das irgendwas mit Software zu tun hat, dann wird 
man nicht verarscht.

42 ist die Antwort auf die Frage nach dem Leben, dem Universum und dem 
ganzen Rest.

Dafür hat der leistungsstärkste Computer seiner Zeit 7,5 Millionen Jahre 
gebraucht, um das auszurechen. Die Antwort ist natürlich völlig 
unbefriedigend. Aber die Frage war auch falsch.

Daraufhin wurde ein neuer noch leistungsfähigerer Computer, dessen 
Hauptbestandteil die Erde war, gebaut, um die Frage auf die Antwort 42 
zu finden.
Leider wurde die Erde von einem Vogonenabrisskommando, fünf Minuten 
bevor die Berechnung fertig war, zerstört, um einer hypergalaktischen 
Umgehungsstrasse Platz zu machen.

42 findet seither in der Software Verwendung als eine Zahl ohne 
Bedeutung.
Das wirst du in diversen Beispielen in diversen Büchern finden.
Bitte zehn Informatiker, dir irgendeine Zahl zu nennen und du wirst 
mindestens 7 Mal die Zahl 42 als Antwort bekommen.

Wenn du sowas liest: "kommentierer Zeile 42 aus!",
ist das fast dasselbe wie "????????????????????????".
Will heissen, ich kann mit deiner Frage so nichts anfangen.

Softwareentwickler haben alle irgendwie einen Knall.

Das zur Netiquette und zur Zahl 42.

Nachzulesen in Douglas Adams, Per Anhalter durch die Galaxis.

Und immer ein Handtuch dabei haben...

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Neuling schrieb:

>
> warum nicht 1023? aber das ist wohl eine andere geschichte

Referenzspannung nicht ganz exakt. Irgendwo ein kleiner 
Übergangswiderstand. Poti (zum Spannungseinstellen) geht der Schleifer 
nicht ganz bis ans Ende, etc. etc.

von Neuling (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Nachzulesen in Douglas Adams, Per Anhalter durch die Galaxis.

Sorry das ich das Buch nicht gelesen habe. Wusste nicht das ich das für 
das Programmieren benötige. Steht hier auch in keinem Tutorial und wie 
mein Name schon sagt ich bin Neuling und beschäftige mich erst so seit 
einem Monat mit der sache. Vorab noch nie etwas Programmiert.

Ein Freund und ich machen das aus dem Spaß herraus wer weiter kommt. 
Idee hatten wir dazu aus der Schule bekommen. Und auch da hatte wir noch 
nie etwas mit 42 im Sinn.

von Holger P. (Gast)


Lesenswert?

lach

Ich merke ich darf Dir keine Tipps geben wo du weiter suchen kannst. Ich 
war zuerst hier grins

Leutz immer langsam wir machen das zum Spaß und ich selber finde das 
Forum echt klasse. Ok sein begrüßung war für sein erstes fragen nicht 
gerade fein.


Ach ja Das mit Dummy1, hättest du Micha nicht schreiben solle. Die regel 
sagt aus keiner schaut vom anderen ab.

wie in meinem Blog unter Beitrag "Viele Fragen und ein kleiner Blog" 
zu sehen ist ist das meine Variable lach

Ach ja wir sind 16 und er ist echt total neu bei der Sache. Also hoho 
Brauner.

von Karl H. (kbuchegg)


Lesenswert?

Neuling schrieb:
> Thomas Eckmann schrieb:
>> Nachzulesen in Douglas Adams, Per Anhalter durch die Galaxis.
>
> Sorry das ich das Buch nicht gelesen habe.

Nicht dass es jetzt in diesem Zusammenhang wichtig wäre.
Wenn du Freude an verschrobenem englischen Humor im Bereich Science 
Fiction hast, dann lies es! Eine unbedingte 5-Sterne Empfehlung.

(Der Anhalter ist seit vielen Jahren so was wie ein 'running Gag' in der 
Software-Szene. Du wirst auch heute noch immer wieder auf viele Zitate 
daraus stossen, die man nicht verstehen kann, wenn man das Buch (und die 
restlichen 4 Teile der Trilogie) nie gelesen hat.)

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.