Forum: Mikrocontroller und Digitale Elektronik Urxc problem


von Björn (Gast)


Lesenswert?

Hallo ich verwende fastavr als Compiler und möchte mit dem Interrupt
Urxc eine bestimmte aktion durchführen. Also das etwas passiert wenn
etwas an die Serielle Schnittstelle gesendet wird habe ich schon
hinbekommen allerdings scheint das Programm stehen zu bleiben nachdem
der Interrupt Ausgelößt wurde. Was kann ich machen damit er wieder ins
Hauptprogramm zurückkehrt?

von crazy horse (Gast)


Lesenswert?

also wenn ich dein Programm so ansehe, fällt mir nichts besonderes auf.

von Björn (Gast)


Lesenswert?

:-) hehe ja hast recht hätt ich auch mal drauf kommen können das zu
posten ;-)

also so sieht es aus:
'/////////////////////////////////////////////////////////
'///   FastAVR Basic Compiler for AVR by MICRODESIGN   ///
'///   Name of Your project
'/////////////////////////////////////////////////////////
$Device= 4433      ' used device
$Stack = 32        ' stack depth
$Clock = 4      ' adjust for used crystal
$Source=On        ' basic source in Asm
$Lcd = PORTB.0, RS = PORTD.3, EN =PORTD.4, 16,2
$Baud = 9600

Dim serial As String*8
Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
Dim e As Integer
Dim f As Integer
Dim g As Integer
Dim h As Integer

Declare Sub main()
Declare Interrupt Urxc()
Enable Interrupts
Enable Urxc

DefLcdChar 0, &h07, &h05, &h07, &h00, &h00, &h00, &h00, &h00
DDRD=&HFF
PORTD.2=1

Sub main()
Do


Start Adc
a = (Adc(0)/2)-276
b = (Adc(1)/2)-278
c = (Adc(2)/2)-278
d = (Adc(3)/2)-276

'Locate 1,1
'Lcd Adc(0)
'Locate 2,1
'Lcd Adc(1)
Stop Adc

Cls
Locate 1,1
Lcd "T1:"
Locate 1,4
Lcd a
Locate 1,6
Lcd Chr(0)
Lcd "C"
Locate 1,9
Lcd "T2:"
Locate 1,12
Lcd b
Locate 1,14
Lcd Chr(0)
Lcd "C"

Locate 2,1
Lcd "T3:"
Locate 2,4
Lcd c
Locate 2,6
Lcd Chr(0)
Lcd "C"
Locate 2,9
Lcd "T4:"
Locate 2,12
Lcd d
Locate 2,14
Lcd Chr(0)
Lcd "C"

WaitMs 150
Loop
End Sub

Interrupt Urxc()

Start Adc
e=Adc(0)
f=Adc(1)
g=Adc(2)
h=Adc(3)
Stop Adc
Print e
Print f
Print g
Print h
End Interrupt
main()

Achso noch eine kleine Anmerkung der Interrupt lässt sich genau ein mal
auslösen. Dann bleibt das Programm stehen...

von Rahul (Gast)


Lesenswert?

liegt es vielleicht daran, dass Du das UDR-Byte nicht ausliest, und
deswegen kein neues Empfangen kannst bzw. kein neues Interrupt
ausgelöst wird?
Ich Kenne mich mit dem Compiler leider nicht aus, aber da es Basic sehr
ähnlich sieht, vermute ich, dass da irgendeine Anweisung zum Auslesen
des UDR fehlt...

von crazy horse (Gast)


Lesenswert?

das kann es eigentlich nicht sein, da fehlendes Lesen von UDR bewirkt,
dass das RXC nicht gelöscht wird, also nach reti + 1 Befehl  direkt
wieder ein Rx-Int erfolgen würde.
Mit Basic kenne ich mich aber überhaupt nicht aus, vielleicht mal im
Simulator laufen lassen?

von Dieter (Gast)


Lesenswert?

Hallo

Kenne mich mit FastAvr zwar nicht aus, aber probiere mal
"save all" bei der Interrupt Routine.

Vielleicht war es das ja

MFG
Dieter

Hilfe:
When the Interrupt routine is more complex, use Save 2, Save 3 or Save
All.

von Rahul (Gast)


Lesenswert?

