PORT-B des ATMEGA168 und auch des ATMEGA48 immer $00

Gast #2183956
Lesenswert?

Hallo!
Ich hab ein kleines Problem mit 2 µC. Betrifft hierbei den ATMEGA168 und 
auch den ATMEGA48. Bei beiden funktioniert das PORT-B nicht als Ausgang. 
Als Eingang gibts keine Probleme. JTAG hab ich ausgeschlossen, da diese 
AVRs angeblich kein JTAG haben und in den Fuses fand ich meiner Meinung 
nach kein falsches Häkchen ( AVR-Studio4 ). Nun gehe ich davon aus, dass 
der Fehler im Sourcecode liegt. Mit dem Mega32 funktioniert die 
Schaltung übrigens einwandfrei. Im Prinzip sollte das doch einfaches 
Projekt werden, dachte ich zumindest ;)

Schönen Gruß!
Angehängte Dateien:
#2183979
Lesenswert?

>Ändere mal

>> ldi speca, LOW(RAMEND)
>> out SPH, speca

>in

>ldi speca, HIGH(RAMEND)
>out SPH, speca

Genau das ist mir auch aufgefallen. Ansonsten scheint in deinem 
geposteten Code nichts weiter verdächtig. Das laden und speichern über 
lds und sts in den höheren ( > 3F) Registern wie ADMUX und ADCSRA hast 
du ja schon umgeändert.

Schreib mal, ob der oben genannte Fehler dein Problem mit PortB behoben 
hat. Die Schaltung sieht nämlich interessant aus. Wo hast du die her?

Steffen
Gast #2183992
Lesenswert?

Steffen H. schrieb:

> Schreib mal, ob der oben genannte Fehler dein Problem mit PortB behoben
> hat. Die Schaltung sieht nämlich interessant aus. Wo hast du die her?
>
> Steffen

Die Schaltung hatte ich mal mit TTL-ICs und einen ADC-IC aufgebaut, 
welche mir mal so eingefallen. Danach wollte ich wissen obs mit AVRs 
auch geht und tat es auch, zumindest mit ATMEGA32 und ATTINY2313. Da 
aber die 28PINs gemütlicher sind als 40PINs hab ich es mit ATMEGA48 und 
ATMEGA168 probieren wollen.
#2184016
Lesenswert?

Mir fällt noch auf:
1
INPUTA:      ; Kanal 0, interne Referenzspannung
2
    ldi     sw, 0b11000000 
3
    STS     ADMUX, sw
4
    ldi     sw2,0b10000000
5
    STS     ADCSRA, sw2
6
  ret
Hier schaltest du den ADC ein. (bit7 in ADCSRA)

Und hier:
1
wait_adc:    ; wenn der ADC fertig ist, wird dieses Bit gelöscht
2
    ldi speca, 0b01000000
3
    STS ADCSRA, speca
4
...
..schaltest du den ADC wieder aus und willst gleichzeitig eine 
Konvertierung starten?

Steffen
#2184021
Lesenswert?

Jetzt hab ich mich sogar noch vertan.

Hier meine ich:
1
sample_adc:  ; den ADC starten
2
    ldi speca, 0b01000000
3
    STS ADCSRA, speca

Und hier willst du doch nur das Statusbit abfragen:
1
wait_adc:    ; wenn der ADC fertig ist, wird dieses Bit gelöscht
2
    ldi speca, 0b01000000  ; <- weglassen
3
    STS ADCSRA, speca      ; <- weglassen
4
    lds  ar0, ADCSRA
5
    cp ar0, speca          ; <- cpi ar0, ADSC (ADSC sollte in der m168.inc 
6
    breq wait_adc          ;                   deklariert sein)

Das geht natürlich nicht so!
Gast #2184024
Lesenswert?

Irgendwas ist an dem ADC code aber auch faul:
1
INPUTA:      ; Kanal 0, interne Referenzspannung
2
    ldi     sw, 0b11000000 
3
    STS     ADMUX, sw
4
    ldi     sw2,0b10000000
5
    STS     ADCSRA, sw2

Dies schaltet den ADC ein (bit #7 in ADCSRA)
1
  ret
2

3
sample_adc:  ; den ADC starten
4
    ldi speca, 0b01000000
5
    STS ADCSRA, speca

Hier schaltest Du den ADC wieder aus?! Bit 7 auf null... Und 
gleichzeitig startest Du eine Wandlung. Wird nicht gehen.
1
 
2
wait_adc:    ; wenn der ADC fertig ist, wird dieses Bit gelöscht
3
    ldi speca, 0b01000000
4
    STS ADCSRA, speca
5
    lds  ar0, ADCSRA
6
    cp ar0, speca
7
    breq wait_adc

Warum versuchst Du in der Schleife die Wandlung immer wieder zu starten 
(bit 6 auf 1?)
Und der Vergleich obs fertig ist wird auch schief gehen:
ADCSRA hat ja noch mehr bits, z.B. wird nach der ersten Wandlung das 
Interrupt-Flag-Bit gesetzt sein und der Vergleich dann immer ergeben 
dass die Schleife verlassen werden kann.

Vielleicht eher so:
1
INPUTA:      ; Kanal 0, interne Referenzspannung
2
    ldi     sw, 0b11000000 
3
    STS     ADMUX, sw
4
    ; ADC ein
5
    ldi     sw2,0b10000000
6
    STS     ADCSRA, sw2
7
    ret
8

9
sample_adc:  ; den ADC starten
10
    ; evtl sollte hier auch noch der ADC 
11
    ;clock prescaler (bit 0..2) geaendert werden, je
12
    ; nach deiner Taktfrequenz
13
    ldi speca, 0b11000000
14
    STS ADCSRA, speca
15
wait_adc:    ; wenn der ADC fertig ist, wird dieses Bit gelöscht
16
    lds  ar0, ADCSRA
17
    andi ar0, 0b01000000 ; ausmaskieren vonbit 6 
18
    brne wait_adc ; schleife, wenn immer noch 1
#2184026
Lesenswert?

Oh man, ist das schon so spät?

Doch kein cpi verwenden!

Dein polling auf ADSC sollte so ausehen:
1
wait_adc:    ; wenn der ADC fertig ist, wird dieses Bit gelöscht
2
    lds  ar0, ADCSRA
3
    sbrc ar0, ADSC
4
    rjmp wait_adc
5
 
6
; ADC einlesen:
7
    lds     speca, ADCL        ; immer zuerst LOW Byte lesen
8
    lds     specb, ADCH        ; danach das High Byte
9
    ret
Gast #2184065
Lesenswert?

Steffen H. schrieb:
> Oh man, ist das schon so spät?
>
> Doch kein cpi verwenden!
>
> Dein polling auf ADSC sollte so ausehen:wait_adc:    ; wenn der ADC fertig ist, 
wird dieses Bit gelöscht
>     lds  ar0, ADCSRA
>     sbrc ar0, ADSC
>     rjmp wait_adc
>
> ; ADC einlesen:
>     lds     speca, ADCL        ; immer zuerst LOW Byte lesen
>     lds     specb, ADCH        ; danach das High Byte
>     ret

Hallo!
Danke, genau das war der fehlende Ansatz.
Nun funktioniert alles wie bei ATMEGA32 ;)
Anscheinend bin ich total durcheinander gekommen mit LDS, STS statt IN 
und OUT

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren