大家好。
我花了整整三天的时间尝试解决这个问题。 我一直在对 MSP430G2533进行编程、以成功完成许多工作、尤其是对 PWM 等。 我还可以对 I2C 主设备进行编程、以便与 BQ 电量监测计芯片通信并获取其充电状态... 只需远程读取一个寄存器,使用函数 Master_Read。
但我需要它向 KXJ3-1057加速计发送几个字节、以便设置它、在运动时发送中断、以及其他事项、即:向加速计中的寄存器发送一个值。 我可以使 WHO_AM_I 从加速计成功读取(使用 Master_Read 进行单字节读取操作)、因此硬件正常。 但是、如果 使用 I2C_EVM 函数传输超过一个字节 Master_Write_Reg、则 不传输任何数据。
IDE 为 CCS 版本:12.5.0.00007、并且编译器为 TI 编译器 V21.6.0.LTS。
I2C_I2C_EVM 这里是否有明显错误的地方 Master_Write_Reg? 如有任何帮助,将不胜感激。
此处提供代码:
/********************** I2C LOW LEVEL DEFINITIONS *********************************/
//******************************************************************************
// Reading and Writing Functions ***********************************************
//******************************************************************************
I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
return MasterMode;
}
I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
CopyArray(reg_data, TransmitBuffer, count); //Copy register data to TransmitBuffer
TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
return MasterMode;
}
//******************************************************************************
// Copy Array for storing it ***************************************************
//******************************************************************************
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex = 0; copyIndex < count; copyIndex++)
{
dest[copyIndex] = source[copyIndex];
}
}
/****************************************************************************************************
////////////////// Interrupt Service Routines (ISR) for Button and Timers ///////////////////////
****************************************************************************************************/
/******************************************************************************
Function: ISR - USCIAB0RX_ISR (I2C)
Description: I2C Interrupt For Start, Restart, Nack, Stop
Inputs: None
Outputs: None
******************************************************************************/
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if (UCB0STAT & UCNACKIFG)
{
UCB0STAT &= ~UCNACKIFG; // Clear NAK Flags
}
if (UCB0STAT & UCSTPIFG) // Stop or NACK Interrupt
{
UCB0STAT &=
~(UCSTTIFG + UCSTPIFG + UCNACKIFG); // Clear START/STOP/NACK Flags
}
if (UCB0STAT & UCSTTIFG)
{
UCB0STAT &= ~(UCSTTIFG); // Clear START Flags
}
}
/******************************************************************************
Function: ISR - USCIAB0TX_ISR (I2C)
Description: I2C Interrupt For Received and Transmitted Data
Inputs: None
Outputs: None
******************************************************************************/
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0RXIFG) // Receive Data Interrupt
{
uint8_t rx_val = UCB0RXBUF; // Must read from UCB0RXBUF
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
}
if (RXByteCtr == 1)
{
UCB0CTL1 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
IE2 &= ~UCB0RXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
else if (IFG2 & UCB0TXIFG) // Transmit Data Interrupt
{
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
UCB0TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;
case SWITCH_TO_RX_MODE:
IE2 |= UCB0RXIE; // Enable RX interrupt
IE2 &= ~UCB0TXIE; // Disable TX interrupt
UCB0CTL1 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB0CTL1 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB0CTL1 & UCTXSTT));
UCB0CTL1 |= UCTXSTP; // Send stop condition
}
break;
case TX_DATA_MODE:
if (TXByteCtr)
{
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
}
else
{
//Done with transmission
UCB0CTL1 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
IE2 &= ~UCB0TXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
default:
__no_operation();
break;
}
}
}
/********************** I2C LOW LEVEL DEFINITIONS *********************************/
//******************************************************************************
// Reading and Writing Functions ***********************************************
//******************************************************************************
I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr = count;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
return MasterMode;
}
I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
/* Initialize state machine */
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
CopyArray(reg_data, TransmitBuffer, count); //Copy register data to TransmitBuffer
TXByteCtr = count;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/* Initialize slave address and interrupts */
UCB0I2CSA = dev_addr;
IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear any pending interrupts
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
return MasterMode;
}
//******************************************************************************
// Copy Array for storing it ***************************************************
//******************************************************************************
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex = 0; copyIndex < count; copyIndex++)
{
dest[copyIndex] = source[copyIndex];
}
}
/****************************************************************************************************
////////////////// Interrupt Service Routines (ISR) for Button and Timers ///////////////////////
****************************************************************************************************/
/******************************************************************************
Function: ISR - USCIAB0RX_ISR (I2C)
Description: I2C Interrupt For Start, Restart, Nack, Stop
Inputs: None
Outputs: None
******************************************************************************/
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if (UCB0STAT & UCNACKIFG)
{
UCB0STAT &= ~UCNACKIFG; // Clear NAK Flags
}
if (UCB0STAT & UCSTPIFG) // Stop or NACK Interrupt
{
UCB0STAT &=
~(UCSTTIFG + UCSTPIFG + UCNACKIFG); // Clear START/STOP/NACK Flags
}
if (UCB0STAT & UCSTTIFG)
{
UCB0STAT &= ~(UCSTTIFG); // Clear START Flags
}
}
/******************************************************************************
Function: ISR - USCIAB0TX_ISR (I2C)
Description: I2C Interrupt For Received and Transmitted Data
Inputs: None
Outputs: None
******************************************************************************/
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0RXIFG) // Receive Data Interrupt
{
uint8_t rx_val = UCB0RXBUF; // Must read from UCB0RXBUF
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
}
if (RXByteCtr == 1)
{
UCB0CTL1 |= UCTXSTP;
}
else if (RXByteCtr == 0)
{
IE2 &= ~UCB0RXIE;
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
else if (IFG2 & UCB0TXIFG) // Transmit Data Interrupt
{
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
UCB0TXBUF = TransmitRegAddr;
if (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE; // Need to start receiving now
else
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
break;
case SWITCH_TO_RX_MODE:
IE2 |= UCB0RXIE; // Enable RX interrupt
IE2 &= ~UCB0TXIE; // Disable TX interrupt
UCB0CTL1 &= ~UCTR; // Switch to receiver
MasterMode = RX_DATA_MODE; // State state is to receive data
UCB0CTL1 |= UCTXSTT; // Send repeated start
if (RXByteCtr == 1)
{
//Must send stop since this is the N-1 byte
while((UCB0CTL1 & UCTXSTT));
UCB0CTL1 |= UCTXSTP; // Send stop condition
}
break;
case TX_DATA_MODE:
if (TXByteCtr)
{
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
}
else
{
//Done with transmission
UCB0CTL1 |= UCTXSTP; // Send stop condition
MasterMode = IDLE_MODE;
IE2 &= ~UCB0TXIE; // disable TX interrupt
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
default:
__no_operation();
break;
}
}
}