尝试与 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