chenyuejian的笔记 https://bbs.21ic.com/?871710 [收藏] [复制] [RSS]

日志

PIC18读取MPU6050传感器

已有 2503 次阅读2013-2-27 15:05 |系统分类:单片机

一:MPU6050的寄存器操作



10.1 描述



内部寄存器可通过 400kHz I2C 接口或 1MHz SPI 接口来操作。



10.2 I2C 接口



二线接口,包括串行数据线(SDA)和串行时钟线(SCL
。连接到 I2C 接口的备可做主设备或从设备。
主设备将 Slave 地址传到总线上,
从设备用与其匹配的地址来识别主设备。当连接到系统芯片时, MPU-60X0 总是作为从设备。 SDA SCL 信号线通常需要接上拉电阻到 VDD。最大总线速率为 400kHzMPU-60X0 Slave 地址为 b110100X7 位字长,最低有效位 X AD0 管脚上的逻辑电平决定。这样就可以允许两个 MPU-60X0 连接到同一条 I2C 总线,此时,一个设备的地址为 b1101000AD0 为逻辑低电平)
,另一个为 b1101001AD0 为逻辑高)。



时序要求:






  
  
  
  
  
  
  
  
  
  
  
  











 



二:PIC18F内部的MSSP主控模块I2C模式:



I²C函数



下列函数支持I2C外设:





  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  
  


  

函数


  

  

简述


  

  

AckI2C


  

  

生成I2C总线应答信号(Acknowledge condition)


  

  

CloseI2C


  

  

屏蔽SSP(同步串行口)模块。


  

  

DataRdyI2C


  

  

I2C缓存中的数据是否可用?


  

  

getsI2C


  

  

在主I2C模式下,从I2C总线读取1个字符串。


  

  

IdleI2C


  

  

循环直到I2C总线出现空闲。


  

  

NotAckI2C


  

  

生成I2C总线不应答信号(Not Acknowledge condition)


  

  

OpenI2C


  

  

设置SSP模块。


  

  

WriteI2C


  

putcI2C


  

  

I2C总线写入1个字节。


  

  

putsI2C


  

  

在主或从模式下,向I2C总线写入1个字符串。


  

  

ReadI2C


  

getcI2C


  

  

I2C总线读取1个字节。


  

  

RestartI2C


  

  

生成I2C总线Restart信号。


  

  

StartI2C


  

  

生成I2C总线START信号。


  

  

StopI2C


  

  

生成I2C总线STOP信号。


  


 



应用以上的库程序,可以有效的节省开发周期。但还需对设置流程,工作原理进行阅读理解,否者容易出错。本次调试过程中,就由于未设置BRG寄存器使开发拖延了近一天



 



/***************PIC18F4550程序:***********************/



void Initi2c()



{



         unsigned char sync_mode;



         unsigned char slew;



         sync_mode = MASTER;



         slew = SLEW_ON;



         //20MHz,产生400k IIC频率,SSPADDR =
Fosc/4/baud-1=20M/4/400k-1=11



         SSPADD = 0x0c;  //385khz



         OpenI2C( sync_mode, slew );



        



}



//**************************************



//MPU6050设备写入一个字节数据



//**************************************



void
Single_WriteI2C(unsigned char REG_Address,unsigned char REG_data)



{



    IdleI2C();                                                //
initiate START condition



    StartI2C();            



    WriteI2C(SlaveAddress);               //发送设备地址+写信号       



    WriteI2C(REG_Address);                       //内部寄存器地址,



    WriteI2C(REG_data);                         //内部寄存器数据,



    StopI2C();                      // send STOP condition



}



//**************************************



//MPU6050设备读取一个字节数据



//**************************************



unsigned char
Single_ReadI2C(unsigned char REG_Address)



{



         unsigned char REG_data;



         IdleI2C();



         StartI2C();                   //send start condition



         WriteI2C(SlaveAddress);       //发送设备地址+写信号



         WriteI2C(REG_Address);        //发送存储单元地址,从0开始 



         IdleI2C();



         StartI2C();                   //起始信号



         WriteI2C(SlaveAddress+1);     //发送设备地址+读信号



         REG_data = ReadI2C();                        //read in single byte



         NotAckI2C();                  // send  ACK condition



         StopI2C();                    //send stop condition



         return REG_data;



}



