最原始版匿名四轴无人机代码注释

基于STM32平台

#include "CONTROL.h"
#include "BSP.H"
#include "UART2.h"
#include "IMU.h"
#include "MPU6050.h"
#include "MOTO.h"
PID PID_ROL,PID_PIT,PID_YAW;
u8 ARMED = 0;
u16 moto1=0,moto2=0,moto3=0,moto4=0;

float Get_MxMi(float num,float max,float min)//将num限制在min与max之间
{
    if(num>max)
        return max;
    else if(num<min)
        return min;
    else
        return num;
}         //解算出来的自我姿态,根据此得出自稳所需改变角度  //遥控发来的所需要改变的角度以进行倾斜的飞行,进行前进后退或转向 
          //Q_ANGLE.X ,         Q_ANGLE.Y,     Q_ANGLE.Z, //RC_Target_ROL, RC_Target_PIT, RC_Target_YAW
void CONTROL(float rol_now, float pit_now, float yaw_now,   float rol_tar, float pit_tar, float yaw_tar)
{

    vs16 throttle;
    vs16 yaw_d;
    float rol = rol_tar + rol_now;//将所有要改变的值加起来
    float pit = pit_tar + pit_now;
    float yaw = yaw_tar + yaw_now;

    throttle = Rc_Get.THROTTLE - 1000;//油门,代表电机的转速
    if(throttle<0)  throttle=0;//消除实际操作误差

    PID_ROL.IMAX = throttle/2;  //积分项限幅=throttle的1/2,为什么和throttle有关?
    Get_MxMi(PID_ROL.IMAX,1000,0);//并将积分项限幅限制在0-1000之间
    PID_PIT.IMAX = PID_ROL.IMAX;


    /****************************  P比例调节   ***********************************/

    PID_ROL.pout = PID_ROL.P * rol;
    PID_PIT.pout = PID_PIT.P * pit;
    PID_YAW.pout = PID_YAW.P * yaw;

    /****************************  I积分调节   **********************************/

    if(rol_tar*rol_tar<0.1 && pit_tar*pit_tar<0.1 && rol_now*rol_now<30 && pit_now*pit_now<30 && throttle>300)
    {//target遥控几乎未动,now当前比较接近水平,油门很大

        PID_ROL.iout += PID_ROL.I * rol;  
        PID_PIT.iout += PID_PIT.I * pit;                                 //积分项容易超调
        PID_ROL.iout = Get_MxMi(PID_ROL.iout,PID_ROL.IMAX,-PID_ROL.IMAX);//积分项限制在积分项限幅内
        PID_PIT.iout = Get_MxMi(PID_PIT.iout,PID_PIT.IMAX,-PID_PIT.IMAX);//防止大角度积累造成积分超调
    }
    else if(throttle<200)//油门很小不需要积分调节,为什么?
    {
        PID_ROL.iout = 0;
        PID_PIT.iout = 0;
    }

  /***************************  D微分调节  ***********************************/ 

    PID_ROL.dout = PID_ROL.D * MPU6050_GYRO_LAST.X;//,飞机头朝X正方向,ROL绕X轴转
    PID_PIT.dout = PID_PIT.D * MPU6050_GYRO_LAST.Y;//6050测得角速度,角度的微分就是角速度

    if(1480>Rc_Get.YAW || Rc_Get.YAW>1520)//YAW的微分调节,1500是什么也不改变的零点值
    {         //自己飘的YAW值       //遥控所需要的改变量,*10提高权重,加快响应
        yaw_d = MPU6050_GYRO_LAST.Z + (Rc_Get.YAW-1500)*10;
        GYRO_I.Z = 0;//假设遥控不动的情况下YAW不可能自己飘,没有地磁作参考直接置零算了              
    }   //在IMU的preparedata()中GYRO_I.Z += MPU6050_GYRO_LAST.Z*Gyro_G*0.001;//0.001为dt
                              //GYRO_I.Z相当于绕Z轴(即yaw)旋转的总角度
        //在IMU的 IMUupdata ()中Q_ANGLE.Z = GYRO_I.Z
    else //为什么要分两种情况//遥控的左转右转功能不要了
    yaw_d = MPU6050_GYRO_LAST.Z;//很小的遥控改变量就不要了
    PID_YAW.dout = PID_YAW.D * yaw_d;

    /**************************************************************************************/


    PID_ROL.OUT = PID_ROL.pout + PID_ROL.iout + PID_ROL.dout;//最终的输出量
    PID_PIT.OUT = PID_PIT.pout + PID_PIT.iout + PID_PIT.dout;
    PID_YAW.OUT = PID_YAW.pout + PID_YAW.iout + PID_YAW.dout;

    if(throttle>200)//                                - +                           + +
    {            //两正两负,调整roll的话PID_ROL.OUT要 - +,调整pit的话PID_PIT.OUT 要 - -
        moto3= throttle - PID_ROL.OUT - PID_PIT.OUT + PID_YAW.OUT;//赋给电机值
        moto1= throttle + PID_ROL.OUT - PID_PIT.OUT - PID_YAW.OUT;//加减号一定两正两负,电机对称
        moto2 = throttle + PID_ROL.OUT + PID_PIT.OUT + PID_YAW.OUT;//要改,先注释掉其他三个
        moto4= throttle - PID_ROL.OUT + PID_PIT.OUT - PID_YAW.OUT;
    }
    else//定义电机的死区,避免误操作
    {
        moto1 = 0;
        moto2 = 0;
        moto3 = 0;
        moto4 = 0;
    }
    if(ARMED)   {PCout(13)=0;Moto_PwmRflash(moto1,moto2,moto3,moto4);}//使能电机
    else            {PCout(13)=1;Moto_PwmRflash(0,0,0,0);}
}

#include "imu.h"
#include "MPU6050.h"
#include "math.h"

#define RtA         57.324841               //弧度到角度
#define AtR     0.0174533               //度到角度
#define Acc_G   0.0011963               //加速度变成G
#define Gyro_G  0.0610351               //角速度变成度   此参数对应陀螺2000度每秒
#define Gyro_Gr 0.0010653               //角速度变成弧度   此参数对应陀螺2000度每秒
#define FILTER_NUM 20

S_INT16_XYZ ACC_AVG;            //平均值滤波后的ACC
S_FLOAT_XYZ GYRO_I;             //陀螺仪积分
S_FLOAT_XYZ EXP_ANGLE;      //期望角度
S_FLOAT_XYZ DIF_ANGLE;      //期望角度与实际角度差
S_FLOAT_XYZ Q_ANGLE;            //四元数计算出的角度

int16_t ACC_X_BUF[FILTER_NUM],ACC_Y_BUF[FILTER_NUM],ACC_Z_BUF[FILTER_NUM];  //加速度滑动窗口滤波数组
//filter是滤波的意思
void Prepare_Data(void)
{
    static uint8_t filter_cnt=0;
    int32_t temp1=0,temp2=0,temp3=0;
    uint8_t i;

    MPU6050_Read();
    MPU6050_Dataanl();

    ACC_X_BUF[filter_cnt] = MPU6050_ACC_LAST.X;//更新滑动窗口数组
    ACC_Y_BUF[filter_cnt] = MPU6050_ACC_LAST.Y;
    ACC_Z_BUF[filter_cnt] = MPU6050_ACC_LAST.Z;
    for(i=0;i<FILTER_NUM;i++)
    {
        temp1 += ACC_X_BUF[i];
        temp2 += ACC_Y_BUF[i];
        temp3 += ACC_Z_BUF[i];
    }
    ACC_AVG.X = temp1 / FILTER_NUM;
    ACC_AVG.Y = temp2 / FILTER_NUM;
    ACC_AVG.Z = temp3 / FILTER_NUM;
    filter_cnt++;
    if(filter_cnt==FILTER_NUM)  filter_cnt=0;

    //GYRO_I.X += MPU6050_GYRO_LAST.X*Gyro_G*0.001;//0.001是时间间隔,两次prepare的执行周期
    //GYRO_I.Y += MPU6050_GYRO_LAST.Y*Gyro_G*0.001;//这里已经使用四元数进行结算,因此不用直接累加
    GYRO_I.Z += MPU6050_GYRO_LAST.Z*Gyro_G*0.001;
}

