PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Uart senden empfangen Interrups



ronald
02.03.2006, 21:11
Hallo,
ich möchte mit dem ganz einfachen Programm folgendes machen:
daten empfangen und senden per interrupt

meiner meinung wird das rxcie-bit gesetzt, wenn daten da sind --> also INT_gChar muss doch auslösen, oder?

und wenn TXCIE-bit gesetzt ist löst der senden Interrupt aus, oder?

Wahrscheinlich verstehe ich hier was grundlegendes nicht. Wäre super, wenn mir jemand helfen kann.
Danke schon mal.

SprinterSB
03.03.2006, 14:52
Das asm auseinander zu klabüstern ist mit jetzt etwas zu viel. Vielleicht gibt dir ja eine C-Routine den richtigen Hinweis, wie die ISRs zu machen sind?

https://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc#Mit_Interrupts

ronald
04.03.2006, 17:01
habe rausgefunden, dass ich der tx int nur auslöst, wenn daten gesendet wurden. deshalb habe ich das senden jetzt mit in den rx int gelegt.
geht aber immer noch nicht.

es wäre super, wenn sich das mal einer ansehen könnte und mir sagen kann, was ich falsch mache bzw. falsch verstanden habe.
danke schon einmal.
ronald

SprinterSB
04.03.2006, 17:21
Es gibt zwei IRQs, die mit dem Senden zusammenhängen:
Der TX-IRQ wird getriggert, wenn eine Übertragung komplett ist.
Und der Data-IRQ, der wird getriggert, wenn UDR leer ist und was neues aufnehmen kann (auch wenn der Transmit noch nicht fertig ist).

-- Du musst die Übertragungsart einstellen, also wieviele datenbits, Stop, Parity...
-- Die IRQs, die du haben willst, musst du aktivieren (RXIE, TXIE oder so)
-- Interrupts müssen global aktiviert sein (I in SREG via sei)
-- Die ISRs brauchst du nicht in cli/sei zu fassen, die AVR-Hardware deaktiviert IRQs beim Betreten einer ISR und reaktiviert danach. Das AVR-Handbuch beschreibt das ganz schön
-- r17 hat keinen definierten Wert und überschreibt alles , was auf PORTB passiert.

ronald
04.03.2006, 17:32
danke für deine antwort,

den port 17 habe ich zum testen für die leds gemacht. d.h. wenn er in den int springen würde, würde dann die rote leuchten und wenn er es zum senden schafft, auch die gelbe. das sollte schon so richtig sein.
die baudrate ist eingestellt.

ich möchte folgendes:
wenn daten ankommen, soll der int auslösen. ich möchte mir also die polling abfrage sparen (sbis usr,7), so dass der µC auch noch was anderes machen kann.
also die art der übertragung muss ich glaube nicht einstellen, denn wenn ich es ohne int programmiere, dann gehts ja auch.
danke

SprinterSB
04.03.2006, 17:48
-- wo werden INTs global aktiviert?
-- wo wird RX-Interrupt aktiviert?
-- die Übertragiunsart muss eingestellt werden, die Befehle dazu sind keine Dekoration. Stimmt die Einstellung nicht, empfängst du Müll.
-- wie gesagt, R17 überheinert alles, was du an PORTB machst, und zwar so fix, daß du die LEDs noch nichtmal zucken siehst

ronald
04.03.2006, 18:04
1.) die ints sind automatisch aktiviert, ich habe sie nur am anfang des ints deaktiviert, das dieser empfangsint nicht unterbrochen wird, am ende lasse ich sie wieder zu
2.) in der vektortab verweise ich auf den int, welcher durch das gesetzte bit 7 im usr aufgerufen wird (so zumind. mein Kenntnisstand)
3.) die baudrate habe ich eingestellt (9600)
4.) dadurch, dass ich nur ein bit setze und kein überschreibe, müssten alle leds leuchten, wenn der int einmal durchgelaufen ist

SprinterSB
04.03.2006, 18:14
ad 1) Interupts sind ab Reset deaktiviert bei AVR. Wenn man sie nicht aktiviert (und das tust du nicht, jedenfalls nicht in der obigen Quelle), dann gibts auch keine Interrupts
ad 2) Indem ISRs in die VecTab eingetragen werden, werden diese NICHT automatisch aktiviert RXCIE=?, TXCIE=?, UDRIE=?
ad 3) UCSZ1=?, UCSZ0=?
ad 4) Mit "out PORTB, r17" überschreibst du ALLE Bits von PortB.

ronald
04.03.2006, 18:43
danke, ich teste noch ein wenig :)

ronald
04.03.2006, 19:04
ich habe das ucsrc reg versucht zu setzen, allerdings kommt da ein fehler, das ein konst. wert benötigt wird.
ich habe das zuvor nicht eingestellt.
es wäre super, wenn du dir das nochmal ansehen könntest - danke!!

