2

我有一个项目,它有一个 MSP430G2553 主设备和一个三轴数字输出陀螺仪 ITG-3200 分线从属设备。ITG3200 使用 i²c 协议进行通信,所以我一直在 Msp 上检查 i²c 模块的使用情况。作为初学者,我下载了 TI I²c示例,可在http://www.ti.com/lsds/ti/microcontroller/16-bit_msp430/msp430_software_landing.page中找到TMP100 温度传感器作为从设备。这是示例代码。

//******************************************************************************
//  MSP430G2xx3 Demo - USCI_B0 I2C Master to TMP100, Set P1.0 if Temp > 28C
//
//  Description: I2C interface to TMP100 temperature sensor in 9-bit mode.
//  Timer_A CCR0 interrupt is used to wake up and read the two bytes of
//  the TMP100 temperature register every 62ms. If the temperature is greater
//  than 28C, P1.0 is set, else reset. CPU is operated in LPM0. I2C speed
//  is ~100kHz.
//  ACLK = n/a, MCLK = SMCLK = TACLK = BRCLK = default DCO = ~1.2MHz
//
//         /|\           /|\ /|\
//          |   TMP100   10k 10k     MSP430G2xx3
//          |   -------   |   |   -------------------
//          +--|Vcc SDA|<-|---+->|P1.7/UCB0SDA    XIN|-
//          |  |       |  |      |                   |
//          +--|A1,A0  |  |      |               XOUT|-
//             |       |  |      |                   |
//          +--|Vss SCL|<-+------|P1.6/UCB0SCL   P1.0|---> LED
//         \|/  -------          |                   |
//
//  D. Dang
//  Texas Instruments Inc.
//  February 2011
//   Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>

unsigned int RxByteCtr;
unsigned int RxWord;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= BIT0;                            // P1.0 output
  P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
  P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB0BR1 = 0;
  UCB0I2CSA = 0x4e;                         // Set slave address
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IE2 |= UCB0RXIE;                          // Enable RX interrupt
  TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode

  while (1)
  {
    RxByteCtr = 2;                          // Load RX byte counter
    UCB0CTL1 |= UCTXSTT;                    // I2C start condition
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0, enable interrupts
                                        // Remain in LPM0 until all data
                                        // is RX'd

    if (RxWord < 0x1d00)                    // >28C?
      P1OUT &= ~0x01;                       // No, P1.0 = 0
    else
      P1OUT |= 0x01;                        // Yes, P1.0 = 1

    __disable_interrupt();
    TACCTL0 |= CCIE;                        // TACCR0 interrupt enabled
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0, enable interrupts
                                        // Remain in LPM0 until TACCR0
                                        // interrupt occurs
    TACCTL0 &= ~CCIE;                       // TACCR0 interrupt disabled
  }
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void TA0_ISR(void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
}

// The USCIAB0TX_ISR is structured such that it can be used to receive any
// 2+ number of bytes by pre-loading RxByteCtr with the byte count.
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
  RxByteCtr--;                              // Decrement RX byte counter

  if (RxByteCtr)
  {
    RxWord = (unsigned int)UCB0RXBUF << 8;  // Get received byte
    if (RxByteCtr == 1)                     // Only one byte left?
      UCB0CTL1 |= UCTXSTP;                  // Generate I2C stop condition
  }
  else
  {
    RxWord |= UCB0RXBUF;                    // Get final received byte,
                                        // Combine MSB and LSB
    __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
  }
}

我建立了相同的电路,其中 SDA 和 SCL 上的 2 个 10k 上拉,将从地址更改为 0x69 或 0x68,这是设备用户指南中给出的陀螺仪地址。由于我还没有建立任何监控,我用示波器检查了 SCL 和 SDA 上的脉冲。我没想到会在 SDA 上看到任何东西,但我想知道为什么我什至看不到 SCL 总线上的任何时钟周期。它要么始终处于 3.3V(MSP 内部 vcc)上,要么有时接近 1V(0.80~)。即使我移除陀螺仪、SDA 和 SCL 总线,我在 P1.6 端口上也看不到任何脉冲。有任何想法吗?

另外,如果有人知道这个设备的库,比如 arduino,我真的很想使用它而不是尝试检查所有寄存器和中断。

4

1 回答 1

1

我知道这个线程已经低调了一段时间。在我挖了很多东西并工作了一个月之后,我想出了最后一个干净的代码。我遇到了另一个问题,我将在这里粘贴。

我有这段代码,我一直在研究通过 I2C 总线连接 ITG-3200 陀螺仪从属设备和 MSP430G2553 主设备。它昨天工作正常,但不知何故今天它不工作。我尝试在没有陀螺仪 ACK 的情况下尽可能多地进行调试,但似乎进入 LPM TX 中断后从未发生过,因此它卡在了 LPM 中。你能看看我遗漏的东西吗?我试图尽可能地清理代码,它可能看起来有点复杂,但请随时询问任何功能。

/* --COPYRIGHT--,
 * Copyright (c) 2013, Barışcan Kayaoğlu
 * All rights reserved.
 *
 * --COPYRIGHT--*/
//******************************************************************************
//  MSP430G2xx3 I2C Demo - USCI_B0 I2C Master TX/RX single byte from ITG-3200
//  gyroscope.
//
//  Description: This demo connects a MSP430Gxx3 launchpad to ITG-3200 via
//  USCI_B0 I2C module. The launchpad act as a master and itg-300 act as a
//  slave. Master reads 6 byte consecutively and send it to the vitual COM
//  Port on Usb with USCI_A0 Uart module. DCO = 1MHz
//
//                                /|\  /|\
//                  ITG-3200      10k  10k     MSP430G2xx3
//                   slave         |    |        master
//             -----------------   |    |     -----------------
//            |              SDA|<-|----+---->|P1.7/UCB0SDA     |
//            |              CLK|<-|-.GND     |                 |
//            |              GND|<-|-'        |                 |
//            |              SCL|<-+--------->|P1.6/UCB0SCL     |
//            |              VCC|<--.         |      P1.1/UCA0TX|-------> COM Port (9600 baud)
//            |              VIO|<--'3.3V     |                 |
//            |              INT|             |                 |
//  Barışcan Kayaoğlu
//  May 2013
//  Built with CCS Version 5.3.0.00090
//******************************************************************************
#include <msp430g2553.h>

int TXByteCtr; // This counter used for counting bytes before the stop condition
char xRate_L;  // Variable to hold X_Low register value
char xRate_H;  // Variable to hold X_High register value
char yRate_L;  // Variable to hold Y_Low register value
char yRate_H;  // Variable to hold Y_High register value
char zRate_L;  // Variable to hold Z_Low register value
char zRate_H;  // Variable to hold Z_High register value
int i2c_State; // This counter held the state machine condition of I2C
int Rx = 0;    // Flag for the interrupt vector. 1 for Receive 0 for Transmit
int init = 0;  // Flag for the interrupt vector. 1 for Writing to gyro for config 0 for reading

//Gyro configuration addresses
char WHO_AM_I = 0x00;   // Gyro register where it helds the slave address 0x69 | 0x68
char SMPLRT_DIV= 0x15; // Gyro register where it helds the divider value for sample rate
char DLPF_FS = 0x16;  // Gyro register where it helds the low pass filter config

//Gyro Memory addresses;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;
char TEMP_OUT_H = 0x1B;
char TEMP_OUT_L = 0x1C;
char itgAddress = 0x69;

//Gyro configuration constants
char DLPF_CFG_0 = 1<<0;        // 1
char DLPF_CFG_1 = 1<<1;       // 10
char DLPF_CFG_2 = 1<<2;      // 100
char DLPF_FS_SEL_0 = 1<<3;  // 1000
char DLPF_FS_SEL_1 = 1<<4; //10000

