Forum: Mikrocontroller und Digitale Elektronik ADC will nicht so wie er soll


von Electronicfox (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Da ich mal einen neuen ATMEGA verwenden wollte, also einen ATMega328P, 
habe ich anscheinend auch Probleme dazu bekommen. Die STS, LDS-Story und 
freischalten der ADCs habe ich mir bereits gut durch gelesen und 
trotzdem will der ADC nicht arbeiten. Beim ATMega8 hats ja funktioniert, 
nur halt beim ATMega328P nicht.

Nun gehe ich davon aus, dass irgentwo in der ADC-Routine der Hund 
begraben liegt. Direktes Ansteuern des TDA6610 mit Test-Programm hat 
funktioniert und kann daher einen Hardwarefehler ausschließen und die 
Steuerspannungen zu den ADCs kommen auch sauber an.

Im Anhang ist die Assembler-File zu finden und hoffe man kann mir da 
weiter helfen.

Schöne Grüße!

von spess53 (Gast)


Lesenswert?

Hi

>; ADC initialisieren: ADC0 bis 2, REF 1,1VDC als Referenz, Single >Conversion, 
Vorteiler

Wo?

MfG Spess

von Electronicfox (Gast)


Lesenswert?

Upps!

Stimmt da war doch was. Muss wohl beim Umschreiben vergessen worden 
sein. Werds jedenfalls noch testen.

MAIN:

    ldi TEMPA,$C0
  sts ADMUX,TEMPA
  rcall WARTE
  rcall sample_adc      ; ADC Lautstärke
  sts 0x0060,TEMPB      ; Lautstärkewert ins RAM 0x0060
  inc TEMPA

  sts ADMUX,TEMPA
  rcall WARTE
  rcall sample_adc      ; ADC Tiefen
  sts 0x0061,TEMPB      ; Tiefenwert ins RAM 0x0061
  inc TEMPA

  sts ADMUX,TEMPA
  rcall WARTE
  rcall sample_adc      ; ADC Höhen
  sts 0x0062,TEMPB      ; Höhenwert ins RAM 0x0062

  lds TEMPA, 0x0061     ; Tiefenwert aus dem RAM holen
  lds TEMPB, 0x0062     ; Höhenwert aus dem RAM holen
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
  add TEMPA, TEMPB      ; Tiefen- und Höhenwert addieren um den 
Klangwert zu ermitteln
  mov SOUND, TEMPA      ; und ins Klangregister verschieben

  lds TEMPA, 0x0060     ; Lautstärkenwert aus dem RAM holen
  mov VOL, TEMPA        ; und ins Lautstärkeregister verschieben

    rcall IIC_VOL         ; Lautstärke- und Klangwerte zum TDA6610 
schicken
    rcall IIC_VOL         ; Nochmal schicken, falls ein 
Übertragungsfehler auftrat
    rcall WARTE

    sbis PIND, 1
    rjmp UKW
    sbis PIND, 2
    rjmp EXT
    sbis PIND, 3
    rjmp STEREO
    sbis PIND, 4
    rjmp SPATIAL
    rjmp MAIN

sample_adc:

    sbr TEMPB,$47
    sts ADCSRA, TEMPB

wait_adc:
    lds TEMPA,ADCSRA
    sbrc TEMPA, ADSC         ; wenn der ADC fertig ist, wird dieses Bit 
gelöscht
  sts ADCSRA, TEMPA
    rjmp    wait_adc



    lds      TEMPB, ADCL        ; immer zuerst LOW Byte lesen
  lds      TEMPA, ADCH        ; danach das mittlerweile gesperrte High 
Byte
    ret

von Electronicfox (Gast)


Lesenswert?

Upps!

Stimmt da war doch was. Muss wohl beim Umschreiben vergessen worden
sein. Werds jedenfalls noch testen.
1
MAIN:
2
3
    ldi TEMPA,$C0
4
  sts ADMUX,TEMPA
5
  rcall WARTE
6
  rcall sample_adc      ; ADC Lautstärke
7
  sts 0x0060,TEMPB      ; Lautstärkewert ins RAM 0x0060
8
  inc TEMPA
9
10
  sts ADMUX,TEMPA
11
  rcall WARTE
12
  rcall sample_adc      ; ADC Tiefen
13
  sts 0x0061,TEMPB      ; Tiefenwert ins RAM 0x0061
14
  inc TEMPA
15
16
  sts ADMUX,TEMPA
17
  rcall WARTE
18
  rcall sample_adc      ; ADC Höhen
19
  sts 0x0062,TEMPB      ; Höhenwert ins RAM 0x0062
20
21
  lds TEMPA, 0x0061     ; Tiefenwert aus dem RAM holen
22
  lds TEMPB, 0x0062     ; Höhenwert aus dem RAM holen
23
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
24
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
25
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
26
  lsl TEMPB             ; 4-BIT Tiefenwert nach links schieben
27
  add TEMPA, TEMPB      ; Tiefen- und Höhenwert addieren um den Klangwert zu ermitteln
28
  mov SOUND, TEMPA      ; und ins Klangregister verschieben
29
30
  lds TEMPA, 0x0060     ; Lautstärkenwert aus dem RAM holen
31
  mov VOL, TEMPA        ; und ins Lautstärkeregister verschieben
32
33
    rcall IIC_VOL         ; Lautstärke- und Klangwerte zum TDA6610 schicken
34
    rcall IIC_VOL         ; Nochmal schicken, falls ein Übertragungsfehler auftrat
35
    rcall WARTE
36
37
    sbis PIND, 1
38
    rjmp UKW
39
    sbis PIND, 2
40
    rjmp EXT
41
    sbis PIND, 3
42
    rjmp STEREO
43
    sbis PIND, 4
44
    rjmp SPATIAL
45
    rjmp MAIN
46
47
sample_adc:
48
49
    sbr TEMPB,$47
50
    sts ADCSRA, TEMPB
51
52
wait_adc:
53
    lds TEMPA,ADCSRA
54
    sbrc TEMPA, ADSC         ; wenn der ADC fertig ist, wird dieses Bit gelöscht
55
  sts ADCSRA, TEMPA
56
    rjmp    wait_adc
57
58
59
60
    lds      TEMPB, ADCL        ; immer zuerst LOW Byte lesen
61
  lds      TEMPA, ADCH        ; danach das mittlerweile gesperrte High Byte
62
    ret

Danke und schöne Grüße!

von Karl H. (kbuchegg)


Lesenswert?

Der Teil hier
1
wait_adc:
2
  lds TEMPA,ADCSRA
3
  sbrc TEMPA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
4
  sts ADCSRA, TEMPA
5
  rjmp wait_adc

ist auch noch nicht koscher.
Du hängst da jetzt in einer Endlosschleife.
der sts gehört da nicht hin. Du fragst nur das Bit im ADCSRA ab, ob es 0 
ist. Wenn ja, kannst du die Schleife verlassen.
-> du brauchst nichts ins ADCSRA zurückschreiben
-> du willst den rjmp überspringen, wenn sich das Bit als 0 erweist.

BIst du dir sicher, dass du das hier
1
...
2
  inc TEMPA
3
4
  sts ADMUX,TEMPA
5
...
tun willst?
Der vorhergehende Aufruf von sample_adc hat dir TEMPA zerstört.

von Karl H. (kbuchegg)


Lesenswert?

Dafür speicherst du vom Ergebnis des Wandelvorgangs
1
  rcall sample_adc      ; ADC Lautstärke
2
  sts 0x0060,TEMPB      ; Lautstärkewert ins RAM 0x0060
nur die unteren 8 Bit.

Bist du sicher, dass das so gewollt ist? Wenn ADLAR nicht gesetzt ist, 
dann kriegst du vom ADC ein 10 Bit Ergebnis.

Und bitte: tu dir selbst einen Gefallen und mach einen Bogen um so Dinge 
wie ein direktes reinschreiben con 0x0060 in den Code. Das ist doch auf 
lange Sicht viel zu fehleranfällig!
Lass doch den Assembler darüber Buch führen, welche Speicherzellen du 
benutzt hast und welche noch frei sind und benutze statt dessen 
symbolische Namen im Code!

http://www.mikrocontroller.net/articles/AVR-Tutorial:_SRAM

1
....
2
  rcall sample_adc        ; ADC Lautstärke
3
  sts VolumeLevel,TEMPB
4
....
5
6
  lds TEMPA, VolumeLevel
7
  mov VOL, TEMPA          ; ins Lautstärkeregister verschieben
8
....
9
10
11
12
.DSEG
13
VolumeLevel .BYTE  1
14
BassLevel   .BYTE  1
15
HeightLevel .BYTE  1

Siehst du, wie einige der Kommentare überflüssig geworden sind, ganz 
einfach dadurch, dass ich dem Byte im SRAM einen Namen gegeben habe?
Dass die Lautstärke, aka 'VolumeLevel' an der Adresse 0x0060 im Speicher 
liegt, interessiert mich doch gar nicht. Das ist der Job des Assemblers 
darüber Buch zu führen. Mich interessiert nur, das es im SRAM liegt. 
Wenn ich die Adresse des Bytes brauche, dann benutze ich 'VolumeLevel'. 
Welcher Zahlenwert dahinter steckt, das erledigt der Assembler für mich. 
Benutze ich überall den gleichen Namen, dann habe ich automatisch 
überall die gleiche Adresse stehen, ohne dass ich mir darüber den Kopf 
zerbrechen muss oder höllisch darauf aufpassen müsste überall die 
gleiche Zahl zu benutzen und nur ja keinen blöden Tippfehler zu machen.
Programmieren ist schon schwer genug. Du muss ich mir nicht auch noch 
absichtlich Prügel zwischen die Beine werfen um nur ja möglichst viele 
Stolperfallen aufzubauen.

von Electronicfox (Gast)


Lesenswert?

Danke, das macht es einfacher.

Mal schauen ob es dann geht.

Früher hab ich das mal so gelernt gehabt mit der Direkteingabe, aber 
jetzt hab ich wieder was dazu gelernt.

Heißt das jetzt auch, dass ich mir keine Sorgen machen muss, dass nichts 
in einem Speicher landet, wo ich später keinen Zugriff mehr habe nach 
dem Programmieren?
Bei AVR-Studio kann man bei den Fuses ja den RAM-Bereich justieren, 
welcher frei gegeben werden kann. Oder landen diese Eingaben automatisch 
in der Minimalebene, welche immer freigegeben ist?

von Karl H. (kbuchegg)


Lesenswert?

Electronicfox schrieb:

> Heißt das jetzt auch, dass ich mir keine Sorgen machen muss, dass nichts
> in einem Speicher landet, wo ich später keinen Zugriff mehr habe nach
> dem Programmieren?

Allerdings.
Vor allen Dingen hättest du mit deinem Code in den "Extended Register" 
Bereich geschrieben. Mit 0x0060 hättest du am Watchdog Control Register 
WDTCSR rumgefummelt. Nicht ganz das, was du willst.

> Bei AVR-Studio kann man bei den Fuses ja den RAM-Bereich justieren,
> welcher frei gegeben werden kann.

Das hat nicht viel mit dem AVR Studio zu tun, sondern damit, was dein 
Controller kann. Und der Mega328P hat frei verfügbares SRAM beginnend ab 
der Adresse 0x0100. Liest denn heute keiner mehr Datenblätter? Gerade 
für Assemblerprogrammierer gilt doch: Das Datenblatt ist deine Bibel.

> Oder landen diese Eingaben automatisch
> in der Minimalebene, welche immer freigegeben ist?

Keine Ahnung wovon du überhaupt sprichst.
Schau dir im Datenblatt zum 328P das Kapitel 7 "AVR Memories" an.
http://www.atmel.com/Images/doc8161.pdf

Aber: Durch das .DSEG befreist du dich davon, die genaue Adresslage zu 
kennen. Der Assembler kennt sie, passend zu deinem benutzten Controller. 
Und das reicht dann schon.

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.