Exynos_4412——IIC控制器和MPU6050

news/2024/11/29 10:36:47/

目录

一、Exynos_4412下的IIC控制器

二、IIC寄存器

三、MPU6050原理

MPU6050

MPU6050的主要参数

MPU6050通信接口

MPU6050官方芯片手册 

 MPU6050寄存器

四、MPU6050寄存器读写时序

向MPU6050写一个字节数据

向MPU6050读一个字节数据

五、IIC编程

六、小项目


Exynos_4412——IIC总线概述_宇努力学习的博客-CSDN博客

一、Exynos_4412下的IIC控制器

 4412有四个IIC,如果要使用需要配置四个寄存器;

I2CCON  配置一些功能

I2CSTAT   控制一些功能、显示一些状态

I2CDS     发送和接收数据

I2CADD   当4142作为从机时需要一个地址,这个寄存器用于设置地址

极少数IIC的地址是10位的,标准模式下最快速度是100K,快速模式下可以达到400k,支持主机发送主机接收,从机发送从机接收,支持中断和轮询

 

 

主机发送模式下4412的工作过程

 

主机接收模式下的4412工作流程

由于主控很少作为从机另外两个模式就不看了

二、IIC寄存器

 

【7】接收到一个字节数据后是否产生应答信号   1产生   0不产生

【6】分频,影响IIC的通信速度。

【5】中断的开关,IIC在接收和发送一个信号后都会产生一个中断信号通知你

【4】当中断产生这位自动置1,在处理完中断信号后要写成0

【3:0】影响IIC的通信速度,改变时钟频率

 

【7:6】模式选择

【5】起始和停止信号

【4】就是总线收发的开关

【3:0】只能读,表示IIC的状态

 

 

滤波器和延时用不上就不设置了 

三、MPU6050原理

MPU6050

    MPU6050是一个运动处理传感器,其内部集成了3轴加速度传感器和3轴陀螺仪(角速度传感器),以及一个可扩展数字运动处理器。

MPU6050的主要参数

    可测量X、Y、Z轴三个方向的角速度

    可编程设置角速度测量范围为±250、±500、±1000、±2000°/sec

    可测量X、Y、Z轴三个方向的加速度

    可编程设置加速度测量范围为±2g、±4g、±8g、±16g

    可编程设置低功耗模式

    可编程设置采样频率

     ... ...

MPU6050通信接口

    MPU6050可以使用IIC总线和其他器件进行数据交互,我们可以使用IIC总线向MPU6050中的控制寄存器写入数据来设置MPU6050的工作参数,也可以使用IIC总线从MPU6050中的数据寄存器读取数据来获取加速度、角速度等信息。

 

MPU6050官方芯片手册 

 

 

 

 MPU6050寄存器

 

 

我们主要是使用4412而不是MPU6050,会常用的几个寄存器就行:

 

/****************MPU6050内部常用寄存器地址****************/

#define    SMPLRT_DIV        0x19    //陀螺仪采样率,典型值:0x07(125Hz)
#define    CONFIG            0x1A    //低通滤波频率,典型值:0x06(5Hz)
#define    GYRO_CONFIG        0x1B    //陀螺仪自检及测量范围,典型值:0x18(不自检,2000°/s)
#define    ACCEL_CONFIG    0x1C    //加速计自检及测量范围及高通滤波频率,典型值:0x0(不自检,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    SlaveAddress    0x68    //MPU6050-I2C地址

三轴加速度三轴角速度和温度的传感器值可通过这些寄存器读取

 

它的IIC地址有两个一个0x68一个0x69,他的地址由ADO决定

 

所以他的地址是0x68,为了避免冲突所以可以改地址。

四、MPU6050寄存器读写时序

MPU6050 在设计的时候只能作为从机

向MPU6050写一个字节数据

1.主机(Exynos4412)发送起始信号

2.主机发送从机地址(MPU6050的地址)及读写方向(写)

3.从机(MPU6050)发送应答信号

4.主机发送一个字节数据(要写的寄存器的地址)

5.从机发送应答信号

6.主机发送一个字节数据(要写到寄存器的数据)

7.从机发送应答信号
8.主机发送停止信号

向MPU6050读一个字节数据

1.主机(Exynos4412)发送起始信号

2.主机发送从机地址(MPU6050的地址)及读写方向(写)

3.从机(MPU6050)发送应答信号

4.主机发送一个字节数据(要写的寄存器的地址)

