Forum: Mikrocontroller und Digitale Elektronik wieder das Thema DMX512


von jornbyte (Gast)


Lesenswert?

Hallo Alle
Ich möchte das erste Byte (Kanal) vom DMX512 auf ein LCD anzeigen 
lassen. Die anderen Kanäle sind später mal dran. Dazu habe ich einen 
8515 mit 8MHz auf dem STK500. Im Simulator läuft alles korrekt. Nur 
macht der Controller nicht so mit, wie er es soll.
Quarz, 75176 und Controller sind schon getauscht, daran liegt es nicht.
Die Bit’s 0,1 und 2 haben immer 010 als Ergebnis. Also ist das 
Resultat ja keineswegs der wirkliche Wert. Ist da irgendwo einen Fehler 
drin und ich sehe den nicht? Es währe nett wenn da mal einer darüber 
sehen könnte.


; 8515 mit 8MHz

.include "8515def.inc"

.EQU    BlinkOff  = 0b00001100   ;LCD An und Blinken aus
.EQU  LCD_Aus  = 0b00001000   ;LCD Ausschalten
.EQU  LCD_Pos1  = 0b10000000   ;1. Zeile 1pos
.EQU  LCD_Pos2  = 0b11000000   ;2. Zeile 1pos
.EQU  RxD  =0      ;Receive pin ist PD0

.def   temp   = r16
.def   temp1   = r17
.def   temp2   = r18
.def  temp3  = r19
.def  bitcnt  =R20
.def  RXbyte  =R21
.def  adressL =R22
.def  bytecntL=R23
.def  TempL  =R24
.def   Timer  =R25

.org  $000
  rjmp  INIT    ;Program/Reset Handler
.org  INT0addr
  reti      ;External Interrupt0 Vector Address
.org  INT1addr
  reti      ;External Interrupt1 Vector Address
.org  ICP1addr
  reti      ;Input Capture1 Interrupt Vector Address
.org  OC1Aaddr
  reti      ;Output Compare1A Interrupt Vector Address
.org  OC1Baddr
  reti      ;Output Compare1B Interrupt Vector Address
.org  OVF1addr
  reti      ;Overflow1 Interrupt Vector Address
.org  OVF0addr
  reti      ;Overflow0 Interrupt Vector Address
.org  SPIaddr
  reti      ;SPI Interrupt Vector Address
.org  URXCaddr
  reti      ;UART Receive Complete Interrupt Vector Address
.org  UDREaddr
  reti      ;UART Data Register Empty Interrupt Vector Address
.org  UTXCaddr
  reti      ;UART Transmit Complete Interrupt Vector Address
.org  ACIaddr
  reti      ;Analog Comparator Interrupt Vector Address
.org  0x010

init:
  ldi  temp1,High(RamEnd)
  out  sph,temp1
  ldi  temp1,Low(RamEnd)
  out  spl,temp1
  ldi temp1, 0x00
  out DDRA, temp1  ;Port A = Eingang
  out DDRD, temp1     ;Port D = Eingang
  ldi temp1, 0xFF
  out DDRB, temp1     ;Port B = Ausgang
  out DDRC, temp1  ;Port C = Ausgang
  rcall lcd_init     ;Display initialisieren
  rcall lcd_clear    ;Display löschen
loop:

check_reset:  sbis   PIND,Rxd  ;warte auf high
    rjmp   check_reset
   check_1:  clc      ;lösche carry
    sbic   PIND,Rxd  ;warte auf low
    rjmp   check_1
    ldi  TempL,234  ;reset länge 234 @ 8 mhz =88µs
   check_2:  sbic  PIND,Rxd  ;ist pin high
    sec      ;set carryflag
    brcs   check_1  ;nein, es sind daten
    dec  TempL
    brne  check_2  ;warte bis break vorbei ist
    ldi  bytecntL,0  ;reset bytecounter
start:    inc   bytecntL  ;Adresse mitzählen
forever:     sbis  PIND,Rxd  ;end reset und end mark
    rjmp  forever
