[技术问题解答] 求助!飞思卡尔调试MPU6050(IIC接口)

[复制链接]
 楼主| 夶人物 发表于 2015-11-10 15:04 | 显示全部楼层 |阅读模式
我用的是飞思卡尔MC9S12XEP100,现在在调试传感器MPU6050,可是遇到了问题,由于实在找不到解决的办法,所以在此求助!下面简单说一下我的问题:我在用CodeWarrior单步调试后,发现可以发送数据给MPU6050,但是在接收来自MPU6050的数据的时候,只能接收第一个字节的数据,然后主机就无法发送停止信号了,一直在那里等待总线空闲。当我注释掉等待空闲该语句时,下一个字节仍然发送不过来,就会一直停留在等待接收应答的语句上。我昨天就调了一天了,一直没结果,希望大家能帮我看看,下面是源代码
  1. #include <hidef.h>      /* common defines and macros */
  2. #include "derivative.h"      /* derivative-specific definitions */

  3. /*IIC0总线引脚定义*/
  4. #define SDA PTJ_PTJ6 //I2C0数据线
  5. #define SCL PTJ_PTJ7 //I2C0时钟线
  6. #define INT PTP_PTP7 //I2C0中断输出   

  7. /*IIC0总线引脚寄存器定义*/
  8. #define SDA_dir DDRJ_DDRJ6
  9. #define SCL_dir DDRJ_DDRJ7

  10. /* 定义MPU6050内部地址*/
  11. #define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
  12. #define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
  13. #define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  14. #define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  15. #define        ACCEL_XOUT_H        0x3B
  16. #define        ACCEL_XOUT_L        0x3C
  17. #define        ACCEL_YOUT_H        0x3D
  18. #define        ACCEL_YOUT_L        0x3E
  19. #define        ACCEL_ZOUT_H        0x3F
  20. #define        ACCEL_ZOUT_L        0x40
  21. #define        TEMP_OUT_H                0x41
  22. #define        TEMP_OUT_L                0x42
  23. #define        GYRO_XOUT_H                0x43
  24. #define        GYRO_XOUT_L                0x44       
  25. #define        GYRO_YOUT_H                0x45
  26. #define        GYRO_YOUT_L                0x46
  27. #define        GYRO_ZOUT_H                0x47
  28. #define        GYRO_ZOUT_L                0x48
  29. #define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
  30. #define        WHO_AM_I                        0x75        //IIC0地址寄存器(默认数值0x68,只读)
  31. #define        Slave_Address        0xD0        //IIC0写入时的地址字节数据,+1为读取(其中高7位表示IIC地址,最低1位表示读(0)还是写(1))

  32. #define somenop(); asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
  33.                    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
  34.                    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
  35.                    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");

  36. /*定义接收数据的变量*/
  37. int ACCEL_XOUT,ACCEL_YOUT,ACCEL_ZOUT,GYRO_XOUT,GYRO_YOUT,GYRO_ZOUT,Temperature;

  38. /*微妙级延时*/
  39. void Delay_ms(unsigned int t)//微妙级延时(系统时钟频率为32MHz的情况下)
  40. {
  41.   unsigned int i,j;
  42.   for(i=0;i<t;i++)
  43.     for(j=0;j<5318;j++)
  44.     {}
  45. }

  46. /*设置系统时钟频率为32MHz*/
  47. void Set_PLL(void)
  48. {
  49.   CLKSEL&=0x7f; //选择系统时钟源为OSCCLK,fBUS=fOSC/2;
  50.   PLLCTL&=0x8f; //关闭PLL并关闭IPLL的调频即FM[1:0]=0
  51.   SYNR=0x43;  //  配置系统所需的时钟频率
  52.   REFDV=0x81; //同上
  53.   POSTDIV=0x00; //同上
  54.   PLLCTL|=0x70; //再打开PLL
  55.   asm NOP;  //等待两个时钟周期
  56.   asm NOP;  //
  57.   while(!(CRG标志寄存器&0x08)); //等待PLLCLK稳定
  58.   CLKSEL|=0x80;   //最后再选择系统时钟频率为PLLCLK   
  59. }

  60. unsigned char IIC0_SingleByteRead(unsigned char register_address)
  61. {
  62.   unsigned char receive_data;
  63.   while(IIC0_IBSR_IBB); //检查IIC0总线是否空闲
  64.   
  65.   IIC0_IBCR_TX_RX=1;  //选择MCU作为发送模式
  66.   IIC0_IBCR_MS_SL=1; //MCU设置成主设备,产生开始信号
  67.   while(IIC0_IBSR_IBB==0);  //等待IIC0处于"忙"状态,即SDA=0,即已经检测到了开始信号
  68.   
  69.   IIC0_IBDR=Slave_Address;  //发送从设备的地址,最低一位是读(0)/写(1)
  70.   while(IIC0_IBSR_IBIF==0); //等待数据完成
  71.   IIC0_IBSR_IBIF=1;        //清除数据发送完成标志位
  72.   while(IIC0_IBSR_RXAK);   //等待接收应答,为0表示接收到了应答,1表示没有接收到应答
  73.   
  74.   IIC0_IBDR=register_address; //发送寄存器的地址
  75.   while(IIC0_IBSR_IBIF==0);  //等待数据传送完成
  76.   IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
  77.   while(IIC0_IBSR_RXAK);//等待接收应答
  78.   
  79.   IIC0_IBCR_TX_RX=1;  //设置为发送模式   
  80.   IIC0_IBCR_MS_SL=1;  //设置为主机模式,并产生开始信号
  81.   while(IIC0_IBSR_IBB==0);//等待SDA=0,即表示已经产生了开始信号

  82.   IIC0_IBDR=Slave_Address+1;//加1表示准备读取数据
  83.   while(IIC0_IBSR_IBIF==0);//等待数据接收完成
  84.   IIC0_IBSR_IBIF=1;  //清除标志位
  85.   while(IIC0_IBSR_RXAK); //等待接收应答
  86.   
  87.   IIC0_IBCR_TX_RX=0; //设置MCU为接收模式
  88.   IIC0_IBCR_TXAK=1;  //接受完一个字节的数据后不发送应答信号

  89.   receive_data=IIC0_IBDR;  //读取IIC0_IBDR准备下个字节的数据接收  
  90.   while(IIC0_IBSR_IBIF==0); //等待数据传送完成
  91.   IIC0_IBSR_IBIF=1;     //清除数据传送完成标志位

  92.   IIC0_IBCR_MS_SL=0; //产生停止信号
  93.   while(IIC0_IBSR_IBB);//等待IIC0总线空闲,即已发生停止信号
  94.   
  95.   receive_data=IIC0_IBDR; //读取接收到的数据
  96.   return receive_data;    //并返回该值  
  97. }

  98. void IIC0_SingleByteWrite(unsigned char register_address,unsigned char transmit_data)
  99. {
  100.   while(IIC0_IBSR_IBB); //检查IIC0总线是否空闲

  101.   IIC0_IBCR_TXAK=1;  //接受完一个字节的数据后发送应答信号
  102.   IIC0_IBCR_TX_RX=1; //设置为发送模式
  103.   
  104.   IIC0_IBCR_MS_SL=1; //设置为主机模式,并产生开始信号
  105.   while(IIC0_IBSR_IBB==0); //等待SDA=0

  106.   IIC0_IBDR=Slave_Address;  //发送从设备的地址
  107.   while(IIC0_IBSR_IBIF==0);  //等待数据传送完成
  108.   IIC0_IBSR_IBIF=1; //清除数据传送完成标志位
  109.   while(IIC0_IBSR_RXAK);//等待接收应答
  110.   
  111.   IIC0_IBDR=register_address; //发送寄存器地址
  112.   while(IIC0_IBSR_IBIF==0);  //等待数据传送完成
  113.   IIC0_IBSR_IBIF=1;  //清除数据传送完成标志位
  114.   while(IIC0_IBSR_RXAK); //等待接收应答
  115.   
  116.   IIC0_IBDR=transmit_data;  //发送需要发送的数据
  117.   while(IIC0_IBSR_IBIF==0);
  118.   IIC0_IBSR_IBIF=1;
  119.   while(IIC0_IBSR_RXAK);
  120.   
  121.   IIC0_IBCR_MS_SL=0; //产生停止信号
  122.   while(IIC0_IBSR_IBB);//等待IIC0总线空闲,即已发生停止信号
  123. }

  124. int GetData(unsigned char Register_Address)
  125. {
  126.   int whole_Data,Data_L,Data_H;
  127.   Data_H=IIC0_SingleByteRead(Register_Address);
  128.   Data_L=IIC0_SingleByteRead(Register_Address+1);
  129.   whole_Data=(Data_H<<8)|Data_L;
  130.   return whole_Data;
  131. }   

  132. void Init_IIC0(void)
  133. {
  134.   IIC0_IBCR_IBEN=1;  //IIC0使能
  135.   IIC0_IBFD=0x14;   //设置IIC0的主频为100KHz,系统主频为32MHz
  136.   IIC0_IBSR_IBAL=1; //清除标志位
  137.   IIC0_IBCR_IBIE=0;   //关闭IIC0中断
  138. }

  139. void Init_MPU6050(void)
  140. {
  141.   IIC0_SingleByteWrite(PWR_MGMT_1,0x00);
  142.   IIC0_SingleByteWrite(CONFIG,0x06);
  143.   IIC0_SingleByteWrite(SMPLRT_DIV,0x07);
  144.   IIC0_SingleByteWrite(GYRO_CONFIG,0x18);
  145.   IIC0_SingleByteWrite(ACCEL_CONFIG,0x01);
  146. }

  147. void main(void)
  148. {
  149.   Set_PLL();
  150.   Init_IIC0();
  151.   Init_MPU6050();
  152.         EnableInterrupts;
  153.   for(;;)
  154.   {
  155.     ACCEL_XOUT=GetData(ACCEL_XOUT_H);
  156.     ACCEL_YOUT=GetData(ACCEL_YOUT_H);
  157.     ACCEL_ZOUT=GetData(ACCEL_ZOUT_H);
  158.     GYRO_XOUT=GetData(GYRO_XOUT_H);
  159.     GYRO_YOUT=GetData(GYRO_YOUT_H);
  160.     GYRO_ZOUT=GetData(GYRO_ZOUT_H);
  161.     Temperature=GetData(TEMP_OUT_H); //读出温度原始值         
  162.   }
  163. }
 楼主| 夶人物 发表于 2015-11-10 15:24 | 显示全部楼层