Natürlich liegst Du mit reti + 1 richtig, nur weiss man ja nicht, wie
der Compiler das Problem löst.
Vielleicht liegt es auch daran, dass die Interruptroutine ziemlich
lang, mehrfach aufgerufen wird und leider zu einem Stack-Überlauf
führt.
Abhilfe wäre ja: Entgegennahme des Interrupt, Flag setzen, im
Hauptprogramm auf Flag reagieren und ADC-Kram ausführen.
Hauptprogramm würde die ganze Zeit nach dem Flag gucken und bei
gesetztem die ADC-Sachen machen, Flag löschen und somit Interrupt
wieder zulassen.

Simulator wäre eine Möglichkeit, ASM-Datei posten eine weitere...
Gruß Rahul

von Björn (Gast)


Lesenswert?

Ok ich werde eure Vorschläge mal Testen sollte das nichts bringen kann
ich die ASM datei mal Posten soweit aber schonmal Danke :-)

von Björn (Gast)


Lesenswert?

Hier nun der ASM Code ich hab es jetzt so gemacht das in der interrupt
routine eine Variable gesetzt wird die dann im Hauptprogramm abgefragt
wird. Ausserdem lässt der Controller noch eine LED blinken wenn die AD
werte über die Serielle Schnittstelle gesendet werden. Es scheint so zu
sein, als ob die Interrupt routine ständig ausgeführt wird ich weiß
aber nicht warum...

So hier nun der Inhalt der ASM Datei:

.include  "C:\FASTAVR\inc\4433DEF.INC"
;
    .DSEG
serset:      .byte   1
serial:      .byte   9
a:      .byte   2
b:      .byte   2
c:      .byte   2
d:      .byte   2

    .CSEG
.ORG  0
    rjmp  _Reset
.ORG    INT0addr
    reti
.ORG    INT1addr
    reti
.ORG    ICP1addr
    reti
.ORG    OC1Aaddr
    reti
.ORG    OVF1addr
    reti
.ORG    OVF0addr
    reti
.ORG    SPIaddr
    reti
.ORG    URXCaddr
    rjmp  IntN8

_Reset:
    ldi    yl,low(RAMEND)
    out    SPL,yl
    sbiw  yl,32
    ldi    zl,0x18
    out    UCSRB,zl

    ldi    zh,high(25)
    ldi    zl,low(25)
    out    UBRR,zl

    rcall  LcdIni

;******  USERS BASIC CODE **********************

;-Line--0020----Enable Interrupts--
    sei

;-Line--0021----Enable Urxc--
    sbi    UCSRB,7

;-Line--0022----DefLcdChar 0, &h07, &h05, &h07, &h00, &h00, &h00, &h00,
&h00--
    ldi    r24,0x40
    rcall  _LCtr
LcdCh0:
    .db  0x07,0x05,0x07,0x00,0x00,0x00,0x00,0x00
    ldi    zl,low(LcdCh0*2)
    ldi    zh,high(LcdCh0*2)
    rcall  _Def
    ldi    r24,1
    rcall  _LCtr
    ldi    zl,2
    rcall  _Wms

;-Line--0023----DDRD=&HFF--
    ldi    zl,low(255)
    out    ddrd,zl

;-Line--0024----PORTD.2=1--
    sbi    PORTD,2

;-Line--0025----serset = 0--
    ldi    zl,low(0)
    sts    serset,zl

;-Line--0027----main:--
main:

;-Line--0028----Do            --
L0000:

;-Line--0031----If serset=1 Then--
    lds    r24,serset
    ldi    zl,low(1)
    cp    r24,zl
    breq  PC+0x02
    rjmp  L0003
L0004:

;-Line--0032----PORTD.2=0--
    cbi    PORTD,2

;-Line--0033----Start Adc--
    ldi    zl,0x85
    out    ADCSR,zl

;-Line--0034----Print Adc(0)--
    ldi    zl,low(0)
    out    ADMUX,zl
    rcall  _Adc
    rcall  _W2Str
    rcall  _PrBW
    rcall  _PCL

;-Line--0035----Print Adc(1)--
    ldi    zl,low(1)
    out    ADMUX,zl
    rcall  _Adc
    rcall  _W2Str
    rcall  _PrBW
    rcall  _PCL

;-Line--0036----Print Adc(2)--
    ldi    zl,low(2)
    out    ADMUX,zl
    rcall  _Adc
    rcall  _W2Str
    rcall  _PrBW
    rcall  _PCL

