我用的是飞思卡尔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); //读出温度原始值
}
}
|