void init_I2C(void);
void Transmit(void);
void Receive(void);
void initUart(void);
void initGyro(void);

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1Mhz
  DCOCTL = CALDCO_1MHZ;
  //__delay_cycles(15000);                  // Wait gyro to wake up
  P1SEL |= BIT1 + BIT2 + BIT6 + BIT7;       // Assign I2C pins to USCI_B0 // Assign Uart pins to USCI_A0
  P2SEL |= BIT1 + BIT2 + BIT6 + BIT7;       // Assign I2C pins to USCI_B0 // Assign Uart pins to USCI_A0
  init_I2C();
  initUart();
  initGyro();
  init = 0;                                 // Flag to reading from configuration writing

  while(1) {
      switch(i2c_State) {
          case 0: // Wait state
            __delay_cycles(8000); // 10 ms
            i2c_State++;
            break;
          case 1: // Read X_High state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 2: // Read X_Low state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 3: // Read Y_High state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 4: // Read Y_Low state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 5: // Read Z_High state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 6: // Read Z_Low state
            Rx = 0; // Receive flag = transmit
            TXByteCtr = 1; // TXByteCtr 1 for sending register address and stop
            Transmit();  // I2C start condition with Write operation

            Rx = 1; // Receive flag = receive
            Receive();  // I2C start condition with Read operation
            i2c_State++;
            break;
          case 7:
            UCA0TXBUF = 0x58; // X
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x3A; // :
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = xRate_H;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = xRate_L;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x09; // tab
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            i2c_State++;
            break;
          case 8:
            UCA0TXBUF = 0x59; // Y
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x3A; // :
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = yRate_H;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = yRate_L;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x09; // tab
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            i2c_State++;
            break;
          case 9:
            UCA0TXBUF = 0x5A; // Z
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x3A; // :
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = zRate_H;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = zRate_L;
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x5C; // \
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            UCA0TXBUF = 0x6E; // n
            while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
            i2c_State = 0;
            break;
      } // End of state machine
  }
} // End of Main


 void readX_H() {
      if(Rx == 1){                              // Master Recieve
          xRate_H = UCB0RXBUF;                  // Get RXBuffer value to xRate_H
      }

      else {                                     // Master Transmit
          if (TXByteCtr) {                       // TX byte counter = 1 : send gyro address
              UCB0TXBUF = GYRO_XOUT_H;           // Load TX buffer // request from X_High register
              TXByteCtr--;                       // Decrement TX byte counter
          }
          else {                                      // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX interrupt flag
          }
      }
  }

  void readX_L() {
      if(Rx == 1){                              // Master Recieve
          xRate_L = UCB0RXBUF;                  // Get RXBuffer value to xRate_L
      }

      else {                                     // Master Transmit
          if (TXByteCtr) {                       // TX byte counter = 1 : send gyro address
              UCB0TXBUF = GYRO_XOUT_L;           // Load TX buffer // request from X_Low register
              TXByteCtr--;                       // Decrement TX byte counter
          }
          else {                                      // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX interrupt flag
          }
      }
  }

  void readY_H() {
      if(Rx == 1) {                              // Master Recieve
          yRate_H = UCB0RXBUF;                   // Get RXBuffer value to yRate_H
      }

      else {                                         // Master Transmit
          if (TXByteCtr) {                           // TX byte counter = 1 : send gyro address
              UCB0TXBUF = GYRO_YOUT_H;               // Load TX buffer // request from Y_High register
              TXByteCtr--;                           // Decrement TX byte counter
          }
          else {                                        // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                      // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                       // Clear USCI_B0 TX interrupt flag
          }
      }
  }

  void readY_L() {
      if(Rx == 1){                              // Master Recieve
          yRate_L = UCB0RXBUF;                  // Get RXBuffer value to yRate_L
      }

      else {                                     // Master Transmit
          if (TXByteCtr) {                       // TX byte counter = 1 : send gyro address
              UCB0TXBUF = GYRO_YOUT_L;           // Load TX buffer // request from Y_Low register
              TXByteCtr--;                       // Decrement TX byte counter
          }
          else {                                      // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX interrupt flag
          }
      }
  }


  void readZ_H() {
      if(Rx == 1){                              // Master Recieve
          zRate_H = UCB0RXBUF;                  // Get RXBuffer value to zRate_H
      }

      else {                                     // Master Transmit
          if (TXByteCtr) {                       // TX byte counter = 1 : send gyro address
              UCB0TXBUF = GYRO_ZOUT_H;           // Load TX buffer // request from Z_High register
              TXByteCtr--;                       // Decrement TX byte counter
          }
          else {                                      // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX interrupt flag
          }
      }
  }

  void readZ_L() {
      if(Rx == 1){                              // Master Recieve
          zRate_L = UCB0RXBUF;                   // Get RXBuffer value to zRate_L
      }

      else {                                     // Master Transmit
         if (TXByteCtr)  {                       // TX byte counter = 1 : send gyro address
             UCB0TXBUF = GYRO_ZOUT_L;            // Load TX buffer // request from Z_Low register
             TXByteCtr--;                        // Decrement TX byte counter
         }
         else {                                       // Tx byte counter = 0 : register address sent
              UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
              IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX interrupt flag
          }
      }
  }

  void initGyro(void) {
    TXByteCtr = 2;  // 2 bytes will occur. First register address send, Second Data send
    init = 1;       // config flag to 1 : Sending Divider value
    Transmit();     // Start condition with Writing mode
    init = 2;       // config flag to 2 : Sending Low pass filter value
    TXByteCtr = 2;  // Restart byte counter
    Transmit();     // Start condition with Writing mode
  }

  void init_I2C(void) {
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
      UCB0BR0 = 10;                             // fSCL = 1Mhz/10 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = itgAddress;                   // Slave Address is 069h
      UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      IE2 |= UCB0RXIE + UCB0TXIE;               // Enable RX and TX interrupt
  }
  void initUart(void) {
      UCA0CTL1 |= UCSSEL_2;                     // Use SMCLK
      UCA0BR0 = 104;                            // 1MHz 9600
      UCA0BR1 = 0;                              // 1MHz 9600
      UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  }
  void Transmit(void){
      while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
      UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX with start condition
      __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
  }
  void Receive(void){
        while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
        UCB0CTL1 &= ~UCTR ;                     // Clear I2C TX flag
        UCB0CTL1 |= UCTXSTT;                    // I2C start condition
        while (UCB0CTL1 & UCTXSTT);             // Start condition sent?
        UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
        __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
  }

  void twosCompToDecimal() {

  }

