Arduino Due: TWI/I2C communication using TC - timer counter

SDA20 and SCL21 on the slave? Then SDA1 and SCL1 on the master?

It's up to you, providing you add #define Wire Wire1 at the beginning of your sketch, just after the #include of libraries, as stated above. You could also use SDA1/SCL1 on both cards, and add pull ups of 2K2. It seems that this resistor value is OK.

You can test your code for I2C in Master and I2C in Slave modes with a DUE on a single DUE board, here is an example sketch using the builtin temperature sensor (hook a jumper between SDA/SDA1 and another one between SCL/SCL1):

/******************************************************************************/
/************    Master TWI0, Slave TWI1, temperature reading     *************/
/******************************************************************************/
#define read  1
#define write 0
#define TemperatureAddress      (0b1001000)

/*********************     Init TWIn      ************************/

void I2c_Init(Twi* pTWI, boolean Master) {
  if (pTWI == TWI0) {
    PMC->PMC_PCER0 |= PMC_PCER0_PID22;      // TWI0 power ON
    PIOA->PIO_PDR |= PIO_PDR_P17            // Enable peripheral control
                     | PIO_PDR_P18;
    PIOA->PIO_ABSR &= ~(PIO_PA17A_TWD0      // TWD0 & TWCK0 Peripherals type A
                        | PIO_PA18A_TWCK0);
  }
  else {
    PMC->PMC_PCER0 |= PMC_PCER0_PID23;      // TWI1 power ON
    PIOB->PIO_PDR |= PIO_PDR_P13            // Enable peripheral control
                     | PIO_PDR_P12;
    PIOB->PIO_ABSR &= ~(PIO_PB12A_TWD1      // TWD1 & TWCK1 Peripherals type A
                        | PIO_PB13A_TWCK1);
  }
  // I2C lines are Open drain by hardware, no need to program PIO_MDER

  pTWI->TWI_CR = TWI_CR_SWRST;  // TWIn software reset
  pTWI->TWI_RHR;                // Flush reception buffer

  pTWI->TWI_CR = TWI_CR_SVDIS | TWI_CR_MSDIS; // Disable Master and Slave modes

  //Enable master mode
  if (Master == true) {
    //enter slave address
    pTWI->TWI_MMR |= TWI_MMR_DADR(TemperatureAddress);

    pTWI->TWI_CR = TWI_CR_MSEN;  // Master mode enable
    //clockwave from 100khz to 400khz
    SetClock(pTWI, 400000); // from 100000 to 400000
  }
  else { // Enable Slave mode
    pTWI->TWI_SMR = TWI_SMR_SADR(TemperatureAddress);
    pTWI->TWI_CR = TWI_CR_SVEN;     // Slave mode enable
  }
}

/****************************     Start    ****************************/

void I2c_Start(Twi* pTWI, uint8_t slave_address, uint8_t mread) { //read=1, write=0
  //set slave address
  pTWI->TWI_MMR = (pTWI->TWI_MMR & ~TWI_MMR_DADR_Msk)
                  | TWI_MMR_DADR(slave_address);
  //set read/write direction
  if (mread == write) { //write
    pTWI->TWI_MMR &= ~TWI_MMR_MREAD;
  }
  else if (mread == read) { //read
    pTWI->TWI_MMR |= TWI_MMR_MREAD;
  }
  //send start
  pTWI->TWI_CR |= TWI_CR_START;

  //wait for ack
  while (!(pTWI->TWI_SR & TWI_SR_TXRDY));
}

/***************************   Stop    ****************************/

void I2c_Stop(Twi* pTWI) {
  pTWI->TWI_CR |= TWI_CR_STOP;
}

/**********************     Read 1 byte   **************************/

uint8_t I2c_ReadByte(Twi* pTWI) {
  uint8_t receivedByte;
  //If the stop bit in the control register is not set,
  //Sam3x will automatically ACK after reading TWIn_RHR register
  //RXRDY will be set when data arrives in TWIn_RHR register

  while (!(pTWI->TWI_SR & TWI_SR_RXRDY));
  //reading data will clear RXRDY bit in the status register
  receivedByte = pTWI->TWI_RHR;
  return receivedByte;
}

/*****************     Read the last byte   ***********************/

