TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430G2553: MSP430G2553 i2c从机模式无响应

Part Number:MSP430G2553Other Parts Discussed in Thread:MSP-EXP430G2, MSP430F5438A,

使用官方例程 msp430g2xx3_usci_i2c_standard_slave.c  代码   板子为官方 msp-exp430g2  时 无响应,连I2C起始 中断都不进入,测量P1.6 P1.7电压波形一切正常!有人用过MSP430 硬件I2C从机模式吗?之前试过MSP430F5438A,使用官方例程也没成功.附上官方例程代码

//******************************************************************************
//   MSP430G2xx3 Demo – USCI_B0, I2C Slave multiple byte TX/RX
//
//   Description: I2C master communicates to I2C slave sending and receiving
//   3 different messages of different length. (This is the slave code). The
//   slave will be in LPM0 mode, waiting for the master to initiate the
//   communication. The slave will send/receive bytes based on the master's
//   request. The slave will handle I2C bytes sent/received using the
//   I2C interrupt.
//   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
//
//                   MSP430G2553         3.3V
//                 —————–   /|\ /|\
//            /|\ |                 |   |  4.7k
//             |  |                 |  4.7k |
//             —|RST              |   |   |
//                |                 |   |   |
//                |             P1.6|—|—+- I2C Clock (UCB0SCL)
//                |                 |   |
//                |             P1.7|—+—– I2C Data (UCB0SDA)
//                |                 |
//                |                 |
//
//   Nima Eskandari
//   Texas Instruments Inc.
//   April 2017
//   Built with CCS V7.0
//******************************************************************************

#include <msp430.h>#include <stdint.h>

//******************************************************************************
// Example Commands ************************************************************
//******************************************************************************

#define SLAVE_ADDR  0x48

/* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
 * The slave will send example SlaveTypeX buffers in response.
 *
 * CMD_TYPE_X_MASTER are example commands the master sends to the slave.
 * The slave will initialize itself to receive MasterTypeX example buffers.
 * */

#define CMD_TYPE_0_SLAVE      0
#define CMD_TYPE_1_SLAVE      1
#define CMD_TYPE_2_SLAVE      2

#define CMD_TYPE_0_MASTER      3
#define CMD_TYPE_1_MASTER      4
#define CMD_TYPE_2_MASTER      5

#define TYPE_0_LENGTH   1
#define TYPE_1_LENGTH   2
#define TYPE_2_LENGTH   6

#define MAX_BUFFER_SIZE     20

/* MasterTypeX are example buffers initialized in the master, they will be
 * sent by the master to the slave.
 * SlaveTypeX are example buffers initialized in the slave, they will be
 * sent by the slave to the master.
 * */

uint8_t MasterType2 [TYPE_2_LENGTH] = {0};
uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0};
uint8_t MasterType0 [TYPE_0_LENGTH] = { 0};

uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {15, 16};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {12};

//******************************************************************************
// General I2C State Machine ***************************************************
//******************************************************************************

typedef enum I2C_ModeEnum{
    IDLE_MODE,
    NACK_MODE,
    TX_REG_ADDRESS_MODE,
    RX_REG_ADDRESS_MODE,
    TX_DATA_MODE,
    RX_DATA_MODE,
    SWITCH_TO_RX_MODE,
    SWITHC_TO_TX_MODE,
    TIMEOUT_MODE
} I2C_Mode;

/* Used to track the state of the software state machine*/
I2C_Mode SlaveMode = RX_REG_ADDRESS_MODE;

/* The Register Address/Command to use*/
uint8_t ReceiveRegAddr = 0;

/* ReceiveBuffer: Buffer used to receive data in the ISR
 * RXByteCtr: Number of bytes left to receive
 * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
 * TransmitBuffer: Buffer used to transmit data in the ISR
 * TXByteCtr: Number of bytes left to transfer
 * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
 * */
uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;

/* Initialized the software state machine according to the received cmd
 *
 * cmd: The command/register address received
 * */
void I2C_Slave_ProcessCMD(uint8_t cmd);

/* The transaction between the slave and master is completed. Uses cmd
 * to do post transaction operations. (Place data from ReceiveBuffer
 * to the corresponding buffer based in the last received cmd)
 *
 * cmd: The command/register address corresponding to the completed
 * transaction
 */