ronald
04.03.2006, 19:36
achso, das sei habe ich noch dazu gefügt (allerdings noch nicht im obigen quelltext), ronald

SprinterSB
04.03.2006, 19:38
Kennt dein Assembler diese Notation von Binärkonstanten? Die kenn ich nur von einigen Versionen von GCC.

ronald
04.03.2006, 19:45
habe es auch mit 0x86 (b10000110) probiert, aber bin-konst. geht zumind. beim laden zu arbeitsreg
danke

izaseba
05.03.2006, 03:32
Hallo Ronald,
ich würd Dir gerne helfen ,aber so wie Du Dein Code schreibst, bekommt das kein Mensch zu lesen(nicht böse sein...), ich bin mir auch sicher, daß Du selber in einem Monat nicht mehr weißt, was Du geproggt hast....

Hier ein paar Beispiele, wie Du es besser machen könntest:
1. die Bedeutung von .org .def .equ kennenlernen


.include "m8def.inc"

;UART Konstanten
.equ CLOCK = 10000000
.equ BAUD = 9600
.equ UBRRVAL = CLOCK / (BAUD*16)-1

;DataPort
.equ DataPort = PORTB
.equ DataDDR = DDRB
.equ DataPin = PINB

;RamRingPuffer Einstellungen
.equ PUFFER = 0x0060
.equ PUFFER_END = PUFFER + 0x32

;Ringpufferinit
ldi XH,HIGH(PUFFER)
ldi XL,LOW(PUFFER)
ldi YH,HIGH(PUFFER)
ldi YL,LOW(PUFFER)

;Registerdefinieren
.def LCD_read = R1 ;Display Ausleseregister
.def Parameter_Counter = R2
.def Save_rueckspH = R3
.def Save_rueckspL = R4
.def Cursor_Status = R5
.def Zaehler1 = R6
.def tmp = R16 ;Arbeitsregister 1
.def tmp2 = R17 ;Arbeitsregister 2
.def tmp3 = R18 ;Arbeitsregister 3
.def Status = R19 ;Register fuer diverse Flags
.def DDRAM = R20 ;DDRAM Zaehler


So weißt man direkt, welcher Register für was ist, und welche Konstante was zu sagen hat.

2. Die Vektoren und die reset routine:


.org 0x0000
rjmp reset

.org URXCaddr
rjmp read
reset:

ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
sbi EnableDDR,Enable
sbi RSDDR,RS
sbi RWDDR,RW
sbi BacklightDDR,Backlight
sbi KontrastDDR,Kontrast
ldi tmp,0x0F
out DataDDR,tmp
;UARTinit
ldi tmp,HIGH(UBRRVAL)
out UBRRH,tmp
ldi tmp,LOW(UBRRVAL)
out UBRRL,tmp
ldi tmp,(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
out UCSRC,tmp
ldi tmp,(1<<RXEN) | (1<<TXEN) | (1<<RXCIE)
out UCSRB,tmp
sei
loop:
rjmp loop


So, hier sieht man ja welche Bits bei welchen Registern gesetzt werden, auch nach Jahren gut zu lesen....

3. ISR:



read:

push tmp
in tmp,SREG
push tmp
in tmp,UDR
st X+,tmp
ldi tmp2,LOW(PUFFER_END)
ldi tmp,HIGH(PUFFER_END)
cp XL,tmp2
cpc XH,tmp
brlo read1
ldi XH,HIGH(PUFFER)
ldi XL,LOW(PUFFER)
read1:
pop tmp
out SREG,tmp
pop tmp
reti

Da brauchst Du kein cli mehr machen (sagte der Sprinter ja schon)

Diese Beispiele habe ich gerade per copy/paste eingefügt, es ist nicht vollständig, nur als Beispiel anzusehen, aber so werden die Interrupt auf jedem Fall ausgelöst O:)

gute Nacht Sebastian

ronald
06.03.2006, 19:05
hallo,

also mit sbi setzt man wirklich nur ein bit und nicht den ganzen port bzw register.

vielen dank trotzdem für die infos, aber bei einem so kleinen programm, war ich zu faul, erst die register usw. umzubennen.
ich wollte nur das grundlegende testen, dass der uart int beim empfang von daten auslöst. aber bei größeren progs mache ich das natürllich auch.
danke, ronald

izaseba
06.03.2006, 21:24
also mit sbi setzt man wirklich nur ein bit und nicht den ganzen port bzw register.

Hat hier jemand was anderes behauptet, oder wie ist diese Aussage gemeint?


aber bei einem so kleinen programm, war ich zu faul, erst die register usw. umzubennen.

Dann wundere Dich nicht, wenn hier ein paar Leute zu faul sind Dein Programm zu lesen...

Gruß Sebastian