This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Can't write to I2C and enable interrupts in the same program?

Hi everyone,

I'm having an issue using interrupts to read data from an MPR121 capacitive touch controller with a TIVA TM4C123GXL. Here's the code that I've got:

initI2C();

//writeI2C0(0xB4,0x5E,0x0C);	// Turn on all 12 electrodes and enter run mode
UART0printf("\n\r> I2C test area 0");

// Set up the I2C interrupt pin
GPIOPinTypeI2C(GPIO_PORTC_BASE, GPIO_PIN_7);
UART0printf("\n\r> I2C test area 1");

// Enable the I2C interrupt
IntEnable(INT_I2C0);
UART0printf("\n\r> I2C test area 2");
I2CMasterIntEnable(I2C0_BASE);
UART0printf("\n\r> I2C test area 3");

writeI2C0(0xB4,0x5E,0x0C);
UART0printf("\n\r> I2C test area 4");

When I run the code as is, I don't get the "test area 4" output - the code gets stuck somewhere in the writeI2C0 function. However, the interrupt functions as expected. When I push a key on the keypad, the value registers and displays. The problem is I can't get to the rest of my program, obviously.

I thought this function was the problem, but then if I change things around - comment out this line, and uncomment the first line, I don't get the "test area 3" output, meaning the code is stuck in the I2CMasterIntEnable function.

Here is my writeI2C0 function:

void writeI2C0(uint16_t device_address, uint16_t device_register, uint8_t device_data)
{
   //specify that we want to communicate to device address with an intended write to bus
   I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
UART0printf("\n\r> writeI2C test area 0");
   //register to be read
   I2CMasterDataPut(I2C0_BASE, device_register);
UART0printf("\n\r> writeI2C test area 1");
   //send control byte and register address byte to slave device
   I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
UART0printf("\n\r> writeI2C test area 2");	
   //wait for MCU to finish transaction
   while(I2CMasterBusy(I2C0_BASE));
UART0printf("\n\r> writeI2C test area 3");
   I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
UART0printf("\n\r> writeI2C test area 4");
   //specify data to be written to the above mentioned device_register
   I2CMasterDataPut(I2C0_BASE, device_data);
UART0printf("\n\r> writeI2C test area 5");
   //wait while checking for MCU to complete the transaction
   I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
UART0printf("\n\r> writeI2C test area 6");
   //wait for MCU & device to complete transaction
   while(I2CMasterBusy(I2C0_BASE));
}

In this function, I'm only getting through to the I2CMasterControl call.

I'm at a loss for what's going on here, but I suspect it's something with how I'm handling the interrupts. Any ideas for what I can try? I tried disabling the interrupts within the call to writeI2C and then re-enabling on exit, but that didn't work.

  • Fixed it! for educational value:

    There were two distinct problems. First, I was using commands for an internal interrupt, when in fact I have an external, hardware interrupt.

    Second, I needed to clear the interrupt prior to enabling it, and clear it each time my interrupt routine finished. My code for writeI2C0 above was fine, but I changed the section of my main program setting up the interrupt. Here's what I've got now:

    initI2C();
    
    GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_7);				// Set pin C7 as input
    GPIOPadConfigSet(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);	// Pullup C7
    GPIOIntDisable(GPIO_PORTC_BASE, GPIO_PIN_7);					// Disable interrupt for PC7 (in case it was enabled)
    GPIOIntClear(GPIO_PORTC_BASE, GPIO_PIN_7);						// Clear pending interrupts for PC7
    GPIOIntRegister(GPIO_PORTC_BASE, MPR121IntHandler);				// Register port C interrupt handler
    GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);	// Configure PC7 for falling edge trigger
    GPIOIntEnable(GPIO_PORTC_BASE, GPIO_PIN_7); 					// Enable interrupt
    
    initMPR121();
    

  • Hello Lee,

    That was a good post (data and specifics clear) and good debug of the issue. Do note that the while loop being used to check the Master Busy Status shall work on TM4C123. On the TM4C129 it may cause an issue (as been noted on the forum). A small delay of 10-50 would allow seamless migration in the future.

    Regards
    Amit