void I2C_Slave_TransactionDone(uint8_t cmd);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);

void I2C_Slave_ProcessCMD(uint8_t cmd)
{
    ReceiveIndex = 0;
    TransmitIndex = 0;
    RXByteCtr = 0;
    TXByteCtr = 0;

    switch (cmd)
    {
        case (CMD_TYPE_0_SLAVE):                        //Send slave device id (This device's id)
            SlaveMode = TX_DATA_MODE;
            TXByteCtr = TYPE_0_LENGTH;
            //Fill out the TransmitBuffer
            CopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH);
            IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
            IE2 |= UCB0TXIE;                        // Enable TX interrupt
            break;
        case (CMD_TYPE_1_SLAVE):                      //Send slave device time (This device's time)
            SlaveMode = TX_DATA_MODE;
            TXByteCtr = TYPE_1_LENGTH;
            //Fill out the TransmitBuffer
            CopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH);
            IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
            IE2 |= UCB0TXIE;                        // Enable TX interrupt
            break;
        case (CMD_TYPE_2_SLAVE):                  //Send slave device location (This device's location)
            SlaveMode = TX_DATA_MODE;
            TXByteCtr = TYPE_2_LENGTH;
            //Fill out the TransmitBuffer
            CopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH);
            IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
            IE2 |= UCB0TXIE;                        // Enable TX interrupt
            break;
        case (CMD_TYPE_0_MASTER):
            SlaveMode = RX_DATA_MODE;
            RXByteCtr = TYPE_0_LENGTH;
            IE2 &= ~UCB0TXIE;                       // Disable RX interrupt
            IE2 |= UCB0RXIE;                        // Enable TX interrupt
            break;
        case (CMD_TYPE_1_MASTER):
            SlaveMode = RX_DATA_MODE;
            RXByteCtr = TYPE_1_LENGTH;
            IE2 &= ~UCB0TXIE;                       // Disable RX interrupt
            IE2 |= UCB0RXIE;                        // Enable TX interrupt
            break;
        case (CMD_TYPE_2_MASTER):
            SlaveMode = RX_DATA_MODE;
            RXByteCtr = TYPE_2_LENGTH;
            IE2 &= ~UCB0TXIE;                       // Disable RX interrupt
            IE2 |= UCB0RXIE;                        // Enable TX interrupt
            break;
        default:
            __no_operation();
            break;
    }
}

void I2C_Slave_TransactionDone(uint8_t cmd)
{
    switch (cmd)
    {
        case (CMD_TYPE_0_SLAVE):                        //Slave device id was sent(This device's id)
            break;
        case (CMD_TYPE_1_SLAVE):                      //Slave device time was sent(This device's time)
            break;
        case (CMD_TYPE_2_SLAVE):                  //Send slave device location (This device's location)
            break;
        case (CMD_TYPE_0_MASTER):
            CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH);
            break;
        case (CMD_TYPE_1_MASTER):
            CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH);
            break;
        case (CMD_TYPE_2_MASTER):
            CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH);
            break;
        default:
            __no_operation();
            break;
    }
}

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];
    }
}

//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************

void initClockTo16MHz()
{
    if (CALBC1_16MHZ==0xFF)                  // If calibration constant erased
    {
        while(1);                               // do not load, trap CPU!!
    }
    DCOCTL = 0;                               // Select lowest DCOx and MODx settings
    BCSCTL1 = CALBC1_16MHZ;                    // Set DCO
    DCOCTL = CALDCO_16MHZ;
}

void initGPIO()
{
    P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
}

void initI2C()
{
    UCB0CTL1 |= UCSWRST;                      // Enable SW reset
    UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
    UCB0I2COA = SLAVE_ADDR;                   // Own Address
    UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
    UCB0I2CIE |= UCSTPIE + UCSTTIE;           // Enable STT and STP interrupt
    IE2 |= UCB0RXIE;                          // Enable RX interrupt
}

//******************************************************************************
// Main ************************************************************************
// Enters LPM0 and waits for I2C interrupts. The data sent from the master is  *
// then interpreted and the device will respond accordingly                    *
//******************************************************************************

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

    initClockTo16MHz();
    initGPIO();
    initI2C();

    __bis_SR_register(LPM0_bits + GIE);
    return 0;
}

