我用的是飞思卡尔MC9S12XEP100,现在在调试传感器MPU6050,可是遇到了问题,由于实在找不到解决的办法,所以在此求助!下面简单说一下我的问题:我在用CodeWarrior单步调试后,发现可以发送数据给MPU6050,但是在接收来自MPU6050的数据的时候,只能接收第一个字节的数据,然后主机就无法发送停止信号了,一直在那里等待总线空闲。当我注释掉等待空闲该语句时,下一个字节仍然发送不过来,就会一直停留在等待接收应答的语句上。我昨天就调了一天了,一直没结果,希望大家能帮我看看,下面是源代码
- #include <hidef.h> /* common defines and macros */
- #include "derivative.h" /* derivative-specific definitions */
- /*IIC0总线引脚定义*/
- #define SDA PTJ_PTJ6 //I2C0数据线
- #define SCL PTJ_PTJ7 //I2C0时钟线
- #define INT PTP_PTP7 //I2C0中断输出
- /*IIC0总线引脚寄存器定义*/
- #define SDA_dir DDRJ_DDRJ6
- #define SCL_dir DDRJ_DDRJ7
- /* 定义MPU6050内部地址*/
- #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
- #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
- #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
- #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
- #define ACCEL_XOUT_H 0x3B
- #define ACCEL_XOUT_L 0x3C
- #define ACCEL_YOUT_H 0x3D
- #define ACCEL_YOUT_L 0x3E
- #define ACCEL_ZOUT_H 0x3F
- #define ACCEL_ZOUT_L 0x40
- #define TEMP_OUT_H 0x41
- #define TEMP_OUT_L 0x42
- #define GYRO_XOUT_H 0x43
- #define GYRO_XOUT_L 0x44
- #define GYRO_YOUT_H 0x45
- #define GYRO_YOUT_L 0x46
- #define GYRO_ZOUT_H 0x47
- #define GYRO_ZOUT_L 0x48
- #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
- #define WHO_AM_I 0x75 //IIC0地址寄存器(默认数值0x68,只读)
- #define Slave_Address 0xD0 //IIC0写入时的地址字节数据,+1为读取(其中高7位表示IIC地址,最低1位表示读(0)还是写(1))
- #define somenop(); asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
- asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
- asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
- asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
- /*定义接收数据的变量*/
- int ACCEL_XOUT,ACCEL_YOUT,ACCEL_ZOUT,GYRO_XOUT,GYRO_YOUT,GYRO_ZOUT,Temperature;
- /*微妙级延时*/
- void Delay_ms(unsigned int t)//微妙级延时(系统时钟频率为32MHz的情况下)
- {
- unsigned int i,j;
- for(i=0;i<t;i++)
- for(j=0;j<5318;j++)
- {}
- }
- /*设置系统时钟频率为32MHz*/
- void Set_PLL(void)
- {
- CLKSEL&=0x7f; //选择系统时钟源为OSCCLK,fBUS=fOSC/2;
- PLLCTL&=0x8f; //关闭PLL并关闭IPLL的调频即FM[1:0]=0
- SYNR=0x43; // 配置系统所需的时钟频率
- REFDV=0x81; //同上
- POSTDIV=0x00; //同上
- PLLCTL|=0x70; //再打开PLL
- asm NOP; //等待两个时钟周期
- asm NOP; //
- while(!(CRG标志寄存器&0x08)); //等待PLLCLK稳定
- CLKSEL|=0x80; //最后再选择系统时钟频率为PLLCLK
- }
- unsigned char IIC0_SingleByteRead(unsigned char register_address)
- {
- unsigned char receive_data;
- while(IIC0_IBSR_IBB); //检查IIC0总线是否空闲
-
- IIC0_IBCR_TX_RX=1; //选择MCU作为发送模式
- IIC0_IBCR_MS_SL=1; //MCU设置成主设备,产生开始信号
- while(IIC0_IBSR_IBB==0); //等待IIC0处于"忙"状态,即SDA=0,即已经检测到了开始信号
-
- IIC0_IBDR=Slave_Address; //发送从设备的地址,最低一位是读(0)/写(1)
- while(IIC0_IBSR_IBIF==0); //等待数据完成
- IIC0_IBSR_IBIF=1; //清除数据发送完成标志位
- while(IIC0_IBSR_RXAK); //等待接收应答,为0表示接收到了应答,1表示没有接收到应答
-
- IIC0_IBDR=register_address; //发送寄存器的地址
- while(IIC0_IBSR_IBIF==0); //等待数据传送完成
- IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
- while(IIC0_IBSR_RXAK);//等待接收应答
-
- IIC0_IBCR_TX_RX=1; //设置为发送模式
- IIC0_IBCR_MS_SL=1; //设置为主机模式,并产生开始信号
- while(IIC0_IBSR_IBB==0);//等待SDA=0,即表示已经产生了开始信号
- IIC0_IBDR=Slave_Address+1;//加1表示准备读取数据
- while(IIC0_IBSR_IBIF==0);//等待数据接收完成
- IIC0_IBSR_IBIF=1; //清除标志位
- while(IIC0_IBSR_RXAK); //等待接收应答
-
- IIC0_IBCR_TX_RX=0; //设置MCU为接收模式
- IIC0_IBCR_TXAK=1; //接受完一个字节的数据后不发送应答信号
- receive_data=IIC0_IBDR; //读取IIC0_IBDR准备下个字节的数据接收
- while(IIC0_IBSR_IBIF==0); //等待数据传送完成
- IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
- IIC0_IBCR_MS_SL=0; //产生停止信号
- while(IIC0_IBSR_IBB);//等待IIC0总线空闲,即已发生停止信号
-
- receive_data=IIC0_IBDR; //读取接收到的数据
- return receive_data; //并返回该值
- }
- void IIC0_SingleByteWrite(unsigned char register_address,unsigned char transmit_data)
- {
- while(IIC0_IBSR_IBB); //检查IIC0总线是否空闲
- IIC0_IBCR_TXAK=1; //接受完一个字节的数据后发送应答信号
- IIC0_IBCR_TX_RX=1; //设置为发送模式
-
- IIC0_IBCR_MS_SL=1; //设置为主机模式,并产生开始信号
- while(IIC0_IBSR_IBB==0); //等待SDA=0
-
- IIC0_IBDR=Slave_Address; //发送从设备的地址
- while(IIC0_IBSR_IBIF==0); //等待数据传送完成
- IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
- while(IIC0_IBSR_RXAK);//等待接收应答
-
- IIC0_IBDR=register_address; //发送寄存器地址
- while(IIC0_IBSR_IBIF==0); //等待数据传送完成
- IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
- while(IIC0_IBSR_RXAK); //等待接收应答
-
- IIC0_IBDR=transmit_data; //发送需要发送的数据
- while(IIC0_IBSR_IBIF==0);
- IIC0_IBSR_IBIF=1;
- while(IIC0_IBSR_RXAK);
-
- IIC0_IBCR_MS_SL=0; //产生停止信号
- while(IIC0_IBSR_IBB);//等待IIC0总线空闲,即已发生停止信号
- }
- int GetData(unsigned char Register_Address)
- {
- int whole_Data,Data_L,Data_H;
- Data_H=IIC0_SingleByteRead(Register_Address);
- Data_L=IIC0_SingleByteRead(Register_Address+1);
- whole_Data=(Data_H<<8)|Data_L;
- return whole_Data;
- }
- void Init_IIC0(void)
- {
- IIC0_IBCR_IBEN=1; //IIC0使能
- IIC0_IBFD=0x14; //设置IIC0的主频为100KHz,系统主频为32MHz
- IIC0_IBSR_IBAL=1; //清除标志位
- IIC0_IBCR_IBIE=0; //关闭IIC0中断
- }
- void Init_MPU6050(void)
- {
- IIC0_SingleByteWrite(PWR_MGMT_1,0x00);
- IIC0_SingleByteWrite(CONFIG,0x06);
- IIC0_SingleByteWrite(SMPLRT_DIV,0x07);
- IIC0_SingleByteWrite(GYRO_CONFIG,0x18);
- IIC0_SingleByteWrite(ACCEL_CONFIG,0x01);
- }
- void main(void)
- {
- Set_PLL();
- Init_IIC0();
- Init_MPU6050();
- EnableInterrupts;
- for(;;)
- {
- ACCEL_XOUT=GetData(ACCEL_XOUT_H);
- ACCEL_YOUT=GetData(ACCEL_YOUT_H);
- ACCEL_ZOUT=GetData(ACCEL_ZOUT_H);
- GYRO_XOUT=GetData(GYRO_XOUT_H);
- GYRO_YOUT=GetData(GYRO_YOUT_H);
- GYRO_ZOUT=GetData(GYRO_ZOUT_H);
- Temperature=GetData(TEMP_OUT_H); //读出温度原始值
- }
- }
|