Microchip® Advanced Software Framework

XMEGA E TWI additions with Bridge and Fast Mode Plus

XMEGA E TWI module provides two additionnnal features compare to regular XMEGA TWI module:

  • Fast Mode Plus communication speed
  • Bridge Mode

The following use case will set up the TWI module to be used in in Fast Mode Plus together with bridge mode. This use case is similar to the regular XMEGA TWI initialization, it only differs by the activation of both Bridge and Fast Mode Plus mode.

#define TWI_MASTER TWIC
#define TWI_MASTER_PORT PORTC
#define TWI_SLAVE TWIC
#define TWI_SPEED 1000000
#define TWI_MASTER_ADDR 0x50
#define TWI_SLAVE_ADDR 0x50
#define DATA_LENGTH 8
TWI_Slave_t slave;
uint8_t data[DATA_LENGTH] = {
0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f
};
uint8_t recv_data[DATA_LENGTH] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
twi_options_t m_options = {
.chip = TWI_MASTER_ADDR,
};
static void slave_process(void) {
int i;
for(i = 0; i < DATA_LENGTH; i++) {
recv_data[i] = slave.receivedData[i];
}
}
ISR(TWIC_TWIS_vect) {
TWI_SlaveInterruptHandler(&slave);
}
void send_and_recv_twi()
{
twi_package_t packet = {
.chip = TWI_SLAVE_ADDR,
.buffer = (void *)data,
.length = DATA_LENGTH,
.no_wait = false
};
uint8_t i;
TWI_MASTER_PORT.PIN0CTRL = PORT_OPC_WIREDANDPULL_gc;
TWI_MASTER_PORT.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;
twi_bridge_enable(&TWI_MASTER);
twi_fast_mode_enable(&TWI_MASTER);
twi_slave_fast_mode_enable(&TWI_SLAVE);
twi_master_init(&TWI_MASTER, &m_options);
twi_master_enable(&TWI_MASTER);
TWI_SlaveInitializeDriver(&slave, &TWI_SLAVE, *slave_process);
TWI_SlaveInitializeModule(&slave, TWI_SLAVE_ADDR,
TWI_SLAVE_INTLVL_MED_gc);
for (i = 0; i < TWIS_SEND_BUFFER_SIZE; i++) {
slave.receivedData[i] = 0;
}
twi_master_write(&TWI_MASTER, &packet);
do {
// Nothing
} while(slave.result != TWIS_RESULT_OK);
}

We first create some definitions. TWI master and slave, speed, and addresses:

#define TWI_MASTER TWIC
#define TWI_MASTER_PORT PORTC
#define TWI_SLAVE TWIC
#define TWI_SPEED 1000000
#define TWI_MASTER_ADDR 0x50
#define TWI_SLAVE_ADDR 0x50
#define DATA_LENGTH 8

We create a handle to contain information about the slave module:

TWI_Slave_t slave;

We create two variables, one which contains data that will be transmitted, and one which will contain the received data:

uint8_t data[DATA_LENGTH] = {
0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f
};
uint8_t recv_data[DATA_LENGTH] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

Options for the TWI module initialization procedure are given below:

twi_options_t m_options = {
.chip = TWI_MASTER_ADDR,
};

The TWI slave will fire an interrupt when it has received data, and the function below will be called, which will copy the data from the driver to our recv_data buffer:

static void slave_process(void) {
int i;
for(i = 0; i < DATA_LENGTH; i++) {
recv_data[i] = slave.receivedData[i];
}
}

Set up the interrupt handler:

ISR(TWIC_TWIS_vect) {
TWI_SlaveInterruptHandler(&slave);
}

We create a packet for the data that we will send to the slave TWI:

twi_package_t packet = {
.chip = TWI_SLAVE_ADDR,
.buffer = (void *)data,
.length = DATA_LENGTH,
.no_wait = false
};

We need to set SDA/SCL pins for the master TWI to be wired and enable pull-up:

TWI_MASTER_PORT.PIN0CTRL = PORT_OPC_WIREDANDPULL_gc;
TWI_MASTER_PORT.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;

We enable all interrupt levels:

We enable the clock to the master module:

We enable the global TWI bridge mode as well as the Fast Mode Plus communication speed for both master and slave:

twi_bridge_enable(&TWI_MASTER);
twi_fast_mode_enable(&TWI_MASTER);
twi_slave_fast_mode_enable(&TWI_SLAVE);

Initialize the master module with the options we described before:

twi_master_init(&TWI_MASTER, &m_options);
twi_master_enable(&TWI_MASTER);

We do the same for the slave, using the slave portion of the driver, passing through the slave_process function, its address, and set medium interrupt level:

TWI_SlaveInitializeDriver(&slave, &TWI_SLAVE, *slave_process);
TWI_SlaveInitializeModule(&slave, TWI_SLAVE_ADDR,
TWI_SLAVE_INTLVL_MED_gc);

We zero out the receive buffer in the slave handle:

for (i = 0; i < TWIS_SEND_BUFFER_SIZE; i++) {
slave.receivedData[i] = 0;
}

And enable interrupts:

Finally, we write our packet through the master TWI module:

twi_master_write(&TWI_MASTER, &packet);

We wait for the slave to finish receiving:

do {
// Waiting
} while(slave.result != TWIS_RESULT_OK);
Note
When the slave has finished receiving, the slave_process() function will copy the received data into our recv_data buffer, which now contains what was sent through the master.