getdata:  ldi   bitcnt,9  ;8 data bit + 1 start bit
getdata1:  sbic   PIND,RxD  ;warte auf start bit
    rjmp   getdata1
    rcall   delay_half  ;0.5 bit delay verzögern
getdata2:  rcall   delay    ;1 bit delay verzögern
    clc      ;lösche carry
    sbic   PIND,RxD  ;ist RX pin high
    sec      ;setze carry
    dec   bitcnt    ;bitzähler
    breq   getdata3  ;wenn 8 bit gelesen return
      ;else
    ror   RXbyte    ;schiebe carrybit in Rxbyte
    rjmp   getdata2  ;nächstes bit lesen
getdata3:  ;sbic   PIND,RxD  ;ist RX pin high dann ist es stop bit
    rjmp anzeige    ;Wert anzeigen
          ;neuen kanal testen......
    ;rjmp  start    ;neuen Wert lesen
anzeige:  out portb, rxbyte
    mov temp,RXbyte
    rcall bcd
    rjmp loop

von Gralf (Gast)


Lesenswert?

Mensch, da hast Du Dir aber viel Mühe gemacht. Leider bin ich noch neu 
im ASM, daher fällt es mir nicht leicht, Deinen Code zu überprüfen.
Hatte auch schon mal dran gedacht, DMX-Signale auszuwerten. Hätte es 
einfach den UART machen lassen. Der macht das ganze Handling. Du mußt 
dann nur noch den Break auswerten und die Kanäle zählen. In der 
Zwischenzeit ist der µC frei.
Aber nun zu Deinem Problem: Hast Du berücksichtigt, daß das Datenformat 
Start+8Data+2Stop ist? Du hast, glaube ich, nur eines ausgewertet.

Bitte verzeihe, wenn ich Dir damit zu blöd komme und Dir nicht 
weiterhelfen konnte.

von mikki merten (Gast)


Lesenswert?

Der interne UART eignet sich recht gut zum Verarbeiten von DMX-Signalen. 
Die BREAK Erkennung kannst du recht zuverlässig über die Auswertung des 
FE-Errors machen. Das ganze mittels RXC Interrupt und die bleibt noch 
jede Menge Zeit die empfangenen Daten auch auszuwerten und anzuzeigen.

von jornbyte (Gast)


Lesenswert?

