Code:
.include "m8def.inc"
;***** pin definitions
.equ dmx_in =PD0 ;receive pin is PD0 (RXD)
;.equ zero_crossing_pin=PD2 ;interrupt 0
;***** constants
.equ channels =1
.equ channels_all =1
.equ spi_start_byte =0xfa
.equ spi_stop_byte =0xff
.equ minvalue=0x09 ;Min value of valid DMX Datas -> Switches Stroboscope off
.equ maxvalue=0xF7 ;Max value of valid DMX Datas -> generates optional Single Flash impuls
;***** global register variables
; ZL, ZH, XL and XH used for memory-comtrolling
; R0 used for memory-operations (lpm)
; R1 used as NULL-register
.def tempL =R24 ;temporary storage register
.def tempH =R25 ;
.def temp =R17 ;
.def dmx_byte =R6 ;value of got byte
.def dmx_count_in =R19 ;counter for valid dmx-byte
.def dmx_countL =R20 ;counter for incomming dmx-byte
.def dmx_countH =R21 ;
.def dmx_status =R16 ;status of incomming data
;0x00 -> ok
;0x01 -> wait for reset
;0x02 -> startbyte
;0xff -> dmx fail
.def dmx_adrL =R4 ;set start adress
.def dmx_adrH =R5 ;
.def shadc =R7 ;actual adc value
.def status =R18 ;Bit0=single Shot
.def actvalue =R9 ;actuell dmx value
;.def currentL =R22 ;data
;.def currentH =R23 ;data
.def led_count =R10 ;counter
.def shdmxbyte =R8
;.def spi_count =R28
.def timer_matchL =R11
.def timer_matchH =R12
.def shUCSRA =R13
;****set interrupt-routines
.org 0
rjmp reset ;general reset
reti ;ext. int.0
reti ;ext. int.1
reti ;timer2 copare match
rjmp stopflash ;timer2 overflow
reti ;timer 1 capture event
rjmp compare ;timer1 compare match A
reti ;timer1 compare match B
reti ;timer1 overflow interrupt
reti ;timer0 overflow interrupt
reti ;spi complete
rjmp get_byte ;uart rx complete
reti ;uart data register empty
reti ;uart tx complete
rjmp adcready ;adc conversion complete
reti ;eeprom ready
reti ;analog comperator
reti ;Two-wire serial interface
reti ;Store Programm Memory ready
reset:
cli
;***** set stackpointer
ldi tempL, low(RAMEND)
ldi tempH, high(RAMEND)
out SPL,tempL
out SPH,tempH
;***** initial adc
ldi tempL,0b11100101 ;adc init ADC ein, Port 5 Interne Referenz
out ADMUX,tempL
ldi tempL,0b11011111 ;ADC start Conversation CK/128 Interrupt enabled
out ADCSRA,tempL
;***** initial portd
ldi tempL,0b11111100 ;Pull up resistors on PD 4..7 high Port 2+3 high
out PORTD,tempL
ldi tempL,0b00001100 ;init port d high Adress
out DDRD,tempL
;***** initial portb
ldi tempL,0b00000000 ;init port b low Adress
out DDRB,tempL
ldi tempL,0b00111111 ;Pull up resistors on
out PORTB,tempL
;***** initial portc
ldi tempL,0b00000000 ;init port c Bit 0 Signal out, Bit 1 DMXLED
out DDRC,tempL
ldi tempL,0b00000000
out PORTC,tempL
;***** initial var
ldi tempL,0x00 ;set R1 to NULL
mov R1,tempL ;
;***** initial timer 0 - not used
; ldi tempL,0b00000001 ;set timer0 to ck
; out TCCR0,tempL ;
;***** initial timer 1
ldi tempL,0b00000000 ;set timer1 to normal function
out TCCR1A,tempL
ldi tempL,0b00000101 ;set timer 1 to clk/1024
out TCCR1B,tempL
ldi tempL,0x00 ;set timer value to 0
out TCNT1H,templ
out TCNT1L,templ
LDI templ,0xFF
out OCR1AH,templ ;set copare match A register to FF hex
out OCR1AL,templ
ldi templ,0b00000000 ;disable Timer 1 A compare match Interrupt
out timsk,templ
;***** initial timer 2
ldi tempL,0b00000011 ;set timer1 to normal function, clk/32
out TCCR2,tempL
ldi tempL,0x00 ;set timer value to 0
out TCNT2,templ
ldi templ,0b00000000 ;disable Timer 2 overflow Interrupt
out timsk,templ
;***** initial var
rcall start_adress ;get start adress
ldi dmx_countL,0x00 ;reset counter
ldi dmx_countH,0x00 ;
ldi dmx_count_in,0x00 ;
;***** initial UART
ldi tempL,0x01 ;set UART to 250 kbaud @ 8mhz
clr tempH
out UBRRL,tempL ;
out UBRRH,temph
ldi tempL,0b00000000 ;set UART to 8 bit
out UCR,tempL ;
sbi UCSRB,RXEN ;enable UART receiver
ldi dmx_status,0x01 ;set dmx-status byte to 'wait for reset'
in dmx_Byte,UDR ;clear UART receive interrupt flag
cbi UCSRA,FE ;clear frame error flag
sbi UCSRB,RXCIE ;enable UART receive interrupt
;***** start working...
sei ;enable global interrupt
main:
rcall start_adress
clr temp
mov templ,dmx_adrL
mov temph,dmx_adrH
CLC
cp temp,templ
cpc temp,temph
brne main2
rcall adcmode
main2: rjmp main
adcmode:
mov temp,shadc
LDI zl,low(timetable*2) ;Timerwerte aus Tabelle auslesen
LDI zh,high(timetable*2)
ADD zl,temp
ADC zh,R1
ADD zl,temp
ADC zh,R1
LPM R0,Z+
MOV timer_matchH,R0 ;
LPM R0,Z
MOV timer_matchL,R0
OUT OCR1AH,timer_matchH
OUT OCR1AL,timer_matchL
IN temp,TIMSK
ORI temp,0b01010000 ;Timer 1 Compare Interrupt einschalten
OUT TIMSK,temp
ret
;***************************************************************************
;*
;* initiate a flash pulse
;*
;***************************************************************************
flash:
push temp
in temp,SREG
push temp
cbi portd,3 ;start Flash puls
LDI temp,0b11011111 ;Start ADC
OUT ADCSRA,temp
LDI temp,0x00
out TCNT1H,temp ;Clear Timer 1
out TCNT1L,temp
out TCNT2,temp ;Counter 2 to Startvalue
LDI temp,0b01010000 ;delete Overflow Flag, delete Timer 1 Compare A
out TIFR,temp
IN temp,TIMSK ;Couter 2 Overflow enable
ORI temp,0b01000000
OUT TIMSK,temp
pop temp
out SREG,temp
pop temp
ret
;***************************************************************************
;*
;* Timer 2 Overflow Interrupt to stop Fashpulse
;*
;***************************************************************************
stopflash:
push temp ;save Registers
in temp,SREG
push temp
SBI portd,3 ;Stop Flash Pulse
IN temp,TIMSK ;Disable timer2 Overflow Interrupt
ANDI temp,0b10111111
OUT TIMSK,temp
pop temp
out SREG,temp
pop temp
reti
;***************************************************************************
;*
;* compare match A timer 1 interrupt
;*
;***************************************************************************
compare:
push temp
IN temp,SREG
push temp
; Timer set routine
ldi ZH,high(timetable*2) ;set Z-pointer to Ttimetable adress
ldi ZL,low(timetable*2) ;
add ZL,shdmxByte ;Set offset in Timetable
adc ZH,R1 ;
add ZL,shdmxByte
adc ZH,R1
LPM R0,Z+ ;Readout compare Match Values
MOV timer_matchH,R0 ;
LPM R0,Z
MOV timer_matchL,R0
OUT OCR1AH,timer_matchH ;Set compare Match A
OUT OCR1AL,timer_matchL
; Timer set routine end
rcall flash
pop temp
OUT SREG,temp
pop temp
reti
;***************************************************************************
;*
;* get dmx-byte from uart-data-register
;*
;***************************************************************************
get_byte:
push temp
in temp,SREG
push temp
push tempL
push tempH
in shUCSRA,UCSRA ;UCSRA is cleared when reading UDR !
in dmx_Byte,UDR
sbrc shUCSRA,3 ;check for overrun -> reset
rjmp overrun
sbrc shUCSRA,4 ;check for receive error -> reset
rjmp frame_error
cpi dmx_status,0x01 ;wait for reset?
brne get_bytea
rjmp ret1 ;return
get_bytea:
CLC
cp dmx_countL,R1 ;startbyte?
cpc dmx_countH,R1 ;
breq startbyte
CLC
cp dmx_countL,dmx_adrL ;compare adress and bytenumber low-byte
cpc dmx_countH,dmx_adrH ; high-byte
brlo return
breq first
next_t: cpi dmx_count_in,channels_all;if maximal channel reached
brsh return
startbyte:
cp dmx_Byte,R1 ;startbyte=0
breq firstl
rjmp overrun ;wait for next reset-cycle
firstl:
rjmp return
first:
inc dmx_count_in
ldi temp,minvalue
MOV shdmxbyte,dmx_Byte ;Mov Actual DMX Value into Shadow Register
cp dmx_Byte,temp ;DMX Wert unter minimalwert Timer 1 aus
brcc first1
in temp,TIMSK
ANDI temp,0b11101111 ;Clear Compare Match A Mask
out TIMSK,temp
CBR status,0b00000001 ;Clear single flash sign if set
rjmp return
first1:
sbic pinb,5 ;Switch single Flash/ continious Flash at Higher Values
rjmp first2
ldi temp,maxvalue ;Input > maxvalue -> single Flash is generated
cp dmx_Byte,temp
brcs first2
in temp,TIMSK
ANDI temp,0b11101111
out TIMSK,temp ;Stop Timer 2 Compare A
sbrs status,0
rcall flash
sbr status,0b00000001
rjmp return
first2:
IN temp,TIMSK
ORI temp,0b01010000 ;Timer 1 Compare Interrupt einschalten
OUT TIMSK,temp
CBR status,0b00000001 ;Clear Single Flash sign if set
return: inc dmx_countL ;set adress to next channel
brne ret1
inc dmx_countH
ret1:
pop tempH
pop tempL
pop temp
out SREG,temp
pop temp
reti
frame_error:
ldi temp,0x10 ;For flashing LED on received Frame
inc led_count
cp led_count,temp
brcs ledoff
cbi portd,2
ldi temp,0x20
cp led_count,temp
brcs ledon
clr led_count
ledoff: sbi portd,2
ledon:
ldi dmx_countL,0x00 ;reset counter
ldi dmx_countH,0x00
ldi dmx_count_in,0x00
ldi dmx_status,0x00 ;set status byte to 'ok'
cbi UCSRA,FE ;clear frame-error flag
rcall start_adress ;get adress
pop tempH
pop tempL
pop temp
out SREG,temp
pop temp
reti
overrun:
ldi dmx_status,0x01 ;set status byte to 'wait for reset'
pop tempH
pop tempL
pop temp
out SREG,temp
pop temp
reti ;return
;***************************************************************************
;*
;* ADC new Value
;*
;***************************************************************************
adcready:
PUSH tempL
IN tempL,SREG
PUSH tempL
in shadc,ADCH
POP tempL
OUT SREG,tempL
POP tempL
reti
;***************************************************************************
;*
;* get start adress
;*
;***************************************************************************
start_adress:
in tempL,pinb ;get 5 LOW DMX Adress bits
andi tempL,0b00011111 ;Filter low byte
in temp,pind ;get 4 HIGH DMX Adress bits
andi temp,0b11110000 ;Filter high byte
ldi tempH,0xFF ;prepare tempH for High Adress
clc ;Carry Flag löschen
rol temp ;Shift MSB into carry
rol tempH ;Shift Carry into tempH
or tempL,temp ;combine to compete Low DMX Adress
com tempL ;Invert adress bits
com tempH
mov dmx_adrL,tempL ;Transfer to DMX adress registers
mov dmx_adrH,tempH ;
ret
.cseg
timetable:
.dw 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x20F4,0xA7DD,0xEDCA,0x15BB,0x80AD,0xBBA1,0x6F97
.dw 0x588E,0x4486,0x0A7F,0x8978,0xA672,0x4D6D,0x6A68,0xF063,0xD15F,0x045C,0x7E58,0x3955,0x2E52,0x574F,0xAE4C,0x304A
.dw 0xD947,0xA545,0x9243,0x9B41,0xC03F,0xFE3D,0x533C,0xBE3A,0x3C39,0xCC37,0x6E36,0x1F35,0xE033,0xAE32,0x8A31,0x7130
.dw 0x642F,0x622E,0x6A2D,0x7B2C,0x952B,0xB82A,0xE329,0x1629,0x5028,0x9027,0xD726,0x2526,0x7825,0xD024,0x2E24,0x9123
.dw 0xF922,0x6622,0xD721,0x4C21,0xC520,0x4220,0xC31F,0x471F,0xCE1E,0x591E,0xE71D,0x781D,0x0C1D,0xA31C,0x3C1C,0xD81B
.dw 0x761B,0x171B,0xBA1A,0x5F1A,0x071A,0xB019,0x5C19,0x0919,0xB818,0x6918,0x1C18,0xD017,0x8617,0x3E17,0xF716,0xB216
.dw 0x6E16,0x2B16,0xEA15,0xAA15,0x6B15,0x2E15,0xF214,0xB714,0x7D14,0x4414,0x0C14,0xD513,0xA013,0x6B13,0x3713,0x0413
.dw 0xD212,0xA112,0x7112,0x4112,0x1312,0xE511,0xB811,0x8B11,0x6011,0x3511,0x0B11,0xE110,0xB810,0x9010,0x6910,0x4210
.dw 0x1C10,0xF60F,0xD10F,0xAC0F,0x880F,0x640F,0x420F,0x1F0F,0xFD0E,0xDC0E,0xBB0E,0x9A0E,0x7A0E,0x5A0E,0x3B0E,0x1D0E
.dw 0xFE0D,0xE00D,0xC30D,0xA60D,0x890D,0x6D0D,0x510D,0x350D,0x1A0D,0xFF0C,0xE50C,0xCB0C,0xB10C,0x970C,0x7B0C,0x650C
.dw 0x4D0C,0x340C,0x1C0C,0x050C,0xED0B,0xD60B,0xBF0B,0xA90B,0x930B,0x7C0B,0x670B,0x510B,0x3C0B,0x270B,0x120B,0xFE0A
.dw 0xE90A,0xD50A,0xC10A,0xAE0A,0x9A0A,0x870A,0x740A,0x610A,0x4F0A,0x3C0A,0x2A0A,0x180A,0x060A,0xF509,0xE309,0xD209
.dw 0xC109,0xB009,0x9F09,0x8F09,0x7E09,0x6E09,0x5E09,0x4E09,0x3E09,0x2F09,0x1F09,0x1009,0x0109,0xF208,0xE308,0xD408
.dw 0xC608,0xB808,0xA908,0x9B08,0x8D08,0x7F08,0x7108,0x6408,0x5608,0x4908,0x3C08,0x2F08,0x2208,0x1508,0x0808,0xFB07
.dw 0xEF07,0xE207,0xD607,0xCA07,0xBD07,0xB107,0xA607,0x9A07,0x8E07,0x8207,0x7707,0x2107,0x1507,0x0A07,0xFF06,0xA906
.dw 0x9E06,0x9306,0x8806,0x3306,0x2806,0x1E06,0x1306,0xBE05,0xB405,0xA905,0x9F05,0x4A05,0x4005,0x3605,0x2C05,0x2005
Äh ein Hardwarefehler, wie eine vertauschte + / - Leitung auf der RS485 Schnittstelle kann es nicht sein ?
Lesezeichen