企业网站建设的优缺点,小程序低代码开发平台,都江堰网站建设培训,网站开发培训班多少报名费IIC总线简介 IIC总线是Philips公司在八十年代初推出的一种串行、半双工总线 主要用于近距离、低速的芯片之间的通信#xff1b;IIC总线有两根双向的信号线一根数据线SDA用于收发数据#xff0c;一根时钟线SCL用于通信双方时钟的同步#xff1b;IIC总线硬件结构简单#xff…IIC总线简介 IIC总线是Philips公司在八十年代初推出的一种串行、半双工总线 主要用于近距离、低速的芯片之间的通信IIC总线有两根双向的信号线一根数据线SDA用于收发数据一根时钟线SCL用于通信双方时钟的同步IIC总线硬件结构简单成本较低因此在各个领域得到了广泛的应用 IIC总线是一种多主机总线连接在IIC总线上的器件分为主机和从机主机有权发起和结束一次通信而从机只能被主机呼叫当总线上有多个主机同时启用总线时IIC也具备冲突检测和仲裁的功能来防止错误产生 每个连接到IIC总线上的器件都有一个唯一的地址(7bit)且每个器件都可以作为主机也可以作为从机(同一时刻只能有一个主机),总线上的器件增加和删除不影响其他器件正常工作IIC总线在通信时总线上发送数据的器件为发送器接收数据的器件为接收器
IIC总线通信过程
1.主机发送起始信号启用总线2.主机发送一个字节数据指明从机地址和后续字节的传送方向3.被寻址的从机发送应答信号回应主机4.发送器发送一个字节数据5.接收器发送应答信号回应发送器… … 循环步骤4、5n.通信完成后主机发送停止信号释放总线
IIC总线寻址方式
IIC总线上传送的数据是广义的既包括地址又包括真正的数据主机在发送起始信号后必须先发送一个字节的数据该数据的高7位为从机地址最低位表示后续字节的传送方向0’表示主机发送数据1’表示主机接收数据总线上所有的从机接收到该字节数据后都将这7位地址与自己的地址进行比较如果相同则认为自己被主机寻址然后再根据第8位将自己定为发送器或接收器
起始信号和停止信号
SCL为高电平时SDA由高变低表示起始信号SCL为高电平时SDA由低变高表示停止信号起始信号和停止信号都是由主机发出起始信号产生后总线处于占用状态 停止信号产生后总线处于空闲状态 字节传送与应答
IIC总线通信时每个字节为8位长度数据传送时先传送最高位后传送低位发送器发送完一个字节数据后接收器必须发送1位应答位来回应发送器即一帧共有9位 同步信号
IIC总线在进行数据传送时时钟线SCL为低电平期间发送器向数据线上发送一位数据在此期间数据线上的信号允许发生变化时钟线SCL为高电平期间接收器从数据线上读取一位数据在此期间数据线上的信号不允许发生变化必须保持稳定 典型IIC时序 主机向从机发送数据 从机向主机发送数据 主机先向从机发送数据然后从机再向主机发送数据 注阴影部分表示数据由主机向从机传送无阴影部分则表示数据由从机向主机传送A表示应答 A非表示非应答S表示起始信号P表示终止信号
代码实现
#include exynos_4412.h/****************MPU6050内部寄存器地址****************/#define SMPLRT_DIV 0x19 //陀螺仪采样率典型值0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率典型值0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围典型值0x18(不自检2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率典型值0x18(不自检2G5Hz)
#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 //IIC地址寄存器(默认数值0x68只读)
#define SlaveAddress 0x68 //MPU6050-I2C地址void mydelay_ms(int time)
{int i,j;while(time--){for(i0;i5;i)for(j0;j514;j);}
}void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)
{/*对时钟源进行512倍预分频 打开IIC中断每次完成一个字节的收发后中断标志位会自动置位*/I2C5.I2CCON I2C5.I2CCON | (16) | (15);/*设置IIC模式为主机发送模式 使能IIC发送和接收*/I2C5.I2CSTAT 0xd0;/*将第一个字节的数据写入发送寄存器 即从机地址和读写位MPU6050-I2C地址写位0*/I2C5.I2CDS slave_addr1;/*设置IIC模式为主机发送模式 发送起始信号启用总线 使能IIC发送和接收*/I2C5.I2CSTAT 0xf0;/*等待从机接受完一个字节后产生应答信号应答后中断挂起位自动置位*/while(!(I2C5.I2CCON (14)));/*将要发送的第二个字节数据即MPU6050内部寄存器的地址写入发送寄存器*/I2C5.I2CDS addr;/*清除中断挂起标志位 开始下一个字节的发送*/I2C5.I2CCON I2C5.I2CCON (~(14));/*等待从机接受完一个字节后产生应答信号应答后中断挂起位自动置位*/while(!(I2C5.I2CCON (14)));/*将要发送的第三个字节数据即要写入到MPU6050内部指定的寄存器中的数据写入发送寄存器*/I2C5.I2CDS data;/*清除中断挂起标志位 开始下一个字节的发送*/I2C5.I2CCON I2C5.I2CCON (~(14));while(!(I2C5.I2CCON (14)));/*发送停止信号 结束本次通信*/I2C5.I2CSTAT 0xD0;/*清除中断挂起标志位*/I2C5.I2CCON I2C5.I2CCON (~(14));/*延时*/mydelay_ms(10);
}unsigned char iic_read(unsigned char slave_addr, unsigned char addr)
{unsigned char data 0;/*对时钟源进行512倍预分频 打开IIC中断每次完成一个字节的收发后中断标志位会自动置位*/I2C5.I2CCON I2C5.I2CCON | (16) | (15);/*设置IIC模式为主机发送模式 使能IIC发送和接收*/I2C5.I2CSTAT 0xd0;/*将第一个字节的数据写入发送寄存器 即从机地址和读写位MPU6050-I2C地址写位0*/I2C5.I2CDS slave_addr1;/*设置IIC模式为主机发送模式 发送起始信号启用总线 使能IIC发送和接收*/I2C5.I2CSTAT 0xf0;/*等待从机接受完一个字节后产生应答信号应答后中断挂起位自动置位*/while(!(I2C5.I2CCON (14)));/*将要发送的第二个字节数据即要读取的MPU6050内部寄存器的地址写入发送寄存器*/I2C5.I2CDS addr;/*清除中断挂起标志位 开始下一个字节的发送*/I2C5.I2CCON I2C5.I2CCON (~(14));/*等待从机接受完一个字节后产生应答信号应答后中断挂起位自动置位*/while(!(I2C5.I2CCON (14)));/*清除中断挂起标志位 重新开始一次通信 改变数据传送方向*/I2C5.I2CCON I2C5.I2CCON (~(14));/*将第一个字节的数据写入发送寄存器 即从机地址和读写位MPU6050-I2C地址读位1*/I2C5.I2CDS slave_addr 1 | 0x01;/*设置IIC为主机接收模式 发送起始信号 使能IIC收发*/I2C5.I2CSTAT 0xb0;/*等待从机接收到数据后应答*/while(!(I2C5.I2CCON (14)));/*禁止主机应答信号即开启非应答 因为只接收一个字节 清除中断标志位*/I2C5.I2CCON I2C5.I2CCON (~(17))(~(14));/*等待接收从机发来的数据*/while(!(I2C5.I2CCON (14)));/*将从机发来的数据读取*/data I2C5.I2CDS;/*直接发起停止信号结束本次通信*/I2C5.I2CSTAT 0x90;/*清除中断挂起标志位*/I2C5.I2CCON I2C5.I2CCON (~(14));/*延时等待停止信号稳定*/mydelay_ms(10);return data;
} void MPU6050_Init ()
{iic_write(SlaveAddress, PWR_MGMT_1, 0x00); //设置使用内部时钟8Miic_write(SlaveAddress, SMPLRT_DIV, 0x07); //设置陀螺仪采样率iic_write(SlaveAddress, CONFIG, 0x06); //设置数字低通滤波器iic_write(SlaveAddress, GYRO_CONFIG, 0x18); //设置陀螺仪量程-2000度/siic_write(SlaveAddress, ACCEL_CONFIG, 0x0); //设置加速度量程-2g
}int main(void)
{unsigned char zvalue_h,zvalue_l; //存储读取结果short int zvalue;/*设置GPB_2引脚和GPB_3引脚功能为I2C传输引脚*/GPB.CON (GPB.CON ~(0xF12)) | 0x312; //设置GPB_3引脚功能为I2C_5_SCLGPB.CON (GPB.CON ~(0xF8)) | 0x38; //设置GPB_2引脚功能为I2C_5_SDAuart_init(); //初始化串口MPU6050_Init(); //初始化MPU6050printf(\n********** I2C test!! ***********\n);while(1){zvalue_h iic_read(SlaveAddress, GYRO_ZOUT_H); //获取MPU6050-Z轴角速度高字节zvalue_l iic_read(SlaveAddress, GYRO_ZOUT_L); //获取MPU6050-Z轴角速度低字节zvalue (zvalue_h8)|zvalue_l; //获取MPU6050-Z轴角速度printf( GYRO--Z :Hex: %d \n, zvalue); //打印MPU6050-Z轴角速度mydelay_ms(100);}return 0;
}