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

TMS320F28335連接MPU6050

我們在網路上找到以下程式碼,但是無法讀取MPU6050的data,請問問題在哪裡呢?

#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組中斷

}

mangui zhang:我觉得SPI比较好用,如果用I2C的话,看看I2C 从地址的地址由引脚9(AD0)设置(一般接地)怎么处理的,
检测一下地址是否正常,有响应吗?

我們在網路上找到以下程式碼,但是無法讀取MPU6050的data,請問問題在哪裡呢?

#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組中斷

}

Chia Yu Chang:

回复 mangui zhang:

你好,檢測後仍沒有任何變化。

我查到別人的說明是程式碼內沒有對Rparams動作,但對此項說明不是很了解,是否能為我說明一下,謝謝~

我們在網路上找到以下程式碼,但是無法讀取MPU6050的data,請問問題在哪裡呢?

#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組中斷

}

mangui zhang:

回复 Chia Yu Chang:

MPU6050.docx有双通道示波器的话先看看IIC设备有没有响应ACK

附件是其他控制器的  请参考

我們在網路上找到以下程式碼,但是無法讀取MPU6050的data,請問問題在哪裡呢?

#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組中斷

}

Chia Yu Chang:

回复 mangui zhang:

確認是ACK沒有動作,只有接收到NACK,但程式碼我不曉得從何修改,是否能為我解惑?

赞(0)
未经允许不得转载:TI中文支持网 » TMS320F28335連接MPU6050
分享到: 更多 (0)