Forum: Mikrocontroller und Digitale Elektronik Anfänger mit Problemen - Atmega48 & Assemblercode


von Pascal K. (Firma: MHK) (pascal2002)


Angehängte Dateien:

Lesenswert?

Wir haben in der Schule ein Board mit einem Atmega48.

Dazu soll ich, bzw. darf ich ein kleines Programm schreiben, das die
Funktion des UART im Atmega48 veranschaulichen soll. Ich hab mir dazu
einfach den Code aus dem Tutorial genommen und mal ganz treudoof
assembliert. Da es dann logischerweise Fehler gab, da der Code im
Tutorial für ein Atmega8 ist, habe ich dann auch noch erkannt.
Allerdgins bin ich mir nicht sicher, ob meine "Anpassungen" so richtig
sind. Wenn ich das ganze ausprobieren will, passiert nix.

Ich habe das Programm AVR-Stduio 4 und wollte den Beispielcode (Anhang)
benutzen:

.include "m48def.inc"

.def temp = R16
.def temp1 = R17

.equ F_CPU = 8000000        ; Systemtakt in Hz
.equ BAUD  = 9600           ; Baudrate

; Berechnungen
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille

.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille
Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit
zu hoch!"
.endif


.org 0x00
        rjmp main

.org URXCaddr
        rjmp int_rxc

; Hauptprogramm
main:
        ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

        ldi temp, 0xFF                    ; Port B = Ausgang
        out DDRB, temp

        ; Baudrate einstellen
        ldi temp, HIGH(UBRR_VAL)
        sts UBRR0H, temp
        ldi temp, LOW(UBRR_VAL)
        sts UBRR0L, temp

        ; Frame-Format: 8 Bit
        ldi temp, (3<<USBS0)|(1<<UCSZ00)
        sts UCSR0C, temp

     lds temp, UCSR0B          ; Interrupt bei Empfang
    sbr temp, RXCIE0
        sts UCSR0B, temp

    lds temp1, UCSR0B                 ; RX (Empfang) aktivieren
        sbr temp1, RXEN0
    sts UCSR0B, temp1

    sei                               ; Interrupts global aktivieren

loop:   rjmp loop                         ; Endlosschleife

; Interruptroutine: wird ausgeführt sobald ein Byte über das UART
empfangen wurde
int_rxc:
        push temp                         ; temp auf dem Stack sichern

        lds temp, UDR0
        cpi temp, '1'                     ; empfangenes Byte mit '1'
vergleichen
        brne int_rxc_1                    ; wenn nicht gleich, dann zu
int_rcx_1
        cbi PORTB, 0                      ; LED einschalten
        rjmp int_rxc_2                    ; Zu int_rxc_2 springen
int_rxc_1:
        cpi temp, '0'                     ; empfangenes Byte mit '0'
vergleichen
        brne int_rxc_2                    ; wenn nicht gleich, dann zu
int_rcx_2
        sbi PORTB, 0                      ; LED ausschalten
int_rxc_2:
        pop temp                          ; temp wiederherstellen
        reti



Das Programm soll ein Signal das seriell über eine Terminalsoftware
gesendet wird, auswerten und der Atmega soll eine LED schalten, je nach
Zustand.


Vielen Dank im Voraus.

Pascal

von Falk B. (falk)


Lesenswert?

@  Pascal Knies (Firma MHK) (pascal2002)

>Dazu soll ich, bzw. darf ich ein kleines Programm schreiben, das die
>Funktion des UART im Atmega48 veranschaulichen soll. Ich hab mir dazu
>einfach den Code aus dem Tutorial genommen und mal ganz treudoof
>assembliert.

Ist ja erstmal nicht verwerflich ;-)

>Allerdgins bin ich mir nicht sicher, ob meine "Anpassungen" so richtig
>sind. Wenn ich das ganze ausprobieren will, passiert nix.

AVR-Tutorial: UART
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART
Interrupt

Hehe, böser Fehler. Probiers mal so.

1
     lds temp, UCSR0B          ; Interrupt bei Empfang
2
     sbr temp, (1<<RXCIE0)
3
     sts UCSR0B, temp
4
5
     lds temp1, UCSR0B                 ; RX (Empfang) aktivieren
6
     sbr temp1, (1<<RXEN0)
7
     sts UCSR0B, temp1

Siehe Bitmanipulation.

MFG
Falk

von spess53 (Gast)


Lesenswert?

Hi

Ersetze mal 'sbr temp, RXCIE0' durch 'sbr temp, 1<<RXCIE0' und 'sbr 
temp1, RXEN0' durch 'sbr temp1, 1<<RXEN0'

'sbr' erwartet eine Bitmaske, keine Bitnummer.

MfG Spess

von Pascal K. (Firma: MHK) (pascal2002)


Lesenswert?

habs geändert, passiert aber trotzdem nichts. :(

mit einem basic code gehts einwandfrei


EDIT: jetzt geht es, allerdings so das bei 0 die LED leuchtet anstatt 
bei 1

von Falk B. (falk)


Lesenswert?

@ Pascal Knies (Firma MHK) (pascal2002)

>EDIT: jetzt geht es, allerdings so das bei 0 die LED leuchtet anstatt
>bei 1

Logisch, die werden ja auch LOW aktiv angesteuert.

MFG
Falk

von Pascal K. (Firma: MHK) (pascal2002)


Lesenswert?

naja eigentlich will ich es aber anderstrum ^^

von Karl H. (kbuchegg)


Lesenswert?

Pascal Knies wrote:
> naja eigentlich will ich es aber anderstrum ^^

Dann drehs halt um. Wo liegt das Problem?

von Pascal K. (Firma: MHK) (pascal2002)


Lesenswert?

hmm.....irgendwie bin ich zu doof dafür ^

muss ich da nicht einfach die zwei zeilen:

cpi temp, '1'                     ; empfangenes Byte mit '1' vergleichen

cpi temp, '0'                     ; empfangenes Byte mit '0' vergleichen


umschrieben, das es so aussieht?

cpi temp, '0'                     ; empfangenes Byte mit '1' vergleichen

cpi temp, '1'                     ; empfangenes Byte mit '0' vergleichen


mfg
p.knies

von spess53 (Gast)


Lesenswert?

Hi

Ja. Oder du tauscht die Befehle 'cbi PORTB, 0' und 'sbi PORTB, 0'.

MfG Spess

von Pascal K. (Firma: MHK) (pascal2002)


Lesenswert?

habs gefunden, was es war.
hab jetzt sbi und cbi getauscht.


int_rxc:
   push temp                         ; temp auf dem Stack sichern

   lds temp, UDR0
   cpi temp, '1'                     ; empfangenes Byte mit '1' 
vergleichen
   brne int_rxc_1                    ; wenn nicht gleich, dann zu 
int_rcx_1
   sbi PORTB, 0                      ; LED einschalten
   rjmp int_rxc_2                    ; Zu int_rxc_2 springen

int_rxc_1:
   cpi temp, '0'                     ; empfangenes Byte mit '0' 
vergleichen
   brne int_rxc_2                    ; wenn nicht gleich, dann zu 
int_rcx_2
   cbi PORTB, 0                      ; LED ausschalten

int_rxc_2:
   pop temp                          ; temp wiederherstellen
   reti

von Pascal K. (Firma: MHK) (pascal2002)


Lesenswert?

spess53 wrote:
> Hi
>
> Ja. Oder du tauscht die Befehle 'cbi PORTB, 0' und 'sbi PORTB, 0'.
>
> MfG Spess

ah danke....habe es auch gerade gemerkt ^^

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.