void Get_Attitude(void)
{
    IMUupdate(MPU6050_GYRO_LAST.X*Gyro_Gr,
                        MPU6050_GYRO_LAST.Y*Gyro_Gr,
                        MPU6050_GYRO_LAST.Z*Gyro_Gr,
                        ACC_AVG.X,ACC_AVG.Y,ACC_AVG.Z); //*0.0174转成弧度=π%180
}

#define Kp 10.0f                        // proportional gain governs rate of convergence to accelerometer/magnetometer
#define Ki 0.008f                          // integral gain governs rate of convergence of gyroscope biases
#define halfT 0.001f                   // half the sample period采样周期的一半

float q0 = 1, q1 = 0, q2 = 0, q3 = 0;    // quaternion elements representing the estimated orientation
float exInt = 0, eyInt = 0, ezInt = 0;    // scaled integral error
void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
{
  float norm;
//  float hx, hy, hz, bx, bz;
  float vx, vy, vz;// wx, wy, wz;
  float ex, ey, ez;

  // 先把这些用得到的值算好
  float q0q0 = q0*q0;
  float q0q1 = q0*q1;
  float q0q2 = q0*q2;
//  float q0q3 = q0*q3;
  float q1q1 = q1*q1;
//  float q1q2 = q1*q2;
  float q1q3 = q1*q3;
  float q2q2 = q2*q2;
  float q2q3 = q2*q3;
  float q3q3 = q3*q3;

    if(ax*ay*az==0)
        return;

  norm = sqrt(ax*ax + ay*ay + az*az);       //acc数据归一化
  ax = ax /norm;
  ay = ay / norm;
  az = az / norm;

  // estimated direction of gravity and flux (v and w)              估计重力方向和流量/变迁
  vx = 2*(q1q3 - q0q2);                                             //四元素中xyz的表示
  vy = 2*(q0q1 + q2q3);
  vz = q0q0 - q1q1 - q2q2 + q3q3 ;

  // error is sum of cross product between reference direction of fields and direction measured by sensors
  ex = (ay*vz - az*vy) ;                                             //向量外积在相减得到差分就是误差
  ey = (az*vx - ax*vz) ;
  ez = (ax*vy - ay*vx) ;

  exInt = exInt + ex * Ki;                                //对误差进行积分
  eyInt = eyInt + ey * Ki;
  ezInt = ezInt + ez * Ki;

  // adjusted gyroscope measurements
  gx = gx + Kp*ex + exInt;                                              //将误差PI后补偿到陀螺仪,即补偿零点漂移
  gy = gy + Kp*ey + eyInt;
  gz = gz + Kp*ez + ezInt;                                          //这里的gz由于没有观测者进行矫正会产生漂移,表现出来的就是积分自增或自减

  // integrate quaternion rate and normalise                           //四元素的微分方程
  q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
  q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
  q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
  q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

  // normalise quaternion
  norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
  q0 = q0 / norm;
  q1 = q1 / norm;
  q2 = q2 / norm;
  q3 = q3 / norm;

  Q_ANGLE.Z = GYRO_I.Z;//atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* 57.3; // yaw
  Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
  Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
}

#include "MOTO.h"

int16_t MOTO1_PWM = 0;
int16_t MOTO2_PWM = 0;
int16_t MOTO3_PWM = 0;
int16_t MOTO4_PWM = 0;

void Moto_PwmRflash(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
{       
    if(MOTO1_PWM>Moto_PwmMax)   MOTO1_PWM = Moto_PwmMax;
    if(MOTO2_PWM>Moto_PwmMax)   MOTO2_PWM = Moto_PwmMax;
    if(MOTO3_PWM>Moto_PwmMax)   MOTO3_PWM = Moto_PwmMax;
    if(MOTO4_PWM>Moto_PwmMax)   MOTO4_PWM = Moto_PwmMax;
    if(MOTO1_PWM<0) MOTO1_PWM = 0;
    if(MOTO2_PWM<0) MOTO2_PWM = 0;
    if(MOTO3_PWM<0) MOTO3_PWM = 0;
    if(MOTO4_PWM<0) MOTO4_PWM = 0;

    TIM4->CCR1 =MOTO1_PWM;
    TIM4->CCR2 = MOTO2_PWM;
    TIM4->CCR3 = MOTO3_PWM;
    TIM4->CCR4 = MOTO4_PWM;
}

void Tim4_init(void)
{
    TIM_TimeBaseInitTypeDef     TIM_TimeBaseStructure;
    TIM_OCInitTypeDef               TIM_OCInitStructure;
    uint16_t PrescalerValue = 0;
    /* -----------------------------------------------------------------------
    TIM3 Configuration(配置): generate 4 PWM signals with 4 different duty cycles(占空比):
    The TIM3CLK frequency(频率) is set to SystemCoreClock (Hz), to get TIM3 counter
    clock at 24 MHz the Prescaler is computed(计算) as following:
    - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    SystemCoreClock is set to 72 MHz for Low-density(密度), Medium-density, High-density
    and Connectivity(连通性) line devices and to 24 MHz for Low-Density Value line and
    Medium-Density Value line devices

    The TIM3 is running at 36 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
    = 24 MHz / 1000 = 24 KHz
    TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
    TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
    TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
    TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
    ----------------------------------------------------------------------- */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//TIM3和TIM4同在APB1时钟下
    /* Compute the prescaler value */
    PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 999;     //计数上线  ,CNT=999时中断计数器并结束一个周期,进行下一个从零开始的周期
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;   //pwm时钟分频 72MHz多大分频分成24MHz
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     //向上计数
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    /* PWM1 Mode configuration: Channel */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//CNT<CCR1时为有效电平
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;//初始占空比为0
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//低电平有效
    TIM_OC1Init(TIM4, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
    TIM_OC3Init(TIM4, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
    TIM_OC4Init(TIM4, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM4, ENABLE);
    TIM_Cmd(TIM4, ENABLE);
}


void Moto_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //使能电机用的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); 
    //设置电机使用到得管脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 ; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    Tim4_init();    
}

#include "MPU6050.h"
#include "Tim.h"

u8                      mpu6050_buffer[14];                 //iic读取后存放数据
S_INT16_XYZ     GYRO_OFFSET,ACC_OFFSET;         //零漂
u8                      GYRO_OFFSET_OK = 1;
u8                      ACC_OFFSET_OK = 1;
S_INT16_XYZ     MPU6050_ACC_LAST,MPU6050_GYRO_LAST;     //最新一次读取值



/**************************实现函数*****************************************************

将iic读取到得数据分拆,放入相应寄存器

如果上位机要计算零漂,便发回OFFSET数据
****************************************************************************************/

void MPU6050_Dataanl(void)
{
    if(!GYRO_OFFSET_OK)//没有计算零偏,一开始不会计算零漂,
                       //只有上位机将GYRO_OFFSET_OK置零后才将其置零
    {                   
        static int32_t  tempgx=0,tempgy=0,tempgz=0;
        static uint8_t cnt_g=0;
//      LED1_ON;
        if(cnt_g==0)
        {
            GYRO_OFFSET.X=0;
            GYRO_OFFSET.Y=0;
            GYRO_OFFSET.Z=0;
            tempgx = 0;
            tempgy = 0;
            tempgz = 0;
            cnt_g = 1;
            return;
        }
        tempgx+= MPU6050_GYRO_LAST.X;
        tempgy+= MPU6050_GYRO_LAST.Y;
        tempgz+= MPU6050_GYRO_LAST.Z;
        if(cnt_g==200)
        {
            GYRO_OFFSET.X=tempgx/cnt_g;//累加200次取平均值
            GYRO_OFFSET.Y=tempgy/cnt_g;
            GYRO_OFFSET.Z=tempgz/cnt_g;
            cnt_g = 0;
            GYRO_OFFSET_OK = 1;
//          EE_SAVE_GYRO_OFFSET();//保存数据
            return;
        }
        cnt_g++;
    }
    if(!ACC_OFFSET_OK)
    {
        static int32_t  tempax=0,tempay=0,tempaz=0;
        static uint8_t cnt_a=0;
//      LED1_ON;
        if(cnt_a==0)
        {
            ACC_OFFSET.X = 0;
            ACC_OFFSET.Y = 0;
            ACC_OFFSET.Z = 0;
            tempax = 0;
            tempay = 0;
            tempaz = 0;
            cnt_a = 1;
            return;
        }
        tempax+= MPU6050_ACC_LAST.X;
        tempay+= MPU6050_ACC_LAST.Y;
        //tempaz+= MPU6050_ACC_LAST.Z;
        if(cnt_a==200)
        {
            ACC_OFFSET.X=tempax/cnt_a;
            ACC_OFFSET.Y=tempay/cnt_a;
            ACC_OFFSET.Z=tempaz/cnt_a;
            cnt_a = 0;
            ACC_OFFSET_OK = 1;
//          EE_SAVE_ACC_OFFSET();//保存数据
            return;
        }
        cnt_a++;        
    }
}

/*****************  底层的读取MPU6050_ACC_LAST,MPU6050_GYRO_LAST  数据  *****************/
void MPU6050_Read(void)
{
      MPU_Get_Accelerometer(&MPU6050_ACC_LAST.X ,&MPU6050_ACC_LAST.Y ,&MPU6050_ACC_LAST.Z );    //得到加速度传感器数据
            MPU_Get_Gyroscope(&MPU6050_GYRO_LAST.X ,&MPU6050_GYRO_LAST.Y ,&MPU6050_GYRO_LAST.Z );   //得到陀螺仪数据
}

/************************** 初始化     MPU6050 以进入可用状态  *****************************/

u8 MPU6050_Init(void)
{ 
    u8 res; 
    MPU_IIC_Init();//初始化IIC总线
    MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050
 delay_ms(100);
    MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050 
    MPU_Set_Gyro_Fsr(3);                    //陀螺仪传感器,±2000dps
    MPU_Set_Accel_Fsr(0);                   //加速度传感器,±2g
    MPU_Set_Rate(50);                       //设置采样率50Hz
    MPU_Write_Byte(MPU_INT_EN_REG,0X00);    //关闭所有中断
    MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭
    MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);   //关闭FIFO
    MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效


    res=MPU_Read_Byte(MPU_DEVICE_ID_REG); 
    if(res==MPU_ADDR)//器件ID正确
    {
        MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考
        MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作
        MPU_Set_Rate(50);                       //设置采样率为50Hz
    }else return 1;
    return 0;
}

/**********************   设置MPU6050的传感器   ********************************/

//陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Gyro_Fsr(u8 fsr)
{
    return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围  
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Accel_Fsr(u8 fsr)
{
    return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围  
}
//设置MPU6050的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_LPF(u16 lpf)
{
    u8 data=0;
    if(lpf>=188)data=1;
    else if(lpf>=98)data=2;
    else if(lpf>=42)data=3;
    else if(lpf>=20)data=4;
    else if(lpf>=10)data=5;
    else data=6; 
    return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器  
}
//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Rate(u16 rate)
{
    u8 data;
    if(rate>1000)rate=1000;
    if(rate<4)rate=4;
    data=1000/rate-1;
    data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);  //设置数字低通滤波器
    return MPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半
}



/***********************  读取六轴以及温度原始数据,并减去零偏  **************************/
//得到温度值
//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{
    u8 buf[2]; 
    short raw;
    float temp;
    MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); 
    raw=((u16)buf[0]<<8)|buf[1];  
    temp=36.53+((double)raw)/340;  
    return temp*100;;
}