void InitMPU6050()



{



         unsigned char sync_mode;



         unsigned char slew;



         sync_mode = MASTER;



         slew = SLEW_ON;



         //20MHz,产生400k IIC频率,SSPADDR =
Fosc/4/baud-1=20M/4/400k-1=11



         //385khz



         SSPADD = 0x0c;



         OpenI2C( sync_mode, slew );



         Single_WriteI2C(PWR_MGMT_1, 0x00);          //解除休眠状态



         Single_WriteI2C(SMPLRT_DIV, 0x07);      //陀螺仪采样率,典型值:0x07(125Hz)



         Single_WriteI2C(F_CONFIG, 0x06);           //低通滤波频率,典型值:0x06(5Hz)



         Single_WriteI2C(GYRO_CONFIG, 0x18);  //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)   0x00 
250



         Single_WriteI2C(ACCEL_CONFIG, 0x01); //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G5Hz)    ±4g 8192LSB/g



}



int GetData(unsigned
char REG_Address)



{



         char H,L;



         H=Single_ReadI2C(REG_Address);



         L=Single_ReadI2C(REG_Address+1);



         return (H<<8)+L;   //合成数据



}



Void main()



{



         int Accx=0;



         int temp=0;     



         while(1)



         {                                   



                   InitMPU6050();



                   //Accx=GetData(ACCEL_XOUT_H);



                   temp=GetData(TEMP_OUT_H);



                   CloseI2C();      



                   Display(4,temp);              



         }



}



//-----------------------



//几个重要的源函数



//------------------------



void OpenI2C( unsigned char
sync_mode, unsigned char
slew )



{



  SSPSTAT &= 0x3F;                //
power on state



  SSPCON1 = 0x00;                 //
power on state



  SSPCON2 = 0x00;                 //
power on state



  SSPCON1 |= sync_mode;           // select
serial mode



  SSPSTAT |= slew;                //
slew rate on/off



 



  I2C_SCL = 1;



  I2C_SDA = 1;



  SSPCON1 |= SSPENB;              //
enable synchronous serial port



 



}



signed char WriteI2C( unsigned
char data_out )



{



  SSPBUF = data_out;           // write
single byte to SSPBUF



  if (
SSPCON1bits.WCOL )      // test if write collision occurred



   return ( -1
);              //
if WCOL bit is set return negative #



  else



  {



     if(
((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) )  //Slave mode only



     {



          
SSPCON1bits.CKP = 1;        // release clock line



          
while ( !PIR1bits.SSPIF );  // wait until ninth
clock pulse received



 



          
if ( ( !SSPSTATbits.R_W ) && (
!SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was
received



          
{



            
return ( -2 );           //return
NACK



          
}



          
else



          
{



              return
( 0 );               //return ACK



          



     }



     else if( ((SSPCON1&0x0F)==0x08) ||
((SSPCON1&0x0F)==0x0B) )  //master mode only



     {



         while( SSPSTATbits.BF );   // wait until
write cycle is complete  



        
IdleI2C();                 // ensure module is idle



         if ( SSPCON2bits.ACKSTAT ) //
test for ACK condition received



           return ( -2 );             // return NACK



         else return ( 0 );              //return
ACK



     }



    



  }



}



unsigned char ReadI2C( void )



{



if( ((SSPCON1&0x0F)==0x08) ||
((SSPCON1&0x0F)==0x0B) )  //master mode only



  SSPCON2bits.RCEN = 1;           // enable
master for 1 byte reception



  while (
!SSPSTATbits.BF );      // wait until byte received 



  return (
SSPBUF );              // return with read byte



}



void AckI2C( void )



{



  SSPCON2bits.ACKDT = 0;           // set
acknowledge bit state for ACK



  SSPCON2bits.ACKEN = 1;           //
initiate bus acknowledge sequence



}



void IdleI2C( void )



{



  while ( (
SSPCON2 & 0x1F ) || ( SSPSTATbits.R_W ) )



     continue;



}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)