您的位置:首页 > 编程语言

STC15F2K60S2/STC15系列读取MPU6050陀螺仪角度加速度串口显示程序代码

2017-07-15 13:54 441 查看
STC15F2K60S2/STC15系列读取MPU6050陀螺仪角度加速度串口显示程序代码

调试通过,复制粘贴即编译可使用,无需调试,晶振:24M,串口输出,波特率:115200

为方便大家调试,特附该程序的项目文件,下载打开即可调试,下载地址:http://download.csdn.net/detail/liyu3519/9899708



//*********************************************************************
//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();                                         //等待机器反应
}

//========================================================================<
118ee
/span>
// 函数: 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