STC15F2K60S2/STC15系列读取MPU6050陀螺仪角度加速度串口显示程序代码
2017-07-15 13:54
441 查看
STC15F2K60S2/STC15系列读取MPU6050陀螺仪角度加速度串口显示程序代码
调试通过,复制粘贴即编译可使用,无需调试,晶振:24M,串口输出,波特率:115200
为方便大家调试,特附该程序的项目文件,下载打开即可调试,下载地址:http://download.csdn.net/detail/liyu3519/9899708
调试通过,复制粘贴即编译可使用,无需调试,晶振: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; }
相关文章推荐
- STC15系列读取MPU6050陀螺仪角度加速度串口显示代码
- STC15系列读取DS18B20温度传感器串口显示代码
- 安装问题+读取图像、放缩、形态学开闭运算、显示图像的opencv程序代码
- 在硬盘读取文档,并在文本域显示的JAVA程序代码
- STC89C58串口接收GPS信号(GPRMC)读取经纬度,时间。1604液晶(HD44780)显示
- STC89C58串口接收GPS信号(GPRMC)读取经纬度,时间。1604液晶(HD44780)显示
- STC12C5620AD系列单片机EEPROM/IAP 功能测试程序(官方改良版,增加串口监控功能,本人亲自测试通过)
- STC15F2K60S2读取DHT11温湿度串口显示实例
- OpenCV显示图像的方法——否则程序运行好了都不知道图像怎么读取的
- STC51系列单片机不断电自动下载程序
- OpenCV最基本的测试代码-图像的读取与显示!
- C语言系列(一):最近重拾C语言的想法,谈到C中易错点,难点;以及开源代码中C语言的一些常用技巧,以及如何利用define、typedef、const等写健壮的C程序
- 归纳STM32 FLASH 擦除(以及如何防止误擦除程序代码)、写入、读取方法
- 在DataGridView控件中一次显示出多个圆饼图的原始程序代码
- 用ASP读取显示TXT文件内容的代码
- 分批读取文件中数据的程序流程及其C代码实现
- vs2008 MFC程序 读取显示图像、更改背景图像
- SerialPort如何读取串口数据并显示在TextBox上,多线程委托
- 在linux中用C程序实现读取一个文件中的字符,计算它的个数,并把个数显示在另外一个文件夹内