天天看點

STC15系列讀取MPU6050陀螺儀角度加速度序列槽顯示代碼

STC15系列讀取MPU6050陀螺儀角度加速度序列槽顯示程式代碼

調試通過,複制粘貼即編譯可使用,無需調試,晶振:24M,序列槽輸出,波特率:115200

為友善大家調試,特附該程式的項目檔案,下載下傳打開即可調試,下載下傳位址:

STC15系列讀取MPU6050陀螺儀角度加速度序列槽顯示代碼
//*********************************************************************
//STC15系列讀取MPU6505陀螺儀資料
//調試通過,複制粘貼即編譯可使用,無需調試,晶振:24M,序列槽輸出,波特率:115200
//版本:2.0		日期:2017-07-15
//*********************************************************************


#include <STC15W4K32S4.H>	//引用STC15系列頭檔案,下載下傳位址https://pan.baidu.com/s/1dQTSS2
#include <INTRINS.H>
#include <MATH.H>

#define 	I2C_SCL 	P14		 //時鐘信号線
#define 	I2C_SDA 	P15		 //資料信号線

#define	PWR_MGMT_1		0x6B	  //電源管理,典型值:0x00(正常啟用)
#define	WHO_AM_I		0x75	  //IIC位址寄存器(預設數值0x68,隻讀)
#define	SlaveAddress	0xD0	  //IIC寫入時的位址位元組資料,+1為讀取

#define NOP1() nop_()
#define NOP2() NOP1(),NOP1()

#define MAIN_Fosc					24000000L				//主時鐘,不同的晶振頻率可以直接修改
#define serial_one_read_max 		16						//接收緩存區長度
#define serial_one_baud_rate		115200L					//波特率,波特率可以直接修改
#define	Timer1_Reload_Usart			(65536UL -(MAIN_Fosc / 4 / serial_one_baud_rate))		//Timer1重裝值,定時器1産生波特率


//****************************************
// 定義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


void Delay1000ms()		//延時函數1秒
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 85;
	j = 12;
	k = 155;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


//========================================================================
// 函數: void I2C_Start()
// 描述: I2C起始信号.
// 參數: none.
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void I2C_Start()
{
    I2C_SDA = 1;                    //拉高資料線
    I2C_SCL = 1;                    //拉高時鐘線
    NOP2();							//等待機器反應
    I2C_SDA = 0;                    //産生下降沿
    I2C_SCL = 0;                    //拉低時鐘線
}

//========================================================================
// 函數: void I2C_Stop()
// 描述: I2C停止信号.
// 參數: none.
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void I2C_Stop()
{
    I2C_SDA = 0;                    //拉低資料線
    I2C_SCL = 1;                    //拉高時鐘線
    NOP2();							//等待機器反應
    I2C_SDA = 1;                    //産生上升沿
    NOP1();							//等待機器反應
}

//========================================================================
// 函數: void I2C_SendACK(bit ack)
// 描述: I2C發送應答信号.
// 參數: ack (0:ACK 1:NAK).
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void I2C_SendACK(bit ack)
{
    I2C_SDA = ack;                  //寫應答信号
    I2C_SCL = 1;                    //拉高時鐘線
    NOP2();                  						//等待機器反應
    I2C_SCL = 0;                    //拉低時鐘線
    NOP1();                  						//等待機器反應
}

//========================================================================
// 函數: bit I2C_RecvACK()
// 描述: I2C接收應答信号.
// 參數: none.
// 傳回: 1:成功,0:失敗.
// 版本: V1.0, 2017-06-23
//========================================================================
bit I2C_RecvACK()
{
    I2C_SCL = 1;            //拉高時鐘線
    NOP2();                  		//等待機器反應
    CY = I2C_SDA;           //讀應答信号
    I2C_SCL = 0;            //拉低時鐘線
    return CY;
}

//========================================================================
// 函數: void I2C_SendByte(u8 dat)
// 描述: 向I2C總線發送一個位元組資料.
// 參數: dat:要發送的資料.
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void I2C_SendByte(unsigned char dat)
{
    unsigned char i;
    for (i=0; i<8; i++)         //8位計數器
    {
        dat <<= 1;              //移出資料的最高位
        I2C_SDA = CY;           //送資料口
        I2C_SCL = 1;                //拉高時鐘線
        NOP2();                  				//等待機器反應
        I2C_SCL = 0;                //拉低時鐘線
    }
    I2C_RecvACK();
}