;-Line--0037----Print Adc(3)--
    ldi    zl,low(3)
    out    ADMUX,zl
    rcall  _Adc
    rcall  _W2Str
    rcall  _PrBW
    rcall  _PCL

;-Line--0038----Stop Adc--
    cbi    ADCSR,7

;-Line--0039----serset = 0--
    ldi    zl,low(0)
    sts    serset,zl

;-Line--0040----WaitMs 150--
    ldi    zl,low(150)
    rcall  _wms

;-Line--0041----PORTD.2=1--
    sbi    PORTD,2

;-Line--0042----Enable Urxc--
    sbi    UCSRB,7

;-Line--0043----End If--
L0003:
L0002:

;-Line--0045----Start Adc--
    ldi    zl,0x85
    out    ADCSR,zl

;-Line--0046----a = (Adc(0)/2)-276--
    ldi    zl,low(0)
    out    ADMUX,zl
    rcall  _Adc
    push  zh
    push  zl
    ldi    zl,low(2)
    ldi    zh,high(2)
    pop    r24
    pop    r25
    rcall  Di16u
    push  zh
    push  zl
    ldi    zl,low(276)
    ldi    zh,high(276)
    pop    r24
    pop    r25
    sub    r24,zl
    sbc    r25,zh
    mov    zl,r24
    mov    zh,r25
    sts    a,zl
    sts    a+1,zh

;-Line--0047----b = (Adc(1)/2)-278--
    ldi    zl,low(1)
    out    ADMUX,zl
    rcall  _Adc
    push  zh
    push  zl
    ldi    zl,low(2)
    ldi    zh,high(2)
    pop    r24
    pop    r25
    rcall  Di16u
    push  zh
    push  zl
    ldi    zl,low(278)
    ldi    zh,high(278)
    pop    r24
    pop    r25
    sub    r24,zl
    sbc    r25,zh
    mov    zl,r24
    mov    zh,r25
    sts    b,zl
    sts    b+1,zh

;-Line--0048----c = (Adc(2)/2)-278--
    ldi    zl,low(2)
    out    ADMUX,zl
    rcall  _Adc
    push  zh
    push  zl
    ldi    zl,low(2)
    ldi    zh,high(2)
    pop    r24
    pop    r25
    rcall  Di16u
    push  zh
    push  zl
    ldi    zl,low(278)
    ldi    zh,high(278)
    pop    r24
    pop    r25
    sub    r24,zl
    sbc    r25,zh
    mov    zl,r24
    mov    zh,r25
    sts    c,zl
    sts    c+1,zh

;-Line--0049----d = (Adc(3)/2)-276--
    ldi    zl,low(3)
    out    ADMUX,zl
    rcall  _Adc
    push  zh
    push  zl
    ldi    zl,low(2)
    ldi    zh,high(2)
    pop    r24
    pop    r25
    rcall  Di16u
    push  zh
    push  zl
    ldi    zl,low(276)
    ldi    zh,high(276)
    pop    r24
    pop    r25
    sub    r24,zl
    sbc    r25,zh
    mov    zl,r24
    mov    zh,r25
    sts    d,zl
    sts    d+1,zh

;-Line--0055----Stop Adc--
    cbi    ADCSR,7

;-Line--0057----Cls--
    ldi    r24,1
    rcall  _LCtr
    ldi    zl,0x02
    rcall  _Wms

;-Line--0058----Locate 1,1--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(1)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0059----Lcd "T1:"--
    ldi    zl,low(S00*2)
    ldi    zh,high(S00*2)
    rcall  _LSc

;-Line--0060----Locate 1,4--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(4)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0061----Lcd a--
    lds    zl,a
    lds    zh,a+1
    rcall  _I2Str
    rcall  _LBW

;-Line--0062----Locate 1,6--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(6)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0063----Lcd Chr(0)--
    ldi    zl,low(0)
    mov    r24,zl
    rcall  _Lch

;-Line--0064----Lcd "C"--
    ldi    zl,low(S01*2)
    ldi    zh,high(S01*2)
    rcall  _LSc

;-Line--0065----Locate 1,9--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(9)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0066----Lcd "T2:"--
    ldi    zl,low(S02*2)
    ldi    zh,high(S02*2)
    rcall  _LSc

;-Line--0067----Locate 1,12--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(12)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0068----Lcd b--
    lds    zl,b
    lds    zh,b+1
    rcall  _I2Str
    rcall  _LBW

