This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335與MPU6050連接

Other Parts Discussed in Thread: TMS320F28335

TMS320F28335有讀取到陀螺儀MPU6050的值,但改變陀螺儀的角度後,F28335讀取到的值並未改變,請問該如何解決?

  • 请详细描述下您的问题,硬件接线和软件代码,以便论坛更好帮助到您!
  • 這是我們在網上找到的陀螺儀與I2C程式碼,目前程式debug執行後並沒有錯誤,但我們讀取(陀螺儀)程式碼中的Rparams值沒有改變,請問該如何解決?
    
    
    #include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
    #include "DSP2833x_Examples.h"   // DSP2833x Examples Include File
    #include "MPU6050_Memmap.h"
    
    #define I2C_SLAVE_ADDR       0x68  //MPU Address
    #define I2C_NUMBYTES          1
    #define I2C_RNUMBYTES         14  //14 Bytes  Basic params according to 7 varities.
    #define Data_NUM            7
    #define SelftestAddr    0x0d   //讀自檢參數初地址
    #define Recieve_Data    0
    #define Send_Data     1
    //#define
    //#define I2C_RTC_LOW_ADDR   0x30
    
    // Note: I2C Macros used in this example can be found in the
    // DSP2833x_I2C_defines.h file
    
    // Prototype statements for functions found within this file.
    extern void  InitI2C(void);   //初始化I2CA的中斷資源函數 in file ‘DSP2833x_I2C’
    extern void SCIB_Initial(void);//初始化SCIB
    void MPU_Initial(void); //初始化MPU6050工作模式函數
    Uint16 I2CA_WriteData(struct I2CMSG *msg);  //向匯流排寫一幀資料
    Uint16 I2CA_ReadData(struct I2CMSG *msg);  //從匯流排讀一幀資料
    void WriteData(struct I2CMSG *msg,Uint16 *MsgBuffer,Uint16 MemoryAdd,Uint16 NumOfBytes);  //連續寫資料
    interrupt void i2c_int1a_isr(void);  //I2C 中斷服務副程式
    interrupt void scib_int_isr(void); //SCI 中斷服務副程式
    void pass(void);  //通過?
    void fail(void); //失敗?
    
    // Global variables
    // One byte will be used for the outgoing address,
    struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,  //初始化一個輸出資料幀 {狀態、MPU位址、位元組數,內部位址}
                              I2C_SLAVE_ADDR,
                              I2C_NUMBYTES,
                              SelftestAddr};
    
    
    struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP, //初始化一個讀入資料幀 {狀態、MPU位址、位元組數,內部位址}
                              I2C_SLAVE_ADDR,
                              I2C_RNUMBYTES,
                              ACCEL_XOUT_H};
    
    struct I2CMSG *CurrentMsgPtr;       // Used in interrupts 當前消息指標
    //參數表,通過查表給MPU寫入參數值 :{內部位址,值}
    const Uint16 Wparam[][2] =
       {
           // {寄存器位址,寄存器值},
           //------(暫時沒用)-----------------
           //{SELF_TEST_X,},
           //{SELF_TEST_Y,},
           //{SELF_TEST_Z,},
           //{SELF_TEST_A,},
           {PWR_MGMT_1,1}, // 退出睡眠模式,設取樣時鐘為陀螺X軸。
           //{PWR_MGMT_2,0},
           {SMPLRT_DIV,4}, // 取樣時鐘4分頻,1k/4,取樣率為25Hz。
           {CONFIG,2    }, // 低通濾波,截止頻率100Hz左右。
           {GYRO_CONFIG,0<<3  }, // 陀螺量程 0:250dps;1:500dps;2:1000dps,3:2000dps。
           {ACCEL_CONFIG,0<<3 }, // 加速度計量程0:2g; 1: 4g;    2:8g; 3:16g。
    //     {I2C_MST_CTRL,0},    //MPU不作為主設備使用
           {INT_PIN_CFG,0x32  }, // 中斷信號為高電平,推挽輸出,直到有讀取操作才消失,直通輔助I2C。
           {INT_ENALE,1       }, // 使用“資料準備好”中斷。
           {USER_CTRL,0x00  },  // 不使用輔助I2C。
           //{FIFO_R_W,0},            //
       };
    Uint16 PassCount; //跳過的次數統計
    Uint16 FailCount; //失敗統計
    Uint16 Sys_stat;
    Uint16 Rparams[Data_NUM];//data need to be read
    Uint16 ACCEL_X;   //give their names.
    Uint16 ACCEL_Y;
    Uint16 ACCEL_Z;
    Uint16 TEMP;
    Uint16 GYRO_X;
    Uint16 GYRO_Y;
    Uint16 GYRO_Z;
    int16 databuffer[I2C_RNUMBYTES];  //暫存感測器8位元資料;
    
    
    //*====================================$0 主程序=================================================*/
    void main(void)
    {
       Uint16 i;
       CurrentMsgPtr = &I2cMsgOut1;//當前需發送的資料;
    //-----------------$1 系統初始化----------------------------------------------------------
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
       InitSysCtrl();    //初始化系統控制塊
    //  InitPeripheralClocks(); //初始化外設時鐘   included in the InitSysCtrl()
    //-----------------$2 GPIO----------------------------------------------------------
    // Step 2. Initalize GPIO:
    // This example function is found in the DSP2833x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio();
    // Setup only the GP I/O only for I2C functionality
    // 相關GPIO的設置在I2C 、SCI初始化中完成,如果需要對其他GPIO進行設置,可以在這裡加入代碼
    //-----------------$3 配置中斷-----------------------------------------------------------
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
      DINT;   //遮罩CPU中斷
    // Initialize PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    
    
    // Disable CPU interrupts and clear all CPU interrupt flags:
       IER = 0x0000;  //遮罩所有中斷
       IFR = 0x0000;  //清空中斷標誌位元
    
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
    // This function is found in DSP2833x_PieVect.c.
    
       InitPieCtrl();  //初始化外設向量控制寄存器
       InitPieVectTable();  //初始化外設中斷向量表
       //清零數據緩衝區
          for(i=0;i<I2C_RNUMBYTES;i+=1)
            {
            databuffer[i]=0;  //clear databuffer
            ScibRegs.SCITXBUF==databuffer[i];  //putdata into txbuffer
             }
            i=0;
            PassCount=0;
            FailCount=0;
     // Enable interrupts required for this example
    // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
    //I2C中斷為第8組裡的中斷序號1
       PieCtrlRegs.PIEIER8.bit.INTx1 = 1;//允許I2C中斷
    //第9組的第4位為 SCIBTXINT  3位 SCIBRXINT
       PieCtrlRegs.PIEIER9.bit.INTx4 = 1;//允許SCIB TX中斷
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
       EALLOW;  // This is needed to write to EALLOW protected registers
       PieVectTable.I2CINT1A = &i2c_int1a_isr;   //指定I2C中斷服務副程式
       PieVectTable.SCITXINTB = &scib_int_isr;  //指定SCI的中斷服務副程式
       EDIS;   // This is needed to disable write to EALLOW protected registers
       //-----------------$4 外設初始化-----------------------------------------------------------
    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP2833x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
       InitI2C();  //初始化I2C相關資源
    //-----------------$5 中斷初始化-----------------------------------------------------------
    // Step 5. Initial the SCI
    // MPU_Initial();
       InitSci();  //初始化SCI
    
    // Enable CPU INT8 which is connected to PIE group 8
       IER |= M_INT8; //允許向CPU發送中斷
       IER |= M_INT9; //是否放到I2C結束後再允許?
       EINT;  //開放CPU中斷
       ERTM;  //開全域中斷
       Sys_stat=Recieve_Data;
       I2cMsgOut1.MsgStatus = I2C_MSGSTAT_SEND_WITHSTOP;
    //   param_msg.SlaveAddress=I2C_SLAVE_ADDR;
      // param_msg.NumOfBytes=Wnum;
    //*--------------------$6 主循環體--------------------------------------------------------------*/
       for(;;)
       {
          //////////////////////////////////
          // Write data to MPU CTRL section //
          //////////////////////////////////
          
          // Check the outgoing message to see if it should be sent.
          // In this example it is initialized to send with a stop bit.
    
       if(Sys_stat==Recieve_Data)
        {
           I2caRegs.I2CFFRX.bit.RXFFIENA=1; //允許I2C中斷
          // I2caRegs.I2CFFRX.bit.RXFFINTCLR=1;
           ScibRegs.SCIFFTX.bit.TXFFINTCLR=0; //遮罩TX FF中斷
           ScibRegs.SCIFFTX.bit.TXFFIENA=0;
    
           if(I2cMsgOut1.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)
            {
              DELAY_US(100000); //延時約700us,等待匯流排穩定
              MPU_Initial(); //初始化MPU6050
    
              }  // end of write section
    
          ///////////////////////////////////
          // Read data from RTC section //
          ///////////////////////////////////
    
          // Check outgoing message status. Bypass read section if status is
          // not inactive.
             if (I2cMsgOut1.MsgStatus == I2C_MSGSTAT_INACTIVE)
            {
             // Check incoming message status.
                if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)//無停止位發送
                  {
                // MPU address setup portion
                  while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS) //讀數據失敗
                  {
                   // Maybe setup an attempt counter to break an infinite while
                   // loop. The RTC will send back a NACK while it is performing
                   // a write operation. Even though the write communique is
                   // complete at this point, the RTC could still be busy
                   // programming the data. Therefore, multiple attempts are
                   // necessary.
                      if(FailCount>20|PassCount>20){break;}
                }
                // Update current message pointer and message status
                CurrentMsgPtr = &I2cMsgIn1;  //消息指標指向輸入資料
                I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY;
             }
    
             // Once message has progressed past setting up the internal address
             // of the RTC, send a restart to read the data bytes from the
             // RTC. Complete the communique with a stop bit. MsgStatus is
             // updated in the interrupt service routine.
             else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART)
             {
                DELAY_US(100000);
    //   $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
               //讀取MPU6050的14個連續位址資料
                for(i=0;i<I2C_RNUMBYTES;i+=1)
                  { 
                    databuffer[i]= I2cMsgIn1.MsgBuffer[i];  //get the Byte DATA from MPU
                   }
                i=0;
                   ACCEL_X=Rparams[0];   //give their names.
                   ACCEL_Y=Rparams[1];
                   ACCEL_Z=Rparams[2];
                   TEMP=Rparams[3];
                   GYRO_X=Rparams[4];
                   GYRO_Y=Rparams[5];
                   GYRO_Z=Rparams[6];
                // Read data portion
    
    
                while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)
                {
                   // Maybe setup an attempt counter to break an infinite while
                   // loop.
                    if(FailCount>20|PassCount>20){break;}
                }//end of while;
                // Update current message pointer and message status
                CurrentMsgPtr = &I2cMsgIn1;                //指定要讀取的數據
                I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY;  //匯流排修改為讀繁忙狀態
                Sys_stat=Send_Data;
                ScibRegs.SCIFFTX.bit.TXFFIENA=1; //開串口TX FIFO中斷;
                ScibRegs.SCIFFTX.bit.TXFFINTCLR=1;//清除FIFO中斷標誌
    
             }
    
          } // end of read section
    
    
    
       }//end if(Sys_stat)
       else if(Sys_stat==Send_Data)
       {
           while(!ScibRegs.SCICTL2.bit.TXRDY){};//等待發送匯流排空閒
            ScibRegs.SCIFFTX.bit.TXFFIENA=1;
            I2caRegs.I2CFFRX.bit.RXFFIENA=0;
            I2caRegs.I2CFFRX.bit.RXFFINTCLR=0;//
    
       }
       else
       {
         Sys_stat=Recieve_Data;
       }
    
    
    
    
       }   // end of for(;;)
    }   // end of main
    
    
    /*-----------------------------------------------初始化函數-------------------------------------------------------*/
    void MPU_Initial()
    {
    //Uint16 tested;
    Uint16 Wnum,i,PTR,CONTENT;
    //struct I2CMSG param_msg;  //定義一個資料幀結構體變數
    //functions need to be realized:
    //1. registers configuration
    Wnum=sizeof(Wparam)/2;   //get the size of param_pairs.
    //param_msg.MsgStatus=I2C_MSGSTAT_SEND_WITHSTOP;  //選定發送方式,發送一個資料給一個停止位元
    //param_msg.SlaveAddress=I2C_SLAVE_ADDR;    //I2C從地址
    //param_msg.NumOfBytes=Wnum;   //寫的位元組數
       for(i=0;i<Wnum;i++)     //查參數表,給MPU寄存器賦值
          {
             PTR=Wparam[i][1];    //取出需傳送的資料值
             CONTENT=Wparam[i][0];   //MPU內部位址
             WriteData(&I2cMsgOut1,&PTR,CONTENT,1);              //write the param to MPU6050 register
     //取一個數,傳送一個能否修改為一次傳送14個數?
           }
    }
    
    
    /*-----------------------------------------------$7 I2C讀寫函數-------------------------------------------------------*/
    
    Uint16 I2CA_WriteData(struct I2CMSG *msg)
    {
       Uint16 i;
    
       // Wait until the STP bit is cleared from any previous master communication.
       // Clearing of this bit by the module is delayed until after the SCD bit is
       // set. If this bit is not checked prior to initiating a new message, the
       // I2C could get confused.
       if (I2caRegs.I2CMDR.bit.STP == 1)  //如果停止位為1
       {
          return I2C_STP_NOT_READY_ERROR;  //返回錯誤資訊
       }
    
       // Setup slave address
       I2caRegs.I2CSAR = msg->SlaveAddress;  //設置從設備位址
    
       // Check if bus busy
       if (I2caRegs.I2CSTR.bit.BB == 1)  //匯流排繁忙
       {
          return I2C_BUS_BUSY_ERROR;  //返回錯誤資訊
       }
    
       // Setup number of bytes to send
       // MsgBuffer + Address
       I2caRegs.I2CCNT = msg->NumOfBytes+1; //還需加上從設備位址 1個位元組
       // Setup data to send
      // I2caRegs.I2CDXR = msg->MemoryHighAddr;
       I2caRegs.I2CDXR = msg->MPUAddr; //位址資料讀入寄存器
    // for (i=0; i<msg->NumOfBytes-2; i++)
       for (i=0; i<msg->NumOfBytes; i++) //通過I2C的FIFO連續讀取14個參數
       {
          I2caRegs.I2CDXR = *(msg->MsgBuffer+i); //寫資料存到發送寄存器
       }
    
       // Send start as master transmitter
       I2caRegs.I2CMDR.all = 0x6E20;  //設定I2C工作模式
    
       return I2C_SUCCESS;  //返回成功信號
    }
    
    
    Uint16 I2CA_ReadData(struct I2CMSG *msg)
    {
       // Wait until the STP bit is cleared from any previous master communication.
       // Clearing of this bit by the module is delayed until after the SCD bit is
       // set. If this bit is not checked prior to initiating a new message, the
       // I2C could get confused.
       if (I2caRegs.I2CMDR.bit.STP == 1)
       {
          return I2C_STP_NOT_READY_ERROR;   //如果STP位為1,則報錯
       }
    
       I2caRegs.I2CSAR = msg->SlaveAddress; //設定從設備位址
    
       if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)
       {
          // Check if bus busy
          if (I2caRegs.I2CSTR.bit.BB == 1)//現在繁忙
          {
             return I2C_BUS_BUSY_ERROR;  //返回錯誤資訊
          }
          I2caRegs.I2CCNT = 1;//傳幾位元組的位址
    //      I2caRegs.I2CDXR = msg->MemoryHighAddr;
          I2caRegs.I2CDXR = msg->MPUAddr; //位址發往寄存器
          I2caRegs.I2CMDR.all = 0x2620;         // Send data to setup MPU address 發送地址
       }  //發送從設備位址
       else if(msg->MsgStatus == I2C_MSGSTAT_RESTART)
       {
          I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect //數據長度
          I2caRegs.I2CMDR.all = 0x2C20;         // Send restart as master receiver //發送資料
       }
    
       return I2C_SUCCESS;  //返回傳輸成功狀態信號
    }
    
    //連續向I2C匯流排寫資料
    void WriteData(struct I2CMSG *msg,Uint16 *MsgBuffer,Uint16 MemoryAdd,Uint16 NumOfBytes)
    {
        Uint16 i,Error;
        for(i = 0; i < I2C_RNUMBYTES; i++)
        {
            msg->MsgBuffer[i] = MsgBuffer[i];        //將資料傳送至結構體的附加陣列
        }
        //msg->MemoryHighAddr = MemoryAdd >> 8;
        msg->MPUAddr = MemoryAdd & 0xff;  //取低8位
        msg->NumOfBytes = NumOfBytes;  //寫幾個位元組
        Error = I2CA_WriteData(&I2cMsgOut1); //調用I2CA_WriteData
    
        if (Error == I2C_SUCCESS)
        {
            CurrentMsgPtr = &I2cMsgOut1;    //需傳送的資料指標指向I2cMsgOut1
            I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
        }
        while(I2cMsgOut1.MsgStatus != I2C_MSGSTAT_INACTIVE);
        DELAY_US(1000);
    }
    
    
    void pass()
    {
        asm("  ESTOP0");  //跳過,停止模擬
        PassCount++;
       // for(;;);
    }
    
    void fail()
    {
        asm("  ESTOP0");  //出錯,跟pass同樣的作用
        FailCount++;
       // for(;;);
    }
    
    
    //*--------------------------------中斷服務副程式--------------------------------*/
    interrupt void i2c_int1a_isr(void)     // I2CA 中斷服務副程式
    {
       Uint16 IntSource, i;
      // ScibRegs.SCIFFTX.bit.TXFFIENA=0;
       // Read interrupt source
       IntSource = I2caRegs.I2CISRC.all;
      DINT;
       // Interrupt source = stop condition detected
       if(IntSource == I2C_SCD_ISRC)
       {
          // If completed message was writing data, reset msg to inactive state
          if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY)
          {
             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;  //將資訊狀態修改為繁忙
          }
          else
          {
             // If a message receives a NACK during the address setup portion of the
             // RTC read, the code further below included in the register access ready
             // interrupt source code will generate a stop condition. After the stop
             // condition is received (here), set the message status to try again.
             // User may want to limit the number of retries before generating an error.
             if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
             {
                CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
             }
             // If completed message was reading RTC data, reset msg to inactive state
             // and read data from FIFO.
             else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY)
             {
                CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;//I2C_MSGSTAT_INACTIVE;
                for(i=0; i < CurrentMsgPtr->NumOfBytes; i++)  //read 14data from MPU and save them in MsgBuffer
                {
                  CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR;  //連續讀取FIFO寄存器的資料
                }
             }
            // ScibRegs.SCIFFTX.bit.TXFFIENA=1;
          }
       }  // end of stop condition detected
       // Interrupt source = Register Access Ready
       // This interrupt is used to determine when the RTC address setup portion of the
       // read data communication is complete. Since no stop bit is commanded, this flag
       // tells us when the message has been sent instead of the SCD flag. If a NACK is
       // received, clear the NACK bit and command a stop. Otherwise, move on to the read
       // data portion of the communication.
       else if(IntSource == I2C_ARDY_ISRC)
       {
          if(I2caRegs.I2CSTR.bit.NACK == 1)
          {
             I2caRegs.I2CMDR.bit.STP = 1;
             I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
          }
          else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
          {
             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;  //重定消息狀態
          }
       }  // end of register access ready
    
       else
       {
          // Generate some error due to invalid interrupt source
          asm("   ESTOP0");  //有錯誤的話,停止模擬,
       }
    
       // Enable future I2C (PIE Group 8) interrupts
    
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP8 | PIEACK_GROUP9; //使能外設中斷 第8組
      //同時使能第9組中斷
       EINT;
    }
    
    interrupt void scib_int_isr(void)
    {
        Uint16 i;
    
    
        for(i=0;i<I2C_RNUMBYTES;i++)  //連續發送14個位元組到 SCIFIFO
        {
            ScibRegs.SCITXBUF=databuffer[i];
        }
    
        //
        ScibRegs.SCIFFTX.bit.TXFFINTCLR=1;//清除FIFO中斷標誌
        Sys_stat=Recieve_Data;
    
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP8 | PIEACK_GROUP9;  //使能外設中斷 第8組同時使能第9組中斷
    
    }

  • 代码里没有看到对数组Rparams进行操作呢,数组databuffer有数据吗?

  • 改變陀螺儀角度之後,MsgBuffer的值並沒有跟著改變

  • 想請問作者問題有解決了嗎,是如何解決的,我們也遇到同樣的問題。

  • 你好,我近期在學習28335與MPU6050並參考了上面的程式碼,但對於I2C的讀取不是很理解,請問要如何對Rparams進行操作呢?

    為何MsgBuffer的值亦沒有變化呢?

  • 看看这个链接的分享 (