//========================================================================
// 函數: unsigned char I2C_RecvByte()
// 描述: 從I2C總線接收一個位元組資料.
// 參數: none.
// 傳回: 接收到的資料.
// 版本: V1.0, 2017-06-23
//========================================================================
unsigned char I2C_RecvByte()
{
    unsigned char i;
    unsigned char dat = 0;
    I2C_SDA = 1;                    //使能内部上拉,準備讀取資料,
    for (i=0; i<8; i++)    				      //8位計數器
    {
        dat <<= 1;
        I2C_SCL = 1;                //拉高時鐘線
        NOP2();                  				//等待機器反應
        dat |= I2C_SDA;             //讀資料               
        I2C_SCL = 0;                //拉低時鐘線
    }
    return dat;
}

//========================================================================
// 函數: void Single_WriteI2C(unsigned char REG_Address,unsigned char REG_data)
// 描述: 向I2C裝置寫入一個位元組資料.
// 參數: REG_Address:位址.
//			 REG_data:要寫入的資料.
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void Single_WriteI2C(unsigned char REG_Address,unsigned char REG_data)
{
    I2C_Start();                  //起始信号
    I2C_SendByte(SlaveAddress);   //發送裝置位址+寫信号
    I2C_SendByte(REG_Address);    //内部寄存器位址,
    I2C_SendByte(REG_data);       //内部寄存器資料,
    I2C_Stop();                   //發送停止信号
}

//========================================================================
// 函數: unsigned char Single_ReadI2C(unsigned char REG_Address)
// 描述: 從I2C裝置讀取一個位元組資料.
// 參數: REG_Address:位址.
// 傳回: 讀取到的資料.
// 版本: V1.0, 2017-06-23
//========================================================================
unsigned char Single_ReadI2C(unsigned char REG_Address)
{
	unsigned char REG_data;
	I2C_Start();                   //起始信号
	I2C_SendByte(SlaveAddress);    //發送裝置位址+寫信号
	I2C_SendByte(REG_Address);     //發送存儲單元位址,從0開始	
	I2C_Start();                   //起始信号
	I2C_SendByte(SlaveAddress+1);  //發送裝置位址+讀信号
	REG_data=I2C_RecvByte();       //讀出寄存器資料
	I2C_SendACK(1);                //接收應答信号
	I2C_Stop();                    //停止信号
	return REG_data;
}

//========================================================================
// 函數: void MPU6050_init()
// 描述: 初始化MPU6050.
// 參數: none.
// 傳回: none.
// 版本: V1.0, 2017-06-23
//========================================================================
void MPU6050_Init()
{
	Single_WriteI2C(PWR_MGMT_1, 0x00);	//解除休眠狀态
	Single_WriteI2C(SMPLRT_DIV, 0x07);
	Single_WriteI2C(CONFIG, 0x06);
	Single_WriteI2C(GYRO_CONFIG, 0x18);
	Single_WriteI2C(ACCEL_CONFIG, 0x01);
}

//========================================================================
// 函數: int GetData(u8 REG_Address)
// 描述: 讀取資料并合成為int型資料.
// 參數: REG_Address:位址.
// 傳回: 讀取到的資料.
// 版本: V1.0, 2017-06-23
//========================================================================
int GetData(unsigned char REG_Address)
{
	unsigned char H,L;
	H = Single_ReadI2C(REG_Address);
	L = Single_ReadI2C(REG_Address + 1);
	return (H << 8) + L;   //合成資料
}

========================================================================
 函數: int get_x_angle()
 描述: 擷取三軸角速度,三軸加速度
 參數: gyro_id:資料ID,1:x角速度,2:y角速度,3:z角速度,4:x加速度,5:y加速度,6:z加速度.
 傳回: 陀螺儀值.
 版本: V2.0, 2017-07-15
