請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
Young Hu:能说一下是什么类型的错误么?
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
Seven Han:请详细描述下您的问题,包括F28335和MPU6050通讯方式,硬件连接和代码。
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
S S85:
回复 Young Hu:
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
S S85:
回复 Seven Han:
我們使用I2C和SPI將F28335與MPU6050連接
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
S S85:
以下是我們在網路上找到的資源,我們拿此程式來測試陀螺儀與F28335的連接
#include "DSP2833x_Device.h"// DSP2833x Headerfile Include File #include "DSP2833x_Examples.h"// DSP2833x Examples Include File #include "MPU6050_Memmap.h"#define I2C_SLAVE_ADDR0x68//MPU Address #define I2C_NUMBYTES1 #define I2C_RNUMBYTES14//14 BytesBasic params according to 7 varities. #define Data_NUM7 #define SelftestAddr0x0d//讀自檢參數初地址 #define Recieve_Data0 #define Send_Data1 //#define //#define I2C_RTC_LOW_ADDR0x30// 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 voidInitI2C(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 interruptsDINT;//遮罩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 databufferScibRegs.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組裡的中斷序號1PieCtrlRegs.PIEIER8.bit.INTx1 = 1;//允許I2C中斷 //第9組的第4位為 SCIBTXINT3位 SCIBRXINTPieCtrlRegs.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 registersPieVectTable.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 exampleInitI2C();//初始化I2C相關資源 //-----------------$5 中斷初始化----------------------------------------------------------- // Step 5. Initial the SCI // MPU_Initial();InitSci();//初始化SCI// Enable CPU INT8 which is connected to PIE group 8IER |= 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 portionwhile(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 statusCurrentMsgPtr = &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 portionwhile(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 statusCurrentMsgPtr = &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 addressI2caRegs.I2CSAR = msg->SlaveAddress;//設置從設備位址// Check if bus busyif (I2caRegs.I2CSTR.bit.BB == 1)//匯流排繁忙{return I2C_BUS_BUSY_ERROR;//返回錯誤資訊}// Setup number of bytes to send// MsgBuffer + AddressI2caRegs.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 transmitterI2caRegs.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 busyif (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_WriteDataif (Error == I2C_SUCCESS){CurrentMsgPtr = &I2cMsgOut1;//需傳送的資料指標指向I2cMsgOut1I2cMsgOut1.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 sourceIntSource = I2caRegs.I2CISRC.all;DINT;// Interrupt source = stop condition detectedif(IntSource == I2C_SCD_ISRC){// If completed message was writing data, reset msg to inactive stateif (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 readyelse{// Generate some error due to invalid interrupt sourceasm("ESTOP0");//有錯誤的話,停止模擬,}// Enable future I2C (PIE Group 8) interruptsPieCtrlRegs.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組中斷}
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
Seven Han:
回复 S S85:
编译报错是因为InitSci()在工程中没有定义。
請問如何讓TMS320F28335接收到陀螺儀MPU6050的訊號?
已經寫出I2C和MPU6050的程式,但還是有錯誤導致28335接收不到訊號
S S85:
回复 Seven Han:
有找到InitSci也成功定義了,目前程式debug執行後並沒有錯誤,但我們讀到的陀螺儀Rparams值沒有改變,請問該如何解決?