Hello. I am doing a university lab project regarding i2c communications. We are not allowed to use any of the build in libraries. We must write everything at the GPIO level using the datasheet.
I have configured I2C0 as the master and I2C3 as the slave. I am trying to send a single byte of data from 1 to the other, but i am not having any success. Using the built in library, I was able to successfully transmit in loopback mode from the master i2c0 back to itself, but doing things manually is not working.
Here is my code configuring the I2C ports. I configured 4 ports, thinking I can communicate between them:
void I2C_Init(void){ SYSCTL_RCGCI2C_R |= 0x000F; // activate I2C0, I2C1, I2C2, I2C3 SYSCTL_RCGCGPIO_R |= 0x0642; // activate ports B(I2C0), G(I2C1), L(I2C2) K(I2C3) while((SYSCTL_PRGPIO_R&0x0642) == 0){}; // ready? GPIO_PORTB_AHB_AFSEL_R |= 0x0C; // 3) enable alt funct on PB2,3 GPIO_PORTG_AHB_AFSEL_R |= 0x03; // 3) enable alt funct on PG0,1 GPIO_PORTL_AFSEL_R |= 0x03; // 3) enable alt funct on PL0,1 GPIO_PORTK_AFSEL_R |= 0x30; // 3) enable alt funct on PK4,5 GPIO_PORTB_AHB_ODR_R |= 0x08; // 4) enable open drain on PB3 only GPIO_PORTG_AHB_ODR_R |= 0x02; // 4) enable open drain on PG1 only GPIO_PORTL_ODR_R |= 0x02; // 4) enable open drain on PL1 only GPIO_PORTK_ODR_R |= 0x10; // 4) enable open drain on PK4 only GPIO_PORTB_AHB_DEN_R |= 0x0C; // 5) enable digital I/O on PB2,3 GPIO_PORTG_AHB_DEN_R |= 0x03; // 5) enable digital I/O on PG0,1 GPIO_PORTL_DEN_R |= 0x03; // 5) enable digital I/O on PL0,1 GPIO_PORTK_DEN_R |= 0x30; // 5) enable digital I/O on PK4,5 GPIO_PORTB_AHB_PCTL_R |= 0x00003300; // 6) configure PB2,3 as I2C GPIO_PORTG_AHB_PCTL_R |= 0x00000033; // 6) configure PG0,1 as I2C GPIO_PORTL_PCTL_R |= 0x00000033; // 6) configure PL0,1 as I2C GPIO_PORTK_PCTL_R |= 0x00330000; // 6) configure PK4,5 as I2C GPIO_PORTB_AHB_AMSEL_R &= ~0x0C; // 7) disable analog functionality on PB2,3 GPIO_PORTG_AHB_AMSEL_R &= ~0x03; // 7) disable analog functionality on PB2,3 GPIO_PORTL_AMSEL_R &= ~0x03; // 7) disable analog functionality on PB2,3 GPIO_PORTK_AMSEL_R &= ~0x30; // 7) disable analog functionality on PB2,3 I2C0_MTPR_R = 0x07; // 8) configure for 100 kbps clock TPR = 7 for 16MHz clock freq TPR = (SYSCLKFREQ/(20*SCLCLKSPEED))-1 = (16MHz/(20*100K))-1 I2C3_MTPR_R = 0x07; // 8) configure for 100 kbps clock TPR = 7 for 16MHz clock freq TPR = (SYSCLKFREQ/(20*SCLCLKSPEED))-1 = (16MHz/(20*100K))-1 }
Here is my main function:
#define SLAVE_ADDRESS 0x76
void main(void) { uint8_t dataTx; uint8_t dataRx; InitConsole(); UARTprintf("Initializing I2C\n"); I2C_Init(); UARTprintf("Done initializing!"); I2C0_MCR_R = 0x10; //master function enable for I2C0 I2C0_MSA_R = SLAVE_ADDRESS>>1; //set slave address that the master will write to I2C3_MCR_R = 0x20; //enable i2c3 as slave I2C3_SCSR_R = 0x01; //enable i2c3 as a slave I2C3_SOAR_R = SLAVE_ADDRESS>>1; //set i2c3 slave address dataTx = 0x11; UARTprintf("Tranferring from: Master -> Slave\n"); I2C0_MDR_R = dataTx; //place data to transmit in the MDR register of the master I2C0_MCS_R = 0x07; //initialzes transmit of 1 byte of data from master to slave while(I2C0_MCS_R & 0x01); //wait until master bus is no longer busy dataRx=I2C3_SDR_R; //read data from the slave data register UARTprintf("Received: '%c'\n", dataRx); //print data while(1){}; }
I have a couple of problems here.
First, is everything configured correctly? I think my INIT function is correct, but I am more concerned with how I have configured the master and slave. I want I2C0 as master on pins PB2,3 and I2c3 as slave on pins PK4,5.
Second. When I write I2C0_MDR_R = dataTx; the Master data register(MDR) value in the debugger stays the same. It does not update to the value of 00010001, which is what I want to send. Is that normal??
I don't see any error readings in the I2C0MCR register. It becomes 0x01 momentarily and then back to idle state, which is what I expect.
The output from the console is:
Initializing I2C
Done initializing!
Tranferring from: Master -> Slave
Received: ' '
The data read is always zero, I assume because the master data register always reads 0?? transmission is occurring, but only with a 0 as the load. Any ideas here, or can i provide any more information??
void I2C_Init(void){ SYSCTL_RCGCI2C_R |= 0x000F; // activate I2C0, I2C1, I2C2, I2C3 SYSCTL_RCGCGPIO_R |= 0x0642; // activate ports B(I2C0), G(I2C1), L(I2C2) K(I2C3) while((SYSCTL_PRGPIO_R&0x0642) == 0){}; // ready?
GPIO_PORTB_AHB_AFSEL_R |= 0x0C; // 3) enable alt funct on PB2,3 GPIO_PORTG_AHB_AFSEL_R |= 0x03; // 3) enable alt funct on PG0,1 GPIO_PORTL_AFSEL_R |= 0x03; // 3) enable alt funct on PL0,1 GPIO_PORTK_AFSEL_R |= 0x30; // 3) enable alt funct on PK4,5 GPIO_PORTB_AHB_ODR_R |= 0x08; // 4) enable open drain on PB3 only GPIO_PORTG_AHB_ODR_R |= 0x02; // 4) enable open drain on PG1 only GPIO_PORTL_ODR_R |= 0x02; // 4) enable open drain on PL1 only GPIO_PORTK_ODR_R |= 0x10; // 4) enable open drain on PK4 only GPIO_PORTB_AHB_DEN_R |= 0x0C; // 5) enable digital I/O on PB2,3 GPIO_PORTG_AHB_DEN_R |= 0x03; // 5) enable digital I/O on PG0,1 GPIO_PORTL_DEN_R |= 0x03; // 5) enable digital I/O on PL0,1 GPIO_PORTK_DEN_R |= 0x30; // 5) enable digital I/O on PK4,5
GPIO_PORTB_AHB_PCTL_R |= 0x00003300; // 6) configure PB2,3 as I2C GPIO_PORTG_AHB_PCTL_R |= 0x00000033; // 6) configure PG0,1 as I2C GPIO_PORTL_PCTL_R |= 0x00000033; // 6) configure PL0,1 as I2C GPIO_PORTK_PCTL_R |= 0x00330000; // 6) configure PK4,5 as I2C GPIO_PORTB_AHB_AMSEL_R &= ~0x0C; // 7) disable analog functionality on PB2,3 GPIO_PORTG_AHB_AMSEL_R &= ~0x03; // 7) disable analog functionality on PB2,3 GPIO_PORTL_AMSEL_R &= ~0x03; // 7) disable analog functionality on PB2,3 GPIO_PORTK_AMSEL_R &= ~0x30; // 7) disable analog functionality on PB2,3 //I2C0_MCR_R = I2C_MCR_MFE; // 9) master function enable for I2C0 I2C0_MTPR_R = 0x07; // 8) configure for 100 kbps clock TPR = 7 for 16MHz clock freq TPR = (SYSCLKFREQ/(20*SCLCLKSPEED))-1 = (16MHz/(20*100K))-1 I2C3_MTPR_R = 0x07; // 8) configure for 100 kbps clock TPR = 7 for 16MHz clock freq TPR = (SYSCLKFREQ/(20*SCLCLKSPEED))-1 = (16MHz/(20*100K))-1}