//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{
    u8 buf[6],res;  
    res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
    if(res==0)
    {
        *gx=(((u16)buf[0]<<8)|buf[1])-GYRO_OFFSET.X;  
        *gy=(((u16)buf[2]<<8)|buf[3])-GYRO_OFFSET.Y;  
        *gz=(((u16)buf[4]<<8)|buf[5])-GYRO_OFFSET.Z;
    }   
    return res;;
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{
    u8 buf[6],res;  
    res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
    if(res==0)
    {
        *ax=(((u16)buf[0]<<8)|buf[1])-ACC_OFFSET.X;  
        *ay=(((u16)buf[2]<<8)|buf[3])-ACC_OFFSET.Y;  
        *az=(((u16)buf[4]<<8)|buf[5])-ACC_OFFSET.Z;
    }   
    return res;;
}

/***************************  IIC读写器件寄存器函数  ******************************************/
//IIC连续写
//addr:器件地址 
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
    u8 i; 
    MPU_IIC_Start(); 
    MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 
    if(MPU_IIC_Wait_Ack())  //等待应答
    {
        MPU_IIC_Stop();      
        return 1;       
    }
    MPU_IIC_Send_Byte(reg); //写寄存器地址
    MPU_IIC_Wait_Ack();     //等待应答
    for(i=0;i<len;i++)
    {
        MPU_IIC_Send_Byte(buf[i]);  //发送数据
        if(MPU_IIC_Wait_Ack())      //等待ACK
        {
            MPU_IIC_Stop();  
            return 1;        
        }       
    }    
    MPU_IIC_Stop();  
    return 0;   
} 
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{ 
    MPU_IIC_Start(); 
    MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 
    if(MPU_IIC_Wait_Ack())  //等待应答
    {
        MPU_IIC_Stop();      
        return 1;       
    }
    MPU_IIC_Send_Byte(reg); //写寄存器地址
    MPU_IIC_Wait_Ack();     //等待应答
    MPU_IIC_Start();
    MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令 
    MPU_IIC_Wait_Ack();     //等待应答 
    while(len)
    {                                     //可以连续读取6各数据,而不用写6个寄存器地址
        if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK,直到此时读取完毕 
        else *buf=MPU_IIC_Read_Byte(1);     //读数据,发送ACK,接着读取下一个地址的寄存器中的数据  
        len--;
        buf++; 
    }    
    MPU_IIC_Stop(); //产生一个停止条件 
    return 0;   
}
//IIC写一个字节 
//reg:寄存器地址
//data:数据
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Byte(u8 reg,u8 data)                
{ 
    MPU_IIC_Start(); 
    MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 
    if(MPU_IIC_Wait_Ack())  //等待应答
    {
        MPU_IIC_Stop();      
        return 1;       
    }
    MPU_IIC_Send_Byte(reg); //写寄存器地址
    MPU_IIC_Wait_Ack();     //等待应答 
    MPU_IIC_Send_Byte(data);//发送数据
    if(MPU_IIC_Wait_Ack())  //等待ACK
    {
        MPU_IIC_Stop();  
        return 1;        
    }        
    MPU_IIC_Stop();  
    return 0;
}
//IIC读一个字节 
//reg:寄存器地址 
//返回值:读到的数据
u8 MPU_Read_Byte(u8 reg)
{
    u8 res;
    MPU_IIC_Start(); 
    MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 
    MPU_IIC_Wait_Ack();     //等待应答 
    MPU_IIC_Send_Byte(reg); //写寄存器地址
    MPU_IIC_Wait_Ack();     //等待应答
    MPU_IIC_Start();
    MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令 
    MPU_IIC_Wait_Ack();     //等待应答 
    res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK 
    MPU_IIC_Stop();         //产生一个停止条件 
    return res;     
}




#include "MPU6050iic.h"

/*******************************   延时函数   *************************************/

static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
void delay_init()    
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);   //选择外部时钟  HCLK/8
    fac_us=SystemCoreClock/8000000; //为系统时钟的1/8  
        fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数 
}                                   
void delay_ms(u16 nms)
{                 
    u32 temp;          
    SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
    SysTick->VAL =0x00;           //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数  
    do
    {
        temp=SysTick->CTRL;
    }
    while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
    SysTick->VAL =0X00;       //清空计数器           
} 

