STC15W4K32S4讀取MPU6050陀螺儀角度加速度串列埠顯示程式程式碼
阿新 • • 發佈:2018-12-31
STC15W4K32S4讀取MPU6050陀螺儀角度加速度串列埠顯示程式程式碼
除錯通過,複製貼上即編譯可使用,無需除錯,晶振:24M,串列埠輸出,波特率:115200
為方便大家除錯,特附該程式的專案檔案,下載開啟即可除錯,下載地址:
http://download.csdn.net/detail/liyu3519/9899708
//*********************************************************************
//STC15系列讀取MPU6505陀螺儀資料
//除錯通過,複製貼上即編譯可使用,無需除錯,晶振:24M,串列埠輸出,波特率:115200
//版本:2.0 日期:2017-07-15
//*********************************************************************
#include <STC15W4K32S4.H> //引用STC15系列標頭檔案,百度上搜索下載
#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;
}