;-Line--0069----Locate 1,14--
    ldi    r24,0x7F
    push  r24
    ldi    zl,low(14)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0070----Lcd Chr(0)--
    ldi    zl,low(0)
    mov    r24,zl
    rcall  _Lch

;-Line--0071----Lcd "C"--
    ldi    zl,low(S01*2)
    ldi    zh,high(S01*2)
    rcall  _LSc

;-Line--0073----Locate 2,1--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(1)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0074----Lcd "T3:"--
    ldi    zl,low(S03*2)
    ldi    zh,high(S03*2)
    rcall  _LSc

;-Line--0075----Locate 2,4--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(4)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0076----Lcd c--
    lds    zl,c
    lds    zh,c+1
    rcall  _I2Str
    rcall  _LBW

;-Line--0077----Locate 2,6--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(6)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0078----Lcd Chr(0)--
    ldi    zl,low(0)
    mov    r24,zl
    rcall  _Lch

;-Line--0079----Lcd "C"--
    ldi    zl,low(S01*2)
    ldi    zh,high(S01*2)
    rcall  _LSc

;-Line--0080----Locate 2,9--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(9)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0081----Lcd "T4:"--
    ldi    zl,low(S04*2)
    ldi    zh,high(S04*2)
    rcall  _LSc

;-Line--0082----Locate 2,12--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(12)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0083----Lcd d--
    lds    zl,d
    lds    zh,d+1
    rcall  _I2Str
    rcall  _LBW

;-Line--0084----Locate 2,14--
    ldi    r24,0xBF
    push  r24
    ldi    zl,low(14)
    pop    r24
    add    r24,zl
    rcall  _LCtr

;-Line--0085----Lcd Chr(0)--
    ldi    zl,low(0)
    mov    r24,zl
    rcall  _Lch

;-Line--0086----Lcd "C"--
    ldi    zl,low(S01*2)
    ldi    zh,high(S01*2)
    rcall  _LSc

;-Line--0087----WaitMs 150--
    ldi    zl,low(150)
    rcall  _wms

;-Line--0088----Loop--
    rjmp  L0000
L0001:

;-Line--0091----Interrupt Urxc()--

;-Line--0092----serset=1--
IntN8:
    in    r2,SREG
    ldi    zl,low(1)
    sts    serset,zl

;-Line--0093----Disable Urxc--
    cbi    UCSRB,7

;-Line--0094----End Interrupt--
    out    SREG,r2
    reti

;-Line--0095----GoTo main--
    rjmp    main

;****** END OF USER BASIC CODE ****************

; String constants:
S00:  .db  "T1:", 0
S01:  .db  "C", 0
S02:  .db  "T2:", 0
S03:  .db  "T3:", 0
S04:  .db  "T4:", 0


;////// Print Byte & Word /////////////////
_PrBW:  ld    r24,Z+
    tst    r24
    breq  _PBW1
    rcall  _Pch
    rjmp  _PrBW
_PBW1:  ret

;////// Print Cr, Lf & any char////////////
_PCL:  ldi    r24,13
    rcall  _Pch
    ldi    r24,10
_Pch:  sbis  UCSRA,5
    rjmp  _Pch
    out    UDR,r24
    ret

;////// LcdInit ///////////////////////////
LcdIni:  in    zl,DDRB
    ori    zl,0x0f
    out    DDRB,zl
    sbi    DDRD,3
    sbi    DDRD,4
    cbi    PORTD,3
    cbi    PORTD,4
    ldi    zl,16
    rcall  _Wms
    ldi    r24,0x03
    rcall  _LOut
    ldi    zl,5
    rcall  _Wms
    rcall  _LEN
    ldi    zl,6
    rcall  _Wus
    rcall  _LEN
    cbi    PORTB,0
    rcall  _LEN
    ldi    r24,0x28
    rcall  _LCtr
    ldi    r24,0x06
    rcall  _LCtr
    ldi    r24,0x0c
    rcall  _LCtr
    ldi    r24,0x01
    rcall  _LCtr
    ldi    zl,0x03
    rcall  _Wms
    ret

_Lch:  sbi    PORTD,3
    rjmp  _LNib
_LCtr:  cbi    PORTD,3
_LNib:  mov    r21,r24
    swap  r24
    rcall  _LOut
    mov    r24,r21
_LOut:  in    r23,PORTB
    andi  r23,0xf0
    andi  r24,0x0f
    or    r24,r23
    out    PORTB,r24
    rcall  _LEN
    ret