//MPU IIC 延时函数
void MPU_IIC_Delay(void)//2us
{
    u32 temp;
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟  HCLK/8
    SysTick->LOAD=2*fac_us; //时间加载,2us           
    SysTick->VAL=0x00;        //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数     
    do
    {
        temp=SysTick->CTRL;
    }
    while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
    SysTick->VAL =0X00;       //清空计数器    
}

/*******************************   初始化IIC的IO口   ***************************************/

void MPU_IIC_Init(void)
{                        
  GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//先使能外设IO PORTC时钟 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;     // 端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出,可输出高低电平,连接数字器件
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //IO口速度为50MHz
  GPIO_Init(GPIOB, &GPIO_InitStructure);                     //根据设定参数初始化GPIO 

  GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);                       //PB10,PB11 输出高    

}

/***************************  IIC底层读写的时序函数  **************************************/

//产生IIC起始信号
void MPU_IIC_Start(void)
{
    MPU_SDA_OUT();     //sda线输出
    MPU_IIC_SDA=1;        
    MPU_IIC_SCL=1;
    MPU_IIC_Delay();
    MPU_IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    MPU_IIC_Delay();
    MPU_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}     
//产生IIC停止信号
void MPU_IIC_Stop(void)
{
    MPU_SDA_OUT();//sda线输出
    MPU_IIC_SCL=0;
    MPU_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
    MPU_IIC_Delay();
    MPU_IIC_SCL=1;  
    MPU_IIC_SDA=1;//发送I2C总线结束信号
    MPU_IIC_Delay();                                
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 MPU_IIC_Wait_Ack(void)
{
    u8 ucErrTime=0;
    MPU_SDA_IN();      //SDA设置为输入  
    MPU_IIC_SDA=1;MPU_IIC_Delay();     
    MPU_IIC_SCL=1;MPU_IIC_Delay();   
    while(MPU_READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            MPU_IIC_Stop();
            return 1;
        }
    }
    MPU_IIC_SCL=0;//时钟输出0      
    return 0;  
} 
//产生ACK应答
void MPU_IIC_Ack(void)
{
    MPU_IIC_SCL=0;
    MPU_SDA_OUT();
    MPU_IIC_SDA=0;
    MPU_IIC_Delay();
    MPU_IIC_SCL=1;
    MPU_IIC_Delay();
    MPU_IIC_SCL=0;
}
//不产生ACK应答          
void MPU_IIC_NAck(void)
{
    MPU_IIC_SCL=0;
    MPU_SDA_OUT();
    MPU_IIC_SDA=1;
    MPU_IIC_Delay();
    MPU_IIC_SCL=1;
    MPU_IIC_Delay();
    MPU_IIC_SCL=0;
}                                        
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答           
void MPU_IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
    MPU_SDA_OUT();      
    MPU_IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        MPU_IIC_SDA=(txd&0x80)>>7;
        txd<<=1;      
        MPU_IIC_SCL=1;
        MPU_IIC_Delay(); 
        MPU_IIC_SCL=0;  
        MPU_IIC_Delay();
    }    
}       
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 MPU_IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    MPU_SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        MPU_IIC_SCL=0; 
        MPU_IIC_Delay();
        MPU_IIC_SCL=1;
        receive<<=1;
        if(MPU_READ_SDA)receive++;   
        MPU_IIC_Delay(); 
    }                    
    if (!ack)
        MPU_IIC_NAck();//发送nACK
    else
        MPU_IIC_Ack(); //发送ACK   
    return receive;
}
#include "rc.h"
#include "BSP.h"
//#include "app/uart/uart1.h"
//#include "app/imu/imu.h"
//#include "app/control/control.h"

#define BYTE0(dwTemp)       (*(char *)(&dwTemp))
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))

#define RX_DR           6       //中断标志
#define TX_DS           5
#define MAX_RT      4

RC_GETDATA Rc_Get;//接收到的RC数据,1000~2000
float RC_Target_ROL=0,RC_Target_PIT=0,RC_Target_YAW=0;

void RC_FUN(void)
{
//判断解锁
    static u16 _armed_cnt1 = 0,_armed_cnt2 = 0;
    if(ARMED==0 && Rc_Get.THROTTLE < 1100 && Rc_Get.YAW <1100)
        _armed_cnt1++;
    else
        _armed_cnt1=0;
    if(_armed_cnt1>100) ARMED = 1;          //解锁

    if(ARMED==1 && Rc_Get.THROTTLE <1100 && Rc_Get.YAW >1900)
        _armed_cnt2++;
    else
        _armed_cnt2=0;
    if(_armed_cnt2>100) ARMED = 0;
}
void HC05_DataAnl(void)
{
    u8 sum = 0;
    for(u8 i=0;i<31;i++)
        sum += NRF24L01_RXDATA[i];
    if(!(sum==NRF24L01_RXDATA[31]))     return;     //判断sum,校验和
    if(!(NRF24L01_RXDATA[0]==0x8A))     return;     //判断帧头
    if(NRF24L01_RXDATA[1]==0x8A)                                //判断功能字,=0x8a,为遥控数据
    {
        Rc_Get.THROTTLE = (vs16)(NRF24L01_RXDATA[3]<<8)|NRF24L01_RXDATA[4];//数据合并,一次接受八位数据,
        Rc_Get.YAW          = (vs16)(NRF24L01_RXDATA[5]<<8)|NRF24L01_RXDATA[6];//但是需要合成16位
        Rc_Get.ROLL         = (vs16)(NRF24L01_RXDATA[7]<<8)|NRF24L01_RXDATA[8];
        Rc_Get.PITCH        = (vs16)(NRF24L01_RXDATA[9]<<8)|NRF24L01_RXDATA[10];
        Rc_Get.AUX1         = (vs16)(NRF24L01_RXDATA[11]<<8)|NRF24L01_RXDATA[12];
        Rc_Get.AUX2         = (vs16)(NRF24L01_RXDATA[13]<<8)|NRF24L01_RXDATA[14];
        Rc_Get.AUX3         = (vs16)(NRF24L01_RXDATA[15]<<8)|NRF24L01_RXDATA[16];
        Rc_Get.AUX4         = (vs16)(NRF24L01_RXDATA[17]<<8)|NRF24L01_RXDATA[18];
        Rc_Get.AUX5         = (vs16)(NRF24L01_RXDATA[19]<<8)|NRF24L01_RXDATA[20];
        RC_FUN();
        RC_Target_ROL = (Rc_Get.ROLL-1500)/30;     //一打摇杆偏得很可以将30改大
        RC_Target_PIT = (Rc_Get.PITCH-1500)/30;
        RC_Target_YAW = (Rc_Get.YAW-1500)/30;
    }
    if(NRF24L01_RXDATA[1]==0X8B)                                //判断功能字,=0x8B,为控制数据
    {
        if(NRF24L01_RXDATA[3]==0xAA)    //校准传感器
        {
            if(NRF24L01_RXDATA[4]==0xA2)    GYRO_OFFSET_OK = 0;
            if(NRF24L01_RXDATA[4]==0xA1)    ACC_OFFSET_OK = 0;
            if(NRF24L01_RXDATA[4]==0xA3)    {GYRO_OFFSET_OK = 0;ACC_OFFSET_OK = 0;}
        }
        if(NRF24L01_RXDATA[3]==0xA0)    {ARMED = 0;NRF_Send_ARMED();}
        if(NRF24L01_RXDATA[3]==0xA1)    {ARMED = 1;NRF_Send_ARMED();}
        if(NRF24L01_RXDATA[3]==0xAB)    //接收OFFSET
        {
            ACC_OFFSET.X = (NRF24L01_RXDATA[4]<<8) + NRF24L01_RXDATA[5];
            ACC_OFFSET.Y = (NRF24L01_RXDATA[6]<<8) + NRF24L01_RXDATA[7];
            EE_SAVE_ACC_OFFSET();
            //EE_SAVE_GYRO_OFFSET();
        }
        if(NRF24L01_RXDATA[3]==0xAC)    NRF_Send_OFFSET();
        if(NRF24L01_RXDATA[3]==0xAD)    NRF_Send_PID();
        if(NRF24L01_RXDATA[3]==0xAE)    //接收PID
        {
            PID_ROL.P = (float)((vs16)(NRF24L01_RXDATA[4]<<8)|NRF24L01_RXDATA[5])/100;
            PID_ROL.I = (float)((vs16)(NRF24L01_RXDATA[6]<<8)|NRF24L01_RXDATA[7])/100;
            PID_ROL.D = (float)((vs16)(NRF24L01_RXDATA[8]<<8)|NRF24L01_RXDATA[9])/100;
            PID_PIT.P = (float)((vs16)(NRF24L01_RXDATA[10]<<8)|NRF24L01_RXDATA[11])/100;
            PID_PIT.I = (float)((vs16)(NRF24L01_RXDATA[12]<<8)|NRF24L01_RXDATA[13])/100;
            PID_PIT.D = (float)((vs16)(NRF24L01_RXDATA[14]<<8)|NRF24L01_RXDATA[15])/100;
            PID_YAW.P = (float)((vs16)(NRF24L01_RXDATA[16]<<8)|NRF24L01_RXDATA[17])/100;
            PID_YAW.I = (float)((vs16)(NRF24L01_RXDATA[18]<<8)|NRF24L01_RXDATA[19])/100;
            PID_YAW.D = (float)((vs16)(NRF24L01_RXDATA[20]<<8)|NRF24L01_RXDATA[21])/100;
            EE_SAVE_PID();
        }
    }
}
void Nrf_Check_Event(void)
{
    u8 sta = NRF_Read_Reg(NRF_READ_REG + NRFRegSTATUS);//读取状态寄存器
    
    
    if(sta & (1<<RX_DR))//检验sta是不是接收中断
    {
        u8 rx_len = NRF_Read_Reg(R_RX_PL_WID);
        if(rx_len<33)
        {
            NRF_Read_Buf(RD_RX_PLOAD,NRF24L01_RXDATA,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
            NRF_DataAnl();//进行数据分析
            LED1_ONOFF();
        }
        else//当前数据有误 
        {
            NRF_Write_Reg(FLUSH_RX,0xff);//清空缓冲区
        }
    }
    
    
    if(sta & (1<<TX_DS))
    {
        LED1_ONOFF();
    }
    
    
    static uint8_t led2_state = 0;
    if(sta & (1<<MAX_RT))//??????????
    {
        if(led2_state)
        {
            LED2_OFF;
            led2_state = 0;
        }
        else
        {
            LED2_ON;
            led2_state = 1;
        }
        if(sta & 0x01)  //TX FIFO FULL
        {
            NRF_Write_Reg(FLUSH_TX,0xff);
        }
    }
    
    
    NRF_Write_Reg(NRF_WRITE_REG + NRFRegSTATUS, sta);
}
void NRF_Send_AF(void)
{
    uint8_t i,sum;
    uint16_t _temp;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xAF;
    NRF24L01_TXDATA[2]=0x1C;
    NRF24L01_TXDATA[3]=BYTE1(MPU6050_ACC_LAST.X);
    NRF24L01_TXDATA[4]=BYTE0(MPU6050_ACC_LAST.X);
    NRF24L01_TXDATA[5]=BYTE1(MPU6050_ACC_LAST.Y);
    NRF24L01_TXDATA[6]=BYTE0(MPU6050_ACC_LAST.Y);
    NRF24L01_TXDATA[7]=BYTE1(MPU6050_ACC_LAST.Z);
    NRF24L01_TXDATA[8]=BYTE0(MPU6050_ACC_LAST.Z);
    NRF24L01_TXDATA[9]=BYTE1(MPU6050_GYRO_LAST.X);
    NRF24L01_TXDATA[10]=BYTE0(MPU6050_GYRO_LAST.X);
    NRF24L01_TXDATA[11]=BYTE1(MPU6050_GYRO_LAST.Y);
    NRF24L01_TXDATA[12]=BYTE0(MPU6050_GYRO_LAST.Y);
    NRF24L01_TXDATA[13]=BYTE1(MPU6050_GYRO_LAST.Z);
    NRF24L01_TXDATA[14]=BYTE0(MPU6050_GYRO_LAST.Z);
    NRF24L01_TXDATA[15]=0;
    NRF24L01_TXDATA[16]=0;
    NRF24L01_TXDATA[17]=0;
    NRF24L01_TXDATA[18]=0;
    NRF24L01_TXDATA[19]=0;
    NRF24L01_TXDATA[20]=0;
    _temp = (int)(Q_ANGLE.X*100);
    NRF24L01_TXDATA[21]=BYTE1(_temp);
    NRF24L01_TXDATA[22]=BYTE0(_temp);
    _temp = (int)(Q_ANGLE.Y*100);
    NRF24L01_TXDATA[23]=BYTE1(_temp);
    NRF24L01_TXDATA[24]=BYTE0(_temp);
    _temp = (int)(Q_ANGLE.Z*10);
    NRF24L01_TXDATA[25]=BYTE1(_temp);
    NRF24L01_TXDATA[26]=BYTE0(_temp);

    if(ARMED==0)                NRF24L01_TXDATA[27]=0xA0;
    else if(ARMED==1)       NRF24L01_TXDATA[27]=0xA1;

    sum = 0;
    for(i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}
void NRF_Send_AE(void)
{
    uint8_t i,sum;
    uint16_t _temp;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xAE;
    NRF24L01_TXDATA[2]=0x1C;
    NRF24L01_TXDATA[3]=BYTE1(Rc_Get.THROTTLE);
    NRF24L01_TXDATA[4]=BYTE0(Rc_Get.THROTTLE);
    NRF24L01_TXDATA[5]=BYTE1(Rc_Get.YAW);
    NRF24L01_TXDATA[6]=BYTE0(Rc_Get.YAW);
    NRF24L01_TXDATA[7]=BYTE1(Rc_Get.ROLL);
    NRF24L01_TXDATA[8]=BYTE0(Rc_Get.ROLL);
    NRF24L01_TXDATA[9]=BYTE1(Rc_Get.PITCH);
    NRF24L01_TXDATA[10]=BYTE0(Rc_Get.PITCH);
    NRF24L01_TXDATA[11]=BYTE1(Rc_Get.AUX1);
    NRF24L01_TXDATA[12]=BYTE0(Rc_Get.AUX1);
    NRF24L01_TXDATA[13]=BYTE1(Rc_Get.AUX2);
    NRF24L01_TXDATA[14]=BYTE0(Rc_Get.AUX2);
    NRF24L01_TXDATA[15]=BYTE1(Rc_Get.AUX3);
    NRF24L01_TXDATA[16]=BYTE0(Rc_Get.AUX3);
    NRF24L01_TXDATA[17]=BYTE1(Rc_Get.AUX4);
    NRF24L01_TXDATA[18]=BYTE0(Rc_Get.AUX4);
    NRF24L01_TXDATA[19]=BYTE1(Rc_Get.AUX5);
    NRF24L01_TXDATA[20]=BYTE0(Rc_Get.AUX5);

    _temp = TIM2->CCR1/10;
    NRF24L01_TXDATA[21]=BYTE1(_temp);
    NRF24L01_TXDATA[22]=BYTE0(_temp);
    _temp = TIM2->CCR2/10;
    NRF24L01_TXDATA[23]=BYTE1(_temp);
    NRF24L01_TXDATA[24]=BYTE0(_temp);
    _temp = TIM2->CCR3/10;
    NRF24L01_TXDATA[25]=BYTE1(_temp);
    NRF24L01_TXDATA[26]=BYTE0(_temp);
    _temp = TIM2->CCR4/10;
    NRF24L01_TXDATA[27]=BYTE1(_temp);
    NRF24L01_TXDATA[28]=BYTE0(_temp);

    _temp = ADC_ConvertedValue/6;
    NRF24L01_TXDATA[29]=BYTE1(_temp);
    NRF24L01_TXDATA[30]=BYTE0(_temp);

    sum = 0;
    for(i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}
void NRF_Send_OFFSET(void)
{
    uint8_t i,sum;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xAC;
    NRF24L01_TXDATA[2]=0x1C;
    NRF24L01_TXDATA[3]=0xAC;
    NRF24L01_TXDATA[4]=BYTE1(ACC_OFFSET.X);
    NRF24L01_TXDATA[5]=BYTE0(ACC_OFFSET.X);
    NRF24L01_TXDATA[6]=BYTE1(ACC_OFFSET.Y);
    NRF24L01_TXDATA[7]=BYTE0(ACC_OFFSET.Y);
    NRF24L01_TXDATA[8]=BYTE1(ACC_OFFSET.Z);
    NRF24L01_TXDATA[9]=BYTE0(ACC_OFFSET.Z);
    NRF24L01_TXDATA[10]=BYTE1(GYRO_OFFSET.X);
    NRF24L01_TXDATA[11]=BYTE0(GYRO_OFFSET.X);
    NRF24L01_TXDATA[12]=BYTE1(GYRO_OFFSET.Y);
    NRF24L01_TXDATA[13]=BYTE0(GYRO_OFFSET.Y);
    NRF24L01_TXDATA[14]=BYTE1(GYRO_OFFSET.Z);
    NRF24L01_TXDATA[15]=BYTE0(GYRO_OFFSET.Z);
    sum = 0;
    for(i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}
void NRF_Send_PID(void)
{
    uint8_t i,sum;
    u16 _temp;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xAC;
    NRF24L01_TXDATA[2]=0x1C;
    NRF24L01_TXDATA[3]=0xAD;

    _temp = PID_ROL.P * 100;
    NRF24L01_TXDATA[4]=BYTE1(_temp);
    NRF24L01_TXDATA[5]=BYTE0(_temp);
    _temp = PID_ROL.I * 100;
    NRF24L01_TXDATA[6]=BYTE1(_temp);
    NRF24L01_TXDATA[7]=BYTE0(_temp);
    _temp = PID_ROL.D * 100;
    NRF24L01_TXDATA[8]=BYTE1(_temp);
    NRF24L01_TXDATA[9]=BYTE0(_temp);
    _temp = PID_PIT.P * 100;
    NRF24L01_TXDATA[10]=BYTE1(_temp);
    NRF24L01_TXDATA[11]=BYTE0(_temp);
    _temp = PID_PIT.I * 100;
    NRF24L01_TXDATA[12]=BYTE1(_temp);
    NRF24L01_TXDATA[13]=BYTE0(_temp);
    _temp = PID_PIT.D * 100;
    NRF24L01_TXDATA[14]=BYTE1(_temp);
    NRF24L01_TXDATA[15]=BYTE0(_temp);
    _temp = PID_YAW.P * 100;
    NRF24L01_TXDATA[16]=BYTE1(_temp);
    NRF24L01_TXDATA[17]=BYTE0(_temp);
    _temp = PID_YAW.I * 100;
    NRF24L01_TXDATA[18]=BYTE1(_temp);
    NRF24L01_TXDATA[19]=BYTE0(_temp);
    _temp = PID_YAW.D * 100;
    NRF24L01_TXDATA[20]=BYTE1(_temp);
    NRF24L01_TXDATA[21]=BYTE0(_temp);

    sum = 0;
    for(i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}
void NRF_Send_ARMED(void)//解锁信息
{
    uint8_t i,sum;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xAC;
    NRF24L01_TXDATA[2]=0x1C;
    if(ARMED)   NRF24L01_TXDATA[3]=0xA1;
    else            NRF24L01_TXDATA[3]=0xA0;
    sum = 0;
    for(i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}
void NRF_SEND_test(void)
{
    u8 sum;

    static u8 temp=0;

    temp++;

    NRF24L01_TXDATA[0]=0x88;
    NRF24L01_TXDATA[1]=0xA1;
    NRF24L01_TXDATA[2]=28;
    NRF24L01_TXDATA[3]=BYTE3(Q_ANGLE.X);
    NRF24L01_TXDATA[4]=BYTE2(Q_ANGLE.X);
    NRF24L01_TXDATA[5]=BYTE1(Q_ANGLE.X);
    NRF24L01_TXDATA[6]=BYTE0(Q_ANGLE.X);

    NRF24L01_TXDATA[7]=temp;

    for(u8 i=0;i<31;i++)
        sum += NRF24L01_TXDATA[i];

    NRF24L01_TXDATA[31]=sum;

    NRF_TxPacket(NRF24L01_TXDATA,32);
}

#include "UART2.h"
#include "CONTROL.h"
#include "stm32f10x.h"
#include "Uart1.h"
#include "MPU6050iic.h"

RC_GETDATA Rc_Get;//接收到的RC数据,1000~2000
float RC_Target_ROL=0,RC_Target_PIT=0,RC_Target_YAW=0;
int arm=0;

/************************* 飞控与手机APP的通讯 **************************************/

                      /*********串口2的初始化函数***********/

void Uart2_Init(u32 br_num)//时钟低电平活动,禁用了同步通讯,因此只有Uart,即只是异步通讯
{
    USART_InitTypeDef USART_InitStructure;
    USART_ClockInitTypeDef USART_ClockInitStruct;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //开启USART1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    

    //配置PA2作为USART1 Tx
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA , &GPIO_InitStructure);
    //配置PA3作为USART1 Rx
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA , &GPIO_InitStructure);

    //配置USART1
    //中断被屏蔽了
    USART_InitStructure.USART_BaudRate = br_num;       //波特率可以通过地面站配置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //8位数据
    USART_InitStructure.USART_StopBits = USART_StopBits_1;   //在帧结尾传输1个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;    //禁用奇偶校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;  //发送、接收使能
    //配置USART1时钟
    USART_ClockInitStruct.USART_Clock = USART_Clock_Disable;  //时钟低电平活动
    USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low;  //SLCK引脚上时钟输出的极性->低电平
    USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge;  //时钟第二个边沿进行数据捕获
    USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位数据的时钟脉冲不从SCLK输出

    USART_Init(USART2, &USART_InitStructure);
    USART_ClockInit(USART2, &USART_ClockInitStruct);

    //使能USART1接收中断
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    //使能USART1
    USART_Cmd(USART2, ENABLE); 
}                    



uint8_t Tx2Buffer[0xff];
u8 Tx2Counter=0;
u8 count2=32; 
u8 Rx2_Buf[2][32];  //两个32字节的串口接收缓存
u8 Rx2_Act=0;       //正在使用的buf号
u8 Rx2_Adr=0;       //正在接收第几字节
u8 Rx2_Ok0 = 0;
u8 Rx2_Ok1 = 0;


/**************************串口1的收发中断********************************************/

void Uart2_IRQ(void)//与PC上位机的通讯
{ 
    u8 com_data;

    if(USART2->SR & USART_IT_ORE)
    {
         com_data=USART2->SR;
    }
               /****************接收中断 (接收寄存器非空)************/ 

    //接收中断 (接收寄存器非空) 
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)    
    {   
        arm=0;

        //别忘了,只要接收到数据就是解锁(即APP连接了蓝牙)
         com_data = USART2->DR;
        if(Rx2_Adr==0)      //寻找帧头0X8A
        {
            if(com_data==0xAA)  //接收数据如果是0X8A,则写入缓存
            {

                Rx2_Buf[Rx2_Act][0] = com_data;
                Rx2_Adr = 1;

            }
        }
        else        //正在接收数据
        {
            Rx2_Buf[Rx2_Act][Rx2_Adr] = com_data;
            Rx2_Adr ++;
        }


        if(Rx2_Adr==25)     //数据接收完毕//如果adr等于了32,
                                         //那么这次act=0的数据接收完成,切换缓存到act=1;
        {

            Rx2_Adr = 0;
            if(Rx2_Act) 
            { 
                Rx2_Ok1 = 1;        //标志act=1的数组接收完成
                Rx2_Act = 0;            //切换缓存,去接收act=0的数组

            }
            else                
            {
                Rx2_Act = 1;
                Rx2_Ok0 = 1;
            }

        }

        USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清除接收中断标志位
  }

}


/**********************************串口接收的缓存数据de分析*********************************/
void Uart2_DataAnl(u8 buf_num)      //
{

    u8 sum = 0,i=0;
    if(Rx2_Buf[buf_num][1]!=0xAF)       return;     //检验第二位是不是AF




    if(Rx2_Buf[buf_num][2]==0x03)//下面进行对遥控数据的处理,应该在Uart2蓝牙  //判断功能字,=0x,为遥控数据
    {
        for(i=0;i<24;i++) //判断校验字节是否正确
      sum += Rx2_Buf[buf_num][i];   //sum是8位,自动截取最后8位
      if(!(sum==Rx2_Buf[buf_num][24]))      return;     //判断sum

        Rc_Get.THROTTLE = (vs16)(Rx2_Buf[buf_num][4]<<8)|Rx2_Buf[buf_num][5];   //首先进行8位数据的合并成16位赋值给遥控变量
        Rc_Get.YAW          = (vs16)(Rx2_Buf[buf_num][6]<<8)|Rx2_Buf[buf_num][7];
        Rc_Get.ROLL         = (vs16)(Rx2_Buf[buf_num][8]<<8)|Rx2_Buf[buf_num][9];
        Rc_Get.PITCH        = (vs16)(Rx2_Buf[buf_num][10]<<8)|Rx2_Buf[buf_num][11];
        Rc_Get.AUX1         = (vs16)(Rx2_Buf[buf_num][12]<<8)|Rx2_Buf[buf_num][13];
        Rc_Get.AUX2         = (vs16)(Rx2_Buf[buf_num][14]<<8)|Rx2_Buf[buf_num][15];
        RC_Target_ROL = (1500-Rc_Get.ROLL)/30;    //可以调遥控的灵敏度,一打杆偏大了,把30改大
        RC_Target_PIT = (1500-Rc_Get.PITCH)/30;   //要改变的RC_Target就变小了
        RC_Target_YAW = (Rc_Get.YAW-1500)/30;
    }
  if(Rx2_Buf[buf_num][2]==0x01)
        {


        if(Rx2_Buf[buf_num][4]==0xA0)   {ARMED = 0;TxCounter=0;Uart1_Send_ARMED();}
        if(Rx2_Buf[buf_num][4]==0xA1)   {ARMED = 1;TxCounter=0;Uart1_Send_ARMED();}
      }     
}

void Uart2_RXCheckEvent(void)
{ 
    //USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//处理某一组数据时不能被UART2的接收中断打断
    //因为UART2的中断优先级低于定时器中断,所以在执行定时器中断的程序(即Uart2_RXCheckEvent())时,
    //不可能被UART2的接收中断所打断
    if(Rx2_Ok0)
    {
        Rx2_Ok0 = 0;
        Uart2_DataAnl(0);
    }
    if(Rx2_Ok1)
    {
        Rx2_Ok1 = 0;
        Uart2_DataAnl(1);
    }
    //USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //重新打开接收中断
}
/******************************************************************************************/
/*此文件由HC05和Uart1调用*/

#include "stm32f10x.h"    
#include "usart.h"

#define BYTE0(dwTemp)       (*(char *)(&dwTemp))
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))

typedef union {unsigned char byte[4];float num;}t_floattobyte;
t_floattobyte floattobyte;

void Uart1_Init(u32 br_num)//时钟低电平活动,禁用了同步通讯,因此只有Uart
{
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStruct;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	
	//配置PA9作为USART1 Tx
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA , &GPIO_InitStructure);
	//配置PA10作为USART1 Rx
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA , &GPIO_InitStructure);
	
	//配置USART1
	//中断被屏蔽了
	USART_InitStructure.USART_BaudRate = br_num;       //波特率可以通过地面站配置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //8位数据
	USART_InitStructure.USART_StopBits = USART_StopBits_1;   //在帧结尾传输1个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;    //禁用奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;  //发送、接收使能
	//配置USART1时钟
	USART_ClockInitStruct.USART_Clock = USART_Clock_Disable;  //时钟低电平活动
	USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low;  //SLCK引脚上时钟输出的极性->低电平
	USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge;  //时钟第二个边沿进行数据捕获
	USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位数据的时钟脉冲不从SCLK输出
	
	USART_Init(USART1, &USART_InitStructure);
	USART_ClockInit(USART1, &USART_ClockInitStruct);

	//使能USART1接收中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	//使能USART1
	USART_Cmd(USART1, ENABLE); 
}




