InterruptIn with I2C interface on F042K6

I am trying to configure a custom test board I have using a F044K6 board. I have a button on the custom board that when pressed I want to trigger an I2C transaction. I am using InterruptIn and it does trigger the I2C interface to start but the entire transaction doesn’t complete. Just the first word goes out. If I use the button as a DigitalIn, the process works fine although the switch is slow to respond. That is why I want to use the InterrupIn. I assume the ISR process is conflicting with the I2C interface but not sure how to fix it.

void set_brightness(char BRIGHT) {
data_write[0] = PWM_REG_16;
data_write[1] = BRIGHT;
i2c.write(LWADD, data_write, 2, 0);
data_write[0] = PWM_REG_3;
data_write[1] = BRIGHT;
i2c.write(LWADD, data_write, 2, 0);
data_write[0] = UPDATE;
data_write[1] = 0x00;
i2c.write(LWADD, data_write, 2, 0);
}
void test_sequence(void) {
n++;
testseq = 0;
if (n <= NUM_TEST) {
if(n == 1) {
set_brightness(0x19);
testseq = 1;
wait(1);
testseq = 0;
pc.printf(“%d\n”, n);
}
else if (n == 2) {
set_brightness(0x80);
testseq = 1;
wait(1);
testseq = 0;
}
else if (n == 3) {
set_brightness(0xE6);
testseq = 1;
wait(1);
testseq = 0;
pc.printf(“%d\n”, n);
}
else if (n == 4) {
set_channel(LED_CTRL_1);
testseq = 1;
wait(1);
testseq = 0;
}
else if (n == 5) {
set_channel(LED_CTRL_2);
testseq = 1;
wait(1);
testseq = 0;
}
else if (n == 6) {
set_channel(0xFF);
testseq = 1;
wait(1);
testseq = 0;
pc.printf(“%d\n”, n);
}
else {
return;
}
}
else {
pc.printf(“%d\n”, n);
pc.printf(“Test Complete\r\n”);
return;
}
}
int main()
{

/* Configure the LED Driver    */
int placeholder;
data_write[0] = CONFIG_REG;
data_write[1] = 0x00;
int status = i2c.write(LWADD, data_write, 2, 0);
if (status != 0) { // Error
    while (1) {
        myled = !myled;
        wait(0.2);
    }
}
testpass = 1; //initialize "TEST PASS" LED
testseq = 1; //initialize the Blue LED on the test sequence button
n = 0;
testinc.mode (PullUp);
testinc.fall(&test_sequence);

Ahoj,

please use these symbols ``` before and after your code in your post. Then it looks nicely and it is better readable.

Since you probably use the Mbed2, it should not so big impact but anyway.
During an ISR is not recommended of using a long wait, a printf and another slow, blocking or complicated functions. You want to have ISR shortest as is possible.

You can set a flag in the ISR and the flag can be processed and cleaned in the main loop. For example like bellow.

#include "mbed.h"

DigitalOut led(LED1);
InterruptIn button(USER_BUTTON);

volatile bool button_state = false;

void cb_button(){
    if(!button_state){
        button.disable_irq()   // protection against further interruption
        button_state = true;
    } 
}

int main(){
    printf("Starting\n");
    button.fall(callback(&cb_button));
    while (true) {
        if(button_state){
            printf("Button was pressed!\n");
            // do something magic - I2C transmission and so on
            button_state = false;
            button.enable_irq();
        }
        led = !led;
        wait(0.1);
    }
}

BR, Jan

1 Like