;////// LcdEN /////////////////////////////
_LEN:  sbi    PORTD,4
    nop
    nop
    cbi    PORTD,4
    push  zl
    ldi    zl,0x04
    rcall  _Wus
    pop    zl
    ret

;////// LCD Byte & Word ///////////////////
_LBW:  ld    r24,Z+
    tst    r24
    breq  _LBW1
    rcall  _Lch
    rjmp  _LBW
_LBW1:  ret

;////// LCD string constants //////////////
_LSc:  lpm
    tst    r0
    breq  _LSc1
    mov    r24,r0
    rcall  _Lch
    adiw  zl,1
    rjmp  _LSc
_Lsc1:  ret

;////// ADC ///////////////////////////////
_Adc:  sbi    ADCSR,6
_Adc1:  sbic  ADCSR,6
    rjmp  _Adc1
    in    zl,ADCL
    in    zh,ADCH
    ret

;////// CopyLCDChars //////////////////////
_Def:  ldi    r25,0x08
_Def1:  lpm
    adiw  zl,0x01
    mov    r24,r0
    rcall  _Lch
    dec    r25
    brne  _Def1
    ret

;////// IntToStr //////////////////////////
_B2str:  clr  zh
    clt
    rjmp  _W2st4
_W2str:  clt
    rjmp  _W2st4
_I2str:  clt
    sbrs  zh,0x07
    rjmp  _W2st4
    com    zl
    com    zh
    subi  zl,-0x01
    sbci  zh,-0x01
    set
_W2st4:  push  yl
    clr    r6
    st    -Y,r6
_N2str:  ldi    xl,0x10
    sub    xh,xh
_N2st1:  lsr    r6
    rol    zl
    rol    zh
    rol    xh
    rol    r6
    cpi    xh,0x0a
    brcs  _N2st2
    sbci  xh,0x0a
    inc    zl
_N2st2:  dec    xl
    brne  _N2st1
    subi  xh,-0x30
    st    -Y,xh
    mov    xh,zl
    or    xh,zh
    brne  _N2str
_N2st5:  brtc  _N2st3
    ldi    zl,0x2d
    st    -Y,zl
_N2st3:  mov    zl,yl
    pop    yl
    ret

;////// _Waitms ///////////////////////////
_Wms:  ldi    r20,0x14
_Wms1:  ldi    r21,0x42
_Wms2:  dec    r21
    brne  _Wms2
    dec    r20
    brne  _Wms1
    dec    zl
    brne  _Wms
    ret

;////// _waitus ///////////////////////////
_wus:  ldi    r22,12
_wus1:  dec    r22
    brne  _wus1
    dec    zl
    brne  _wus
    ret

;////// 16/16 unsigned division ///////////
Di16u:  mov    r22,zl
    mov    r23,zh
    mov    zl,r24
    mov    zh,r25
    clr    r24
    sub    r25,r25
    ldi    r20,0x11
d16u1:  rol    zl
    rol    zh
    dec    r20
    brne  d16u2
    ret
d16u2:  rol    r24
    rol    r25
    sub    r24,r22
    sbc    r25,r23
    brcc  d16u3
    add    r24,r22
    adc    r25,r23
    clc
    rjmp  d16u1
d16u3:  sec
    rjmp  d16u1

;System Global Variables: 0  bytes
;User   Global Variables: 18  bytes

von crazy horse (Gast)


Lesenswert?

wenn die ständig ausgeführt wird, macht das Sinn - hatte ich schon
geschrieben - um das RxC-zu löschen, muss man UDR lesen. Wenn
Statusbits per Software gelöscht werden sollen, ist i.a. das Schreiben
einer "1" nötig, beim RxC steht das allerdings nicht dabei...
Also lies das UDR.
Hat mal jemand probiert, ob sich das RxC-Bit durch Schreiben einer 1
löschen lässt?

von Björn (Gast)


Lesenswert?

So ich hab jetzt einfach mit der Holzhammer Methode ein bisschen ASM
Code in den Basic Code gepackt und es geht :-) es lag tatsächlich am
UDR

von Rahul (Gast)


Lesenswert?

Ich hab es noch nicht ausprobiert. Im Normalfall verwendet man ja auch
die Daten von der seriellen Schnittstelle für irgendwas und nicht nur
zu Triggern eines ADC.
Das einfachste ist UDR auszulesen.

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.