uint8_t TxBuffer[0xff];
u8 TxCounter=0;
u8 count=; 
u8 Rx_Buf[2][32];	//两个32字节的串口接收缓存
u8 Rx_Act=0;		//正在使用的buf号
u8 Rx_Adr=0;		//正在接收第几字节
u8 Rx_Ok0 = 0;
u8 Rx_Ok1 = 0;



void Uart1_IRQ(void)//与PC上位机的通讯
{
	if(USART1->SR & USART_IT_ORE)//有数据过载了,赶进读
	{
		USART1->SR;//没什么用
	}
	
	
               /*******************发送中断***********************/
	
	if((USART1->SR & (1<<7))&&(USART1->CR1 & USART_CR1_TXEIE))//if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET)
	{                                                          //如果打开了写中断使能
		USART1->DR = TxBuffer[TxCounter++]; //写数据到DR          
		if(TxCounter == count)//如果TxCounter达到了最大量count
		{
			USART1->CR1 &= ~USART_CR1_TXEIE;		//关闭TXE写入中断
			//USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
		}
	}
	
	
              /****************接收中断 (接收寄存器非空)************/ 
	
	if(USART1->SR & (1<<5))//if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)    
	{                       //接收中断为1代表接收数据寄存器已满
		u8 com_data = USART1->DR;//赶进读
		  
		//寻找接收的数据中帧头0XAAAF
		
			if(Rx_Adr==0)//检验Rx_Buf[Rx_Act][0,1,2,3]            
			{            //对应0xAA,AF,FUN,LEN	
				if(com_data==0xAA)	
				{
					Rx_Buf[Rx_Act][0] = com_data;
					Rx_Adr = 1;
				}
			}
			else if(Rx_Adr==1)
			{
				if(com_data==0xAF)	
				{
					Rx_Buf[Rx_Act][1] = com_data;
					Rx_Adr = 2;
				}
				else
					Rx_Adr = 0;
			}
			else if(Rx_Adr==2)		//FUN
			{
				Rx_Buf[Rx_Act][2] = com_data;
				Rx_Adr = 3;
			}
			else if(Rx_Adr==3)		//LEN
			{
				Rx_Buf[Rx_Act][3] = com_data;
				Rx_Adr = 4;
			}
			else
			{
				Rx_Buf[Rx_Act][Rx_Adr] = com_data;
				Rx_Adr ++;
			}                              
			if(Rx_Adr==Rx_Buf[Rx_Act][3]+5)//如果adr等于了前面接收到的LEN
			{                              //那么这次act=0的数据接收完成,切换缓存到act=1;
				Rx_Adr = 0;
				if(Rx_Act)	
				{ 
					Rx_Act = 0; 			//切换缓存
					Rx_Ok1 = 1;
				}
				else 				
				{
					Rx_Act = 1;
					Rx_Ok0 = 1;
				}
		}
	}
}


