Giao tiếp I2C giữa MSP430G2553 và MPS430G2452

Phạm Thành Danh

Thành Viên PIF
Hiện em muốn kết nối I2C giữa con g2553 và con g2452 (vì k mua được g2553 nữa :gach) nhưng không biết làm sao cả, code I2C của con g2452 khác nhau quá. Em muốn dùng g2553 làm master , g2452 làm slave để gửi một mảng 2 số từ master tới slave.Anh chị nào từng dùng qua thì giúp em với nhé!!. Em có thử code như thế này nhưng không thành công, nó bị treo ở dòng while ở master.
Master code:
Code:
{
      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 = 0x58;                        // Slave Address is 058h
      UCB0CTL1 &= ~UCSWRST;                    // Clear SW reset, resume operation
      //IE2 |= UCB0TXIE;
    // _BIS_SR(GIE);
      TxData[0]=hour;
      TxData[1]=min;
 
      PTxData = (unsigned char *)TxData;      // TX array start address
          TXByteCtr = sizeof TxData;              // Load TX byte counter
          /*while (UCB0CTL1 & UCTXSTP);            // Ensure stop condition got sent
          UCB0CTL1 |= UCTR + UCTXSTT;
          _BIS_SR(GIE);*/
          while (UCB0CTL1 & UCTXSTP);                // Loop until I2C STT is sent
          UCB0CTL1 |= UCTR + UCTXSTT;                // I2C TX, start condition
          while (!(IFG2&UCB0TXIFG));
              unsigned char i;
              for( i=0;i<TXByteCtr;i++)
              {
                  UCB0TXBUF= *(PTxData+i) ;
                  while (!(IFG2&UCB0TXIFG));
              }
              UCB0CTL1 |= UCTXSTP;                      // I2C stop condition after 1st TX
              IFG2 &= ~UCB0TXIFG;                        // Clear USCI_B0 TX int flag
Slave code
Code:
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                // Stop watchdog
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
  {
    while(1);                              // If calibration constants erased
                                            // do not load, trap CPU!!
  }
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  P2SEL &=  ~(BIT6 +BIT0+ BIT7+BIT1 +BIT2 +BIT3 +BIT4); // 2.6,2.7 are GPIO
  P2SEL2 &=  ~(BIT6 + BIT0+ BIT7+BIT1 +BIT2 +BIT3 +BIT4);
  P1SEL &= ~(d1+d2+d3+d4);
  P1SEL2 &= ~(d1+d2+d3+d4);
  P1DIR |=(d1+d2+d3+d4);
  P2DIR |=( BIT0 + BIT1 + BIT2+BIT3 +BIT4);
  while(1)
  {
  Setup_USI_Slave();
  PRxData = (unsigned char *)data;
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
{
  if (USICTL1 & USISTTIFG)                  // Start entry?
  {
    //P1OUT |= 0x01;                          // LED on: sequence start
    I2C_State = 2;                          // Enter 1st state on start
  }
 
  switch(__even_in_range(I2C_State,14))
    {
      case 0:                               // Idle, should not get here
              break;
 
      case 2: // RX Address
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
              USICTL1 &= ~USISTTIFG;        // Clear start flag
              I2C_State = 4;                // Go to next state: check address
              break;
 
      case 4: // Process Address and send (N)Ack
              if (USISRL & 0x01){            // If master read...
                SLV_Addr = 0xB1;             // Save R/W bit
                transmit = 1;}
              else{transmit = 0;
                  SLV_Addr = 0xB0;}
              USICTL0 |= USIOE;             // SDA = output
              if (USISRL == SLV_Addr)       // Address match?
              {
                USISRL = 0x00;              // Send Ack
               // P1OUT &= ~0x01;             // LED off
                if (transmit == 0){
                  I2C_State = 6;}           // Go to next state: RX data
                if (transmit == 1){
                  I2C_State = 10;}          // Else go to next state: TX data
              }
              else
              {
                USISRL = 0xFF;              // Send NAck
               // P1OUT |= 0x01;              // LED on: error
                I2C_State = 8;              // next state: prep for next Start
              }
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
              break;
 
    case 6: // Receive data byte
              Data_RX();
              break;
 
      case 8:// Check Data & TX (N)Ack
              USICTL0 |= USIOE;             // SDA = output
              if (Bytecount <= (Number_of_Bytes-2))
                                            // If not last byte
              {
           *PRxData++ = USISRL;
                USISRL = 0x00;              // Send Ack
                I2C_State = 6;              // Rcv another byte
                Bytecount++;
                USICNT |= 0x01;             // Bit counter = 1, send (N)Ack bit
              }
              else                          // Last Byte
              {
                USISRL = 0xFF;              // Send NAck
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0xB0;              // Reset slave address
              I2C_State = 0;                // Reset state machine
              Bytecount =0;                 // Reset counter for next TX/RX
              }
 
 
              break;
 
     case 10: // Send Data byte
              TX_Data();
              break;
 
      case 12:// Receive Data (N)Ack
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack
              I2C_State = 14;               // Go to next state: check (N)Ack
              break;
 
      case 14:// Process Data Ack/NAck
           if (USISRL & 0x01)               // If Nack received...
              {
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0xB0;              // Reset slave address
              I2C_State = 0;                // Reset state machine
               Bytecount = 0;
             // LPM0_EXIT;                  // Exit active for next transfer
              }
              else                          // Ack received
              {
                //P1OUT &= ~0x01;             // LED off
                TX_Data();                  // TX next byte
               }
      break;
 
      }
  USICTL1 &= ~USIIFG;                       // Clear pending flags
}
 
void Data_RX(void){
 
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |=  0x08;              // Bit counter = 8, RX data
              I2C_State = 8;                // next state: Test data and (N)Ack
}
 
void TX_Data(void){
              USICTL0 |= USIOE;             // SDA = output
              USISRL = SLV_Data++;
              USICNT |=  0x08;              // Bit counter = 8, TX data
              I2C_State = 12;               // Go to next state: receive (N)Ack
}
 
void Setup_USI_Slave(void){
  //P1OUT = 0xC0;                             // P1.6 & P1.7 Pullups
  //P1REN |= 0xC0;                            // P1.6 & P1.7 Pullups
  //P1DIR = 0xFF;                             // Unused pins as outputs
  //P2OUT = 0;
  //P2DIR = 0xFF;
P1SEL |= BIT6 + BIT7;                      // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7;
 
  USICTL0 = USIPE6+USIPE7+USISWRST;         // Port & USI mode setup
  USICTL1 = USII2C+USIIE+USISTTIE;          // Enable I2C mode & USI interrupts
  USICKCTL = USICKPL;                       // Setup clock polarity
  USICNT |= USIIFGCC;                       // Disable automatic clear control
  USICTL0 &= ~USISWRST;                     // Enable USI
  USICTL1 &= ~USIIFG;                       // Clear pending flag
 
  transmit = 0;
  _EINT();
 
}
:9cool_too_sad:
 
Top