尝试与 IS31FL3236A LED 驱动器通信。 当我与驾驶员交谈时、它将突然停止工作并冻结整个程序。
初始化驱动程序效果很好、 但一旦 LED 开始亮起、软件就会卡住。
通过检查、使用逻辑分析仪、我会得到一个随机 NACK、并且它从不在同一位置(随机位于从器件地址字节或寄存器地址或数据字节之后):

NACK 标志被置位、导致总线忙、SCL 线路变为低电平、所有通信完全停止。
非常感谢您的任何帮助、我已经勾画了产品系列用户指南和数据表、但我似乎找不到我的答案。
下面是我要使用的 I2C 代码以及 LED 驱动器的数据表。
#include "eusci_iic_driver.h"
// NEED TO TRACK USCI STATUS AND PROVIDE DATA POINTER FOR USE IN ISR
volatile eUSCI_status ui8Status;
uint8_t* pData;
uint8_t ui8DummyRead;
/* ***************************************************************************
* UCB0_MasterI2C_init
* INITIALIZE I2C IN MASTER MODE
* SEE EUSCI_DEF.H FOR SETUP DEFINITIONS
*
*/
void UCB1_MasterI2C_init(void)
{
UCB1CTLW0 = UCSWRST; // RESET USCI MODULE
UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
UCB1BRW = USCI_B1_BAUD; // SET BAUDRATE
UCB1CTLW0 &= ~UCSWRST; // ENABLE USCI MODULE
}
/*
* MASTER I2C WRITE
* RETURNS: FALSE IF NO ERRORS
* RETURNS: TRUE IF SLAVE NACK'D
*/
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
uint8_t ui8index;
UCB1CTLW0 |= UCSWRST;
UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
UCB1CTLW1 |= UCASTP_1;
UCB1TBCNT = ui8ByteCount + 1;
UCB1I2CSA = ui8Addr;
UCB1CTLW0 &= ~UCSWRST;
UCB1CTLW0 |= (UCTR + UCTXSTT);
while(!(UCB1IFG & UCTXIFG)); //WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT
UCB1TXBUF = ui8Reg; //LOAD TXBUF WITH THE TARGET REGISTER
for(ui8index = 0; ui8index < ui8ByteCount; ui8index++)
{
while(!(UCB1IFG & UCTXIFG0));
UCB1TXBUF = Data[ui8index];
}
while(!(UCB1IFG & UCTXIFG));
while (!(UCB1IFG & UCBCNTIFG));
UCB1CTL1 |= UCTXSTP;
while (!(UCB1IFG & UCSTPIFG)); // Ensure stop condition got sent
UCB1CTL1 |= UCSWRST;
return(true);
}
/*
* MASTER I2C READ
* RETURNS: FALSE IF NO ERRORS
* RETURNS: TRUE IF SLAVE NACK'D
*/
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
uint8_t ui8index;
UCB1CTLW0 |= UCSWRST;
UCB1TBCNT = 0x0002; // SETUP THE NUMBER OF BYTES TO RECEIVE (CAN ONLY BE DONE HERE WHEN EUSCI IN RESET)
UCB1CTLW1 |= UCASTP_1; // GENERATE AUTOMATIC STOP BIT WHEN UCB0TBCNT = TARGET
UCB1I2CSA = ui8Addr; // LOAD THE DEVICE SLAVE ADDRESS
UCB1CTLW0 &= ~UCSWRST; // RESUME
UCB1CTLW0 |= (UCTR + UCTXSTT);
while(!(UCB1IFG & UCTXIFG)); // WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT BEFORE LOADING TARGET REGISTER
UCB1TXBUF = ui8Reg; // LOAD TXBUF WITH THE TARGET REGISTER
while(!(UCB1IFG & UCTXIFG));
UCB1CTL1 &= ~UCTR; //TURN OFF TRANSMIT (ENABLE RECEIVE)
UCB1CTL1 |= UCTXSTT; // GENERATE (RE-)START BIT
while(!(UCB0IFG & UCRXIFG0));
for(ui8index = 0; ui8index < ui8ByteCount - 1; ui8index++)
{
while(!(UCB1IFG & UCRXIFG0));
Data[ui8index] = UCB0RXBUF;
if(ui8index == ui8ByteCount - 1)
{
UCB1CTL1 |= UCTXSTP; //send stop after next RX
}
}
UCB1CTLW0 |= UCTXSTP; //send stop after next RX
while(!(UCB1IFG & UCRXIFG));
Data[ui8index] = UCB1RXBUF;
while (!(UCB1IFG & UCSTPIFG)); // Ensure stop condition got sent
UCB1CTL1 |= UCSWRST;
return(true);
}
#ifndef EUSCI_IIC_DRIVER_H_
#define EUSCI_IIC_DRIVER_H_
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
#include "driverlib.h"
#define USCI_B1_BAUD 5
typedef enum {
eUSCI_IDLE=0,
eUSCI_SUCCESS = 0,
eUSCI_BUSY =1,
eUSCI_NACK=2,
eUSCI_STOP,
eUSCI_START
}eUSCI_status;
void UCB1_MasterI2C_init(void);
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);
#endif