Witam kolegów,
Jak napisałem w temacie mam problem z komunikacja Atmegi162 z czujnikiem ciśnienia i temperatury scp1000-d11. Generalnie problem w tym, że muszę zasymulować I2C bo ATmega162 nie ma sprzętowego, ale do rzeczy.
Próbowałem skorzystać z gotowej biblioteki tutaj i przerobić załączony tam przykład na swoje potrzeby ale niestety nie udało się.
Link do datasheeta scp1000-d11 tutaj. Generalnie próbowałem zrobić to na podstawie przykładu ze strony 27 a kod mojego programu wygląda następująco:
Kody wykorzystywanych funkcji:
Oczywiście w i2cmaster.S pozmieniałem wartości SDA i SCL na PORTE i dostosowałem opóźnienie do 8MHz oscylatora wewnętrznego.
Rezystory podciągające podłączone, na pewno błąd tkwi w moim braku wystarczającej wiedzy na temat I2C.
Środowisko w jakim programuje to WinAVR.
Czy ktoś mógłby naprowadzić mnie na właściwą drogę jak dojść do ładu z transmisją?
Pozdrawiam
Poprawiłem tytuł - regulamin p.11.1
[zumek]
Jak napisałem w temacie mam problem z komunikacja Atmegi162 z czujnikiem ciśnienia i temperatury scp1000-d11. Generalnie problem w tym, że muszę zasymulować I2C bo ATmega162 nie ma sprzętowego, ale do rzeczy.
Próbowałem skorzystać z gotowej biblioteki tutaj i przerobić załączony tam przykład na swoje potrzeby ale niestety nie udało się.
Link do datasheeta scp1000-d11 tutaj. Generalnie próbowałem zrobić to na podstawie przykładu ze strony 27 a kod mojego programu wygląda następująco:
void I2C_SCP1000()
{
unsigned char ret1;
unsigned char ret2;
i2c_init();
i2c_start_wait(0x11+I2C_WRITE); //0x11 to adres urządzenia
i2c_write(0x81); // 0x81 to adres rejestru zawierającego temperaturę (format 14-bit)
i2c_rep_start(0x11+I2C_READ);
ret1 = i2c_readAck();
ret2 = i2c_readNak();
i2c_stop();
//while(1) {PORTC = ~PORTC; _delay_ms(1000);} //tylko do sprawdzenia niestety program nie dochodzi do tego momentu
}
Kody wykorzystywanych funkcji:
;*************************************************************************
; Initialization of the I2C bus interface. Need to be called only once
;
; extern void i2c_init(void)
;*************************************************************************
.global i2c_init
.func i2c_init
i2c_init:
cbi SDA_DDR,SDA ;release SDA
cbi SCL_DDR,SCL ;release SCL
cbi SDA_OUT,SDA
cbi SCL_OUT,SCL
ret
.endfunc
;*************************************************************************
; Issues a start condition and sends address and transfer direction.
; If device is busy, use ack polling to wait until device is ready
;
; extern void i2c_start_wait(unsigned char addr);
; addr = r24
;*************************************************************************
.global i2c_start_wait
.func i2c_start_wait
i2c_start_wait:
mov __tmp_reg__,r24
i2c_start_wait1:
sbi SDA_DDR,SDA ;force SDA low
rcall i2c_delay_T2 ;delay T/2
mov r24,__tmp_reg__
rcall i2c_write ;write address
tst r24 ;if device not busy -> done
breq i2c_start_wait_done
rcall i2c_stop ;terminate write operation
rjmp i2c_start_wait1 ;device busy, poll ack again
i2c_start_wait_done:
ret
.endfunc
;*************************************************************************
; Terminates the data transfer and releases the I2C bus
;
; extern void i2c_stop(void)
;*************************************************************************
.global i2c_stop
.func i2c_stop
i2c_stop:
sbi SCL_DDR,SCL ;force SCL low
sbi SDA_DDR,SDA ;force SDA low
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
rcall i2c_delay_T2 ;delay T/2
cbi SDA_DDR,SDA ;release SDA
rcall i2c_delay_T2 ;delay T/2
ret
.endfunc
;*************************************************************************
; Send one byte to I2C device
; return 0 = write successful, 1 = write failed
;
; extern unsigned char i2c_write( unsigned char data );
; data = r24, return = r25(=0):r24
;*************************************************************************
.global i2c_write
.func i2c_write
i2c_write:
sec ;set carry flag
rol r24 ;shift in carry and out bit one
rjmp i2c_write_first
i2c_write_bit:
lsl r24 ;if transmit register empty
i2c_write_first:
breq i2c_get_ack
sbi SCL_DDR,SCL ;force SCL low
brcc i2c_write_low
nop
cbi SDA_DDR,SDA ;release SDA
rjmp i2c_write_high
i2c_write_low:
sbi SDA_DDR,SDA ;force SDA low
rjmp i2c_write_high
i2c_write_high:
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
rcall i2c_delay_T2 ;delay T/2
rjmp i2c_write_bit
i2c_get_ack:
sbi SCL_DDR,SCL ;force SCL low
cbi SDA_DDR,SDA ;release SDA
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
i2c_ack_wait:
sbis SCL_IN,SCL ;wait SCL high (in case wait states are inserted)
rjmp i2c_ack_wait
clr r24 ;return 0
sbic SDA_IN,SDA ;if SDA high -> return 1
ldi r24,1
rcall i2c_delay_T2 ;delay T/2
clr r25
ret
.endfunc
Oczywiście w i2cmaster.S pozmieniałem wartości SDA i SCL na PORTE i dostosowałem opóźnienie do 8MHz oscylatora wewnętrznego.
Rezystory podciągające podłączone, na pewno błąd tkwi w moim braku wystarczającej wiedzy na temat I2C.
Środowisko w jakim programuje to WinAVR.
Czy ktoś mógłby naprowadzić mnie na właściwą drogę jak dojść do ładu z transmisją?
Pozdrawiam
Poprawiłem tytuł - regulamin p.11.1
[zumek]