Danke für eure Antworten. Wenn das mit der Uart besser gehen soll, habt 
ihr da ein Beispiel? Damit habe ich mich auch Ergebnislos beschäftigt, 
oder ich bin an der Stelle zu Dumm :(

von jornbyte (Gast)


Lesenswert?

Hallo
Das ist mein versuch mit der Uart. Geht aber auch nicht.
Ist da ein Fehler den ich nicht sehe? Wer hat ein Bespiel das auch 
funktioniert? Gibt es eine andere Lösung?
Ich bin für jeden Hinweis offen.

;8515 mit 8MHz

.include "8515def.inc"

.EQU    BlinkOff  = 0b00001100   ;LCD An und Blinken aus
.EQU  LCD_Aus    = 0b00001000   ;LCD Ausschalten
.EQU  LCD_Pos1  = 0b10000000   ;1. Zeile 1pos
.EQU  LCD_Pos2  = 0b11000000   ;2. Zeile 1pos

.equ  STARTBIT =1    ;Start bit flag
.equ  NEWDATA  =2    ;New data flag
.equ  UPPERDA  =3    ;When 1 We are on Current Byte + 256 (IE CB = 10 
then

.def   temp     = r16
.def   temp1     = r17
.def   temp2     = r18
.def  temp3    = r19

.def  BYTE1  =R20      ;bit counter*
.def  RXbyte  =R21      ;Received data*
.def  adressL  =R22      ;adress registe
.def  FLAGT  =R23      ;byte counter low*
.def  TempL  =R24      ;temporary storage register low*
.def   CURRENTBYTE  =R25
.def  Data  =R26

.org  $000
  rjmp  INIT    ;Program/Reset Handler
.org  INT0addr
  reti      ;External Interrupt0 Vector Address
.org  INT1addr
  reti      ;External Interrupt1 Vector Address
.org  ICP1addr
  reti      ;Input Capture1 Interrupt Vector Address
.org  OC1Aaddr
  reti      ;Output Compare1A Interrupt Vector Address
.org  OC1Baddr
  reti      ;Output Compare1B Interrupt Vector Address
.org  OVF1addr
  reti      ;Overflow1 Interrupt Vector Address
.org  OVF0addr
  reti      ;Overflow0 Interrupt Vector Address
.org  SPIaddr
  reti      ;SPI Interrupt Vector Address
.org  URXCaddr
  rjmp  RX_sub    ;UART Receive Complete Interrupt Vector Address
.org  UDREaddr
  reti      ;UART Data Register Empty Interrupt Vector Address
.org  UTXCaddr
  reti      ;UART Transmit Complete Interrupt Vector Address
.org  ACIaddr
  reti      ;Analog Comparator Interrupt Vector Address
.org  0x010      ;Code follows from here


init:
  ldi  temp1,High(RamEnd)
  out  sph,temp1
  ldi  temp1,Low(RamEnd)
  out  spl,temp1

  ldi temp1, 0x00
  out DDRA, temp1     ;Port A = Eingang
  out DDRD, temp1    ;Port D = Eingang
  ldi temp1, 0xFF
  out DDRB, temp1    ;Port B = Ausgang
  out DDRC, temp1     ;Port C = Ausgang

  ldi  TEMPL,0x01  ;set baudrate to 250K (8Mhz xtal)
        out  UBRR,TEMPL
        sbi  UCR,RXEN   ;enable serial recieve interrupts
  sbi  UCR,RXCIE
  sbi  UCR,CHR9   ;enable 9 bit data
  in adressL,pinA     ;Adresse von Port laden
  sei

  rcall lcd_init     ;Display initialisieren
  rcall lcd_clear    ;Display löschen

  ldi temp1, 'D'     ;Zeichen anzeigen
  rcall lcd_data
  ldi temp1, 'a'     ;Zeichen anzeigen
  rcall lcd_data
  ldi temp1, 't'     ;Zeichen anzeigen
  rcall lcd_data
  ldi temp1, ':'     ;Zeichen anzeigen
  rcall lcd_data

loop:
;cli
anzeige:  out portb, data
    mov temp,data
    rcall bcd
       in adressL,pinA  ;Adresse von Port laden
    ;mov temp,adressL
    ;rcall bcd
;sei
    rjmp loop




;******************************************************
RX_sub:

  push  TEMPL
  in  TEMPL,SREG
        push  TEMPL

        in  DATA,UDR
  sbis  UCR,RXB8
  rjmp  NODATA

  ldi  TEMPL,0x00
  cp  TEMPL,CURRENTBYTE
  brne  CURRENTBYTE1
  ldi  TEMPL,0x00
  cp  TEMPL,DATA
  brne  NODATA
  rjmp  ENDR

CURRENTBYTE1:
  cp  CURRENTBYTE,adressL
  brne  ENDR
  mov  BYTE1,DATA
  sbrs  FLAGT,3
  sbr  FLAGT,2
ENDR:
  clc
  inc  CURRENTBYTE
  brbc  1,ENDR1
  sbr  FLAGT,3
ENDR1:
  pop  TEMPL
        out  SREG,TEMP
        pop  TEMPL
        reti
NODATA:
  ldi  TEMPL,0x00
  mov  CURRENTBYTE,TEMPL
  cbr  FLAGT,3
  rjmp  ENDR1


;******************************************************

von Phil (Gast)


Lesenswert?

Hallo,
wenn ich mich nicht irre, ist das doch der Code von Martin Schneebacher, 
oder? Kannst du den nicht vollständig übernehmen und auf den Proz laden 
(vielleicht ein Parr Interruptvektoren ändern), das müsste doch gehen. 
Und dann eben auf das erste byte beschränken.
Viel Erfolg
Phil

von jornbyte (Gast)


Lesenswert?

Das ist der Code von Martin. Nur eben auf einem 1200'er mit 12 MHz, 
dehalb auch die Spielerei mit den Warteschleifen. Aber wie gesagt, ohne 
Erfolg. Die Bits 0, 1 und 2 stehen immer auf 010.

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.