========================================================================
int Get_Gyro_Data(unsigned char gyro_id)
{
	switch(gyro_id)
	{
		case 1:	return GetData(ACCEL_XOUT_H);	break;
		case 2:	return GetData(ACCEL_YOUT_H);	break;
		case 3:	return GetData(ACCEL_ZOUT_H);	break;
		case 4:	return GetData(GYRO_XOUT_H) ;	break;
		case 5:	return GetData(GYRO_YOUT_H) ;	break;
		case 6:	return GetData(GYRO_ZOUT_H) ;	break;
	}
	return 0;
}

//========================================================================
// 函數: int MPU6050_Get_Angle(float x,float y,float z,u8 dir)
// 描述: 轉化成與三個方向的夾角.
// 參數: x:x方向資料.
//		 y:y方向資料.
//		 z:z方向資料.
//		 dir:方向ID.
// 傳回: 夾角角度值(放大10倍).
// 版本: V1.0, 2017-06-23
//========================================================================
int MPU6050_Get_Angle(int x,int y,int z,unsigned char dir)
{
	float xdata temp;
	float xdata res = 0;
	switch(dir)
	{
		case 0://與z軸的夾角
				temp = sqrt(((float)x*(float)x+(float)y*(float)y))/(float)z;
				res  = atan(temp);
		break;
		case 1://與x軸的夾角
				temp = (float)x/sqrt(((float)y*(float)y+(float)z*(float)z));
				res  = atan(temp);
		break;
		case 2://與y軸的夾角
				temp = (float)y/sqrt(((float)x*(float)x+(float)z*(float)z));
				res  = atan(temp);
		break;
	}
	return (int)(res*1800/3.1416);//弧度轉換為角度,擴大10倍
}

//========================================================================
// int get_included_angle(unsigned dat)
// 描述: 擷取角度或加速度
// 參數: angle_id:方向訓示變量(1:X軸角度,2:Y軸角度,3:Z軸角度,4:X軸加速度,5:Y軸加速度,6:Z軸加速度).
// 傳回: 夾角角度值(放大10倍).
// 版本: V1.0, 2017-06-23
//========================================================================
int MPU6050_Get_Data(unsigned angle_id)
{
	switch(angle_id)
	{
		case 1:return MPU6050_Get_Angle( Get_Gyro_Data(1), Get_Gyro_Data(2), Get_Gyro_Data(3), 1);break;
		case 2:return MPU6050_Get_Angle( Get_Gyro_Data(1), Get_Gyro_Data(2), Get_Gyro_Data(3), 2);break;
		case 3:return MPU6050_Get_Angle( Get_Gyro_Data(1), Get_Gyro_Data(2), Get_Gyro_Data(3), 0);break;
		case 4:return (int)((float)((float)Get_Gyro_Data(4)/16384)*9.8*100);
		case 5:return (int)((float)((float)Get_Gyro_Data(5)/16384)*9.8*100);
		case 6:return (int)((float)((float)Get_Gyro_Data(6)/16384)*9.8*100);
	}
	return 0;
}

//序列槽初始化
void Uart_Init()
{
	SCON |= 0x40;				//8位資料
	P_SW1 &=  ~0xc0;		//UART1 使用P30 P31口	預設
	TR1 = 0;						//關閉定時器1
	AUXR &= ~0x01;			//序列槽1波特率使用定時器1
	TMOD &= ~(1<<6);		//Timer1 set As Timer
	TMOD &= ~0x30;			//16位自動重裝
	AUXR |=  (1<<6);		//定時器使用1T模式
	TH1 = (unsigned char)(Timer1_Reload_Usart >> 8);
	TL1 = (unsigned char)Timer1_Reload_Usart;
	TR1 = 1;						//打開定時器1
	PS  = 1;						//高優先級中斷
	REN = 1;						//允許接收
	ES  = 1;						//允許中斷
	EA  = 1;						//允許全局中斷
}

//========================================================================
// 函數: serial_one_send_byte(unsigned char dat)
// 描述: 序列槽1發送一個位元組.
// 參數: dat:字元(無符号八位整型資料).
// 傳回: none.
// 版本: V1.0, 2017-06-22
//========================================================================
void serial_one_send_byte(unsigned char dat)
{
	SBUF = dat;
	while(!TI);
	TI = 0; 
}