uint8_t I2c_ReadLastByte(Twi* pTWI) {
  uint8_t receivedByte;
  //Sam3x requires stop bit to be set before data is set on the TWIn_RHR
  //when stop bit is set, Sam3x will send a NACK instead of an ACK automatically
  I2c_Stop(pTWI);
  //When data arrives in the TWIn_RHR register RXRDY is set in the Status Register
  while (!(pTWI->TWI_SR & TWI_SR_RXRDY));
  //reading data will clear RXRDY bit in the status register
  receivedByte = pTWI->TWI_RHR;
  while (!(pTWI->TWI_SR & TWI_SR_TXCOMP));
  return receivedByte;
}

/************************     Write 1 byte     *******************/

void I2c_WriteByte(Twi* pTWI, uint8_t data) { 
  pTWI->TWI_THR |= data;
  //wait for ack
  while (!(pTWI->TWI_SR & TWI_SR_TXRDY));
}

/***********************    Write last byte    *******************/

void I2c_WriteLastByte(Twi* pTWI, uint8_t data) { 
  pTWI->TWI_THR |= data;
  I2c_Stop(pTWI);
  //wait for ack
  while (!(pTWI->TWI_SR & TWI_SR_TXRDY));
  while (!(pTWI->TWI_SR & TWI_SR_TXCOMP));
}

/*****************   Set Interrupt Configuration   *********************/

void I2c_Interrupt(Twi* pTWI, uint32_t InterrConfig) {
  pTWI->TWI_IER = InterrConfig;
  if (pTWI == TWI0) {
    NVIC_EnableIRQ(TWI0_IRQn);
  }
  else {
    NVIC_EnableIRQ(TWI1_IRQn);
  }
}

/*******************        TWI1 Handler    ***********************/

void TWI1_Handler(void) {
  uint32_t status = TWI1->TWI_SR;
  if (status & TWI_SR_SVREAD) {
    TWI1->TWI_RHR;
    TWI1->TWI_THR = temperature();
  }
}

/**********************    Configure clock    *********************/

void SetClock(Twi* pTWI , uint32_t frequency) {
  uint32_t CLDIV = 0;
  uint32_t CKDIV = 0;
  uint8_t readyByte = 0;

  while (!readyByte) {
    CLDIV = ((VARIANT_MCK / (2 * frequency)) - 4) / (1 << CKDIV) ;
    if ( CLDIV <= 255 ) {
      readyByte = 1 ;
    }
    else {
      CKDIV++ ;
    }
  }
  pTWI->TWI_CWGR = (CKDIV << 16) | (CLDIV << 8) | CLDIV;
}

void setup() {

  // Power OFF all peripherals
  PMC->PMC_PCDR0 = 0xFFFFFFFF;
  PMC->PMC_PCDR1 = 0xFFFFFFFF;
  Serial.begin(250000);
  PMC->PMC_PCER1 |= PMC_PCER1_PID37;  // ADC power ON
  ADC->ADC_ACR |= ADC_ACR_TSON;       // Temperature sensor ON

  I2c_Init(TWI0, true);   // TWI0 Master
  I2c_Init(TWI1, false);  // TWI1 Slave
  uint32_t InterruptConfig = TWI_IER_SVACC;  // | TWI_IER_SVREAD
  I2c_Interrupt(TWI1, InterruptConfig);

}

void loop() {

  uint8_t ReceivedByte;
  static uint32_t Oldmillis;

  if ((millis() - Oldmillis) > 1000) {
    Oldmillis = millis();
    I2c_Start(TWI0, TemperatureAddress, 1);
    ReceivedByte = I2c_ReadLastByte(TWI0);
    printf("%d\xB0" "C\n", ReceivedByte );
  }
}

/*****************   Temperature function    *******************/

uint8_t temperature() {
  float trans = 3.3 / 4096;
  float offset = 0.76;
  float factor = 0.00265;
  float fixtemp = 15;
  uint32_t ulValue;
  float treal;
  uint8_t __treal;

  ADC->ADC_CHER |= 1 << ADC_TEMPERATURE_SENSOR;
  ADC->ADC_CR = ADC_CR_START;
  while (!(ADC->ADC_ISR & ADC_ISR_DRDY));
  ulValue = ADC->ADC_LCDR;

  ADC->ADC_CHDR |= 1 << ADC_TEMPERATURE_SENSOR;
  treal = fixtemp + (( trans * ulValue ) - offset ) / factor;
  __treal = (uint8_t) treal;
  return __treal;
}