|
一:MPU6050的寄存器操作
10.1 描述
内部寄存器可通过 400kHz 的 I2C 接口或 1MHz 的 SPI 接口来操作。
10.2 I2C 接口
二线接口,包括串行数据线(SDA)和串行时钟线(SCL)
。连接到 I2C 接口的备可做主设备或从设备。
主设备将 Slave 地址传到总线上,
从设备用与其匹配的地址来识别主设备。当连接到系统芯片时, MPU-60X0 总是作为从设备。 SDA 和 SCL 信号线通常需要接上拉电阻到 VDD。最大总线速率为 400kHz。MPU-60X0 的 Slave 地址为 b110100X,7 位字长,最低有效位 X 由 AD0 管脚上的逻辑电平决定。这样就可以允许两个 MPU-60X0 连接到同一条 I2C 总线,此时,一个设备的地址为 b1101000(AD0 为逻辑低电平)
,另一个为 b1101001(AD0 为逻辑高)。
时序要求:
二: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(不自检,2G,5Hz) ±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;
}