/**********************************串口接收的缓存数据分析*********************************/
void Uart_DataAnl(u8 buf_num)		//
{
	if((Rx_Buf[buf_num][1]==0xAA)&&(Rx_Buf[buf_num][2]==0xAF))//如果串口收到的是AA,AF
		                                                         //是PC上位机发送给飞控的数据
	{
	
	}
}



void Uart_CheckEvent(void)
{
	if(Rx_Ok0)
	{
		Rx_Ok0 = 0;
		Uart_DataAnl(0);
	}
	if(Rx_Ok1)
	{
		Rx_Ok1 = 0;
		Uart_DataAnl(1);
	}
}
/******************************************************************************************/

/**************************实现函数********************************************
*******************************************************************************/
uint8_t Uart1_Put_Char(unsigned char DataToSend)
{
	TxBuffer[count++] = DataToSend;  
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE); 
	return DataToSend;
}
uint8_t Uart1_Put_Int16(uint16_t DataToSend)
{
	uint8_t sum = 0;
	TxBuffer[count++] = BYTE1(DataToSend);
	TxBuffer[count++] = BYTE0(DataToSend);
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	sum += BYTE1(DataToSend);
	sum += BYTE0(DataToSend);
	return sum;
}
uint8_t Uart1_Put_Float(float DataToSend)
{
	uint8_t sum = 0;
	floattobyte.num=DataToSend;
	TxBuffer[count++] = floattobyte.byte[3];  
	TxBuffer[count++] = floattobyte.byte[2];  
	TxBuffer[count++] = floattobyte.byte[1];  
	TxBuffer[count++] = floattobyte.byte[0];  
	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	sum += BYTE3(DataToSend);
	sum += BYTE2(DataToSend);
	sum += BYTE1(DataToSend);
	sum += BYTE0(DataToSend);
	return sum;	
}
void Uart1_Put_String(unsigned char *Str)
{
	//判断Str指向的数据是否有效.
	while(*Str)
	{
	//是否是回车字符 如果是,则发送相应的回车 0x0d 0x0a
	if(*Str=='\r')Uart1_Put_Char(0x0d);
		else if(*Str=='\n')Uart1_Put_Char(0x0a);
			else Uart1_Put_Char(*Str);
	//指针++ 指向下一个字节.
	Str++;
	}
}