//========================================================================
// 函數: serial_one_send_string(u8 *dat)
// 描述: 序列槽1發送字元串.
// 參數: dat:字元串.
// 傳回: none.
// 版本: V1.0, 2017-06-22
//========================================================================
void serial_one_send_string(unsigned char *dat)
{
	while(*dat)
		serial_one_send_byte(*dat++);
}

//========================================================================
// 函數: void serial_one_send_number(long num)
// 描述: 序列槽1發送整型資料.
// 參數: num:整型數值.
// 傳回: none.
// 版本: V1.0, 2017-06-22
//========================================================================
void serial_one_send_number(long num)
{
	long dat = 0;
	unsigned char  length = 0;
	if(num < 0)										//當數值為負數時
	{
		serial_one_send_byte('-');	//輸出負号
		num = -num;									//将數值取相反數
	}
	
	if(num == 0)									//當數值為0時
		serial_one_send_byte('0');	//輸出字元0
	else											//當數值不為0時
	{
		while(num)									//将數值倒過來
		{
			dat = dat * 10;
			dat = dat + num % 10;
			num = num / 10;
			length++;
		}
		
		while(length--)							//從第一位開始輸出倒過來的數值
		{
			serial_one_send_byte(dat % 10 + '0');
			dat = dat / 10;
		}
	}
}

void serial_one_send_float(double float_val, char bit_val)
{
	long xdata value_int = 0;
	long xdata value_flt = 0;
	
	if(float_val < 0)
	{
		serial_one_send_byte('-');
		float_val = -float_val;
	}
	
	value_int = (long)float_val;
	
	float_val = float_val - (double)value_int;
	
	for(;bit_val;bit_val--)
		float_val = float_val * 10;
	
	serial_one_send_number(value_int);
	serial_one_send_byte('.');
	serial_one_send_number((long)float_val);
}

float value = 0;

//主函數
void main()
{
	Delay1000ms();
	Uart_Init();			//序列槽初始化
	MPU6050_Init();			//初始化MPU6505
	while(1)
	{
		value = MPU6050_Get_Data(1);					//擷取與x軸的夾角,角度被放大10倍
		serial_one_send_string("子產品與x軸的夾角為:");
		serial_one_send_float(value / 10,1);			//角度除以10,并從序列槽發出,第二個參數為保留一位小數
		serial_one_send_string("\r\n");					//換行
		
		value = MPU6050_Get_Data(2);					//擷取與y軸的夾角,角度被放大10倍
		serial_one_send_string("子產品與y軸的夾角為:");
		serial_one_send_float(value / 10,1);			//角度除以10,并從序列槽發出
		serial_one_send_string("\r\n");					//換行
		
		value = MPU6050_Get_Data(3);					//擷取與z軸的夾角,角度被放大10倍
		serial_one_send_string("子產品與z軸的夾角為:");
		serial_one_send_float(value / 10,1);			//角度除以10,并從序列槽發出
		serial_one_send_string("\r\n");					//換行
		
		value = MPU6050_Get_Data(4);					//擷取與x軸加速度,數值被放大100倍
		serial_one_send_string("x軸加速度為:");
		serial_one_send_float(value/100,1);			//角度除以100,并從序列槽發出,第二個參數為保留一位小數
		serial_one_send_string(" M/S2\r\n");					//換行
		
		value = MPU6050_Get_Data(4);					//擷取與y軸加速度,數值被放大100倍
		serial_one_send_string("y軸加速度為:");
		serial_one_send_float(value / 100,1);			//角度除以100,并從序列槽發出
		serial_one_send_string(" M/S2\r\n");					//換行
		
		value = MPU6050_Get_Data(4);					//擷取與z軸加速度,數值被放大100倍
		serial_one_send_string("z軸加速度為:");
		serial_one_send_float(value / 100,1);			//角度除以100,并從序列槽發出
		serial_one_send_string(" M/S2\r\n\r\n");					//換行
		
		Delay1000ms();
		Delay1000ms();
	}
}

//序列槽中斷
void Uart1_Int (void) interrupt 4
{
	if(RI)
		RI = 0;
}
           

繼續閱讀