#pragma vector = USCIAB0TX_VECTOR       // USCI TX interrupt vector. I2C module share RX and TX interrupts.
__interrupt void USCIAB0TX_ISR(void)    // This will occur either when RXBuffer is full or TXBuffer is sent.
{
    if(init == 1) {                 // Gyro writing for configuration. Sending LPF register address
        if (TXByteCtr == 2) {       // byte counter = 2 : sending register address
            UCB0TXBUF = DLPF_FS;    // Low pass filter value register address to TXBuffer
            TXByteCtr--;            // Decrement TX byte counter
        }
        else if(TXByteCtr == 1) {                                       // byte counter = 1 : sending config value
              UCB0TXBUF = (DLPF_FS_SEL_0|DLPF_FS_SEL_1|DLPF_CFG_0);     // config value to TXBuffer
              TXByteCtr--;                                              // Decrement TX byte counter
        }
        else {                                      // byte counter = 0 : stop condition
            UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
            IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
            __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
        }
    }
    else if(init == 2) {                // Gyro writing for configuration. Sending Sample Rate Divider register address
        if (TXByteCtr == 2) {           // byte counter = 1 : sending config value
            UCB0TXBUF = SMPLRT_DIV;     // Sample Rate Divider value to TXBuffer
            TXByteCtr--;                // Decrement TX byte counter
        }
        else if(TXByteCtr == 1) {           // byte counter = 1 : sending config value
            UCB0TXBUF = 9;                  // config value to TXBuffer
            TXByteCtr--;                    // Decrement TX byte counter
        }
        else {                                      // byte counter = 0 : stop condition
            UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
            IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
            __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
        }
    }
    else {  // Gyro Reading operation.
      switch(i2c_State) {
          case 1: // Read X High
              readX_H();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
          case 2: // Read X Low
            readX_L();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
          case 3: // Read Y High
            readY_H();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
          case 4: // Read Y Low
            readY_L();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
         case 5: // Read Z High
            readZ_H();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
         case 6: // Read Z Low
            readZ_L();
            __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
              break;
      }
  }

}
于 2013-05-11T14:20:57.340 回答