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!
Hi
>; ADC initialisieren: ADC0 bis 2, REF 1,1VDC als Referenz, Single >Conversion,
Vorteiler
Wo?
MfG Spess
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
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!
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.
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.
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.