Code:
kompasmodul cmps03 auslesen mit dieser routine,funktioniert 100%:
int main (void)
{
char s[10];
uint16_t wert_1;
uint8_t buffer_r[4];
usart_init( (READ + WRITE) , READ);
i2cInit(100000);
for (;;) {
i2cMemRead(192, 0, buffer_r, 4);
wert_1=buffer_r[2]*256;
wert_1=wert_1+buffer_r[3]; // wert_1 ist gradzahl * 10
itoa( wert_1, s, 10);
usart_writeString(s);
usart_writeString("\r");
warte(20000);
}
}
i2c-eeprom 24c256 beschreiben und lesen geht 100%,
5 werte werden geschrieben und ausgelesen an adresse 26777:
int main(void)
{
lcd_init(LCD_DISP_ON);
lcd_clrscr();
i2cInit(100000);
uint8_t output[8];
uint8_t buffer_w [8];
uint8_t buffer_r [8];
uint8_t i;
buffer_w [0] = 77;
buffer_w [1] = 76;
buffer_w [2] = 75;
buffer_w [3] = 74;
buffer_w [4] = 73;
i2cMemWrite(0xA0, 26777, buffer_w, 5, 0);
warte(2000);
i2cMemRead(0xA0, 26777, buffer_r, 5);
for (i = 0; i < 5; i++) {
itoa(buffer_r[i],output,10);
lcd_puts(output);
lcd_putc(' ');
warte(2000);
}
}
die i2c.h :
#include <avr/io.h>
#include <compat/twi.h>
#ifndef i2c_H
#define i2c_H
#ifdef XTAL
#define TWI_TWBR(baudrate) (uint8_t)(((XTAL + baudrate -1) / baudrate - 15.0) / 2.0)
#else
#define TWI_TWBR(baudrate) (uint8_t)(((8000000 + baudrate -1) / baudrate - 15.0) / 2.0)
#endif
#define i2cInit(baudrate) {TWBR = TWI_TWBR(baudrate);}
// follow functions retuns always i2cStatus() == TWSR == TWI Status register
extern uint8_t i2cStart(void);
extern uint8_t i2cStop(void); // deactivate TWI !!
extern uint8_t i2cStatus(void); // returns TWSR status register
extern uint8_t i2cWait(void); // same as i2cStatus() but wait for current action ready
extern uint8_t i2cWrite(uint8_t Value);
// resceive a byte, returns resceived Byte, transmit acknowledge dependend of Ack
extern uint8_t i2cRead(uint8_t Ack);
// select EEPROM with hardware address Device, setup memory address to Address, and if Wait != 0 waits eventually for prior
// written bytes to finish. returns != 0 if all operations success, otherwise returns 0.
extern uint8_t i2cMemSelect(uint8_t Device, uint16_t Address, uint8_t Wait);
// write from Source, Count bytes to memory location at Address on EEPROM Device. If FlashStored != 0 Source points to
// programmemory. Returns count of succesfully bytes written.
extern uint16_t i2cMemWrite(uint8_t Device, uint16_t Address, const uint8_t *Source, uint16_t Count, uint8_t FlashStored);
// read from EEPROM Device at memory location Address Count bytes to Dest. Returns count of successfully bytes read.
extern uint16_t i2cMemRead(uint8_t Device, uint16_t Address, const uint8_t *Dest, uint16_t Count);
#endif
die i2c.S, asm routine :
nolist
#include <avr/io.h>
#include <compat/twi.h>
.list
#ifndef EEPROM_ADDRESS_BYTES
#define EEPROM_ADDRESS_BYTES 2 // set to 1 for 1 byte memory address
#endif
#ifndef EEPROM_PAGE_SIZE
#define EEPROM_PAGE_SIZE 64 // page size of I2C eeprom chip
#endif
#define EERPOM_PAGE_MASK EEPROM_PAGE_SIZE -1
#define SANITY_CHECKS 1 // activate some sanity checks, set to 0 to save 12 bytes
#define FAST_READ 1 // activate buffering of current memory address
// ATTENTION! this can work if only one I2C eeprom chip is connected
#define P0L r24
#define P0H r25
#define P1L r22
#define P1H r23
#define P2L r20
#define P2H r21
#define P3L r18
#define P3H r19
#define P4L r16
#define P4H r17
#define TMP r0
#define ZERO r1
.macro out_ port value
.if (_SFR_IO_ADDR(\port) > 63)
sts \port, \value
.else
out _SFR_IO_ADDR(\port), \value
.endif
.endm
.macro in_ value port
.if (_SFR_IO_ADDR(\port) > 63)
lds \value, \port
.else
in \value, _SFR_IO_ADDR(\port)
.endif
.endm
.section .text
.global i2cStart // uint8_t i2cStart(void);
.global i2cWait // uint8_t i2cWait(void);
.global i2cStatus // uint8_t i2cStatus(void);
.global i2cWrite // uint8_t i2cWrite(uint8_t Value);
.global i2cStop // uint8_t i2cStop(void);
.global i2cRead // uint8_t i2cRead(uint8_t Ack);
i2cStart: ldi P0L, (1 << TWEN) | (1 << TWINT) | (1 << TWSTA)
i2cStart1: out_ TWCR, P0L
i2cWait: in_ P0L, TWCR
sbrs P0L, TWINT
rjmp i2cWait
i2cStatus: in_ P0L, TWSR
andi P0L, 0xF8
cp P0L, P0H // P0H hidden parameter to save some code
ldi P0H, 0 // P0H = 0, zeroize result, but preserve flags !
ret
i2cWrite: out_ TWDR, P0L
ldi P0L, (1 << TWEN) | (1 << TWINT)
rjmp i2cStart1
i2cStop: ldi P0L, (1 << TWEN) | (1 << TWINT) | (1 << TWSTO)
out_ TWCR, P0L
ldi P0L, 14 // small wait loop before deactivation of TWI
i2cStop1: dec P0L
brne i2cStop1
out_ TWCR, P0L // P0L already 0
rjmp i2cStatus
i2cRead: tst P0L
breq i2cRead1
ldi P0L, (1 << TWEA)
i2cRead1: ori P0L, (1 << TWEN) | (1 << TWINT)
out_ TWCR, P0L
rcall i2cWait
in_ P0L, TWDR
ret
// 56 bytes
#if FAST_READ == 1
.section .data
i2cAddress: .word 0xFFFF
#endif
.section .text
.global i2cMemSelect // uint8_t i2cMemSelect(uint8_t Device, uint16_t Address, uint8_t Wait);
.global i2cMemWrite // uint16_t i2cMemWrite(uint8_t Device, uint16_t Address, uint16_t Source, uint16_t Count, uint8_t FlashStored);
.global i2cMemRead // uint16_t i2cMemRead(uint8_t Device, uint16_t Address, uint16_t Dest, uint16_t Count);
i2cMemSelect: // P0 Device, P1 Address, P2 Wait
mov TMP, P0L // save device
clt // T flag == wait state
tst P2L
breq i2cMemSelect2
i2cMemSelect1:
set
i2cMemSelect2:
rcall i2cStop
rcall i2cStart
mov P0L, TMP // device
andi P0L, 0xFE
ldi P0H, TW_MT_SLA_ACK
rcall i2cWrite
breq i2cMemSelect3
brts i2cMemSelect2 // wait until ready
rjmp i2cMemSelect4
i2cMemSelect3:
#if FAST_READ == 1
sts i2cAddress +0, P1L
sts i2cAddress +1, P1H
#endif
#if EEPROM_ADDRESS_BYTES == 2
mov P0L, P1H // hi(Address)
ldi P0H, TW_MT_DATA_ACK
rcall i2cWrite
brne i2cMemSelect5
#endif
mov P0L, P1L // lo(Address)
ldi P0H, TW_MT_DATA_ACK
rcall i2cWrite
breq i2cMemSelect5
i2cMemSelect4:
ldi P0L, 0 // result = 0
i2cMemSelect5:
ret
i2cMemWrite: // P0 Device, P1 Address, P2 Source, P3 Count, P4 FlashStored
movw ZL, P2L // Z = Source
movw P2L, P3L // Result = Count
#if SANITY_CHECKS != 0
cp P3L, ZERO // sanity check of input count > 0
cpc P3H, ZERO
breq i2cMemWrite8 // Count == 0 ??
#endif
mov TMP, P0L // save Device
clt // clear wait flag for i2cMemSelect
rjmp i2cMemWrite2
i2cMemWrite1:
mov P4H, P1L
andi P4H, EERPOM_PAGE_MASK
brne i2cMemWrite3 // (Address & 0x1F) != 0 ??
i2cMemWrite2:
rcall i2cMemSelect2
brne i2cMemWrite6
set // set wait flag for i2cMemSelect
i2cMemWrite3:
tst P4L
breq i2cMemWrite4 // if FlashStored == 0 goto load from RAM
lpm P0L, Z+
rjmp i2cMemWrite5
i2cMemWrite4:
ld P0L, Z+
i2cMemWrite5:
ldi P0H, TW_MT_DATA_ACK
rcall i2cWrite
brne i2cMemWrite6 // error on write data ??
subi P1L, lo8(-1) // Address++
sbci P1H, hi8(-1)
subi P3L, lo8(+1) // Count--
sbci P3H, hi8(+1)
brne i2cMemWrite1 // Count > 0 ??
rcall i2cMemSelect2 // wait for finishing writing to eeprom
i2cMemWrite6:
rcall i2cStop
i2cMemWrite7:
sub P2L, P3L
sbc P2H, P3H
#if FAST_READ == 1
lds P3L, i2cAddress +0
lds P3H, i2cAddress +1
add P3L, P2L
adc P3H, P2H
sts i2cAddress +0, P3L
sts i2cAddress +1, P3H
#endif
i2cMemWrite8:
movw P0L, P2L // return(Start Count - Current Count)
ret
i2cMemRead: // P0 Device, P1 Address, P2 Dest, P3 Count
movw ZL, P2L // Z = Dest
movw P2L, P3L // Result = Count
#if SANITY_CHECKS != 0
cp P3L, ZERO // sanity check of input count > 0
cpc P3H, ZERO
breq i2cMemWrite8
#endif
mov TMP, P0L // save device
#if FAST_READ == 1
lds P0H, i2cAddress +0
cp P1L, P0H
lds P0H, i2cAddress +1
cpc P1H, P0H
breq i2cMemRead1
#endif
rcall i2cMemSelect1 // setup address
brne i2cMemWrite6
i2cMemRead1:
rcall i2cStart
mov P0L, TMP
ori P0L, 1
ldi P0H, TW_MR_SLA_ACK
rcall i2cWrite
brne i2cMemWrite6
i2cMemRead2:
ldi P0L, 1 // Ack
ldi P0H, TW_MR_DATA_ACK
cpi P3L, 1
cpc P3H, ZERO
brne i2cMemRead3 // Count <> 1 ??
ldi P0L, 0 // No Ack for least byte read to activate power save mode
ldi P0H, TW_MR_DATA_NACK
i2cMemRead3:
rcall i2cRead
brne i2cMemWrite6
st Z+, P0L
subi P3L, lo8(+1) // Count--
sbci P3H, hi8(+1)
brne i2cMemRead2 // Count > 0 ??
rjmp i2cMemWrite6
// 160 bytes
#undef I2C_TWCR
#undef I2C_TWSR
#undef I2C_TWDR
#undef EEPROM_PAGE_SIZE
#undef EERPOM_PAGE_MASK
#undef EEPROM_ADDRESS_BYTES
#undef P0L
#undef P0H
#undef P1L
#undef P1H
#undef P2L
#undef P2H
#undef P3L
#undef P3H
#undef P4L
#undef P4H
#undef TMP
#undef ZERO
.end
Lesezeichen