//******************************************************************************
// I2C Interrupt For Received and Transmitted Data******************************
//******************************************************************************

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
#else
#error Compiler not supported!
#endif
{
  if (IFG2 & UCB0RXIFG)                 // Receive Data Interrupt
  {
      //Must read from UCB0RXBUF
      uint8_t rx_val = UCB0RXBUF;
      switch (SlaveMode)
      {
          case (RX_REG_ADDRESS_MODE):
              ReceiveRegAddr = rx_val;
              I2C_Slave_ProcessCMD(ReceiveRegAddr);
              break;
          case (RX_DATA_MODE):
              ReceiveBuffer[ReceiveIndex++] = rx_val;
              RXByteCtr–;
              if (RXByteCtr == 0)
              {
                  //Done Receiving MSG
                  SlaveMode = RX_REG_ADDRESS_MODE;
                  IE2 &= ~(UCB0TXIE);
                  IE2 |= UCB0RXIE;                          // Enable RX interrupt
                  I2C_Slave_TransactionDone(ReceiveRegAddr);
              }
              break;
          default:
              __no_operation();
              break;
      }

  }
  else if (IFG2 & UCB0TXIFG)            // Transmit Data Interrupt
  {
      //Must write to UCB0TXBUF
      switch (SlaveMode)
      {
          case (TX_DATA_MODE):
              UCB0TXBUF = TransmitBuffer[TransmitIndex++];
              TXByteCtr–;
              if (TXByteCtr == 0)
              {
                  //Done Transmitting MSG
                  SlaveMode = RX_REG_ADDRESS_MODE;
                  IE2 &= ~(UCB0TXIE);
                  IE2 |= UCB0RXIE;                          // Enable RX interrupt
                  I2C_Slave_TransactionDone(ReceiveRegAddr);
              }
              break;
          default:
              __no_operation();
              break;
      }

  }
}

//******************************************************************************
// I2C Interrupt For Start, Restart, Nack, Stop ********************************
//******************************************************************************

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void)
#else
#error Compiler not supported!
#endif
{

//仿真挂断点连这里都跳不进来
    if (UCB0STAT & UCSTPIFG)                        //Stop or NACK Interrupt
    {
        UCB0STAT &=
            ~(UCSTTIFG + UCSTPIFG + UCNACKIFG);     //Clear START/STOP/NACK Flags
    }
    if (UCB0STAT & UCSTTIFG)
    {
        UCB0STAT &= ~(UCSTTIFG);                    //Clear START Flags
    }
}

Susan Yang:

请问您现在使用的主从机均是开发板?是否有按照例程说明上拉 4.7k 电阻?

,

user6352220:

主机端为电脑+CH341T(内置上拉电阻),I2C器件地址(0x7f)核对无问题,另外电脑端和别人的产品通讯是正常的,产品使用的芯片也是G2553

,

Susan Yang:

下面我附上的文件中,主从有两种通信方式。

g2553_i2c_slave.c 设备正在等待主设备与其通信。然后它将执行 6 个命令之一。

fr5529_i2c_master.c 设备将发送三个消息,并要求读取三个消息。消息长度不同。

使用的引脚是 fr5529 上的 P2.0 和 P2.1。MSP430G2553 上的 P1.6 和 P1.7。

它们都将以 16 MHz 运行。使用的 I2C 上拉电阻是 10k 欧姆电阻。

