I have three INA226 current sensors connected to eUSCI_B, P1.6 and P1.7, on an MSP430FR5739 microcontroller.
My I2C write addr code gives just one NACKIFG, and then forever hangs. On the scope the signals look nearly perfect square, no overshoot and the rise and fall time is 10-20x less than pulse with time of a clock. I use 2k2 Pullups. The wires are about 8cm all together on a PCB.
Previously I even did not manage to get any interrupt, by moving the "UCB0IE |= UCNACKIE | ..." code outside of the UCWRST area, I at least got this one.
#include "i2c.h"
#include "main.h"
#include "uart.h"
#include "ina226.h"
volatile unsigned int RXByte=0;
unsigned char TXData[] ={0, 0, 0, 0}; // Pointer to TX data
unsigned char TXByteCtr=0;
unsigned char TXByteCnt=0;
unsigned char RXByteCnt=0;
volatile unsigned int RXWord=0;
void init_i2c() {
P1SEL1 |= (BIT7 | BIT6);
P1SEL0 &= ~(BIT7 | BIT6);
uart_puts("I2C initialized\n\r");
}
void i2c_write_addr(unsigned int addr, unsigned char byte) {
UCB0CTL1 = UCSWRST; // Enable Module Reset
UCB0CTL0 |= UCMODE_3 | UCMST; // I2C, Master mode, ACLK 12MHz
UCB0CTL1 |= UCSSEL__ACLK;
UCB0BRW = 120;//200; //15; // 24MHz/240 = 100kHz Clock, 24MHz/60 = 400kHz
UCB0I2CSA = addr;
UCB0CTLW1 = UCASTP_2; // Automatic stop and interrupt, reduce deglich to 25 ns
UCB0CTLW0 |= UCTR; //Tranciever
UCB0TBCNT = 1;
UCB0CTL1 &= ~UCSWRST;
UCB0IE |= UCNACKIE | UCTXIE0 | UCRXIE | UCBCNTIE | UCNACKIE | UCSTTIE | UCSTPIE;
TXData[0] = byte;
TXByteCtr = 1; // Load TX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(GIE + CPUOFF); // Enter LPM0 w/ interrupts
uart_puts("i2c_write_addr 6\n\r");
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
LED1OUT |= LED1B;
switch(__even_in_range(UCB0IV,0x1E)) {
case 0x00: break; // Vector 0: No interrupts break;
case 0x02: break; // Vector 2: ALIFG break;
case 0x04: // Vector 4: NACKIFG break;
UCB0CTL1 |= UCTXSTT; // Resend I2C start condition
uart_puts("NACKIFG\n\r");
break;
case 0x06: break; // Vector 6: STTIFG break;
case 0x08: break; // Vector 8: STPIFG break;
case 0x0a: break; // Vector 10: RXIFG3 break;
case 0x0c: break; // Vector 14: TXIFG3 break;
case 0x0e: break; // Vector 16: RXIFG2 break;
case 0x10: break; // Vector 18: TXIFG2 break;
case 0x12: break; // Vector 20: RXIFG1 break;
case 0x14: break; // Vector 22: TXIFG1 break;
case 0x16: // Vector 24: RXIFG0 break;
RXByte = UCB0RXBUF; // Get RX data
RXWord = RXWord <<8;
RXWord |= RXByte;
uart_puts("RXIFG0\n\r");
break;
case 0x18: // Vector 26: TXIFG0 break;
if (TXByteCtr) // Check TX byte counter
{
TXByteCtr--;
UCB0TXBUF = TXData[TXByteCtr]; // Load TX buffer
}
else
{
//UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
//UCB0CTLW0 |= UCTXSTP;
__bic_SR_register_on_exit(CPUOFF);// Exit LPM0
}
uart_puts("TXIFG0\n\r");
break;
case 0x1a: // Vector 28: BCNTIFG break;
uart_puts("BCNTIFG\n\r");
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
break;
case 0x1c: // Vector 30: clock low timeout break;
LED1OUT ^= LED1B;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
uart_puts("CLKLOWTO\n\r");
break;
case 0x1e: break; // Vector 32: 9th bit break;
default: break;
}
}
And my stripped down main.c
void configure_clock()
{
FRCTL0 = FWPW | NACCESS_2 | NPRECHG_1; // Change the NACCESS_x value to add the right amount of waitstates
// Configure Clock System
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_3 | DCORSEL; // Set DCO = 24MHz
CSCTL2 = SELA__DCOCLK | SELS__DCOCLK | SELM__DCOCLK;// Set ACLK=VLO SMCLK=DCO
CSCTL3 = DIVA__2 | DIVS__1 | DIVM__2; // Set all dividers (A=12MHz, S=24MHz, M=12MHz)
CSCTL0_H = 0; // Lock CS registers
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
configure_clock();
//Configure Debug UART
init_uart_115200();
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
//Configure i2c
init_i2c();
_enable_interrupts();
i2c_write_addr(U3_ADDR, 0xFE); // Already stops here
uart_puts("INA216 ID: ");
uart_puti(i2c_read_uint(U3_ADDR));
while (1) {}
}