添加mpu9250驱动测试代码

master
DESKTOP-4RNDQIC\29019 2019-04-06 12:14:25 +08:00
parent 29a35471f7
commit 3e6fa2cdde
19 changed files with 2274 additions and 851 deletions

15
.gitignore vendored
View File

@ -13,3 +13,18 @@
*.dep
*.o
*.crf
*.siwork
*.xml
*.siproj
*.sip_xsd
*.sip_xsb
*.sip_xr
*.sip_xm
*.sip_xf
*.sip_xc
*.sip_xad
*.sip_xab
*.sip_sym
*.SearchResults
*.sisc
*.iex

File diff suppressed because one or more lines are too long

View File

@ -48,7 +48,7 @@ void OLED_SingleWrite(uint8_t index, uint8_t data)
uint8_t OLED_SingleRead(uint8_t index)
{
uint8_t tmp;
uint8_t tmp;
I2C_START(LCD_I2C_PORT); //Start
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -2,11 +2,14 @@
".\objects\main.o"
".\objects\hal.o"
".\objects\mpu.o"
".\objects\imu.o"
".\objects\mymath.o"
".\objects\clk.o"
".\objects\i2c.o"
".\objects\timer.o"
".\objects\retarget.o"
".\objects\startup_m451series.o"
".\objects\system_m451series.o"
".\objects\clk.o"
".\objects\i2c.o"
--ro-base 0x00000000 --entry 0x00000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors --strict --summary_stderr --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols
--info sizes --info totals --info unused --info veneers
--list ".\Listings\mpu9250.map" -o .\Objects\mpu9250.axf

View File

@ -18,5 +18,6 @@
#define RTE_Drivers_CLK /* Driver CLK */
#define RTE_Drivers_I2C /* Driver I2C */
#define RTE_Drivers_Timer /* Driver Timer */
#endif /* RTE_COMPONENTS_H */

View File

@ -27,8 +27,37 @@ typedef struct{
int16_t gyroX;
int16_t gyroY;
int16_t gyroZ;
int16_t magX;
int16_t magY;
int16_t magZ;
}_st_Mpu;
typedef struct {
float accX;
float accY;
float accZ;
float gyroX;
float gyroY;
float gyroZ;
float magX;
float magY;
float magZ;
}_st_Mpu_Angle;
struct _1_ekf_filter
{
float LastP;
float Now_P;
float out;
float Kg;
float Q;
float R;
};
//void ekf_1(struct EKF *ekf,void *input); //一维å<C2B4>¡å°”æ¼
extern void kalman_1(struct _1_ekf_filter *ekf,float input); //一维å<C2B4>¡å°”æ¼
typedef struct{
int16_t magX;
@ -93,7 +122,9 @@ typedef volatile struct
extern _st_Remote Remote;
extern _st_Mpu MPU6050;
extern _st_Mag AK8975; //保留,需外接磁力计
extern _st_Mpu MPU6050UnFiltered;
extern _st_Mpu_Angle MPU6050Angle;
extern _st_Mag AK8975; //ä¿<C3A4>留,需å¤æŽ¥ç£<C3A7>åŠè®?
extern _st_AngE Angle;
@ -111,5 +142,10 @@ extern PidObject pidYaw;
extern PidObject pidHeightRate;
extern PidObject pidHeightHigh;
extern int i2c0Lock;
extern void I2C0_LCK ();
extern void I2C0_UNLOCK();
#endif

View File

@ -2,228 +2,134 @@
#include "M451Series.h"
#include <stdio.h>
#include "hal.h"
#define LCD_I2C_PORT I2C0
int MPUWriteReg( char RegAddr, char pucDATD_AA)
int MPUWriteReg(char ad,char RegAddr, char pucDATD_AA)
{
int i=0;
while(i<32) i++;
I2C_START(LCD_I2C_PORT); //Start
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag
I2C_START(I2C0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x08)
{
printf("I2CD_STArt write fail,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_DATA(LCD_I2C_PORT, ad); //send slave address
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag
I2C_SET_DATA(I2C0,0xd0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0)!= 0x18)
{
printf("I2C write ADW fail\r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
//дÈë¶ÁµØÖ·
I2C_SET_DATA(I2C0,RegAddr);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x28)
{
printf("I2C write reg addr fail\r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_DATA(LCD_I2C_PORT, RegAddr); //send index
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag
I2C_SET_DATA(I2C0,pucDATD_AA);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x28)
{
printf("I2C write control fail\r\n");
while (1);
}
//Í£Ö¹
I2C_Trigger(I2C0,0,1,1,0);
//printf("I2C write ok\r\n");
return 0;
}
int MPUWriteAddr()
{
if (I2C_GET_STATUS(I2C0) != 0x08)
{
printf("I2CD_STArt write add fail,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
//½øÈë¶Áд¿ØÖƲÙ×÷
I2C_SET_DATA(I2C0,0xd0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0)!= 0x18)
{
printf("I2C write ADW fail\r\n");
return FALSE;
}
return 1;
I2C_SET_DATA(LCD_I2C_PORT, pucDATD_AA); //send Data
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI|I2C_CTL_STO);//Stop
}
int MPUWriteACK(char cDat)
{
if((I2C_GET_STATUS(I2C0) != 0x18)&&(I2C_GET_STATUS(I2C0) != 0x28))
{
printf("I2C MPUWriteAddrAck STATUS error \r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
//дÈë¶ÁµØÖ·
I2C_SET_DATA(I2C0,cDat);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0)!= 0x28)
{
printf("MPUWriteAddrAck fail ACK no recv\r\n");
return FALSE;
}
return 1;
}
char MPUReadReg( int unAddr/*, int unLength*/)
{
char ret;
int i=0;
char MPUReadReg(char ad,int unAddr/*, int unLength*/){
uint8_t tmp;
I2C_START(LCD_I2C_PORT); //Start
I2C_WAIT_READY(LCD_I2C_PORT);
//LCD_I2C_PORT->INTSTS |= I2C_INTSTS_INTSTS_Msk; //clear flag
I2C_SET_DATA(LCD_I2C_PORT,ad ); //send slave address+W
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
I2C_SET_DATA(LCD_I2C_PORT, unAddr); //send index
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_STA | I2C_CTL_SI); //Start
I2C_WAIT_READY(LCD_I2C_PORT);
while(i<32) i++;
I2C_Trigger(I2C0,0,0,1,0);
I2C_START(I2C0); //Æô¶¯
//Æô¶¯
I2C_WAIT_READY(I2C0);
if(I2C_GET_STATUS(I2C0) != 0x08)
{
printf("I2CD_STArt read reg fail,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
//½øÈë¶Áд¿ØÖƲÙ×÷
I2C_SET_DATA(I2C0,0xd0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x018)
{
printf("status fault shoube be 0x018 ,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
//дÈë¶ÁµØÖ·
I2C_SET_DATA(I2C0,unAddr);
I2C_Trigger(I2C0,0,0,1,0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0)!= 0x28)
{
printf("I2C write reg addr fail\r\n");
return FALSE;
}
// ÖØÐÂÆô¶¯
I2C_Trigger(I2C0,0,0,1,0);
I2C_Trigger(I2C0,1,0,0,0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x10)
{
printf("I2C repeated D_STArt fail\r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
//½øÈë¶Á²Ù×÷
I2C_SET_DATA(I2C0,0xd0 | 1);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x40)
{
printf("I2C write control fail\r\n");
while (1);
}
//¶ÁÈ¡Êý¾Ý
I2C_Trigger(I2C0,0,0,1,0);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x58)
{
printf("I2C read fail\r\n");
return FALSE;
}
ret = I2C_GET_DATA(I2C0);
I2C_Trigger(I2C0,0,1,1,0);
I2C_SET_DATA(LCD_I2C_PORT, (ad+1)); //send slave address+R
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI);
I2C_WAIT_READY(LCD_I2C_PORT);
// I2C_WAIT_READY(I2C0);
return ret;
tmp = I2C_GET_DATA(LCD_I2C_PORT); //read data
I2C_SET_CONTROL_REG(LCD_I2C_PORT, I2C_CTL_SI|I2C_CTL_STO);//Stop
return tmp;
}
int MPUReadBuf( int unAddr, char *pucDATD_AA, int unLength)
int MPUReadBuf(char slaveAddress,int unAddr, char *pucDATD_AA, int unLength)
{
char ret;
int i=0;
while(i<32) i++;
I2C_Trigger(I2C0,0,0,1,0);
I2C_START(I2C0);
I2C_START(I2C0); //启动
//启动
I2C_WAIT_READY(I2C0);
if(I2C_GET_STATUS(I2C0) != 0x08)
{
printf("I2CD_STArt fail,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_SET_DATA(I2C0,0xd0);
//进入读写控制操作
I2C_SET_DATA(I2C0,slaveAddress);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x18)
{
printf("I2CD_STArt fail,I2D_STATUS %02X\r\n",I2C_GET_STATUS(I2C0));
return FALSE;
}
//写入读地址
I2C_SET_DATA(I2C0,unAddr);
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0)!= 0x28)
{
printf("I2C write reg addr fail\r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
I2C_Trigger(I2C0,1,0,0,0);
}
// 重新启动
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_STA);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x10)
{
printf("I2C repeated D_STArt fail\r\n");
return FALSE;
}
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_DATA(I2C0,0xd0 | 1);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
//进入读操作
I2C_SET_DATA(I2C0,slaveAddress | 1);
I2C_WAIT_READY(I2C0);
if (I2C_GET_STATUS(I2C0) != 0x40)
{
printf("I2C write control fail\r\n");
while (1);
return -1;
}
for(i=0;i<unLength;i++)
//读取数据
for(int i=0;i<unLength;i++)
{
if(i==unLength-1)
I2C_Trigger(I2C0,0,0,1,0);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
else
I2C_Trigger(I2C0,0,0,1,1);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI | I2C_CTL_SI_AA);
I2C_WAIT_READY(I2C0);
if ((I2C_GET_STATUS(I2C0) != 0x58)&&(I2C_GET_STATUS(I2C0) != 0x50))
if ((I2C_GET_STATUS(I2C0) != 0x50))
{
printf("I2C read fail\r\n");
return FALSE;
}
pucDATD_AA[i] = I2C_GET_DATA(I2C0);
}
I2C_Trigger(I2C0,0,1,1,0);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_STO);
I2C_WAIT_READY(I2C0);
// I2C_WAIT_READY(I2C0);
return ret;
}

View File

@ -1,10 +1,10 @@
#ifndef __HAL__
#define __HAL__
int MPUWriteReg( char RegAddr, char pucDATD_AA);
int MPUWriteReg(char ad,char RegAddr, char pucDATD_AA);
int MPUWriteAddr();
char MPUReadReg( int unAddr/*, int unLength*/);
int MPUReadBuf( int unAddr, char *pucDATD_AA, int unLength);
char MPUReadReg( int unAddr/*, int unLength*/);
char MPUReadReg(char ad,int unAddr/*, int unLength*/);
int MPUReadBuf(char slaveAddress,int unAddr, char *pucDATD_AA, int unLength);
void MpuGetData(void); //读取陀螺仪数据加滤波
#endif

263
mpu6050/m451/imu.c Normal file
View File

@ -0,0 +1,263 @@
/******************************************************************************************************
* Update the PID parameters.
*
* @param[in] pid A pointer to the pid object.
* @param[in] measured The measured value
* @param[in] updateError Set to TRUE if error should be calculated.
* Set to False if pidSetError() has been used.
* @return PID algorithm output
*******************************************************************************************************/
#include "imu.h"
#include "myMath.h"
#include <math.h>
static float NormAcc;
//float ex_int = 0, ey_int = 0, ez_int = 0; //X、Y、Z轴的比例误差
//float q0 = 1, q1 = 0, q2 = 0, q3 = 0; //定义四元素
//float his_q0 = 1, his_q1 = 0, his_q2 = 0, his_q3 = 0;
//float q0_yaw = 1, q1_yaw = 0, q2_yaw = 0, q3_yaw = 0; //弥补Mahony算法在无地磁情况解算Yaw轴满足不了大扰动要求的现象
//float his_q0_yaw = 1, his_q1_yaw = 0, his_q2_yaw = 0, his_q3_yaw = 0;
//void GetAngle(const stMpu *pMpu,void *pAngE, float dt)
//{
// static const float KpDef = 0.85f ;
// static const float KiDef = 0.0035f;
// const float Gyro_Gr = 0.0005326f; //面计算度每秒,转换弧度每秒则 0.03051756 * 0.0174533f = 0.0005326
// float HalfTime = 0.5 * dt;
// float gx = pMpu->gyroX * Gyro_Gr;
// float gy = pMpu->gyroY * Gyro_Gr;
// float gz = pMpu->gyroZ * Gyro_Gr;
// float ax = pMpu->accX;
// float ay = pMpu->accY;
// float az = pMpu->accZ;
//
// float vx, vy, vz;
// float ex, ey, ez;
//
// static float his_q0q0;
// static float his_q0q1;
// static float his_q0q2;
// static float his_q1q1;
// static float his_q1q3;
// static float his_q2q2;
// static float his_q2q3;
// static float his_q3q3;
//
// float q0q0;
// float q0q1;
// float q0q2;
// float q1q1;
// float q1q3;
// float q2q2;
// float q2q3;
// float q3q3;
//
// float q0_yawq0_yaw;
// float q1_yawq1_yaw;
// float q2_yawq2_yaw;
// float q3_yawq3_yaw;
// float q1_yawq2_yaw;
// float q0_yawq3_yaw;
//
////**************************Yaw轴计算******************************
//
// //Yaw轴四元素的微分方程
// q0_yaw = his_q0_yaw + (-his_q1_yaw * gx - his_q2_yaw * gy - his_q3_yaw * gz) * HalfTime;
// q1_yaw = his_q1_yaw + ( his_q0_yaw * gx + his_q2_yaw * gz - his_q3_yaw * gy) * HalfTime;
// q2_yaw = his_q2_yaw + ( his_q0_yaw * gy - his_q1_yaw * gz + his_q3_yaw * gx) * HalfTime;
// q3_yaw = his_q3_yaw + ( his_q0_yaw * gz + his_q1_yaw * gy - his_q2_yaw * gx) * HalfTime;
//
// q0_yawq0_yaw = q0_yaw * q0_yaw;
// q1_yawq1_yaw = q1_yaw * q1_yaw;
// q2_yawq2_yaw = q2_yaw * q2_yaw;
// q3_yawq3_yaw = q3_yaw * q3_yaw;
// q1_yawq2_yaw = q1_yaw * q2_yaw;
// q0_yawq3_yaw = q0_yaw * q3_yaw;
//
// //规范化Yaw轴四元数
// norm = Q_rsqrt(q0_yawq0_yaw + q1_yawq1_yaw + q2_yawq2_yaw + q3_yawq3_yaw);
// q0_yaw = q0_yaw * norm;
// q1_yaw = q1_yaw * norm;
// q2_yaw = q2_yaw * norm;
// q3_yaw = q3_yaw * norm;
//
// //if(ax * ay * az == 0)
// //return ;
//
// //归一化加速度计值
// norm = Q_rsqrt(ax * ax + ay * ay + az * az);
// ax = ax * norm;
// ay = ay * norm;
// az = az * norm;
//
// //由姿态阵估计重力方向和流量/变迁
// vx = 2 * (his_q1q3 - his_q0q2);
// vy = 2 * (his_q0q1 + his_q2q3);
// vz = his_q0q0 - his_q1q1 - his_q2q2 + his_q3q3;
//
// //向量外积再相减得到差分就是误差 两个单位向量的差积即为误差向量
// ex = (ay * vz - az * vy) ;
// ey = (az * vx - ax * vz) ;
// ez = (ax * vy - ay * vx) ;
// //对误差进行PI计算
// ex_int = ex_int + ex * KiDef;
// ey_int = ey_int + ey * KiDef;
// ez_int = ez_int + ez * KiDef;
// //校正陀螺仪
// gx = gx + KpDef * ex + ex_int;
// gy = gy + KpDef * ey + ey_int;
// gz = gz + KpDef * ez + ez_int;
//
// //四元素的微分方程
// q0 = his_q0 + (-his_q1 * gx - his_q2 * gy - his_q3 * gz) * HalfTime;
// q1 = his_q1 + ( his_q0 * gx + his_q2 * gz - his_q3 * gy) * HalfTime;
// q2 = his_q2 + ( his_q0 * gy - his_q1 * gz + his_q3 * gx) * HalfTime;
// q3 = his_q3 + ( his_q0 * gz + his_q1 * gy - his_q2 * gx) * HalfTime;
// q0q0 = q0 * q0;
// q0q1 = q0 * q1;
// q0q2 = q0 * q2;
// q1q1 = q1 * q1;
// q1q3 = q1 * q3;
// q2q2 = q2 * q2;
// q2q3 = q2 * q3;
// q3q3 = q3 * q3;
// //规范化Pitch、Roll轴四元数
// norm = Q_rsqrt(q0q0 + q1q1 + q2q2 + q3q3);
// q0 = q0 * norm;
// q1 = q1 * norm;
// q2 = q2 * norm;
// q3 = q3 * norm;
//
// //求解欧拉角
// *((float *)pAngE+2) = atan2f(2 * q2q3 + 2 * q0q1, -2 * q1q1 - 2 * q2q2 + 1) * RtA; //ROLL
// *((float *)pAngE+1) = asin(2 * q0q2 -2 * q1q3) * 57.3; //PITCH
// *(float *)pAngE = atan2f(2 * q1_yawq2_yaw + 2 * q0_yawq3_yaw, -2 * q2_yawq2_yaw - 2 * q3_yawq3_yaw + 1) * RtA; //YAW
//
//
// //存储更替相应的四元数
// his_q0_yaw = q0_yaw;
// his_q1_yaw = q1_yaw;
// his_q2_yaw = q2_yaw;
// his_q3_yaw = q3_yaw;
// his_q0 = q0;
// his_q1 = q1;
// his_q2 = q2;
// his_q3 = q3;
//
// his_q0q0 = q0q0;
// his_q0q1 = q0q1;
// his_q0q2 = q0q2;
// his_q1q1 = q1q1;
// his_q1q3 = q1q3;
// his_q2q2 = q2q2;
// his_q2q3 = q2q3;
// his_q3q3 = q3q3;
//}
typedef volatile struct {
float q0;
float q1;
float q2;
float q3;
} Quaternion;
void GetAngle(const _st_Mpu *pMpu,_st_AngE *pAngE, float dt)
{
volatile struct V{
float x;
float y;
float z;
} Gravity,Acc,Gyro,AccGravity;
static struct V GyroIntegError = {0};
static float KpDef = 0.8f ;
static float KiDef = 0.0003f;
static Quaternion NumQ = {1, 0, 0, 0};
float q0_t,q1_t,q2_t,q3_t;
//float NormAcc;
float NormQuat;
float HalfTime = dt * 0.5f;
// 提取等效旋转矩阵中的重力分量
Gravity.x = 2*(NumQ.q1 * NumQ.q3 - NumQ.q0 * NumQ.q2);
Gravity.y = 2*(NumQ.q0 * NumQ.q1 + NumQ.q2 * NumQ.q3);
Gravity.z = 1-2*(NumQ.q1 * NumQ.q1 + NumQ.q2 * NumQ.q2);
// 加速度归一化
NormAcc = Q_rsqrt(squa(MPU6050.accX)+ squa(MPU6050.accY) +squa(MPU6050.accZ));
Acc.x = pMpu->accX * NormAcc;
Acc.y = pMpu->accY * NormAcc;
Acc.z = pMpu->accZ * NormAcc;
//向量差乘得出的值
AccGravity.x = (Acc.y * Gravity.z - Acc.z * Gravity.y);
AccGravity.y = (Acc.z * Gravity.x - Acc.x * Gravity.z);
AccGravity.z = (Acc.x * Gravity.y - Acc.y * Gravity.x);
//再做加速度积分补偿角速度的补偿值
GyroIntegError.x += AccGravity.x * KiDef;
GyroIntegError.y += AccGravity.y * KiDef;
GyroIntegError.z += AccGravity.z * KiDef;
//角速度融合加速度积分补偿值
Gyro.x = pMpu->gyroX * Gyro_Gr + KpDef * AccGravity.x + GyroIntegError.x;//弧度制
Gyro.y = pMpu->gyroY * Gyro_Gr + KpDef * AccGravity.y + GyroIntegError.y;
Gyro.z = pMpu->gyroZ * Gyro_Gr + KpDef * AccGravity.z + GyroIntegError.z;
// 一阶龙格库塔法, 更新四元数
q0_t = (-NumQ.q1*Gyro.x - NumQ.q2*Gyro.y - NumQ.q3*Gyro.z) * HalfTime;
q1_t = ( NumQ.q0*Gyro.x - NumQ.q3*Gyro.y + NumQ.q2*Gyro.z) * HalfTime;
q2_t = ( NumQ.q3*Gyro.x + NumQ.q0*Gyro.y - NumQ.q1*Gyro.z) * HalfTime;
q3_t = (-NumQ.q2*Gyro.x + NumQ.q1*Gyro.y + NumQ.q0*Gyro.z) * HalfTime;
NumQ.q0 += q0_t;
NumQ.q1 += q1_t;
NumQ.q2 += q2_t;
NumQ.q3 += q3_t;
// 四元数归一化
NormQuat = Q_rsqrt(squa(NumQ.q0) + squa(NumQ.q1) + squa(NumQ.q2) + squa(NumQ.q3));
NumQ.q0 *= NormQuat;
NumQ.q1 *= NormQuat;
NumQ.q2 *= NormQuat;
NumQ.q3 *= NormQuat;
// 四元数转欧拉角
{
#ifdef YAW_GYRO
*(float *)pAngE = atan2f(2 * NumQ.q1 *NumQ.q2 + 2 * NumQ.q0 * NumQ.q3, 1 - 2 * NumQ.q2 *NumQ.q2 - 2 * NumQ.q3 * NumQ.q3) * RtA; //yaw
#else
float yaw_G = pMpu->gyroZ * Gyro_G;
if((yaw_G > 3.0f) || (yaw_G < -3.0f)) //数据太小可以认为是干扰,不是偏航动作
{
pAngE->yaw += yaw_G * dt;
}
#endif
pAngE->pitch = asin(2 * NumQ.q0 *NumQ.q2 - 2 * NumQ.q1 * NumQ.q3) * RtA;
pAngE->roll = atan2(2 * NumQ.q2 *NumQ.q3 + 2 * NumQ.q0 * NumQ.q1, 1 - 2 * NumQ.q1 *NumQ.q1 - 2 * NumQ.q2 * NumQ.q2) * RtA; //PITCH
}
}
/***************************************************END OF FILE***************************************************/

12
mpu6050/m451/imu.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __IMU_H
#define __IMU_H
#include "data.h"
//extern float GetNormAccz(void);
extern void GetAngle(const _st_Mpu *pMpu,_st_AngE *pAngE, float dt);
#endif

View File

@ -1,6 +1,41 @@
#include "M451Series.h"
#include "data.h"
#include "mpu.h"
#include "imu.h"
#define PLL_CLOCK 5000000
void Timer0Init()
{
CLK_EnableModuleClock(TMR0_MODULE);
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,200);
TIMER_EnableCapture(TIMER0,TIMER_CAPTURE_FREE_COUNTING_MODE,TIMER_CAPTURE_FALLING_AND_RISING_EDGE);
TIMER_EnableInt(TIMER0);
TIMER_Start(TIMER0);
SYS_UnlockReg();
NVIC_EnableIRQ(TMR0_IRQn);
SYS_LockReg();
}
void TMR0_IRQHandler()
{
TIMER_ClearIntFlag(TIMER0);
static uint8_t cnt_3ms = 0;
static uint8_t cnt_6ms = 0;
cnt_3ms++;
cnt_6ms++;
if (cnt_6ms >= 2){
cnt_6ms = 0;
MpuGetData();
GetAngle(&MPU6050UnFiltered,&Angle,0.010f);
}
else{
}
}
void HalInit(){
SYS_UnlockReg();
@ -41,7 +76,7 @@ void HalInit(){
SYS->GPD_MFPL &= ~SYS_GPD_MFPL_PD5MFP_Msk;
SYS->GPD_MFPL |= SYS_GPD_MFPL_PD5MFP_I2C0_SCL;
I2C_Open(I2C0,100000);
I2C_Open(I2C0,50000);
printf("I2C clock %d Hz\n", I2C_GetBusClockFreq(I2C0));
@ -60,5 +95,9 @@ void HalInit(){
int main(){
HalInit();
MpuInit();
Timer0Init();
while(1){
}
}

View File

@ -1,55 +1,60 @@
#include "data.h"
#include "hal.h"
#include "mpu.h"
#define SMPLRT_DIV 0x19 //陀螺仪采样率典型值0x07(125Hz)
#define CONFIGL 0x1A //低通滤波频率典型值0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围典型值0x18(不自检2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率典型值0x01(不自检2G5Hz)
#define ACCEL_ADDRESS 0x3B
#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_ADDRESS 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 MPU6050_PRODUCT_ID 0x68
#define MPU6052C_PRODUCT_ID 0x72
#define MPU9250_PRODUCT_ID 0x71 //
//#define MPU6050_is_DRY() GPIO_ReadOutBit(HT_GPIOC, GPIO_PIN_0)//IRQ主机数据输入
#ifdef USE_I2C_HARDWARE
#define MPU6050_ADDRESS 0xD0//0x68
#else
#define MPU6050_ADDRESS 0xD0 //IIC写入时的地址字节数据+1为读取
#define MPU6050_ADDRESS 0xD0 //IIC写入时的地å<C2B0>€å­—èŠæ•°æ<C2B0>®ï¼?1为读å<C2BB>?
#endif
int i2c0Lock = 0;
#define Gyro_Read() MPUReadBuf(MPU6050_ADDRESS,0x3b,buffer,6)
#define Acc_Read() MPUReadBuf(MPU6050_ADDRESS, 0x43,&buffer[6],6)
#define Mag_Read() MPUReadBuf(AK8963_I2C_ADDR,0x03,&buffer[12],6)
void delay_ms(int x){
for(x = 0; x < 1000; x++){
volatile int z = 0;
for (z = 0; z < 100;z++){
int z = 0;
for (z = 0; z < 1020;){
z ++ ;
}
}
}
void I2C0_LCK (){
if (i2c0Lock == 0){
i2c0Lock = 1;
}else{
while(i2c0Lock == 0){
i2c0Lock = 1;
}
}
}
void I2C0_UNLOCK(){
if (i2c0Lock == 1){
i2c0Lock = 0;
}else{
while(i2c0Lock == 1){
i2c0Lock = 0;
}
}
}
int16_t MpuOffset[6] = {0};
_st_AngE Angle;
_st_Mpu MPU6050; //MPU6050原始数据
_st_Mpu MPU6050UnFiltered; //MPU6050原å§æ•°æ<C2B0>®
_st_Mpu_Angle MPU6050Angle;
static volatile int16_t *pMpu = (int16_t *)&MPU6050;
static volatile int16_t *pMpuUnFilter = (int16_t *)&MPU6050UnFiltered;
@ -60,7 +65,7 @@ static volatile int16_t *pMpu = (int16_t *)&MPU6050;
*****************************************************************************************/
int8_t mpu6050_rest(void)
{
if(MPUWriteReg( PWR_MGMT_1, 0x80) == FAILED)
if(MPUWriteReg(MPU6050_ADDRESS,PWR_MGMT_1, 0x80) == FAILED)
return FAILED; //复位
//delay_ms(20);
return SUCCESS;
@ -70,26 +75,60 @@ int8_t mpu6050_rest(void)
*@brief
*@param[in]
*****************************************************************************************/
int8_t MpuInit(void) //初始化
int8_t MpuInit(void) //åˆ<EFBFBD>å§åŒ?
{
uint8_t date = SUCCESS;
do
{
date = MPUWriteReg( PWR_MGMT_1, 0x80); //复位
date = MPUWriteReg(MPU6050_ADDRESS, PWR_MGMT_1, 0x00); // reset
delay_ms(30);
date += MPUWriteReg( SMPLRT_DIV, 0x02); //陀螺仪采样率0x00(500Hz)
date += MPUWriteReg( PWR_MGMT_1, 0x03); //设置设备时钟源陀螺仪Z轴
date += MPUWriteReg( CONFIGL, 0x03); //低通滤波频率0x03(42Hz)
date += MPUWriteReg( GYRO_CONFIG, 0x18);//+-2000deg/s
date += MPUWriteReg( ACCEL_CONFIG, 0x09);//+-4G
date += MPUWriteReg(MPU6050_ADDRESS,SMPLRT_DIV, 0x02); //sample rate
date += MPUWriteReg( MPU6050_ADDRESS,PWR_MGMT_1, 0x03); // clock source
date += MPUWriteReg( MPU6050_ADDRESS,CONFIGL, 0x03); // lpf
date += MPUWriteReg( MPU6050_ADDRESS,GYRO_CONFIG, 0x18);//+-2000deg/s
date += MPUWriteReg( MPU6050_ADDRESS,ACCEL_CONFIG, 0x09);//+-4G
delay_ms(30);
delay_ms(30);
MPUWriteReg(MPU6050_ADDRESS,USER_CTRL,0x00); //
delay_ms(30);
delay_ms(30);
date += MPUWriteReg( MPU6050_ADDRESS,INT_PIN_CFG ,0X02); //bypass mode
delay_ms(30);
delay_ms(30);
delay_ms(30);
//MPUWriteReg(AK8963_I2C_ADDR,AK8963_CNTL1, 0x11);
delay_ms(30);
delay_ms(30);
delay_ms(30);
delay_ms(30);
date += MPUWriteReg( AK8963_I2C_ADDR,0x0A,0x01); //one-time messure
date = MPUReadReg(MPU6050_ADDRESS,WHO_AM_I);
//if(date!= MPU9250_PRODUCT_ID)
//return FAILED;
char us = MPUReadReg( AK8963_I2C_ADDR,0);//+-2000deg/s
if (us != 0x48){
return FAIL;
}
while(date != SUCCESS);
date = MPUReadReg(0x75);
if(date!= MPU6050_PRODUCT_ID)
return FAILED;
else
//MpuGetOffset();
return SUCCESS;
}
void MpuAngle(){
MPU6050Angle.accX = MPU6050.accX *360/32768;
MPU6050Angle.accY = MPU6050.accY *360/32768;
MPU6050Angle.accZ = MPU6050.accZ *360/32768;
MPU6050Angle.gyroX = MPU6050.gyroX*3.1415926/180;
MPU6050Angle.gyroY = MPU6050.gyroY*3.1415926/180;
MPU6050Angle.gyroZ = MPU6050.gyroZ*3.1415926/180;
}
void MpuMag(){
}
/****************************************************************************************
*@brief
@ -97,36 +136,47 @@ int8_t MpuInit(void) //初始化
*@param[in]
*****************************************************************************************/
#define Gyro_Read() MPUReadBuf( 0X3B,buffer,6)
#define Acc_Read() MPUReadBuf( 0x43,&buffer[6],6)
void kalman_1(struct _1_ekf_filter *ekf,float input) //一维å<C2B4>¡å°”æ¼
{
ekf->Now_P = ekf->LastP + ekf->Q;
ekf->Kg = ekf->Now_P / (ekf->Now_P + ekf->R);
ekf->out = ekf->out + ekf->Kg * (input - ekf->out);
ekf->LastP = (1-ekf->Kg) * ekf->Now_P ;
}
void MpuGetData(void) //读取陀螺仪数据加滤波
void MpuGetData(void) //读å<C2BB>陀螺仪数æ<C2B0>®åŠ æ»¤æ³?
{
uint8_t i;
int8_t buffer[12];
int8_t buffer[18];
MPUWriteReg( AK8963_I2C_ADDR,0x0A,0x01);
//Mag_Read();
Gyro_Read();
Acc_Read();
for(i=0;i<6;i++)
Acc_Read();
MpuAngle();
for(i = 0; i < 9;i++)
{
pMpu[i] = (((int16_t)buffer[i<<1] << 8) | buffer[(i<<1)+1])-MpuOffset[i];
pMpu[i] = (((int16_t)buffer[2*i] *256)| buffer[2*i + 1]&0xff)-MpuOffset[i];
pMpuUnFilter[i] = (((int16_t)buffer[2*i] *256)| buffer[2*i + 1]&0xff)-MpuOffset[i];
/*
if(i < 3)
{
{
//static struct _1_ekf_filter ekf[3] = {{0.02,0,0,0,0.001,0.543},{0.02,0,0,0,0.001,0.543},{0.02,0,0,0,0.001,0.543}};
//kalman_1(&ekf[i],(float)pMpu[i]); //一维卡尔曼
//pMpu[i] = (int16_t)ekf[i].out;
static struct _1_ekf_filter ekf[3] = {{0.02,0,0,0,0.001,0.543},{0.02,0,0,0,0.001,0.543},{0.02,0,0,0,0.001,0.543}};
kalman_1(&ekf[i],(float)pMpu[i]); //一维å<C2B4>¡å°”æ¼
pMpu[i] = (int16_t)ekf[i].out;
}
}
if(i > 2)
{
uint8_t k=i-3;
const float factor = 0.15f; //滤波因素
static float tBuff[3];
}
if(i > 2)
{
uint8_t k=i-3;
const float factor = 0.15f; //滤波因素
static float tBuff[3];
pMpu[i] = tBuff[k] = tBuff[k] * (1 - factor) + pMpu[i] * factor;
}
pMpu[i] = tBuff[k] = tBuff[k] * (1 - factor) + pMpu[i] * factor;
}*/
}
}

83
mpu6050/m451/mpu.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef __MPU__
#define __MPU__
#include "data.h"
// Read-only Reg
#define AK8963_I2C_ADDR 0x18 // slave address for the AK8963
#define AK8963_DEVICE_ID 0x48
#define AK8963_WIA 0x00
#define AK8963_INFO 0x01
#define AK8963_ST1 0x02 // data ready status bit 0
#define AK8963_XOUT_L 0x03 // data
#define AK8963_XOUT_H 0x04
#define AK8963_YOUT_L 0x05
#define AK8963_YOUT_H 0x06
#define AK8963_ZOUT_L 0x07
#define AK8963_ZOUT_H 0x08
#define AK8963_ST2 0x09 // Data overflow bit 3 and data read error status bit 2
#define AK8963_CNTL 0x0A // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0
#define AK8963_ASTC 0x0C // Self test control
#define AK8963_I2CDIS 0x0F // I2C disable
#define AK8963_ASAX 0x10 // Fuse ROM x-axis sensitivity adjustment value
#define AK8963_ASAY 0x11 // Fuse ROM y-axis sensitivity adjustment value
#define AK8963_ASAZ 0x12 // Fuse ROM z-axis sensitivity adjustment value
// Write/Read Reg
#define AK8963_CNTL1 0x0A
#define AK8963_CNTL2 0x0B
#define AK8963_ASTC 0x0C
#define AK8963_TS1 0x0D
#define AK8963_TS2 0x0E
#define AK8963_I2CDIS 0x0F
// Read-only Reg ( ROM )
#define AK8963_ASAX 0x10
#define AK8963_ASAY 0x11
#define AK8963_ASAZ 0x12
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典åžå€¼ï¼š0x07(125Hz)
#define CONFIGL 0x1A //低通滤波é¢çŽ‡ï¼Œå…¸åžå€¼ï¼š0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检å<E282AC>Šæµé‡<C3A9>范å´ï¼Œå…¸åžå€¼ï¼š0x18(ä¸<C3A4>自检ï¼?000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检ã€<C3A3>æµé‡<C3A9>范å´å<C2B4>Šé«˜é€šæ»¤æ³¢é¢çŽ‡ï¼Œå…¸åžå€¼ï¼š0x01(ä¸<C3A4>自检ï¼?Gï¼?Hz)
#define ACCEL_CONFIG2 0X1D //加速度计低通滤波器 0x06 5hz
#define PWR_MGMT_1 0X6B//电æº<C3A6>管ç<C2A1>†1 å…¸åžå€¼ä¸º0x00
#define INT_PIN_CFG 0x37
#define ACCEL_ADDRESS 0x3B
#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_ADDRESS 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 WHO_AM_I 0x75 //IIC地å<C2B0>€å¯„å­˜å™?默认数å€?x68,å<C592>ªè¯?
#define MPU6050_PRODUCT_ID 0x68
#define MPU6052C_PRODUCT_ID 0x72
#define MPU9250_PRODUCT_ID 0x71 //
#define I2C_SLV0_ADDR 0x25
#define EXT_SENS_DATA_00 0x49
#define I2C_SLV0_CTRL 0x27
#define I2C_SLV0_DO 0x64
#define USER_CTRL 0x6A
extern _st_Mpu MPU6050; //MPU6050原å§æ•°æ<C2B0>®
extern _st_AngE Angle;
extern _st_AngE Angle;
int8_t MpuInit(void); //åˆ<C3A5>å§åŒ?
void MpuGetData(void); //读å<C2BB>陀螺仪数æ<C2B0>®åŠ æ»¤æ³?
#endif

View File

@ -28,7 +28,7 @@
<TargetOption>
<CLKADS>12000000</CLKADS>
<OPTTT>
<gFlags>0</gFlags>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>0</RunSim>
<RunTarget>1</RunTarget>
@ -103,7 +103,7 @@
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>0</nTsel>
<nTsel>8</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
@ -114,9 +114,29 @@
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon>BIN\UL2CM3.DLL</pMon>
<pMon>NULink\Nu_Link.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMRTXEVENTFLAGS</Key>
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGTARM</Key>
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMDBGFLAGS</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>Nu_Link</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>UL2CM3</Key>
@ -124,18 +144,50 @@
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint/>
<WatchWindow1>
<Ww>
<count>0</count>
<WinNumber>1</WinNumber>
<ItemText>MPU6050</ItemText>
</Ww>
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>MPU6050Angle</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>buffer</ItemText>
</Ww>
<Ww>
<count>3</count>
<WinNumber>1</WinNumber>
<ItemText>us</ItemText>
</Ww>
<Ww>
<count>4</count>
<WinNumber>1</WinNumber>
<ItemText>Angle</ItemText>
</Ww>
<Ww>
<count>5</count>
<WinNumber>1</WinNumber>
<ItemText>MpuOffset</ItemText>
</Ww>
</WatchWindow1>
<Tracepoint>
<THDelay>0</THDelay>
</Tracepoint>
<DebugFlag>
<trace>0</trace>
<periodic>1</periodic>
<aLwin>0</aLwin>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>0</viewmode>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
@ -166,6 +218,12 @@
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
<SystemViewers>
<Entry>
<Name>System Viewer\I2C0</Name>
<WinId>35905</WinId>
</Entry>
</SystemViewers>
</TargetOption>
</Target>
@ -223,6 +281,30 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\imu.c</PathWithFileName>
<FilenameWithoutPath>imu.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\myMath.c</PathWithFileName>
<FilenameWithoutPath>myMath.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>

View File

@ -133,12 +133,12 @@
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>0</Capability>
<DriverSelection>-1</DriverSelection>
<Capability>1</Capability>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
@ -257,17 +257,17 @@
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>0</Type>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>0</Type>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>0</Type>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
@ -277,7 +277,7 @@
<Size>0x40000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>0</Type>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT5>
@ -401,6 +401,16 @@
<FileType>5</FileType>
<FilePath>.\data.h</FilePath>
</File>
<File>
<FileName>imu.c</FileName>
<FileType>1</FileType>
<FilePath>.\imu.c</FilePath>
</File>
<File>
<FileName>myMath.c</FileName>
<FileType>1</FileType>
<FilePath>.\myMath.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -459,6 +469,12 @@
<targetInfo name="Target 1"/>
</targetInfos>
</component>
<component Cclass="Device" Cgroup="Driver" Csub="Timer" Cvendor="Nuvoton" Cversion="3.01.001" condition="M4NuMicro M451 Device">
<package name="NuMicro_DFP" schemaVersion="1.2" url="http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack" vendor="Nuvoton" version="1.2.0"/>
<targetInfos>
<targetInfo name="Target 1"/>
</targetInfos>
</component>
<component Cclass="Device" Cgroup="Startup" Cvendor="Nuvoton" Cversion="3.01.001" condition="M4NuMicro M451 Device">
<package name="NuMicro_DFP" schemaVersion="1.2" url="http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack" vendor="Nuvoton" version="1.2.0"/>
<targetInfos>

360
mpu6050/m451/myMath.c Normal file
View File

@ -0,0 +1,360 @@
//========================================================================
// 爱好者电子工作室-淘宝 https://devotee.taobao.com/
// STM32四轴爱好者QQ群: 810149456
// 作者:小刘
// 电话:13728698082
// 邮箱:1042763631@qq.com
// 日期2018.05.17
// 版本V1.0
//========================================================================
//套件购买地址https://devotee.taobao.com/
// 爱好者电子工作室
//特此声明:
//
// 此程序只能用作学习,如用商业用途。必追究责任!
//
//
//
#include "data.h"
#include "myMath.h"
#include <math.h>
const float M_PI = 3.1415926535;
const float RtA = 57.2957795f;
const float AtR = 0.0174532925f;
const float Gyro_G = 0.03051756f*2; //陀螺仪初始化量程+-2000度每秒于1 / (65536 / 4000) = 0.03051756*2
const float Gyro_Gr = 0.0005326f*2; //面计算度每秒,转换弧度每秒则 2*0.03051756 * 0.0174533f = 0.0005326*2
////in -+500
////out exp -+500
//int16_t Math_AngelEXP(int16_t in){
// int16_t tmp2 ,tmp,value;
// tmp = Math_min(Math_abs(in),500); //[0 , +500]
// tmp2 = tmp/100;
// value = Angel_EXP[tmp2] + (tmp-tmp2*100) * (Angel_EXP[tmp2+1]-Angel_EXP[tmp2]) / 100;
// if(in<0)value = -value;
// return value;
//}
////油门输入转换。
//int16_t Math_ThrEXP(int16_t RCThr){
// int16_t tmp2 ,tmp,value;
// if(RCThr <1000)return RCThr; //低于最小值,直接输出,不做指数变换
// tmp = Math_Constrain(RCThr,1000,2000);
// tmp = (unsigned int)(tmp-1000)*1000/(2000-1000); // [1000;2000] -> [0;1000]
// tmp2 = tmp/100;
// value = ThrottleEXP[tmp2] + (tmp-tmp2*100) * (ThrottleEXP[tmp2+1]-ThrottleEXP[tmp2]) / 100; // [0;1000] -> expo -> [MINTHROTTLE;MAXTHROTTLE]
// return value;
//}
/*====================================================================================================*/
/*====================================================================================================*
** : Q_rsqrt
** :
** : number
** :
** : None
**====================================================================================================*/
/*====================================================================================================*/
//逼近法;线性拟合
//Q (4/M_PI x - 4/M_PI^2 x^2) + P (4/M_PI x - 4/M_PI^2 x^2)^2
#ifndef TAPYOR
float sine(float x) // (-M_PI , M_PI) ???? 0.0005
{
const float Q = 0.775;
const float P = 0.225;
const float B = 4 / M_PI;
const float C = -4 /(M_PI*M_PI);
float y = B * x + C * x * fabs(x);
return (Q * y + P * y * fabs(y));
}
#else
//4级泰勒公式法 在PI出会出现0.7的最大误差
//sinx= x- x^3/3! + x^5/5! - x^7/7!+ x^9/9! . =?(-1)^n x^(2n+1)/(2n+1)!
float sine(float x)
{
float t=x;
float result = x;
float X2 = x*x;
uint8_t cnt = 1;
do
{
t=-t;
t *= X2;
result += t/((cnt<<1)+1);
cnt++;
} while(cnt<5);//6阶
return result;
}
#endif
//http://wenku.baidu.com/link?url=jUswZ3G2z26IUS72IkeZrizc5V9VdR1sTF8xGCOHPFW0P70bGjjm5zhNxvRT36X31TMoFf6S-9lMoIkK4pPwExAaEZGtRpWggdQAzpg3Fsu
//cos(x)=sin(M_PI/2+x)=sin(M_PI/2-x)
//cos(x-M_PI/2)=sin(x)
float cosine(float x)
{
return sine(x+M_PI/2);//奇变偶不变,符号看象限
}
//反正切麦克劳林展开式 阶数越高,值越准确 70°以内是准确的
//http://www.zybang.com/question/246f9997776f7d5cc636b10aff27a1cb.html
float arctan(float x) // (-1 , +1) 6? ?? 0.002958
{
float t = x;
float result = 0;
float X2 = x * x;
unsigned char cnt = 1;
do
{
result += t / ((cnt << 1) - 1);
t = -t;
t *= X2;
cnt++;
}while(cnt <= 6);//5??
return result;
}
//反正弦麦克劳林展开式 -1<x<+1 42°以内是准确的
//http://xuxzmail.blog.163.com/blog/static/25131916200971794014536/
const float PI_2 = 1.570796f;
float arcsin(float x) //(-1 , +1) ? 0 ???? 6? ??0.005
{
float d=1;
float t=x;
unsigned char cnt = 1;
float result = 0;
float X2 = x*x;
if (x >= 1.0f)
{
return PI_2;
}
if (x <= -1.0f)
{
return -PI_2;
}
do
{
result += t / (d * ((cnt << 1) - 1));
t *= X2 * ((cnt << 1) - 1);//
d *= (cnt << 1);//2 4 6 8 10 ...
cnt++;
}while(cnt <= 6);
return result;
}
//保证输入值是有效的
float safe_asin(float v)
{
if (isnan(v)) {
return 0.0;
}
if (v >= 1.0f) {
return M_PI/2;
}
if (v <= -1.0f) {
return -M_PI/2;
}
return asinf(v);
}
/*====================================================================================================*/
/*====================================================================================================*
** : Q_rsqrt
** : 1/Sqrt(x)
** : number
** :
** : None
**====================================================================================================*/
/*====================================================================================================*/
float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration (第一次牛顿迭代)
return y;
}
/**************************实现函数********************************************
*: array_astrict_lower(int16_t *array,int16_t value)
*  :
*array
* value
*******************************************************************************/
void array_astrict(int16_t *array,int16_t lower,int16_t upper)
{
int16_t length = sizeof(array);
uint16_t i = 0;
for(i=0;i<length;i++)
{
if(*(array+i)<lower) *(array+i) = lower;
else if(*(array+i)>upper) *(array+i) = upper;
}
}
/**************************实现函数********************************************
*: array_assign(int16_t *array,int16_t value)
*  :
*array
* value
*******************************************************************************/
void array_assign(int16_t *array,int16_t value)
{
uint16_t length = sizeof(array);
uint16_t i=0;
for(i=0;i<length;i++)
{
*(array+i) = value;
}
}
/**************************实现函数********************************************
*: data_limit(float data,flaot toplimit,float lowerlimit)
*  :
data
* toplimit
* lowerlimit
*******************************************************************************/
float data_limit(float data,float toplimit,float lowerlimit)
{
if(data > toplimit) data = toplimit;
else if(data < lowerlimit) data = lowerlimit;
return data;
}
/***********************************************
* @brief
* @param None
* @retval None
************************************************/
float VariableParameter(float error)
{
float result = 0;
if(error < 0)
{
error = -error;
}
if(error >0.6f)
{
error = 0.6f;
}
result = 1 - 1.667f * error;
if(result < 0)
{
result = 0;
}
return result;
}
float middle_3(float input) //3个数取中间的数
{
int a,b,c,t;
if(a<b)
{
t=a;a=b;b=t;
}
if(b<c)//9 8 7
{
t=b;b=c;c=t;
}
if(a<b)//9 8 7
{
t=a;a=b;b=t;
}
return b;
}
/**************************实现函数********************************************
*: rad(double angle)
*  :
*******************************************************************************/
//float Rad(float angle)
//{
// return angle * AtR ;
//}
/**************************实现函数********************************************
*: degree(double rad)
*  :
*******************************************************************************/
float my_deathzoom_2(float x,float zoom)
{
float t;
if( x> -zoom && x < zoom )
{
t = 0;
}
else
{
t = x;
}
return (t);
}
float my_deathzoom(float x,float zoom)
{
float t;
if(x>0)
{
t = x - zoom;
if(t<0)
{
t = 0;
}
}
else
{
t = x + zoom;
if(t>0)
{
t = 0;
}
}
return (t);
}
/******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/

25
mpu6050/m451/myMath.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef __MY_MATH_H
#define __MY_MATH_H
extern const float M_PI;
extern const float AtR;
extern const float RtA;
extern const float Gyro_G;
extern const float Gyro_Gr;
#define PI 3.1415926f
#define squa( Sq ) (((float)Sq)*((float)Sq))
#define absu16( Math_X ) ((Math_X)<0? -(Math_X):(Math_X))
#define absFloat( Math_X )((Math_X)<0? -(Math_X):(Math_X))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define ABS(x) ((x) > 0 ? (x) : -(x))
#define LIMIT( x,min,max ) ( (x) < (min) ? (min) : ( (x) > (max) ? (max) : (x) ) )
extern float safe_asin(float v);
extern float arcsin(float x);
extern float arctan(float x);
extern float sine(float x);
extern float cosine(float x);
extern float Q_rsqrt(float number);
extern float VariableParameter(float error);
#endif /* __Algorithm_math_H */