5.从机发送应答信号

6.主机(Exynos4412)发送起始信号

7.主机发送从机地址(MPU6050的地址)及读写方向(读)
8.从机(MPU6050)发送应答信号

9.从机发送一个字节数据(要读的寄存器中的数据)

10.主机发送非应答信号(不再接收更多的数据)

11.主机发送停止信号

五、IIC编程

算一下延时

4412的工作频率是200M-1.4G 

 

 找了半天没找到,这个时钟频率是可以配置的,然后在手册中并没有关于4412的指令周期和时钟周期关系的描述。所以没法算这个浪费CPU资源的延时具体是几,老师给了一毫秒的延时函数,先拿来直接用吧,等以后知道这些数据了再来算一算。

开始写程序吧;


#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(不自检,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	//IIC地址寄存器(默认数值0x68,只读)
#define	SlaveAddress	0x68	//MPU6050-I2C地址/************************延时函数************************/void mydelay_ms(int time)
{int i,j;while(time--){for(i=0;i<5;i++)for(j=0;j<514;j++);}
}/*********************************************************************** 函数功能:I2C向特定地址写一个字节* 输入参数:* 		slave_addr: I2C从机地址* 			  addr: 芯片内部特定地址* 			  data:写入的数据
**********************************************************************/void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)
{/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第三个字节数据(即要写入到MPU6050内部指定的寄存器中的数据)写入发送寄存器*/I2C5.I2CDS = data;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*发送停止信号  结束本次通信*/I2C5.I2CSTAT = 0xD0;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时*/mydelay_ms(10);
}/*********************************************************************** 函数功能:I2C从特定地址读取1个字节的数据* 输入参数:         slave_addr: I2C从机地址* 			       addr: 芯片内部特定地址* 返回参数: unsigned char: 读取的数值
**********************************************************************/unsigned char iic_read(unsigned char slave_addr, unsigned char addr)
{unsigned char data = 0;/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即要读取的MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*清除中断挂起标志位  重新开始一次通信  改变数据传送方向*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+读位1)*/I2C5.I2CDS = slave_addr << 1 | 0x01;/*设置IIC为主机接收模式  发送起始信号  使能IIC收发*/I2C5.I2CSTAT = 0xb0;/*等待从机接收到数据后应答*/while(!(I2C5.I2CCON & (1<<4)));/*禁止主机应答信号(即开启非应答  因为只接收一个字节)  清除中断标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<7))&(~(1<<4));/*等待接收从机发来的数据*/while(!(I2C5.I2CCON & (1<<4)));/*将从机发来的数据读取*/data = I2C5.I2CDS;/*直接发起停止信号结束本次通信*/I2C5.I2CSTAT = 0x90;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时等待停止信号稳定*/mydelay_ms(10);return data;}/*********************************************************************** 函数功能:MPU6050初始化
**********************************************************************/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 & ~(0xF<<12)) | 0x3<<12;			 	//设置GPB_3引脚功能为I2C_5_SCLGPB.CON = (GPB.CON & ~(0xF<<8))  | 0x3<<8;				//设置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_h<<8)|zvalue_l;					//获取MPU6050-Z轴角速度printf(" GYRO--Z  :Hex: %d	\n", zvalue);			//打印MPU6050-Z轴角速度mydelay_ms(100);}return 0;
}

 

 

由于没有校准也没设置滤波所以正常情况下不是0正常应该是0的,然后逆时针是正数顺时针是负数 。

六、小项目

综合项目:
实时监测开发板的放置状态,当监测到开发板水平放置时,每隔一分钟向终端上打印一次当前的时间以及开发板的状态
如:“2023-04-05 23:45:00 Status: Normal”
当监测到开发板发生倾斜时,每隔一秒钟向终端上打印一次当前的时间以及开发板的状态
如:“2023-04-05 23:45:00 Status: Warning”
同时让蜂鸣器产生“滴滴”的警报声,在警报状态下,若按下Key2按键,解除蜂鸣器的警报声
提示:
开发板水平静止放置时MPU6050的Z轴上的加速度应该等于重力加速度的值(9.8m/s2),而其X轴和Y轴上的加速度应该等于0
当开发板发生倾斜时MPU6050的Z轴上的加速度的分量会减小,而其X轴和Y轴上的加速度分量会增大
我们可以以此来判断开发板是否发生倾斜


