Code:
'
' SLAVE-Adresse 100
' nur Daten empfangen möglich/erforderlich --> MASTER-WRITE
' 5 Servos
' Im Feld Daten wird die Nr. des Servo's und dessen Laufrichtung verschlüsselt übergeben
'
'******************************************
Servo1 Alias Portb.1
Servo2 Alias Portb.2
Servo3 Alias Portb.3
Servo4 Alias Portb.4
Servo5 Alias Portb.5
Dim Daten As Byte
Dim I As Byte
$baud = 9600
On Int0 Ext_int0
On Ovf0 Tim0_ovf
Goto Reset
$asm
;***************************************************************************
;* Refers to the application note AVR302 documentation for more
;* detailed description.
;*
;* USAGE
;* Insert user code in the two locations marked "insert user code here".
;*
;* NOTES
;* Minimum one instruction will be executed between each interrupt.
;*
;* STATISTICS
;* Code Size : 160
;* Register Usage : 5 High, 0 Low
;* Interrupt Usage : EXT_INT0 and TIM0_OVF
;* Port Usage : PD4(T0) and PD2(INT0)
;* XTAL : - I2C Fast Mode : min 16.0MHz
;* - I2C Standard Mode : min 3.0MHz
;*
;***************************************************************************
;**** Includes ****
.include "2313def.inc"
;**** Global I2C Constants ****
;.def Devadr = 0x50 ; Slave Device Address geändert
;.def Devadrm = 0x7f ; Slave Multi Address Mask geändert
;.def Pinmaskx = 0x14 ; <=>(1 << Pd4) +(1 << Pd2) geändert
;**** Global Register Variables ****
.def Temp = R16 ; Temporary Variable
.def Etemp = R17 ; Extra Temporary Variable
.def I2cdata = R18 ; I2C Data Register
.def I2cadr = R19 ; I2C Address And Direction Register
.def I2cstat = R20 ; I2C Temporary Sreg Storage
;**** Interrupt Vectors ****
; Anpassung wegen Umstellung von 1200 auf 2313 !!!
; rjmp RESET ;Reset handle
; rjmp EXT_INT0 ;INT0 handle
; rjmp Xxx ;int_1 eingefügt
; rjmp Xxx ;time1_capt eingefügt
; rjmp xxx ;time1_compa eingefügt
; rjmp xxx ;time1_compb eingefügt
; Rjmp Xxx ;Time1_ovfl eingefügt
; rjmp TIM0_OVF ;Timer 0 overflow handle
;
; ( rjmp ANA_COMP ) ; ( Analog comparator handle )
;
;Xxx:
;***************************************************************************
;*
;* INTERRUPT
;* EXT_INT0 / i2c_wakeup
;*
;* DESCRIPTION
;* Detects the start condition and handles the data transfer on
;* the I2C bus.
;*
;* Received data is stored in the r0 register and r0 is transmitted
;* during a master read transfer.
;*
;* NOTE
;* This interrupt code, in some cases, jumps to code parts in the
;* TIM0_OVF / i2c_skip section to reduce code size.
;*
;***************************************************************************
Ext_int0:
in i2cstat,SREG ; store SREG
;*************************
;* Get I2C Slave Address *
;*************************
I2c_get_adr:
ldi i2cadr,1 ; initialize address register
Wlo_ga0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga0
rjmp first_ga
Do_ga:
; Do
Wlo_ga:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga
mov temp,i2cadr ; test address
;orginal andi temp,Devadrm ; mask register full floating bit
andi R16,0x7f ;geändert
;orginal cpi temp,devadr ; if device addressed
;*****************************************************************************
;*****************************************************************************
cpi R16,0x32 ;dig.Adresse (RR&Co) = 100 geändert
;0x32 = binär 0110010 + 0 (R/W-Bit)
;100 = binär 01100100
;*****************************************************************************
;*****************************************************************************
in temp,SREG ; set T flag ("T = Z")
bst temp,1
First_ga:
sec ; set carry
Whi_ga:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ga
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cadr ; shift carry into address register
brcc do_ga ; while register not full
Wlo_ca:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ca
;**** Check Address ****
; if T flag set (device addressed)
brts i2c_adr_ack ; acknowledge address
; else
rjmp i2c_adr_miss ; goto address miss handle
;**** Acknowledge Address ****
I2c_adr_ack:
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_aa:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_aa
;**** Check Transfer Direction ****
lsr i2cadr ; if master write
brcc i2c_master_write; goto master write handle
;*******************************
;* Transmit Data (master read) *
;*******************************
I2c_master_read:
;**** Load Data (handle outgoing data) ****
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than ONE instruction then wait
; states MUST be inserted as shown in description.
mov i2cdata,r0 ; insert data in "serial"
; register (user code example)
sec ; shift MSB out and "floating empty flag" in
rol i2cdata
Wlo_mr:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr
;**** Transmitt data ****
brcc fb_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
rjmp fb_mr ; goto read loop
Fb_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
Fb_mr:
Lsl I2cdata ; If Data Register Not Empty
Loop_mr:
Whi_mr:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr
Wlo_mr2:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr2
brcc b_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
rjmp done_mr ; done
B_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
Done_mr:
Whi_mr2:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr2
Wlo_mr3:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr3
cbi DDRD,DDD2 ; release SDA
;**** Read Acknowledge from Master ****
Whi_ra:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ra
sec ; read acknowledge
sbis PIND,PIND2
clc
brcc i2c_master_read ; if ack transfer (next) data
Wlo_ra:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ra
rjmp i2c_wait_cond ; goto wait condition (rep. start or stop)
;*******************************
;* Receive Data (master write) *
;*******************************
I2c_master_write:
Wlo_mw0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mw0
cbi DDRD,DDD2 ; remove acknowledge from SDA
Whi_mw:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mw
in temp,PIND ; sample SDA (first bit) and SCL
;orginal: andi temp,pinmask
andi R16,0x14 ; mask out SDA and SCL geändert
Do_mw:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask
andi R17,0x14 ; mask out SDA and SCL geändert
cp etemp,temp
breq do_mw ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp receive_data ; goto receive data
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
rjmp i2c_stop ; goto transfer stop
Receive_data:
ldi i2cdata,2 ; set i2cdata MSB to zero
sbrc temp,PIND2 ; if SDA sample is one
ldi i2cdata,3 ; set i2cdata MSB to one
Do_rd:
; Do
Wlo_rd:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_rd
sec ; set carry
Whi_rd:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_rd
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cdata ; shift carry into data register
brcc do_rd ; while register not full
;**** Acknowledge Data ****
I2c_dat_ack:
Wlo_da:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_da
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_da:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_da
; (acknowledge is removed later)
;**** Store Data (handle incoming data) ****
; insert wait states here if nessesary
Sbi Ddrd , Ddd4 ;(start Wait State) aktiviert
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than TWO instruction then wait
; states MUST be inserted as shown in description.
mov r0,i2cdata ; Store data receved in "serial"
; register (user code example)
Gosub Bearbeitung
cbi DDRD,DDD4 ; (end wait state) aktiviert
cbi DDRD,DDD2 ; remove acknowledge from SDA
;Rjmp I2c_master_write ; Start On Next Transfer geändert / nur Datenempfang
rjmp I2c_stop
;***************************************************************************
;*
;* INTERRUPT
;* TIM0_OVF / i2c_skip
;*
;* DESCRIPTION
;* This interrupt handles a "address miss". If the slave device is
;* not addressed by a master, it will not acknowledge the address.
;*
;* Instead of waiting for a new start condition in a "busy loop"
;* the slave set up the counter to count 8 falling edges on SCL and
;* returns from the current interrupt. This "skipping" of data
;* do not occupies any processor time. When 8 egdes are counted, a
;* timer overflow interrupt handling routine (this one) will check
;* the next condition that accure. If it 's a stop condition
;* the transfer ends, if it 's a repeated start condition a jump
;* to the i2c_wakeup interrupt will read the new address. If a new
;* transfer is initiated the "skipping" process is repeated.
;*
;***************************************************************************
Tim0_ovf:
; (timer 0 Overflow Handle )
in i2cstat,SREG ; store SREG
I2c_adr_miss:
;**** Drop Acknowledge ****
Whi_dac:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_dac
Wlo_dac:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_dac
; disable timer 0 overflow interrupt
;orginal: ldi temp,(0<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Timsk , Temp
; enable external interrupt request 0
;orginal: ldi temp,(1<<INT0)
clr temp ; eingefügt
sbr temp,&b01000000 ; geändert
Out Gimsk , Temp
;************************
;* Wait for a Condition *
;************************
I2c_wait_cond:
Whi_wc:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_wc
in temp,PIND ; sample SDA (first bit) and SCL
;orginal:andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_wc:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_wc ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp i2c_skip_byte ; goto skip byte
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
; goto transfer stop
;*************************
;* Handle Stop Condition *
;*************************
I2c_stop:
;! Set INT0 to generate an interrupt on low level,
;! then set INT0 to generate an interrupt on falling edge.
;! This will clear the EXT_INT0 request flag.
;orginal: ldi temp,(0<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Mcucr , Temp
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
Out Sreg , I2cstat ; Restore Sreg
reti ; return from interrupt
;****************
;* Skip byte(s) *
;****************
I2c_skip_byte:
; set counter initial value
ldi temp,-7
Out Tcnt0 , Temp
; enable timer 0 overflow interrupt
;orginal: ldi temp,(1<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Timsk , Temp
; disable external interrupt request 0
;orginal: ldi temp,(0<<INT0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Gimsk , Temp
Out Sreg , I2cstat ; Restore Sreg
reti
;***************************************************************************
;*
;* FUNCTION
;* i2c_init
;*
;* DESCRIPTION
;* Initialization of interrupts and port used by the I2C interface
;* and waits for the first start condition.
;*
;* USAGE
;* Jump to this code directly after a reset.
;*
;* RETURN
;* none
;*
;* NOTE
;* Code size can be reduced by 12 instructions (words) if no transfer
;* is started on the I2C bus (bus free), before the interrupt
;* initialization is finished. If this can be ensured, remove the
;* "Wait for I2C Start Condition" part and replace it with a "sei"
;* instruction.
;*
;***************************************************************************
Reset:
I2c_init:
;**** PORT Initialization ****
; Initialize PD2 (INT0) for open colector operation (SDA in/out)
;orginal: ldi temp,(0<<DDD4)+(0<<DDD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Ddrd , Temp
; Initialize PD4 (T0) for open colector operation (SCL in/out)
;orginal: ldi temp,(0<<PD4)+(0<<PD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Portd , Temp
;**** Interrupt Initialization ****
; Set INT0 to generate an interrupt on falling edge
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
; Enable INT0 -> Freigeben INT0 !!!
clr temp
sbr temp,&b01000000 ;setzt bit 6 des Reg. Gimsk ( = INT0) auf 1 / on
Out Gimsk , Temp
; Set clock to count on falling edge of T0
;orginal: ldi temp,(1<<CS02)+(1<<CS01)+(0<< CS00)
clr temp ; eingefügt
sbr temp,&b00000110 ; geändert
Out Tccr0 , Temp
;***************************************************
;* Wait for I2C Start Condition (13 intstructions) *
;***************************************************
Do_start_w:
; Do
in temp,PIND ; sample SDA & SCL
com temp ; invert
;orginal: andi temp,pinmask ; mask SDA and SCL
andi R16,0x14 ; geändert
brne do_start_w ; while (!(SDA && SCL))
in temp,PIND ; sample SDA & SCL
;orginal: andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_start_w2:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_start_w2 ; while no change
sbrc etemp,PIND2 ; if SDA no changed to low
rjmp do_start_w ; repeat
rcall i2c_get_adr ; call(!) interrupt handle (New transfer)
;***************************************************************************
;*
;* PROGRAM
;* main - Test of I2C slave implementation
;*
;***************************************************************************
Main:
Rjmp Main ; Loop Forever
;**** End of File ****
$end Asm
Bearbeitung:
Daten = Peek(0)
Config Portb = Output
Portb = &B11111111 'alle LED aus
If Daten = 1 Or Daten = 11 Then Gosub Servo_1
If Daten = 2 Or Daten = 12 Then Gosub Servo_2
If Daten = 3 Or Daten = 13 Then Gosub Servo_3
If Daten = 4 Or Daten = 14 Then Gosub Servo_4
If Daten = 5 Or Daten = 15 Then Gosub Servo_5
Return
Servo_1:
If Daten = 11 Then Goto Servo_1_links
'-----------------------------------------------
Servo_1_rechts:
For I = 1 To 18 'nach rechts
Portb.1 = 0
Waitms 20
Portb.1 = 1
Waitms 1
Next I
Portb.1 = 0
Return
Servo_1_links:
For I = 1 To 18 'nach links
Portb.1 = 1
Waitms 20
Portb.1 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_2:
If Daten = 12 Then Goto Servo_2_links
For I = 1 To 18 'nach rechts
Portb.2 = 0
Waitms 20
Portb.2 = 1
Waitms 1
Next I
Portb.2 = 0
Return
Servo_2_links:
For I = 1 To 18 'nach links
Portb.2 = 1
Waitms 20
Portb.2 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_3:
If Daten = 13 Then Goto Servo_3_links
For I = 1 To 18 'nach rechts
Portb.3 = 0
Waitms 20
Portb.3 = 1
Waitms 1
Next I
Portb.3 = 0
Return
Servo_3_links:
For I = 1 To 18 'nach links
Portb.3 = 1
Waitms 20
Portb.3 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_4:
If Daten = 14 Then Goto Servo_4_links
For I = 1 To 18 'nach rechts
Portb.4 = 0
Waitms 20
Portb.4 = 1
Waitms 1
Next I
Portb.4 = 0
Return
Servo_4_links:
For I = 1 To 18 'nach links
Portb.4 = 1
Waitms 20
Portb.4 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_5:
If Daten = 15 Then Goto Servo_5_links
For I = 1 To 18 'nach rechts
Portb.5 = 0
Waitms 20
Portb.5 = 1
Waitms 1
Next I
Portb.5 = 0
Return
Servo_5_links:
For I = 1 To 18 'nach links
Portb.5 = 1
Waitms 20
Portb.5 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Lesezeichen