#include <msp430.h>#include <stdint.h>
#include <stdbool.h>#define SLAVE_ADDR0x48#define CMD_TYPE_0_SLAVE0
#define CMD_TYPE_1_SLAVE1
#define CMD_TYPE_2_SLAVE2#define CMD_TYPE_0_MASTER3
#define CMD_TYPE_1_MASTER4
#define CMD_TYPE_2_MASTER5#define TYPE_0_LENGTH1
#define TYPE_1_LENGTH2
#define TYPE_2_LENGTH6#define MAX_BUFFER_SIZE20typedef enum I2C_ModeEnum{IDLE_MODE,NACK_MODE,TX_REG_ADDRESS_MODE,RX_REG_ADDRESS_MODE,TX_DATA_MODE,RX_DATA_MODE,SWITCH_TO_RX_MODE,SWITHC_TO_TX_MODE,TIMEOUT_MODE
} I2C_Mode;uint8_t MasterType2 [TYPE_2_LENGTH] = {'F', '4', '1', '9', '2', 'B'};
uint8_t MasterType1 [TYPE_1_LENGTH] = { 8, 9};
uint8_t MasterType0 [TYPE_0_LENGTH] = { 11};uint8_t SlaveType2 [TYPE_2_LENGTH] = {0};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {0};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};I2C_Mode MasterMode = IDLE_MODE;uint8_t TransmitRegAddr = 0;uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;/* I2C Write and Read Functions */
I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);
I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);void initClockTo16MHz()
{UCSCTL3 |= SELREF_2;// Set DCO FLL reference = REFOUCSCTL4 |= SELA_2;// Set ACLK = REFO__bis_SR_register(SCG0);// Disable the FLL control loopUCSCTL0 = 0x0000;// Set lowest possible DCOx, MODxUCSCTL1 = DCORSEL_5;// Select DCO range 16MHz operationUCSCTL2 = FLLD_0 + 487;// Set DCO Multiplier for 16MHz// (N + 1) * FLLRef = Fdco// (487 + 1) * 32768 = 16MHz// Set FLL Div = fDCOCLK__bic_SR_register(SCG0);// Enable the FLL control loop// Worst-case settling time for the DCO when the DCO range bits have been// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx// UG for optimization.// 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle__delay_cycles(500000);//// Loop until XT1,XT2 & DCO fault flag is cleareddo{UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flagsSFRIFG1 &= ~OFIFG;// Clear fault flags}while (SFRIFG1&OFIFG);// Test oscillator fault flag
}uint16_t setVCoreUp(uint8_t level){uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;//The code flow for increasing the Vcore has been altered to work around//the erratum FLASH37.//Please refer to the Errata sheet to know if a specific device is affected//DO NOT ALTER THIS FUNCTION//Open PMM registers for write accessPMMCTL0_H = 0xA5;//Disable dedicated Interrupts//Backup all registersPMMRIE_backup = PMMRIE;PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |SVSLPE | SVMHVLRIE | SVMHIE |SVSMHDLYIE | SVMLVLRIE | SVMLIE |SVSMLDLYIE);SVSMHCTL_backup = SVSMHCTL;SVSMLCTL_backup = SVSMLCTL;//Clear flagsPMMIFG = 0;//Set SVM highside to new level and check if a VCore increase is possibleSVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMHDLYIFG;//Check if a VCore increase is possibleif((PMMIFG & SVMHIFG) == SVMHIFG){//-> Vcc is too low for a Vcore increase//recover the previous settingsPMMIFG &= ~SVSMHDLYIFG;SVSMHCTL = SVSMHCTL_backup;//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear all FlagsPMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |SVMLVLRIFG | SVMLIFG |SVSMLDLYIFG);//Restore PMM interrupt enable registerPMMRIE = PMMRIE_backup;//Lock PMM registers for write accessPMMCTL0_H = 0x00;//return: voltage not setreturn false;}//Set also SVS highside to new level//Vcc is high enough for a Vcore increaseSVSMHCTL |= (SVSHRVL0 * level);//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMHDLYIFG;//Set VCore to new levelPMMCTL0_L = PMMCOREV0 * level;//Set SVM, SVS low side to new levelSVSMLCTL = SVMLE | (SVSMLRRL0 * level) |SVSLE | (SVSLRVL0 * level);//Wait until SVM, SVS low side is settledwhile((PMMIFG & SVSMLDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMLDLYIFG;//SVS, SVM core and high side are now set to protect for the new core level//Restore Low side settings//Clear all other bits _except_ level settingsSVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +SVSMLRRL1 + SVSMLRRL2);//Clear level settings in the backup register,keep all other bitsSVSMLCTL_backup &=~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);//Restore low-side SVS monitor settingsSVSMLCTL |= SVSMLCTL_backup;//Restore High side settings//Clear all other bits except level settingsSVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +SVSMHRRL0 + SVSMHRRL1 +SVSMHRRL2);//Clear level settings in the backup register,keep all other bitsSVSMHCTL_backup &=~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);//Restore backupSVSMHCTL |= SVSMHCTL_backup;//Wait until high side, low side settledwhile(((PMMIFG & SVSMLDLYIFG) == 0) &&((PMMIFG & SVSMHDLYIFG) == 0)){;}//Clear all FlagsPMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);//Restore PMM interrupt enable registerPMMRIE = PMMRIE_backup;//Lock PMM registers for write accessPMMCTL0_H = 0x00;return true;
}bool increaseVCoreToLevel2()
{uint8_t level = 2;uint8_t actlevel;bool status = true;//Set Mask for Max. levellevel &= PMMCOREV_3;//Get actual VCoreactlevel = PMMCTL0 & PMMCOREV_3;//step by step increase or decreasewhile((level != actlevel) && (status == true)){if(level > actlevel){status = setVCoreUp(++actlevel);}}return (status);
}void initGPIO()
{//LEDsP1OUT = 0x00;// P1 setup for LED & reset outputP1DIR |= BIT0;P4DIR |= BIT7;P4OUT &= ~(BIT7);//I2C PinsP3SEL |= BIT0 + BIT1;// P3.0,1 option select}void initI2C()
{UCB0CTL1 |= UCSWRST;// Enable SW resetUCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;// I2C Master, synchronous modeUCB0CTL1 = UCSSEL_2 + UCSWRST;// Use SMCLK, keep SW resetUCB0BR0 = 192;// fSCL = SMCLK/12 = ~100kHzUCB0BR1 = 0;UCB0I2CSA = 0x48;// Slave Address is 048hUCB0CTL1 &= ~UCSWRST;// Clear SW reset, resume operationUCB0IE |= UCNACKIE;
}int main(void) {WDTCTL = WDTPW | WDTHOLD;// Stop watchdog timerincreaseVCoreToLevel2();initClockTo16MHz();initGPIO();initI2C();I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_0_MASTER, MasterType0, TYPE_0_LENGTH);I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_1_MASTER, MasterType1, TYPE_1_LENGTH);I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_2_MASTER, MasterType2, TYPE_2_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH);CopyArray(ReceiveBuffer, SlaveType0, TYPE_0_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_1_SLAVE, TYPE_1_LENGTH);CopyArray(ReceiveBuffer, SlaveType1, TYPE_1_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_2_SLAVE, TYPE_2_LENGTH);CopyArray(ReceiveBuffer, SlaveType2, TYPE_2_LENGTH);__bis_SR_register(LPM0_bits + GIE);return 0;
}#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{//Must read from UCB0RXBUFuint8_t rx_val = 0;switch(__even_in_range(UCB0IV,0xC)){case USCI_NONE:break;// Vector 0 - no interruptcase USCI_I2C_UCALIFG:break;// Interrupt Vector: I2C Mode: UCALIFGcase USCI_I2C_UCNACKIFG:break;// Interrupt Vector: I2C Mode: UCNACKIFGcase USCI_I2C_UCSTTIFG:break;// Interrupt Vector: I2C Mode: UCSTTIFGcase USCI_I2C_UCSTPIFG:break;// Interrupt Vector: I2C Mode: UCSTPIFGcase USCI_I2C_UCRXIFG:rx_val = UCB0RXBUF;if (RXByteCtr){ReceiveBuffer[ReceiveIndex++] = rx_val;RXByteCtr--;}if (RXByteCtr == 1){UCB0CTL1 |= UCTXSTP;}else if (RXByteCtr == 0){UCB0IE &= ~UCRXIE;MasterMode = IDLE_MODE;__bic_SR_register_on_exit(CPUOFF);// Exit LPM0}break;// Interrupt Vector: I2C Mode: UCRXIFGcase USCI_I2C_UCTXIFG:switch (MasterMode){case TX_REG_ADDRESS_MODE:UCB0TXBUF = TransmitRegAddr;if (RXByteCtr)MasterMode = SWITCH_TO_RX_MODE;// Need to start receiving nowelseMasterMode = TX_DATA_MODE;// Continue to transmision with the data in Transmit Bufferbreak;case SWITCH_TO_RX_MODE:UCB0IE |= UCRXIE;// Enable RX interruptUCB0IE &= ~UCTXIE;// Disable TX interruptUCB0CTL1 &= ~UCTR;// Switch to receiverMasterMode = RX_DATA_MODE;// State state is to receive dataUCB0CTL1 |= UCTXSTT;// Send repeated startif (RXByteCtr == 1){//Must send stop since this is the N-1 bytewhile((UCB0CTL1 & UCTXSTT));UCB0CTL1 |= UCTXSTP;// Send stop condition}break;case TX_DATA_MODE:if (TXByteCtr){UCB0TXBUF = TransmitBuffer[TransmitIndex++];TXByteCtr--;}else{//Done with transmissionUCB0CTL1 |= UCTXSTP;// Send stop conditionMasterMode = IDLE_MODE;UCB0IE &= ~UCTXIE;// disable TX interrupt//IFG2 &= ~(UCB0TXIFG);__bic_SR_register_on_exit(CPUOFF);// Exit LPM0}break;default:__no_operation();break;}break;// Interrupt Vector: I2C Mode: UCTXIFGdefault: break;}
}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;UCB0IFG &= ~(UCTXIFG + UCRXIFG);// Clear any pending interruptsUCB0IE &= ~UCRXIE;// Disable RX interruptUCB0IE |= UCTXIE;// Enable TX interruptUCB0CTL1 |= UCTR + UCTXSTT;// I2C TX, start condition__bis_SR_register(LPM0_bits + GIE);// Enter LPM0 w/ interruptsreturn 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;//Copy register data to TransmitBufferCopyArray(reg_data, TransmitBuffer, count);TXByteCtr = count;RXByteCtr = 0;ReceiveIndex = 0;TransmitIndex = 0;/* Initialize slave address and interrupts */UCB0I2CSA = dev_addr;UCB0IFG &= ~(UCTXIFG + UCRXIFG);// Clear any pending interruptsUCB0IE &= ~UCRXIE;// Disable RX interruptUCB0IE |= UCTXIE;// Enable TX interruptUCB0CTL1 |= UCTR + UCTXSTT;// I2C TX, start condition__bis_SR_register(LPM0_bits + GIE);// Enter LPM0 w/ interruptsreturn MasterMode;
}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];}
}

