PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt Transmit Complete UART



pacer_one
20.01.2008, 17:23
Hallo Leute,

habe mir ein kleines Programm gestrickt, dass Zeichen aus dem RAM an das Hyperterminal schicken soll. Leider bringe ich meinen Atmel nicht dazu einen Interrupt (UTXCaddr) auszulösen.

Eigentlich habe ich alles gemacht was zu tun ist:
sbi UCSRB,TXCIE ; Interrupt für "senden fertig" aktivieren
sei ; globale Interruptfreigabe
sbi UCSRA,TXC ; Initialisierung des Interrupts

Was habe ich vergessen?


.NOLIST ; List-Output unterdrücken
.INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp


.def temp = R16 ; für Interrupt
.def ZEICHEN = R17
.equ VARIABLE = 0 ; Beschreibung der Variable


;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7273800 ; 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


.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher


;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000
rjmp Init ; Interruptvektoren überspringen

.org UTXCaddr ; UART Transmit Complete Interrupt
rjmp serout


;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp

; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp

; Frame-Format: 1 Stop-Bits, 8 Bit
ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; Sender aktivieren
sbi UCSRB,TXCIE ; Interrupt für "senden fertig" aktivieren

sei ; globale Interruptfreigabe
sbi UCSRA,TXC ; Initialisierung des Interrupts
;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:


rjmp Hauptschleife


;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------

;Auslesen der Zeichen und bereitstellen in ZEICHEN
;Erhöhen des Z-Pointers; bei leerem Zeichen --> Zurücksetzen des Z-Pointers

serout:
lpm ; Erstes Byte des Strings nach R0 lesen

mov ZEICHEN,R0
adiw ZL, 1 ; Adresse des Z-Pointers um 1 erhöhen
tst R0 ; Inhalt von R0 auf Bull testen

brbc 1,sprung_b
ldi ZL, LOW(Daten*2) ; Adresse des ersten Strings in den
ldi ZH, HIGH(Daten*2) ; Z-Pointer laden
sprung_b:

out UDR, ZEICHEN ; Zeichen auf UART ausgeben
reti

;------------------------------------------------------
; Datenbereich
;------------------------------------------------------
Daten:
.db 0x12, 0x12
.db 0x20, 0x20
.db 0x63, 0x63
.db 0x58, 0x00

;------------------------------------------------------
; ENDE
;------------------------------------------------------
Ende:
rjmp Ende

mare_crisium
22.01.2008, 23:57
pacer_one,

Dein Programm hat keine offensichtlichen Fehler. Unsicher bin ich nur an einer Stelle: Ich weiss nicht sicher, ob Du die ".org"-Direktive in demselben Segment zweimal verwenden darfst. Versuchsweise könntest Du den Platz zwischen "rjmp Init" und der Adresse 0x000D mit "reti"-Anweisungen füllen. Z.B. so:



.CSEG
.ORG $0000

;*------------------------------------
;
; Reset- and Interrupttabelle
;
rjmp INIT ; 1 - Reset/Init-Routine
reti; IINT0 2 - External Interrupt Request 0
reti; IINT1 3 - External Interrupt Request 1
reti; T2_CMP 4 - Timer/Counter2 Compare match
reti; T2_OVF 5 - Timer/Counter2 Overflow
reti; T1_CPT 6 - Timer/Counter1 Capture event
reti; T1_CMPA 7 - Timer/Counter1 Compare A match
reti; T1_CMPB 8 - Timer/Counter1 Compare B match
reti; T1_OVF 9 - Timer/Counter1 Overflow
reti; T0_OVF 10 - Timer/Counter0 Overflow
reti; SPI_STC 11 - Serial Transfer Complete
reti; RX_FULL 12 - Uart Rx char available
reti; TX_EMPT 13 - Uart Tx data register empty
rjmp serout; TX_DONE 14 - Uart Tx complete
reti; ADC_DONE 15 - ADC conversion complete
reti; EE_RDY 16 - EEPROM Ready
reti; ANA_CMP 17 - Analog comparator
reti; TWI_INT 18 - Two-wire Interface
reti; IINT2 19 - External Interrupt Request 2
reti; T0_CMP 20 - Timer/Count0 Compare match
reti; SPM_RDY 21 - Store Program Memory ready
rjmp INIT ; falls das Programm jemals hier ankommt, ...
; .. dann ist was schief gegangen.

Dann bist Du sicher, dass es nicht an der zweiten "org"-Direktiven lag.

Sonst fällt mir an Deinem Programm wirklich nichts auf.

Hat's geholfen?

mare_crisium

JanB
23.01.2008, 07:35
Hallo,
du sendest ja nix,
also bekommst du auch keinen Interrupt "senden fertig" (TXCn).
Sende doch testweise vor der Hauptschleife mal ein Zeichen.

Evtl. willst du auch den
USART Data Register Empty Interrupt (UDREn) verwenden.

Gruß Jan

pacer_one
23.01.2008, 17:15
stimmt, ich muss natürlich zuerst ein Zeichen senden, ich war da wohl auf dem falschen Dampfer und habe versucht einen Interrupt über das Setzen von:
sbi UCSRA,TXC, was natürlich totaler Quatsch ist, weil ja damit nur das Interruptflag gelöscht wird.

Das mit den .org-Direktiven habe ich aus einem Tutorial als Template übernommen. Zumindest hat das bis jetzt keine Probleme verursacht

Danke für die Hilfe, geht jetzt also...