;**************************************************************************** ;**************************************************************************** ;* I2C slave CPU c2012 by Vladislav Shapovalov * ;* CPU: ATtiny2313 * ;* Clock: INT 8 MHz 3dfilm@mail.ru * ;!!!!!!!!!!!!! SCL DDR and PORT are ALWAYS =1 !!!!!!!!!!!!!!!!! * ;!!!!!!!!!!!!! SDA PORT are ALWAYS =1 !!!!!!!!!!!!!!!!! * ;**************************************************************************** ;**************************************************************************** .include "tn2313def.inc" .include "avr.inc" .equ MySlaveAddress = 0xAC .equ DDR_I2C = DDRB .equ PORT_I2C = PORTB .equ PIN_I2C = PINB .equ SCL = 7 ;!!!!!!!!!!!!!SCL DDR and PORT are ALWAYS =1 !!!!!!!!!!!!!!!!! .equ SDA = 5 ;!!!!!!!!!!!!!SDA PORT are ALWAYS =1 !!!!!!!!!!!!!!!!! .equ Flag = GPIOR1 .equ I2Cadr = 7 .equ I2Crw = 6 ;Read=1 .equ I2CsubAddr = 5 ;WriteSubAddr=1 .equ I2Cask = 4 ;=========================================================; .dseg .org SRAM_START ;RAMTOP I2CsubAddrBuf: .byte 1 ;**************************************************************************************** ;----------------------------------------------------------; .cseg .ORG 0 RJMP RESET .ORG USI_STARTaddr ;USI_STRaddr rjmp StartCondition .ORG USI_OVFaddr rjmp I2CdataRX ;----------------------------------------------------------; StartCondition: push AL in AL,SREG push AL cbi DDR_I2C,SDA outi Flag,0 sbic PIN_I2C,SCL ;Wait for SCL to go low to ensure the "Start Condition" has completed. rjmp PC-1 outi USICR,(1<<USISIE)|(1<<USIOIE)|(1<<USIWM1)|(1<<USIWM0)|(1<<USICS1) outi USISR,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF) pop AL out SREG,AL pop AL reti ;----------------------------------------------------------; I2CdataRX: pushw Y pushw A in AL,SREG push AL in AH,USIDR sbis Flag,I2Cadr rjmp CheckAddress sbis Flag,I2Crw rjmp WriteData ;------------------------------------ ;ReadData: sbis Flag,I2Cask rjmp ReadData1 sbis Flag,I2CsubAddr rjmp Ask0 cpi AH,0 brne ResetUSI ;NACK PutData: cbi Flag,I2Cask lds YL,I2CsubAddrBuf clr YH addiw Y,SRAM_START ld AL,Y+ out USIDR,AL subiw Y,SRAM_START sts I2CsubAddrBuf,YL sbi DDR_I2C,SDA ;Set SDA as output ldi AL,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF) rjmp I2CdataRX_outAL Ask0: sbi Flag,I2CsubAddr rjmp PutData ReadData1: sbi Flag,I2Cask cbi DDR_I2C,SDA ;Set SDA as input outi USIDR,0 ;Prepare ACK rjmp I2CdataRX_out7E ;------------------------------------ WriteData: sbis Flag,I2Cask rjmp WriteData0 cbi Flag,I2Cask cbi DDR_I2C,SDA ldi AL,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF) rjmp I2CdataRX_outAL ResetUSI: cbi DDR_I2C,SDA outi Flag,0 outi USICR,(1<<USISIE)|(1<<USIWM1)|(0<<USIWM0)|(1<<USICS1); ;Start Condition Interrupt;Set USI in Two-wire mode;Clock Source = External, positive edge */ \ ldi AL,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC) ;Clear all flags, except Start Cond rjmp I2CdataRX_outAL WriteData0: sbic Flag,I2CsubAddr rjmp DoData ;Save SubAddress sts I2CsubAddrBuf,AH sbi Flag,I2CsubAddr sbi Flag,I2Cask rjmp Send_ASK DoData: lds YL,I2CsubAddrBuf clr YH addiw Y,SRAM_START st Y+,AH subiw Y,SRAM_START sts I2CsubAddrBuf,YL sbi Flag,I2Cask rjmp Send_ASK ;--------------------------------- CheckAddress: bst AH,0 cbr AH,1 cpi AH,MySlaveAddress brne ResetUSI ldi AL,(1<<I2Cadr)|(1<<I2Cask) bld AL,I2Crw out Flag,AL Send_ASK: outi USIDR,0 sbi DDR_I2C,SDA I2CdataRX_out7E: ldi AL,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(0x0E<<USICNT0) I2CdataRX_outAL: out USISR,AL pop AL out SREG,AL popw A popw Y reti ;----------------------------------------------------------; RESET: outi SPL,low(RAMEND) outi DDRD, 0xFF outi PORTD,0 outi DDRB, 0b00000000+(1<<SCL) outi PORTB,0b00000000+(1<<SCL)+(1<<SDA) ;Port 1=OUTputs sbi ACSR,ACD ;disable AnalogCoparator outi MCUCR,(1<<SE) ;Sleep On///Power-Down Mode ldiw X,I2CsubAddrBuf ldi AL,1 st X+,AL inc AL cpi AL,120 brlo PC-3 ;I2Cinit: outi USICR,(1<<USISIE)|(1<<USIWM1)|(0<<USIWM0)|(1<<USICS1) ;| ;Start Condition Interrupt;Set USI in Two-wire mode;Clock Source = External, positive edge */ \ outi USISR,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC) ;Clear all flags outi Flag,0 sei MainLoop: sleep WDR rjmp MainLoop