#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(不自检,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	//IIC地址寄存器(默认数值0x68,只读)
#define	SlaveAddress	0x68	//MPU6050-I2C地址/************************延时函数************************/void mydelay_ms(int time)
{int i,j;while(time--){for(i=0;i<5;i++)for(j=0;j<514;j++);}
}/*********************************************************************** 函数功能:I2C向特定地址写一个字节* 输入参数:* 		slave_addr: I2C从机地址* 			  addr: 芯片内部特定地址* 			  data:写入的数据
**********************************************************************/void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)
{/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第三个字节数据(即要写入到MPU6050内部指定的寄存器中的数据)写入发送寄存器*/I2C5.I2CDS = data;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*发送停止信号  结束本次通信*/I2C5.I2CSTAT = 0xD0;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时*/mydelay_ms(10);
}/*********************************************************************** 函数功能:I2C从特定地址读取1个字节的数据* 输入参数:         slave_addr: I2C从机地址* 			       addr: 芯片内部特定地址* 返回参数: unsigned char: 读取的数值
**********************************************************************/unsigned char iic_read(unsigned char slave_addr, unsigned char addr)
{unsigned char data = 0;/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即要读取的MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*清除中断挂起标志位  重新开始一次通信  改变数据传送方向*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+读位1)*/I2C5.I2CDS = slave_addr << 1 | 0x01;/*设置IIC为主机接收模式  发送起始信号  使能IIC收发*/I2C5.I2CSTAT = 0xb0;/*等待从机接收到数据后应答*/while(!(I2C5.I2CCON & (1<<4)));/*禁止主机应答信号(即开启非应答  因为只接收一个字节)  清除中断标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<7))&(~(1<<4));/*等待接收从机发来的数据*/while(!(I2C5.I2CCON & (1<<4)));/*将从机发来的数据读取*/data = I2C5.I2CDS;/*直接发起停止信号结束本次通信*/I2C5.I2CSTAT = 0x90;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时等待停止信号稳定*/mydelay_ms(10);return data;}/*********************************************************************** 函数功能:MPU6050初始化
**********************************************************************/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
}/*********************************************************************** 函数功能:RTC初始化
**********************************************************************/void RTC_Init()
{//使能RTC控制RTCCON = RTCCON | 1;//校准时间RTC.BCDYEAR = 0x023; //000000100011  2023RTC.BCDMON  = 0x1;   //1RTC.BCDDAY  = 0x8;   //8RTC.BCDWEEK = 0x7;   //星期RTC.BCDHOUR = 0x11;  //11RTC.BCDMIN  = 0x32;  //32RTC.BCDSEC  = 0x50;  //50s//关闭RTC控制RTCCON = RTCCON & 0;}/*********************************************************************** 函数功能:BEEP初始化
**********************************************************************/void BEEP_Init()
{//GPD0_0设置PWM0输出功能GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);//PWM0一级分频  100倍PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | (99);//PWM0二级分频  1倍  PCLk/(99+1)/(0+1) = 1MHzPWM.TCFG1 = PWM.TCFG1 & (~(0xF));//设置PWM0自动重装 PWM.TCON = PWM.TCON | (1<<3);//设置周期 1000PWM.TCNTB0 = 1000;//占空比 60%PWM.TCMPB0 = 600;//手动装载PWM.TCON = PWM.TCON | (1 << 1);//关闭手动装载PWM.TCON = PWM.TCON & (~(1 << 1));//使能PWM0PWM.TCON = PWM.TCON | 1;
}/*********************************************************************** 函数功能:主函数**********************************************************************/int main(void)
{//存储读取结果unsigned char zvalue_h,zvalue_l,xvalue_h,xvalue_l,yvalue_h,yvalue_l;						short int zvalue,xvalue,yvalue;/*设置GPB_2引脚和GPB_3引脚功能为I2C传输引脚*/GPB.CON = (GPB.CON & ~(0xF<<12)) | 0x3<<12;			 		//设置GPB_3引脚功能为I2C_5_SCLGPB.CON = (GPB.CON & ~(0xF<<8))  | 0x3<<8;					//设置GPB_2引脚功能为I2C_5_SDAuart_init(); 												//初始化串口MPU6050_Init();												//初始化MPU6050RTC_Init();													//RTC初始化BEEP_Init();												//BEEP初始化printf("\n********** I2C test!! ***********\n");while(1){zvalue_h = iic_read(SlaveAddress, ACCEL_ZOUT_H);		//获取MPU6050-Z轴加速度高字节zvalue_l = iic_read(SlaveAddress, ACCEL_ZOUT_L);		//获取MPU6050-Z轴加速度低字节zvalue  =  (zvalue_h<<8)|zvalue_l;						//获取MPU6050-Z轴加速度xvalue_h = iic_read(SlaveAddress, ACCEL_XOUT_H);		//获取MPU6050-Z轴加速度高字节xvalue_l = iic_read(SlaveAddress, ACCEL_XOUT_L);		//获取MPU6050-Z轴加速度低字节xvalue  =  (xvalue_h<<8)|xvalue_l;						//获取MPU6050-Z轴加速度yvalue_h = iic_read(SlaveAddress, ACCEL_YOUT_H);		//获取MPU6050-Z轴加速度高字节yvalue_l = iic_read(SlaveAddress, ACCEL_YOUT_L);		//获取MPU6050-Z轴加速度低字节yvalue  =  (yvalue_h<<8)|yvalue_l;						//获取MPU6050-Z轴加速度printf("20%x-%x-%x %x %x:%x:%x  Status: Normal\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);printf(" GYRO--Z  :Hex: %d	\n", zvalue);				//打印MPU6050-Z轴加速度mydelay_ms(100);}return 0;
}

先试试打印加速度

可以打印。

但是蜂鸣器一直响,关闭蜂鸣器,打印三个轴看看

 

桌面不平,所以数值上有差异我就用这个作为水平面的数据了。

加速度的量程要改一下改成16G才能读到正确值,但是我们不需要读取正确值,我们需要的是变化量 ,倾斜开发板的加速度是很小的,正常这种测试应该用角速度的,可能老师想锻炼一下我们用加速度,所以我们就用最小量程也就是最高精度的加速度来做倾斜检测,不对正常应该是结合使用的,角速度转完就没有了,加速度只要倾斜就是一直改变的。所以我们设置一个报警区间当Z小于一个值,X或Y大于一个值时发出警告:

我设置它Z小于19000X或Y大于1000时发出警告,对了还有反方向呢

设置的好像太苛刻了,不动的时候就开响

 

这次没问题了,但是开始会响一下就当提示音了。

 

完整的修改好的代码如下:


#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(不自检,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	//IIC地址寄存器(默认数值0x68,只读)
#define	SlaveAddress	0x68	//MPU6050-I2C地址/************************延时函数************************/void mydelay_ms(int time)
{int i,j;while(time--){for(i=0;i<5;i++)for(j=0;j<514;j++);}
}/*********************************************************************** 函数功能:I2C向特定地址写一个字节* 输入参数:* 		slave_addr: I2C从机地址* 			  addr: 芯片内部特定地址* 			  data:写入的数据
**********************************************************************/void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)
{/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第三个字节数据(即要写入到MPU6050内部指定的寄存器中的数据)写入发送寄存器*/I2C5.I2CDS = data;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*发送停止信号  结束本次通信*/I2C5.I2CSTAT = 0xD0;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时*/mydelay_ms(10);
}/*********************************************************************** 函数功能:I2C从特定地址读取1个字节的数据* 输入参数:         slave_addr: I2C从机地址* 			       addr: 芯片内部特定地址* 返回参数: unsigned char: 读取的数值
**********************************************************************/unsigned char iic_read(unsigned char slave_addr, unsigned char addr)
{unsigned char data = 0;/*对时钟源进行512倍预分频  打开IIC中断(每次完成一个字节的收发后中断标志位会自动置位)*/I2C5.I2CCON = I2C5.I2CCON | (1<<6) | (1<<5);/*设置IIC模式为主机发送模式  使能IIC发送和接收*/I2C5.I2CSTAT = 0xd0;/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+写位0)*/I2C5.I2CDS = slave_addr<<1;/*设置IIC模式为主机发送模式  发送起始信号启用总线  使能IIC发送和接收*/I2C5.I2CSTAT = 0xf0;/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*将要发送的第二个字节数据(即要读取的MPU6050内部寄存器的地址)写入发送寄存器*/I2C5.I2CDS = addr;/*清除中断挂起标志位  开始下一个字节的发送*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*等待从机接受完一个字节后产生应答信号(应答后中断挂起位自动置位)*/while(!(I2C5.I2CCON & (1<<4)));/*清除中断挂起标志位  重新开始一次通信  改变数据传送方向*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*将第一个字节的数据写入发送寄存器  即从机地址和读写位(MPU6050-I2C地址+读位1)*/I2C5.I2CDS = slave_addr << 1 | 0x01;/*设置IIC为主机接收模式  发送起始信号  使能IIC收发*/I2C5.I2CSTAT = 0xb0;/*等待从机接收到数据后应答*/while(!(I2C5.I2CCON & (1<<4)));/*禁止主机应答信号(即开启非应答  因为只接收一个字节)  清除中断标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<7))&(~(1<<4));/*等待接收从机发来的数据*/while(!(I2C5.I2CCON & (1<<4)));/*将从机发来的数据读取*/data = I2C5.I2CDS;/*直接发起停止信号结束本次通信*/I2C5.I2CSTAT = 0x90;/*清除中断挂起标志位*/I2C5.I2CCON = I2C5.I2CCON & (~(1<<4));/*延时等待停止信号稳定*/mydelay_ms(10);return data;}/*********************************************************************** 函数功能:MPU6050初始化
**********************************************************************/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
}/*********************************************************************** 函数功能:RTC初始化
**********************************************************************/void RTC_Init()
{//使能RTC控制RTCCON = RTCCON | 1;//校准时间RTC.BCDYEAR = 0x023; //000000100011  2023RTC.BCDMON  = 0x1;   //1RTC.BCDDAY  = 0x8;   //8RTC.BCDWEEK = 0x7;   //星期RTC.BCDHOUR = 0x11;  //11RTC.BCDMIN  = 0x32;  //32RTC.BCDSEC  = 0x50;  //50s//关闭RTC控制RTCCON = RTCCON & 0;}/*********************************************************************** 函数功能:BEEP初始化
**********************************************************************/void BEEP_Init()
{//GPD0_0设置PWM0输出功能GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);//PWM0一级分频  100倍PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | (99);//PWM0二级分频  1倍  PCLk/(99+1)/(0+1) = 1MHzPWM.TCFG1 = PWM.TCFG1 & (~(0xF));//设置PWM0自动重装 PWM.TCON = PWM.TCON | (1<<3);//设置周期 1000PWM.TCNTB0 = 1000;//占空比 60%PWM.TCMPB0 = 600;//手动装载PWM.TCON = PWM.TCON | (1 << 1);//关闭手动装载PWM.TCON = PWM.TCON & (~(1 << 1));//使能PWM0PWM.TCON = PWM.TCON | 1;
}/*********************************************************************** 函数功能:主函数**********************************************************************/int main(void)
{//存储读取结果unsigned char zvalue_h,zvalue_l,xvalue_h,xvalue_l,yvalue_h,yvalue_l;						short int zvalue,xvalue,yvalue;/*设置GPB_2引脚和GPB_3引脚功能为I2C传输引脚*/GPB.CON = (GPB.CON & ~(0xF<<12)) | 0x3<<12;			 		//设置GPB_3引脚功能为I2C_5_SCLGPB.CON = (GPB.CON & ~(0xF<<8))  | 0x3<<8;					//设置GPB_2引脚功能为I2C_5_SDAuart_init(); 												//初始化串口MPU6050_Init();												//初始化MPU6050RTC_Init();													//RTC初始化BEEP_Init();												//BEEP初始化printf("\n********** I2C test!! ***********\n");PWM.TCON = PWM.TCON & (~(1));								//关闭BEEPwhile(1){zvalue_h = iic_read(SlaveAddress, ACCEL_ZOUT_H);		//获取MPU6050-Z轴加速度高字节zvalue_l = iic_read(SlaveAddress, ACCEL_ZOUT_L);		//获取MPU6050-Z轴加速度低字节zvalue  =  (zvalue_h<<8)|zvalue_l;						//获取MPU6050-Z轴加速度xvalue_h = iic_read(SlaveAddress, ACCEL_XOUT_H);		//获取MPU6050-Z轴加速度高字节xvalue_l = iic_read(SlaveAddress, ACCEL_XOUT_L);		//获取MPU6050-Z轴加速度低字节xvalue  =  (xvalue_h<<8)|xvalue_l;						//获取MPU6050-Z轴加速度yvalue_h = iic_read(SlaveAddress, ACCEL_YOUT_H);		//获取MPU6050-Z轴加速度高字节yvalue_l = iic_read(SlaveAddress, ACCEL_YOUT_L);		//获取MPU6050-Z轴加速度低字节yvalue  =  (yvalue_h<<8)|yvalue_l;						//获取MPU6050-Z轴加速度#if 1		if(zvalue < 19000 & ((xvalue > 1200) | (yvalue > 1200) | (xvalue < 500) | (yvalue < 100))){printf("20%x-%x-%x %x %x:%x:%x  Status: Warning\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);PWM.TCON = PWM.TCON | 1;mydelay_ms(500);PWM.TCON = PWM.TCON & (~(1));mydelay_ms(490);}else{printf("20%x-%x-%x %x %x:%x:%x  Status: Normal\n",RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);PWM.TCON = PWM.TCON & (~(1));mydelay_ms(100);}
#endif//printf("X: %d  Y: %d  Z: %d\n", xvalue, yvalue ,zvalue);//打印MPU6050-x,y,Z轴加速度//mydelay_ms(100);}return 0;
}

http://www.ppmy.cn/news/155598.html

相关文章

CS5210设计HDMI to VGA方案 CS5210方案

CS5210是一款HDMI转VGA转换器方案&#xff0c;其输出VGA信号可送到CRT/LED显示器&#xff0c;及投影机等&#xff0c;输入HDMI信号可以驳接电脑、PS3&#xff0c;XBOX360、蓝光DVD&#xff0c;输出VGA可以CRT/LED显示器、HDTV电视VGA-IN、投影仪VGA-IN等&#xff0c;可方便为没…

行车记录仪发生故障怎么办?怎么恢复视频

行车记录仪是一个普及的设备&#xff0c;它能够帮助我们记录汽车在行驶过程中的视频图像和声音&#xff0c;但在使用过程中也会遇到一些故障问题&#xff0c;那常见的问题有哪些&#xff1f; 1、死机 造成行车记录仪死机的原因有很多种&#xff0c;通常我们都会尝试重启来解决…

行车记录仪 - 国际化 - 光源频率/电源频率

说明 之前做IPC&#xff08;IP camera&#xff09;项目时&#xff0c;IPC有一个设置项叫做电源频率&#xff0c;可选值有50HZ/60HZ&#xff1b;当前做行车记录仪项目&#xff0c;也有一个设置项&#xff1a;光源频率或者光源闪烁频率&#xff0c;可选值也是50HZ/60HZ&#xff…

行车记录仪专用语音识别芯片AT6802ABR1

行车记录仪可记录车辆行驶途中的影像及声音等相关资讯的仪器。安装行车记录仪后&#xff0c;能够记录汽车行驶全过程的视频图像和声音&#xff0c;可为交通事故提供证据。也是为了防止现在社会那些不可避免的碰瓷行为。 市场对智能车载摄像机提出了更高的要求&#xff0c;为满…

行车记录仪冲刺前装450万台,小鹏G9紧急开发功能

根据国标GB 7258-2017《机动车运行安全技术条件》国家标准第2号修改单&#xff0c;自2022年1月1日开始&#xff0c;新生产的乘用车要求必须配备EDR&#xff08;汽车事件数据记录系统&#xff09;。 目前&#xff0c;EDR大部分是集成在原有的安全气囊控制单元&#xff1b;同时&a…

【汽车篇】01. 行车记录仪自动保存 ❀ 特斯拉 Model 3

特斯拉本身自带行车记录仪功能&#xff0c;可以将前后左右摄像头拍摄的内容保存到U盘中&#xff0c;虽然不能记录声音&#xff0c;但是有图像也可以起到很大的作用&#xff0c;关键是不用再花钱买行车记录仪。 很多的人对这个行车记录仪有个误解&#xff0c;那就是应该一直保存…

行车记录仪 - 录像 - 文件缓存

背景 基于ffmpeg实现录像功能&#xff0c;性能不理想&#xff0c;前后路摄像头视频码率相加只有28Mbps加上音频也只有4MB/s左右&#xff0c;使用class 10的sd卡 2秒 ringbuffer缓存的情况下&#xff0c;依然出现写卡不及时导致的丢帧现象&#xff0c;class 4 sd卡表现更差。 …

车载USB DVR(行车记录仪)的源码架构浅析(基于AndroiidM)

基于AndroiidM的USB DVR的源码架构浅析&#xff0c;主要讲述大概流程&#xff0c;以便于分析问题。 APP层 源码路径&#xff1a; AndroidM/vendor/mediatek/proprietary/packages/apps/DVR 主要 DVR操作的两个类 FrontView.java 和 MainActivity.java 1、 FrontView 继承了…