#include <msp430.h>#include <stdint.h>#define SLAVE_ADDR0x48#define CMD_TYPE_0_SLAVE0
#define CMD_TYPE_1_SLAVE1
#define CMD_TYPE_2_SLAVE2#define CMD_TYPE_0_MASTER3
#define CMD_TYPE_1_MASTER4
#define CMD_TYPE_2_MASTER5#define TYPE_0_LENGTH1
#define TYPE_1_LENGTH2
#define TYPE_2_LENGTH6#define MAX_BUFFER_SIZE20typedef enum I2C_ModeEnum{IDLE_MODE,NACK_MODE,TX_REG_ADDRESS_MODE,RX_REG_ADDRESS_MODE,TX_DATA_MODE,RX_DATA_MODE,SWITCH_TO_RX_MODE,SWITHC_TO_TX_MODE,TIMEOUT_MODE
} I2C_Mode;uint8_t MasterType2 [TYPE_2_LENGTH] = {0};
uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0};
uint8_t MasterType0 [TYPE_0_LENGTH] = { 0};uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {15, 16};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {12};I2C_Mode SlaveMode = RX_REG_ADDRESS_MODE;uint8_t ReceiveRegAddr = 0;uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;void initClockTo16MHz()
{if (CALBC1_16MHZ==0xFF)// If calibration constant erased{while(1);// do not load, trap CPU!!}DCOCTL = 0;// Select lowest DCOx and MODx settingsBCSCTL1 = CALBC1_16MHZ;// Set DCODCOCTL = CALDCO_16MHZ;
}void initGPIO()
{P1SEL |= BIT6 + BIT7;// Assign I2C pins to USCI_B0P1SEL2|= BIT6 + BIT7;// Assign I2C pins to USCI_B0
}void initI2C()
{UCB0CTL1 |= UCSWRST;// Enable SW resetUCB0CTL0 = UCMODE_3 + UCSYNC;// I2C Slave, synchronous modeUCB0I2COA = 0x48;// Own Address is 048hUCB0CTL1 &= ~UCSWRST;// Clear SW reset, resume operationUCB0I2CIE |= UCSTPIE + UCSTTIE;// Enable STT and STP interruptIE2 |= UCB0RXIE;// Enable RX interrupt
}inline void I2C_Slave_ProcessCMD(uint8_t cmd);
inline void I2C_Slave_TransactionDone(uint8_t cmd);
inline void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);int main(void) {WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timerinitClockTo16MHz();initGPIO();initI2C();__bis_SR_register(LPM0_bits + GIE);return 0;
}//------------------------------------------------------------------------------
// The USCI_B0 data ISR is used to move data from MSP430 memory to the
// I2C master. PTxData points to the next byte to be transmitted, and TXByteCtr
// keeps track of the number of bytes transmitted.
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
#else
#error Compiler not supported!
#endif
{if (IFG2 & UCB0RXIFG)// Receive Data Interrupt{//Must read from UCB0RXBUFuint8_t rx_val = UCB0RXBUF;switch (SlaveMode){case (RX_REG_ADDRESS_MODE):ReceiveRegAddr = rx_val;I2C_Slave_ProcessCMD(ReceiveRegAddr);break;case (RX_DATA_MODE):ReceiveBuffer[ReceiveIndex++] = rx_val;RXByteCtr--;if (RXByteCtr == 0){//Done Receiving MSGSlaveMode = RX_REG_ADDRESS_MODE;IE2 &= ~(UCB0TXIE);IE2 |= UCB0RXIE;// Enable RX interruptI2C_Slave_TransactionDone(ReceiveRegAddr);}break;default:_no_operation();break;}}else if (IFG2 & UCB0TXIFG)// Transmit Data Interrupt{//Must write to UCB0TXBUFswitch (SlaveMode){case (TX_DATA_MODE):UCB0TXBUF = TransmitBuffer[TransmitIndex++];TXByteCtr--;if (TXByteCtr == 0){//Done Transmitting MSGSlaveMode = RX_REG_ADDRESS_MODE;IE2 &= ~(UCB0TXIE);IE2 |= UCB0RXIE;// Enable RX interruptI2C_Slave_TransactionDone(ReceiveRegAddr);}break;default:_no_operation();break;}}
}//------------------------------------------------------------------------------
// The USCI_B0 state ISR is used to wake up the CPU from LPM0 in order to do
// processing in the main program after data has been transmitted. LPM0 is
// only exit in case of a (re-)start or stop condition when actual data
// was transmitted.
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void)
#else
#error Compiler not supported!
#endif
{if (UCB0STAT & UCSTPIFG)//Stop or NACK Interrupt{UCB0STAT &=~(UCSTTIFG + UCSTPIFG + UCNACKIFG);//Clear START/STOP/NACK Flags}if (UCB0STAT & UCSTTIFG){UCB0STAT &= ~(UCSTTIFG);//Clear START Flags}
}inline void I2C_Slave_ProcessCMD(uint8_t cmd)
{ReceiveIndex = 0;TransmitIndex = 0;RXByteCtr = 0;TXByteCtr = 0;switch (cmd){case (CMD_TYPE_0_SLAVE)://Send slave device id (This device's id)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_0_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_1_SLAVE)://Send slave device time (This device's time)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_1_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_2_SLAVE)://Send slave device location (This device's location)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_2_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_0_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_0_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;case (CMD_TYPE_1_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_1_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;case (CMD_TYPE_2_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_2_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;default:_no_operation();break;}
}inline void I2C_Slave_TransactionDone(uint8_t cmd)
{switch (cmd){case (CMD_TYPE_0_SLAVE)://Slave device id was sent(This device's id)break;case (CMD_TYPE_1_SLAVE)://Slave device time was sent(This device's time)break;case (CMD_TYPE_2_SLAVE)://Send slave device location (This device's location)break;case (CMD_TYPE_0_MASTER):CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH);break;case (CMD_TYPE_1_MASTER):CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH);break;case (CMD_TYPE_2_MASTER):CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH);break;default:_no_operation();break;}
}inline 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];}
}

,

Susan Yang:

您可以对照上面的程序先看一下,后续您上传代码的话,请您使用回复框下的“插入–>代码”来粘贴您的代码,以便于阅读

赞(0)
未经允许不得转载:TI中文支持网 » MSP430G2553: MSP430G2553 i2c从机模式无响应
分享到: 更多 (0)

© 2024 TI中文支持网   网站地图 鲁ICP备2022002796号-1