Działający kod pod Xmegi:
Kod:
///////////////////////////////////////////////////////////////////////////////////////////////////
// procedury do obslugi komunikacji poprzez TWI
///////////////////////////////////////////////////////////////////////////////////////////////////
#define CLK_XMEGA 32000000 //zegar procesora
#define CLK_TWI 100000 //zegar dla TWI
volatile u8 twic_result; //wynik ostatniego dzialania na TWI
///////////////////////////////////////////////////////////////////////////////////////////////////
// TWI - MASTER
///////////////////////////////////////////////////////////////////////////////////////////////////
// TWI_MASTER_cat_RLA_offset = 0x00 // Control Register A
// TWI_MASTER_cat_RLB_offset = 0x01 // Control Register B
// TWI_MASTER_cat_RLC_offset = 0x02 // Control Register C
// TWI_MASTER_STATUS_offset = 0x03 // Status Register
// TWI_MASTER_BAUD_offset = 0x04 // Baurd Rate Control Register
// TWI_MASTER_ADDR_offset = 0x05 // Address Register
// TWI_MASTER_DATA_offset = 0x06 // Data Register
// TWI_SLAVE_cat_RLA_offset = 0x00 // Control Register A
// TWI_SLAVE_cat_RLB_offset = 0x01 // Control Register B
// TWI_SLAVE_STATUS_offset = 0x02 // Status Register
// TWI_SLAVE_ADDR_offset = 0x03 // Address Register
// TWI_SLAVE_DATA_offset = 0x04 // Data Register
// TWI_SLAVE_ADDRMASK_offset = 0x05 // Address Mask Register
// TWI_cat_RL_offset = 0x00 // TWI Common Control Register
// TWI_MASTER_offset = 0x0001 // TWI master module
// TWI_SLAVE_offset = 0x0008 // TWI slave module
///////////////////////////////////////////////////////////////////////////////////////////////////
#define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5) //macro dla twi baud
#define TWI_OK 0 //all OK
#define TWI_ACK 1 //ACK
#define TWI_NACK 3 //no ACK
#define TWI_RIF 4 //flag RIF
#define TWI_BUSERR 5 //bus error
#define TWI_ARBLOST 6 //bus arbitration is lost
///////////////////////////////////////////////////////////////////////////////////////////////////
// Inicjowanie interfejsu TWIC, I2C na C0-SDA, C1-SCL
void twic_master_init( void )
{
//konfiguracja pinow dla TWI_C
PORTC.OUTSET=0b00000011; // ustaw stan pinow na wysoki
PORTC.DIRSET=0b00000011; // SDA, SCL as outputs
PORTC.PIN0CTRL=PORT_SRLEN_bm | PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
PORTC.PIN1CTRL=PORT_SRLEN_bm | PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc;
TWIC.MASTER.BAUD = TWI_BAUD(CLK_XMEGA,CLK_TWI); //(32M/(2*100k)-5) częstotliwość twi 100 kHz
TWIC.CTRL = 0; //SDHOLD, EDIEN - clear common register
TWIC.MASTER.CTRLB = TWI_MASTER_SMEN_bm; //TIMEOUT=0,QCEN=0,SMEN=1 Smart Mode Enable
TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm; //INTLVL=0,RIEN=0,WIEN=0, ENABLE=1
TWIC.MASTER.STATUS= TWI_MASTER_BUSSTATE_IDLE_gc; //force initial bus state to idle
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// TWI test result
u8 twic_test_result(void)
{
u8 status=TWIC.MASTER.STATUS; //wez status TWIC
if (status&TWI_MASTER_ARBLOST_bm) //if arbitration lost
{
TWIC.MASTER.STATUS=status | TWI_MASTER_ARBLOST_bm; //wpisz 1, kasuje flage
return TWI_ARBLOST; //rezultat funkcji
};
if (status&TWI_MASTER_BUSERR_bm) //if bus error
{
TWIC.MASTER.STATUS=status | TWI_MASTER_BUSERR_bm; //wpisz 1, kasuje flage
return TWI_BUSERR; //rezultat funkcji
};
if (status&TWI_MASTER_WIF_bm) //if WIF, zapis do slave
{
//odwrotnie bit dla ACK !!!
if (status&TWI_MASTER_RXACK_bm) //if 1, no ACK od slave
{
TWIC.MASTER.CTRLC=TWI_MASTER_CMD_STOP_gc; //rozkaz STOP dla TWI
return TWI_NACK; // no ACK
}
else //if 0, ACK
{
return TWI_ACK; // ACK
}
};
if (status&TWI_MASTER_RIF_bm) // if RIF, odczyt ze slave
return TWI_RIF; // odebrano bajt od slave
}
///////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char twic_read_reg(unsigned char addr, unsigned char reg)
{
u8 data;
//nadaj adres slave + nr rejstru
TWIC.MASTER.ADDR = addr; //adres ukladu + WR, generuje START
while(!(TWIC.MASTER.STATUS&TWI_MASTER_WIF_bm)); //wait for WIF
twic_result=twic_test_result(); //wez status operacji
if (twic_result!=TWI_ACK) return 0; //ACK idz dalej, inny zwracaj kod bledu
TWIC.MASTER.DATA = reg; //adres rejestru
while(!(TWIC.MASTER.STATUS&TWI_MASTER_WIF_bm)); //wait for WIF
twic_result=twic_test_result(); //wez status operacji
if (twic_result!=TWI_ACK) return 0; //ACK idz dalej, inny zwracaj kod bledu
//nadaj adres do odczytu
TWIC.MASTER.ADDR = addr|0x01; //adres ukladu I2C + RD
while(!(TWIC.MASTER.STATUS&TWI_MASTER_RIF_bm)); //czekaj na zakonczenie odbioru
data = TWIC.MASTER.DATA; //odczytany bajt
// send NACK and STOP
TWIC.MASTER.CTRLC=TWI_MASTER_ACKACT_bm|TWI_MASTER_CMD_STOP_gc;
twic_result=TWI_OK; //poprawna operacja
return data;
}