/*此文件由HC05和Uart1调用*/

#include "stm32f10x.h"    
#include "usart.h"

#define BYTE0(dwTemp)       (*(char *)(&dwTemp))
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))

typedef union {unsigned char byte[4];float num;}t_floattobyte;
t_floattobyte floattobyte;

void Uart1_Init(u32 br_num)//时钟低电平活动,禁用了同步通讯,因此只有Uart
{
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStruct;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	
	//配置PA9作为USART1 Tx
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA , &GPIO_InitStructure);
	//配置PA10作为USART1 Rx
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA , &GPIO_InitStructure);
	
	//配置USART1
	//中断被屏蔽了
	USART_InitStructure.USART_BaudRate = br_num;       //波特率可以通过地面站配置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //8位数据
	USART_InitStructure.USART_StopBits = USART_StopBits_1;   //在帧结尾传输1个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;    //禁用奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;  //发送、接收使能
	//配置USART1时钟
	USART_ClockInitStruct.USART_Clock = USART_Clock_Disable;  //时钟低电平活动
	USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low;  //SLCK引脚上时钟输出的极性->低电平
	USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge;  //时钟第二个边沿进行数据捕获
	USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位数据的时钟脉冲不从SCLK输出
	
	USART_Init(USART1, &USART_InitStructure);
	USART_ClockInit(USART1, &USART_ClockInitStruct);

	//使能USART1接收中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	//使能USART1
	USART_Cmd(USART1, ENABLE); 
}




uint8_t TxBuffer[0xff];
u8 TxCounter=0;
u8 count=; 
u8 Rx_Buf[2][32];	//两个32字节的串口接收缓存
u8 Rx_Act=0;		//正在使用的buf号
u8 Rx_Adr=0;		//正在接收第几字节
u8 Rx_Ok0 = 0;
u8 Rx_Ok1 = 0;



void Uart1_IRQ(void)//与PC上位机的通讯
{
	if(USART1->SR & USART_IT_ORE)//有数据过载了,赶进读
	{
		USART1->SR;//没什么用
	}
	
	
               /*******************发送中断***********************/
	
	if((USART1->SR & (1<<7))&&(USART1->CR1 & USART_CR1_TXEIE))//if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET)
	{                                                          //如果打开了写中断使能
		USART1->DR = TxBuffer[TxCounter++]; //写数据到DR          
		if(TxCounter == count)//如果TxCounter达到了最大量count
		{
			USART1->CR1 &= ~USART_CR1_TXEIE;		//关闭TXE写入中断
			//USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
		}
	}
	
	
              /****************接收中断 (接收寄存器非空)************/ 
	
	if(USART1->SR & (1<<5))//if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)    
	{                       //接收中断为1代表接收数据寄存器已满
		u8 com_data = USART1->DR;//赶进读
		  
		//寻找接收的数据中帧头0XAAAF
		
			if(Rx_Adr==0)//检验Rx_Buf[Rx_Act][0,1,2,3]            
			{            //对应0xAA,AF,FUN,LEN	
				if(com_data==0xAA)	
				{
					Rx_Buf[Rx_Act][0] = com_data;
					Rx_Adr = 1;
				}
			}
			else if(Rx_Adr==1)
			{
				if(com_data==0xAF)	
				{
					Rx_Buf[Rx_Act][1] = com_data;
					Rx_Adr = 2;
				}
				else
					Rx_Adr = 0;
			}
			else if(Rx_Adr==2)		//FUN
			{
				Rx_Buf[Rx_Act][2] = com_data;
				Rx_Adr = 3;
			}
			else if(Rx_Adr==3)		//LEN
			{
				Rx_Buf[Rx_Act][3] = com_data;
				Rx_Adr = 4;
			}
			else
			{
				Rx_Buf[Rx_Act][Rx_Adr] = com_data;
				Rx_Adr ++;
			}                              
			if(Rx_Adr==Rx_Buf[Rx_Act][3]+5)//如果adr等于了前面接收到的LEN
			{                              //那么这次act=0的数据接收完成,切换缓存到act=1;
				Rx_Adr = 0;
				if(Rx_Act)	
				{ 
					Rx_Act = 0; 			//切换缓存
					Rx_Ok1 = 1;
				}
				else 				
				{
					Rx_Act = 1;
					Rx_Ok0 = 1;
				}
		}
	}
}


/**********************************串口接收的缓存数据分析*********************************/
void Uart_DataAnl(u8 buf_num)		//
{
	if((Rx_Buf[buf_num][1]==0xAA)&&(Rx_Buf[buf_num][2]==0xAF))//如果串口收到的是AA,AF
		                                                         //是PC上位机发送给飞控的数据
	{
	
	}
}



void Uart_CheckEvent(void)
{
	if(Rx_Ok0)
	{
		Rx_Ok0 = 0;
		Uart_DataAnl(0);
	}
	if(Rx_Ok1)
	{
		Rx_Ok1 = 0;
		Uart_DataAnl(1);
	}
}
/******************************************************************************************/

/**************************实现函数********************************************
*******************************************************************************/
uint8_t Uart1_Put_Char(unsigned char DataToSend)
{
	TxBuffer[count++] = DataToSend;  
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE); 
	return DataToSend;
}
uint8_t Uart1_Put_Int16(uint16_t DataToSend)
{
	uint8_t sum = 0;
	TxBuffer[count++] = BYTE1(DataToSend);
	TxBuffer[count++] = BYTE0(DataToSend);
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	sum += BYTE1(DataToSend);
	sum += BYTE0(DataToSend);
	return sum;
}
uint8_t Uart1_Put_Float(float DataToSend)
{
	uint8_t sum = 0;
	floattobyte.num=DataToSend;
	TxBuffer[count++] = floattobyte.byte[3];  
	TxBuffer[count++] = floattobyte.byte[2];  
	TxBuffer[count++] = floattobyte.byte[1];  
	TxBuffer[count++] = floattobyte.byte[0];  
	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
	sum += BYTE3(DataToSend);
	sum += BYTE2(DataToSend);
	sum += BYTE1(DataToSend);
	sum += BYTE0(DataToSend);
	return sum;	
}
void Uart1_Put_String(unsigned char *Str)
{
	//判断Str指向的数据是否有效.
	while(*Str)
	{
	//是否是回车字符 如果是,则发送相应的回车 0x0d 0x0a
	if(*Str=='\r')Uart1_Put_Char(0x0d);
		else if(*Str=='\n')Uart1_Put_Char(0x0a);
			else Uart1_Put_Char(*Str);
	//指针++ 指向下一个字节.
	Str++;
	}
}


  • 5
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值