各位!!各位!!我刚刚调出来啦!!!原来是读取数据子函数中的开始信号不能按照一开始一样发送开始信号,需要发送重复开始信号!也就是87、88行的代码换成 IIC0_IBCR_RSTA=1 ,就好了!!这贴子就留着吧,希望给那些跟我遇到同样问题的人一些帮助吧!
 楼主| 夶人物 发表于 2015-11-10 15:25 | 显示全部楼层
顺便说一下,定义的延时函数没什么卵用。。。
FSL_TICS_ZJJ 发表于 2015-11-10 16:16 | 显示全部楼层
夶人物 发表于 2015-11-10 15:24
各位!!各位!!我刚刚调出来啦!!!原来是读取数据子函数中的开始信号不能按照一开始一样发送开始信号, ...

感谢楼主分享自己的解决方案,如果问题解决了,还请帮我们结贴哦。
侣行天下 发表于 2015-11-10 20:32 | 显示全部楼层
夶人物 发表于 2015-11-10 15:24
各位!!各位!!我刚刚调出来啦!!!原来是读取数据子函数中的开始信号不能按照一开始一样发送开始信号, ...

谢谢楼主分享经验啊,学习了
 楼主| 夶人物 发表于 2015-12-7 21:40 | 显示全部楼层
夶人物 发表于 2015-11-10 15:25
顺便说一下,定义的延时函数没什么卵用。。。

哦,确实确实,那是刚开始用作模拟IIC时写的,后来忘记删了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

11

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部