<|start_filename|>project/p10-ANO/application/pid.h<|end_filename|>
#ifndef _PID_H_
#define _PID_H_

/* Exported types ------------------------------------------------------------*/
typedef struct
{
    float P, I, D;  // PID三个参数
    float Desired;  // 期望
    float Error;    // 误差
    float PreError; // 上一次误差
    float Integ;    // 积分值
    float iLimit;   // 积分值限制
    float Deriv;    // 微分值
    float Output;   // 输出
}PID_Typedef;

/* Exported functions ------------------------------------------------------- */
void PID_init(void);
void CtrlAttiAng(void);
void CtrlAttiRate(void);
void CtrlMotorSpeed(void);

/* Exported variables --------------------------------------------------------*/
extern PID_Typedef pitch_angle_PID; // pitch角度PID
extern PID_Typedef roll_angle_PID;
extern PID_Typedef yaw_angle_PID;

extern PID_Typedef pitch_rate_PID;  // pitch角速度PID
extern PID_Typedef roll_rate_PID;
extern PID_Typedef yaw_rate_PID;

#endif /* _PID_H_ */


<|start_filename|>firmware/Nucleo64-User/LED.c<|end_filename|>
/**
  @file    button.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   This file provides firmware functions to user LED on nucleo64.

  LD2 - PA5 - TIM2_CH1
  
*/
#include <stm32f4xx.h>
#include <LED.h>

void GPIO_init_4_LD2 (void)
{
	GPIO_InitTypeDef r1 = {GPIO_Pin_5, GPIO_Mode_OUT, GPIO_High_Speed, GPIO_OType_PP, GPIO_PuPd_NOPULL};
	GPIO_InitTypeDef r2 = {GPIO_Pin_5, GPIO_Mode_OUT, GPIO_High_Speed, GPIO_OType_OD, GPIO_PuPd_UP};
	(void)r1; // PP
	(void)r2; // OD
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	GPIO_Init(GPIOA, &r1);
}


<|start_filename|>project/p1-nucleo64-test/application/main.c<|end_filename|>
#include "main.h"
#include "stm32f4xx_conf.h"
#include "button.h"
#include "LED.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t uwTimingDelay;
RCC_ClocksTypeDef RCC_Clocks;
int s = 100;
int touch = 0;

/* Private function prototypes -----------------------------------------------*/
static void Delay(__IO uint32_t nTime);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
 /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */

  /* SysTick end of count event each 1ms */
  RCC_GetClocksFreq(&RCC_Clocks);
  SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
  
  /* Add your application code here */	
	GPIO_init_4_B1();
	GPIO_init_4_LD2();
     
  /* Infinite loop */
  for (int light = 0;;)
	{
		Delay(s);
		set_LD2(light=!light);
	}
}

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in milliseconds.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{ 
  uwTimingDelay = nTime;

  while(uwTimingDelay != 0)
		if (touch) {
			if (!get_B1) {
				touch = 0;
				s *= 2;
			}
		} else if (get_B1)
			touch = 1;
}

/**
  * @brief  Decrements the TimingDelay variable.
  * @param  None
  * @retval None
  */
void TimingDelay_Decrement(void)
{
  if (uwTimingDelay != 0x00)
  { 
    uwTimingDelay--;
  }
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif


<|start_filename|>project/p9-RT-uasrt/application/main.c<|end_filename|>
#include "stm32f4xx_conf.h"
#include "usart.h"
#include "delay.h"

/* Private typedef -----------------------------------------------------------*/
#define printf_(s, ...) printf("file:%s\tline:%d\t" s, __FILE__, __LINE__, __VA_ARGS__)
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @retval None
  */
int main(void)
{
	
 /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */
	delayinit();
	delay(2000);
  /* Add your application code here */
	int c = 0;
	uart_init(38400);
	for (;;) {
        printf_("no.%d \r\n", ++c);
        while(~USART_RX_STA & 0x8000);
		printf_("i get: %s \r\n", USART_RX_BUF);
        USART_RX_STA = 0;
	}
}


<|start_filename|>project/p5-uart-series-port/application/main.c<|end_filename|>
#include "stm32f4xx_conf.h"
#include "usart.h"
#include "delay.h"

/* Private typedef -----------------------------------------------------------*/
#define printf_(s, ...) printf("file:%s\tline:%d\t" s, __FILE__, __LINE__, __VA_ARGS__)
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @retval None
  */
int main(void)
{
    
    /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */
    delayinit();
    delay(2000);
    /* Add your application code here */
    uart_init(38400);

#if 0 // test printf's efficiency
    char s[1024];
    for (int i=0;i<1023;i++) s[i]='a'; s[1023]=0;
    for (;;) {
        printf_("%s \r\n msCNT = %d \r\n", s, msTimerCounter); // 1024*9/38400 = 0.24s  实测0.309s
    }
#elif 1 // test delay & msCNT
    for (;;) {
        printf_("msCNT = %d \r\n", msTimerCounter); // 实际测试输出9次要1.017s
        delay(100);
    }
#endif

    /* Infinite loop */
    //for (;;);
}


<|start_filename|>firmware/uart-nucleo/usart.h<|end_filename|>
#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "stm32f4xx_conf.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用，未经作者许可，不得用于其它任何用途
//Mini STM32开发板
//串口1初始化		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.csom
//修改日期:2011/6/14
//版本：V1.4
//版权所有，盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//********************************************************************************

// tjua:170730 F407 yuanzi -> F411-nucleo


//V1.3修改说明 
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART2_RX的使能方式
////////////////////////////////////////////////////////////////////////////////// 	
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART2_RX 			1		//使能（1）/禁止（0）串口2接收
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收，请不要注释以下宏定义
void uart_init(u32 bound);
#endif




<|start_filename|>project/p10-ANO/application/data_transfer.c<|end_filename|>
/******************** (C) COPYRIGHT 2014 ANO Tech ********************************
 * 作者   ：匿名科创
 * 文件名  ：data_transfer.c
 * 描述    ：数据传输
 * 官网    ：www.anotc.com
 * 淘宝    ：anotc.taobao.com
 * 技术Q群 ：190169595
**********************************************************************************/

/// modify by tjua in 171210

#include "data_transfer.h"
#include "gpio_mpu6050.h"
#include "gpio_hmc5883.h"
#include "PWM-RCV.h"
#include "motor-PWM.h"
#include "Attitude.h"
#include "pid.h"
#include <stdio.h>

void my1_ANO_DT_Data_Receive_Anl(u8 *RxBuffer, uint32_t length);

/////////////////////////////////////////////////////////////////////////////////////
//数据拆分宏定义，在发送大于1字节的数据类型时，比如int16、float等，需要把数据拆分成单独字节进行发送
// 小端 要求?
#define BYTE0(dwTemp)       ( *( (char *)(&dwTemp)    ) )
#define BYTE1(dwTemp)       ( *( (char *)(&dwTemp) + 1) )
#define BYTE2(dwTemp)       ( *( (char *)(&dwTemp) + 2) )
#define BYTE3(dwTemp)       ( *( (char *)(&dwTemp) + 3) )

dt_flag_t f;            //需要发送数据的标志
u8 data_to_send[50];    //发送数据缓存 //// bug 没有上锁。。。

/////////////////////////////////////////////////////////////////////////////////////
//Data_Exchange函数处理各种数据发送请求，比如想实现每5ms发送一次传感器数据至上位机，即在此函数内实现
//此函数应由用户每1ms调用一次
void ANO_DT_Data_Exchange(uint16_t times, uint16_t time)
{
    static uint16_t maxtime = 0;
    if (maxtime < time) maxtime = time;
    static u8 cnt = 0;
    const u8 senser_cnt    = 16;
    const u8 status_cnt    = 16;
    const u8 rcdata_cnt    = 32;
    const u8 motopwm_cnt   = 32;
    const u8 power_cnt     = 64;
    const u8 F1_cnt        = 16;
    const u8 F2_cnt        = 16;
    const u8 F3_cnt        = 16;
    const u8 F4_cnt        = 16;

    if((cnt % senser_cnt) == (senser_cnt-1))
        f.send_senser = 1;

    if((cnt % status_cnt) == (status_cnt-1))
        f.send_status = 1;

    if((cnt % rcdata_cnt) == (rcdata_cnt-1))
        f.send_rcdata = 1;

    if((cnt % motopwm_cnt) == (motopwm_cnt-1))
        f.send_motopwm = 1;

    if((cnt % power_cnt) == (power_cnt-1))
        f.send_power = 1;

    if((cnt % F1_cnt) == (F1_cnt-1))
        f.send_F1 = 1;

    if((cnt % F2_cnt) == (F2_cnt-1))
        f.send_F2 = 1;

    if((cnt % F3_cnt) == (F3_cnt-1))
        f.send_F3 = 1;

    if((cnt % F4_cnt) == (F4_cnt-1))
        f.send_F4 = 1;

    cnt++;
/////////////////////////////////////////////////////////////////////////////////////
    if(f.send_version)
    {
        f.send_version = 0;
        ANO_DT_Send_Version(4,300,100,400,0);
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_status)
    {
        f.send_status = 0;
        // void ANO_DT_Send_Status(float angle_rol, float angle_pit, float angle_yaw, s32 alt, u8 fly_model, u8 armed);
        // ANO_DT_Send_Status(Roll,Pitch,Yaw,baroAlt,0,fly_ready);
        // 姿态结算数据
        ANO_DT_Send_Status(roll,pitch,yaw,121,122,1); // armed 是否上锁 0加锁/1解锁
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_senser)
    {
        f.send_senser = 0;
        // void ANO_DT_Send_Senser(s16 a_x,s16 a_y,s16 a_z,s16 g_x,s16 g_y,s16 g_z,s16 m_x,s16 m_y,s16 m_z,s32 bar);
        // ANO_DT_Send_Senser(mpu6050.Acc.x,mpu6050.Acc.y,mpu6050.Acc.z,
        //                                      mpu6050.Gyro.x,mpu6050.Gyro.y,mpu6050.Gyro.z,
        //                                      ak8975.Mag_Adc.x,ak8975.Mag_Adc.y,ak8975.Mag_Adc.z,0);
        ANO_DT_Send_Senser(accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2], mag[0], mag[1], mag[2], u16Rcvr_ch3>1100); // bar 压根没用上不知道有什么用
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_rcdata)
    {
        f.send_rcdata = 0;
        // void ANO_DT_Send_RCData(u16 thr,u16 yaw,u16 rol,u16 pit,u16 aux1,u16 aux2,u16 aux3,u16 aux4,u16 aux5,u16 aux6);
        // ANO_DT_Send_RCData(Rc_Pwm_In[0],Rc_Pwm_In[1],Rc_Pwm_In[2],Rc_Pwm_In[3],Rc_Pwm_In[4],Rc_Pwm_In[5],Rc_Pwm_In[6],Rc_Pwm_In[7],0,0);
        ANO_DT_Send_RCData(u16Rcvr_ch3, u16Rcvr_ch4, u16Rcvr_ch1, u16Rcvr_ch2, motor_pwm_1, motor_pwm_2, motor_pwm_3, motor_pwm_4, times, maxtime);
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_motopwm)
    {
        f.send_motopwm = 0;
        // void ANO_DT_Send_MotoPWM(u16 m_1,u16 m_2,u16 m_3,u16 m_4,u16 m_5,u16 m_6,u16 m_7,u16 m_8);
        ANO_DT_Send_MotoPWM(motor_pwm_1, motor_pwm_2, motor_pwm_3, motor_pwm_4, 5,6,7,8);
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_power)
    {
        f.send_power = 0;
        // void ANO_DT_Send_Power(u16 votage, u16 current);
        ANO_DT_Send_Power(100*time, 100*maxtime);
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if(f.send_pid1)
    {
        f.send_pid1 = 0;
        /*
        ANO_DT_Send_PID(1,ctrl_1.PID[PIDROLL].kp,ctrl_1.PID[PIDROLL].ki,ctrl_1.PID[PIDROLL].kd,
                          ctrl_1.PID[PIDPITCH].kp,ctrl_1.PID[PIDPITCH].ki,ctrl_1.PID[PIDPITCH].kd,
                          ctrl_1.PID[PIDYAW].kp,ctrl_1.PID[PIDYAW].ki,ctrl_1.PID[PIDYAW].kd);
        */
        // void ANO_DT_Send_PID(u8 group,float p1_p,float p1_i,float p1_d,float p2_p,float p2_i,float p2_d,float p3_p,float p3_i,float p3_d);
        ANO_DT_Send_PID(1, roll_angle_PID.P, roll_angle_PID.I, roll_angle_PID.D,
                           pitch_angle_PID.P, pitch_angle_PID.I, pitch_angle_PID.D,
                           yaw_angle_PID.P, yaw_angle_PID.I, yaw_angle_PID.D
                           );
    }
    else if(f.send_pid2)
    {
        f.send_pid2 = 0;
        ANO_DT_Send_PID(2, roll_rate_PID.P, roll_rate_PID.I, roll_rate_PID.D,
                           pitch_rate_PID.P, pitch_rate_PID.I, pitch_rate_PID.D,
                           yaw_rate_PID.P, yaw_rate_PID.I, yaw_rate_PID.D
                           );
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if (f.send_F1) {
        f.send_F1 = 0;
        // void ANO_DT_Send_Fx_pid_ans(u8 Fx, float rcver_rol, float rcver_pit, float rcver_yaw,
        //             float error_rol, float error_pit, float error_yaw,
        //             float react_rol, float react_pit, float react_yaw);
        static u8 buf[50];
        ANO_DT_Send_Fx_9float(buf, 0xF1,
                       roll_angle_PID.Desired, pitch_angle_PID.Desired, yaw_angle_PID.Desired,
                       roll_angle_PID.Error,   pitch_angle_PID.Error,   yaw_angle_PID.Error,
                       roll_angle_PID.Output,  pitch_angle_PID.Output,  yaw_angle_PID.Output
                       );
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if (f.send_F2) {
        f.send_F2 = 0;
        // void ANO_DT_Send_Fx_pid_part(u8 Fx, float P_Output_rol, float P_Output_pit, float P_Output_yaw,
        //                      float I_Output_rol, float I_Output_pit, float I_Output_yaw,
        //                      float D_Output_rol, float D_Output_rol, float D_Output_rol);
        static u8 buf[50];
        ANO_DT_Send_Fx_9float(buf, 0xF2,
                        // PID->P * PID->Error
                        roll_angle_PID.D * roll_angle_PID.Error,
                        pitch_angle_PID.D * pitch_angle_PID.Error,
                        yaw_angle_PID.D * yaw_angle_PID.Error,
                        // PID->I * PID->Integ
                        roll_angle_PID.I * roll_angle_PID.Integ,
                        pitch_angle_PID.I * pitch_angle_PID.Integ,
                        yaw_angle_PID.I * yaw_angle_PID.Integ,
                        // PID->D * PID->Deriv,
                        roll_angle_PID.D * roll_angle_PID.Deriv,
                        pitch_angle_PID.D * pitch_angle_PID.Deriv,
                        yaw_angle_PID.D * yaw_angle_PID.Deriv
                        );
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if (f.send_F3) {
        f.send_F3 = 0;
        // void ANO_DT_Send_Fx_pid_ans(u8 Fx, float rcver_rol, float rcver_pit, float rcver_yaw,
        //             float error_rol, float error_pit, float error_yaw,
        //             float react_rol, float react_pit, float react_yaw);
        static u8 buf[50];
        ANO_DT_Send_Fx_9float(buf, 0xF3,
                       roll_rate_PID.Desired, pitch_rate_PID.Desired, yaw_rate_PID.Desired,
                       roll_rate_PID.Error,   pitch_rate_PID.Error,   yaw_rate_PID.Error,
                       roll_rate_PID.Output,  pitch_rate_PID.Output,  yaw_rate_PID.Output
                       );
    }
/////////////////////////////////////////////////////////////////////////////////////
    else if (f.send_F4) {
        f.send_F4 = 0;
        // void ANO_DT_Send_Fx_pid_part(u8 Fx, float P_Output_rol, float P_Output_pit, float P_Output_yaw,
        //                      float I_Output_rol, float I_Output_pit, float I_Output_yaw,
        //                      float D_Output_rol, float D_Output_rol, float D_Output_rol);
        static u8 buf[50];
        ANO_DT_Send_Fx_9float(buf, 0xF4,
                        // PID->P * PID->Error
                        roll_rate_PID.D * roll_rate_PID.Error,
                        pitch_rate_PID.D * pitch_rate_PID.Error,
                        yaw_rate_PID.D * yaw_rate_PID.Error,
                        // PID->I * PID->Integ
                        roll_rate_PID.I * roll_rate_PID.Integ,
                        pitch_rate_PID.I * pitch_rate_PID.Integ,
                        yaw_rate_PID.I * yaw_rate_PID.Integ,
                        // PID->D * PID->Deriv,
                        roll_rate_PID.D * roll_rate_PID.Deriv,
                        pitch_rate_PID.D * pitch_rate_PID.Deriv,
                        yaw_rate_PID.D * yaw_rate_PID.Deriv
                        );
    }
/////////////////////////////////////////////////////////////////////////////////////
}

/////////////////////////////////////////////////////////////////////////////////////
//Send_Data函数是协议中所有发送数据功能使用到的发送函数
//移植时，用户应根据自身应用的情况，根据使用的通信方式，实现此函数
void ANO_DT_Send_Data(u8 *dataToSend , u8 length)
{
    void Usart2_Send(uint8_t *, uint32_t);
    Usart2_Send(dataToSend, length);
}

static void ANO_DT_Send_Check(u8 head, u8 check_sum)
{
    static u8 data_to_send[10]; // 不能和外部用同一个缓冲区

    data_to_send[0]=0xAA;
    data_to_send[1]=0xAA;
    data_to_send[2]=0xEF;
    data_to_send[3]=2;
    data_to_send[4]=head;
    data_to_send[5]=check_sum;


    u8 sum = 0;
    for(u8 i=0;i<6;i++)
        sum += data_to_send[i];
    data_to_send[6]=sum;

    ANO_DT_Send_Data(data_to_send, 7);
}

/////////////////////////////////////////////////////////////////////////////////////
//Data_Receive_Prepare函数是协议预解析，根据协议的格式，将收到的数据进行一次格式性解析，格式正确的话再进行数据解析
//移植时，此函数应由用户根据自身使用的通信方式自行调用，比如串口每收到一字节数据，则调用此函数一次
//此函数解析出符合格式的数据帧后，会自行调用数据解析函数
void ANO_DT_Data_Receive_Prepare(u8 data)
{
    static u8 RxBuffer[50];
    static u8 _data_len = 0,_data_cnt = 0;
    static u8 state = 0;

    if(state==0&&data==0xAA)
    {
        state=1;
        RxBuffer[0]=data;
    }
    else if(state==1&&data==0xAF)
    {
        state=2;
        RxBuffer[1]=data;
    }
    else if(state==2&&data<0XF1)
    {
        state=3;
        RxBuffer[2]=data;
    }
    else if(state==3&&data<50)
    {
        state = 4;
        RxBuffer[3]=data;
        _data_len = data;
        _data_cnt = 0;
    }
    else if(state==4&&_data_len>0)
    {
        _data_len--;
        RxBuffer[4+_data_cnt++]=data;
        if(_data_len==0)
            state = 5;
    }
    else if(state==5)
    {
        state = 0;
        RxBuffer[4+_data_cnt]=data;
        my1_ANO_DT_Data_Receive_Anl(RxBuffer,_data_cnt+5);
    }
    else
        state = 0;
}
/////////////////////////////////////////////////////////////////////////////////////
//Data_Receive_Anl函数是协议数据解析函数，函数参数是符合协议格式的一个数据帧，该函数会首先对协议数据进行校验
//校验通过后对数据进行解析，实现相应功能
//此函数可以不用用户自行调用，由函数Data_Receive_Prepare自动调用
void ANO_DT_Data_Receive_Anl(u8 *data_buf,u8 num)
{
    u8 sum = 0;
    for(u8 i=0;i<(num-1);i++)
        sum += *(data_buf+i);
    if(!(sum==*(data_buf+num-1)))                       return;     //判断sum
    if(!(*(data_buf)==0xAA && *(data_buf+1)==0xAF))     return;     //判断帧头

    if(*(data_buf+2)==0X02)
    {
        if(*(data_buf+4)==0X01)
        {
            f.send_pid1 = 1;
            f.send_pid2 = 1;
            f.send_pid3 = 1;
            f.send_pid4 = 1;
            f.send_pid5 = 1;
            f.send_pid6 = 1;
        }
        if(*(data_buf+4)==0XA0)     //读取版本信息
        {
            f.send_version = 1;
        }
    }

    if(*(data_buf+2)==0X10)                             //PID1
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
        // ctrl_1.PID[PIDROLL].kp  = 0.001*( (vs16)(*(data_buf+4)<<8)|*(data_buf+5) );
        // ctrl_1.PID[PIDROLL].ki  = 0.001*( (vs16)(*(data_buf+6)<<8)|*(data_buf+7) );
        // ctrl_1.PID[PIDROLL].kd  = 0.001*( (vs16)(*(data_buf+8)<<8)|*(data_buf+9) );
        // ctrl_1.PID[PIDPITCH].kp = 0.001*( (vs16)(*(data_buf+10)<<8)|*(data_buf+11) );
        // ctrl_1.PID[PIDPITCH].ki = 0.001*( (vs16)(*(data_buf+12)<<8)|*(data_buf+13) );
        // ctrl_1.PID[PIDPITCH].kd = 0.001*( (vs16)(*(data_buf+14)<<8)|*(data_buf+15) );
        // ctrl_1.PID[PIDYAW].kp   = 0.001*( (vs16)(*(data_buf+16)<<8)|*(data_buf+17) );
        // ctrl_1.PID[PIDYAW].ki   = 0.001*( (vs16)(*(data_buf+18)<<8)|*(data_buf+19) );
        // ctrl_1.PID[PIDYAW].kd   = 0.001*( (vs16)(*(data_buf+20)<<8)|*(data_buf+21) );
                //Param_SavePID();
        roll_angle_PID.P  = 0.001f * ( (*(data_buf+4)<<8) |*(data_buf+5)  );
        roll_angle_PID.I  = 0.001f * ( (*(data_buf+6)<<8) |*(data_buf+7)  );
        roll_angle_PID.D  =  0.01f * ( (*(data_buf+8)<<8) |*(data_buf+9)  );
        pitch_angle_PID.P = 0.001f * ( (*(data_buf+10)<<8)|*(data_buf+11) );
        pitch_angle_PID.I = 0.001f * ( (*(data_buf+12)<<8)|*(data_buf+13) );
        pitch_angle_PID.D =  0.01f * ( (*(data_buf+14)<<8)|*(data_buf+15) );
        yaw_angle_PID.P   = 0.001f * ( (*(data_buf+16)<<8)|*(data_buf+17) );
        yaw_angle_PID.I   = 0.001f * ( (*(data_buf+18)<<8)|*(data_buf+19) );
        yaw_angle_PID.D   =  0.01f * ( (*(data_buf+20)<<8)|*(data_buf+21) );
    }
    if(*(data_buf+2)==0X11)                             //PID2
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
        roll_rate_PID.P  = 0.001f * ( (*(data_buf+4)<<8) |*(data_buf+5)  );
        roll_rate_PID.I  = 0.001f * ( (*(data_buf+6)<<8) |*(data_buf+7)  );
        roll_rate_PID.D  =  0.01f * ( (*(data_buf+8)<<8) |*(data_buf+9)  );
        pitch_rate_PID.P = 0.001f * ( (*(data_buf+10)<<8)|*(data_buf+11) );
        pitch_rate_PID.I = 0.001f * ( (*(data_buf+12)<<8)|*(data_buf+13) );
        pitch_rate_PID.D =  0.01f * ( (*(data_buf+14)<<8)|*(data_buf+15) );
        yaw_rate_PID.P   = 0.001f * ( (*(data_buf+16)<<8)|*(data_buf+17) );
        yaw_rate_PID.I   = 0.001f * ( (*(data_buf+18)<<8)|*(data_buf+19) );
        yaw_rate_PID.D   =  0.01f * ( (*(data_buf+20)<<8)|*(data_buf+21) );
    }
    if(*(data_buf+2)==0X12)                             //PID3
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
    }
    if(*(data_buf+2)==0X13)                             //PID4
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
    }
    if(*(data_buf+2)==0X14)                             //PID5
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
    }
    if(*(data_buf+2)==0X15)                             //PID6
    {
        ANO_DT_Send_Check(*(data_buf+2),sum);
    }
}

void ANO_DT_Send_Version(u8 hardware_type, u16 hardware_ver,u16 software_ver,u16 protocol_ver,u16 bootloader_ver)
{
    u8 _cnt=0;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x00;
    data_to_send[_cnt++]=0;

    data_to_send[_cnt++]=hardware_type;
    data_to_send[_cnt++]=BYTE1(hardware_ver);
    data_to_send[_cnt++]=BYTE0(hardware_ver);
    data_to_send[_cnt++]=BYTE1(software_ver);
    data_to_send[_cnt++]=BYTE0(software_ver);
    data_to_send[_cnt++]=BYTE1(protocol_ver);
    data_to_send[_cnt++]=BYTE0(protocol_ver);
    data_to_send[_cnt++]=BYTE1(bootloader_ver);
    data_to_send[_cnt++]=BYTE0(bootloader_ver);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];
    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_Status(float angle_rol, float angle_pit, float angle_yaw, s32 alt, u8 fly_model, u8 armed)
{
    u8 _cnt=0;
    vs16 _temp;
    vs32 _temp2 = alt;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x01;
    data_to_send[_cnt++]=0;

    _temp = (int)(angle_rol*100);
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = (int)(angle_pit*100);
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = (int)(angle_yaw*100);
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);

    data_to_send[_cnt++]=BYTE3(_temp2);
    data_to_send[_cnt++]=BYTE2(_temp2);
    data_to_send[_cnt++]=BYTE1(_temp2);
    data_to_send[_cnt++]=BYTE0(_temp2);

    data_to_send[_cnt++] = fly_model;

    data_to_send[_cnt++] = armed;

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];
    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_Senser(s16 a_x,s16 a_y,s16 a_z,s16 g_x,s16 g_y,s16 g_z,s16 m_x,s16 m_y,s16 m_z,s32 bar)
{
    u8 _cnt=0;
    vs16 _temp;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x02;
    data_to_send[_cnt++]=0;

    _temp = a_x;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = a_y;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = a_z;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);

    _temp = g_x;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = g_y;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = g_z;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);

    _temp = m_x;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = m_y;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = m_z;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];
    data_to_send[_cnt++] = sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_RCData(u16 thr,u16 yaw,u16 rol,u16 pit,u16 aux1,u16 aux2,u16 aux3,u16 aux4,u16 aux5,u16 aux6)
{
    u8 _cnt=0;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x03;
    data_to_send[_cnt++]=0;
    data_to_send[_cnt++]=BYTE1(thr);
    data_to_send[_cnt++]=BYTE0(thr);
    data_to_send[_cnt++]=BYTE1(yaw);
    data_to_send[_cnt++]=BYTE0(yaw);
    data_to_send[_cnt++]=BYTE1(rol);
    data_to_send[_cnt++]=BYTE0(rol);
    data_to_send[_cnt++]=BYTE1(pit);
    data_to_send[_cnt++]=BYTE0(pit);
    data_to_send[_cnt++]=BYTE1(aux1);
    data_to_send[_cnt++]=BYTE0(aux1);
    data_to_send[_cnt++]=BYTE1(aux2);
    data_to_send[_cnt++]=BYTE0(aux2);
    data_to_send[_cnt++]=BYTE1(aux3);
    data_to_send[_cnt++]=BYTE0(aux3);
    data_to_send[_cnt++]=BYTE1(aux4);
    data_to_send[_cnt++]=BYTE0(aux4);
    data_to_send[_cnt++]=BYTE1(aux5);
    data_to_send[_cnt++]=BYTE0(aux5);
    data_to_send[_cnt++]=BYTE1(aux6);
    data_to_send[_cnt++]=BYTE0(aux6);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];

    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_Power(u16 votage, u16 current)
{
    u8 _cnt=0;
    u16 temp;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x05;
    data_to_send[_cnt++]=0;

    temp = votage;
    data_to_send[_cnt++]=BYTE1(temp);
    data_to_send[_cnt++]=BYTE0(temp);
    temp = current;
    data_to_send[_cnt++]=BYTE1(temp);
    data_to_send[_cnt++]=BYTE0(temp);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];

    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_MotoPWM(u16 m_1,u16 m_2,u16 m_3,u16 m_4,u16 m_5,u16 m_6,u16 m_7,u16 m_8)
{
    u8 _cnt=0;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x06;
    data_to_send[_cnt++]=0;

    data_to_send[_cnt++]=BYTE1(m_1);
    data_to_send[_cnt++]=BYTE0(m_1);
    data_to_send[_cnt++]=BYTE1(m_2);
    data_to_send[_cnt++]=BYTE0(m_2);
    data_to_send[_cnt++]=BYTE1(m_3);
    data_to_send[_cnt++]=BYTE0(m_3);
    data_to_send[_cnt++]=BYTE1(m_4);
    data_to_send[_cnt++]=BYTE0(m_4);
    data_to_send[_cnt++]=BYTE1(m_5);
    data_to_send[_cnt++]=BYTE0(m_5);
    data_to_send[_cnt++]=BYTE1(m_6);
    data_to_send[_cnt++]=BYTE0(m_6);
    data_to_send[_cnt++]=BYTE1(m_7);
    data_to_send[_cnt++]=BYTE0(m_7);
    data_to_send[_cnt++]=BYTE1(m_8);
    data_to_send[_cnt++]=BYTE0(m_8);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];

    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}
void ANO_DT_Send_PID(u8 group,float p1_p,float p1_i,float p1_d,float p2_p,float p2_i,float p2_d,float p3_p,float p3_i,float p3_d)
{
    u8 _cnt=0;
    vu16 _temp;

    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x10+group-1;
    data_to_send[_cnt++]=0;


    _temp = p1_p * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p1_i  * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p1_d  * 100;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p2_p  * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p2_i  * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p2_d * 100;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p3_p  * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p3_i  * 1000;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);
    _temp = p3_d * 100;
    data_to_send[_cnt++]=BYTE1(_temp);
    data_to_send[_cnt++]=BYTE0(_temp);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];

    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}

/******************* (C) COPYRIGHT 2014 ANO TECH *****END OF FILE************/


void ANO_DT_Send_Fx_9float(u8 data_to_send[], u8 Fx,
                    float _f1, float _f2, float _f3,
                    float _f4, float _f5, float _f6,
                    float _f7, float _f8, float _f9)
{
    u8 _cnt=0;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=Fx;
    data_to_send[_cnt++]=0;

    data_to_send[_cnt++]=BYTE3(_f1);
    data_to_send[_cnt++]=BYTE2(_f1);
    data_to_send[_cnt++]=BYTE1(_f1);
    data_to_send[_cnt++]=BYTE0(_f1);
    data_to_send[_cnt++]=BYTE3(_f2);
    data_to_send[_cnt++]=BYTE2(_f2);
    data_to_send[_cnt++]=BYTE1(_f2);
    data_to_send[_cnt++]=BYTE0(_f2);
    data_to_send[_cnt++]=BYTE3(_f3);
    data_to_send[_cnt++]=BYTE2(_f3);
    data_to_send[_cnt++]=BYTE1(_f3);
    data_to_send[_cnt++]=BYTE0(_f3);

    data_to_send[_cnt++]=BYTE3(_f4);
    data_to_send[_cnt++]=BYTE2(_f4);
    data_to_send[_cnt++]=BYTE1(_f4);
    data_to_send[_cnt++]=BYTE0(_f4);
    data_to_send[_cnt++]=BYTE3(_f5);
    data_to_send[_cnt++]=BYTE2(_f5);
    data_to_send[_cnt++]=BYTE1(_f5);
    data_to_send[_cnt++]=BYTE0(_f5);
    data_to_send[_cnt++]=BYTE3(_f6);
    data_to_send[_cnt++]=BYTE2(_f6);
    data_to_send[_cnt++]=BYTE1(_f6);
    data_to_send[_cnt++]=BYTE0(_f6);

    data_to_send[_cnt++]=BYTE3(_f7);
    data_to_send[_cnt++]=BYTE2(_f7);
    data_to_send[_cnt++]=BYTE1(_f7);
    data_to_send[_cnt++]=BYTE0(_f7);
    data_to_send[_cnt++]=BYTE3(_f8);
    data_to_send[_cnt++]=BYTE2(_f8);
    data_to_send[_cnt++]=BYTE1(_f8);
    data_to_send[_cnt++]=BYTE0(_f8);
    data_to_send[_cnt++]=BYTE3(_f9);
    data_to_send[_cnt++]=BYTE2(_f9);
    data_to_send[_cnt++]=BYTE1(_f9);
    data_to_send[_cnt++]=BYTE0(_f9);

    data_to_send[3] = _cnt-4;

    u8 sum = 0;
    for(u8 i=0;i<_cnt;i++)
        sum += data_to_send[i];
    data_to_send[_cnt++]=sum;

    ANO_DT_Send_Data(data_to_send, _cnt);
}


<|start_filename|>firmware/FW6-motor-PWM/motor-PWM.c<|end_filename|>
/**
  @file    motor-PWM.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20171111
  @brief   a source file implement the motor controlor.
*/


/* Includes ------------------------------------------------------------------*/
// #include <assert.h>
#include "motor-PWM.h"

/* Exported functions ---------------------------------------------------------*/
extern uint32_t motor_pwm_range (int32_t x);

/**
  * @brief  init TIM1_CH[1:4] & GPIOA[8:11](AF01).
  */
void motor_pwm_init (void) {
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

	{
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_TIM1);
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_TIM1);
		GPIO_InitTypeDef r1 = {GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11, GPIO_Mode_AF, GPIO_High_Speed, GPIO_OType_PP, GPIO_PuPd_NOPULL};
		GPIO_Init(GPIOA, &r1);
	}

	{ /* 可能TIM1 有不同的默认值，但是结构体的默认值一定是0呀.. */
		TIM_TimeBaseInitTypeDef r1 = {
			.TIM_Prescaler = 99,
			// .TIM_CounterMode = TIM_CounterMode_Up,
			.TIM_Period = motor_pwm_arr // 1M/motor_pwm_arr
			// , .TIM_ClockDivision = TIM_CKD_DIV1
		};
		TIM_TimeBaseInit(TIM1, &r1);
	}

	{
		TIM_OCInitTypeDef r1 = {
			.TIM_OCMode = TIM_OCMode_PWM1,
			.TIM_OutputState = TIM_OutputState_Enable,
			.TIM_OutputNState = TIM_OutputNState_Enable // ?
			// .TIM_Pulse = 0,
			// .TIM_OCPolarity = TIM_OCPolarity_High,
			// .TIM_OCNPolarity = TIM_OCPolarity_High
		};
		TIM_OC1Init(TIM1, &r1);
		TIM_OC2Init(TIM1, &r1);
		TIM_OC3Init(TIM1, &r1);
		TIM_OC4Init(TIM1, &r1);
	}

	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);

	// 注释掉下面这两行，电调两秒一哔（表示没有信号输入）
	// 但是之前LD2-PWM没有这两行却能正确的输出PWM。
	// 留下疑问，日后再解决。
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	TIM_CtrlPWMOutputs(TIM1,ENABLE);

	TIM_Cmd(TIM1, ENABLE);
}


<|start_filename|>project/p10-ANO/application/main.c<|end_filename|>
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
#include "EVAL_define.h"
#include "delay.h"
#include "data_transfer.h"
#include "inv_mpu.h"
#include "gpio_hmc5883.h"
#include "PWM-RCV.h"
#include "motor-PWM.h"
#include "Attitude.h"
#include "pid.h"
#include "math.h"
void my2_ANO_DT_Data_Receive_Anl(void);

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
// #define init_governor // 不用初始化电调
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void USART_Config(void);

/* Private functions ---------------------------------------------------------*/

/**
    * @brief  Main program
    * @param  None
    * @retval None
    */
int main(void)
{
    delayinit();
#ifdef init_governor // 初始化电调。要求stlink提前供电，电调和F411同时上电
    motor_pwm_init();
    motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_4 = motor_pwm_max;
    delay(2000);
    motor_pwm_4 = motor_pwm_min;
    delay(1100);
    motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_min;
#else
    motor_pwm_init();
    motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_4 = motor_pwm_min;
#endif
    RCV_IC_init();
    while (mpu_dmp_init()); // 六轴数据的具体量程见：`int mpu_init(void)` 函数实现上面的注释
    USART_Config();
    PID_init();

    while (InitHMC5883());  // 初始化磁力计

    Attitude();
    yaw_angle_PID.Desired = yaw;
    uint32_t told = msTimerCounter;
    for (uint32_t i=0;;i++) {
        Attitude();
        CtrlAttiAng();
        CtrlAttiRate();
        CtrlMotorSpeed();

        uint32_t tnow = msTimerCounter;
        ANO_DT_Data_Exchange(i, tnow-told);
        my2_ANO_DT_Data_Receive_Anl();
        told = tnow;
    }
}

/**
    * @brief  Configures the USART Peripheral.
    * @param  None
    * @retval None
    */
static void USART_Config(void)
{
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the USARTx Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = MY_COM1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* USARTx configuration ------------------------------------------------------*/
    /* USARTx configured as follows: 38400 8N1
                - BaudRate = 38400 baud
                - Word Length = 8 Bits
                - One Stop Bit
                - No parity
                - Hardware flow control disabled (RTS and CTS signals)
                - Receive and transmit enabled
    */
    USART_InitStructure.USART_BaudRate = 38400;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    MY_COMInit(COM1, &USART_InitStructure);

    /* Enable the MY_COM1 Receive interrupt: this interrupt is generated when the
        MY_COM1 receive data register is not empty */
    USART_ITConfig(MY_COM1, USART_IT_RXNE, ENABLE);
}


<|start_filename|>project/p4-button-EXTI/application/main.c<|end_filename|>
#include "main.h"
#include "stm32f4xx_conf.h"
#include "btn_exti.h"
#include "LD2pwm.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @retval None
  */
int main(void)
{
 /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */

  /* Add your application code here */
	
  /* Initialize LEDs mounted on EVAL board */
	GPIO_init_4_LD2_PWM();

	pwm_LD2 = pwm_arr;
	
  /* Configure EXTI Line13 in interrupt mode */
  GPIO_init_4_BTN_EXTI();
	
  /* Generate software interrupt: simulate a falling edge applied on EXTI13 line */
  EXTI_GenerateSWInterrupt(EXTI_Line13);

  /* Infinite loop */
  for (;;);
}


<|start_filename|>project/p1-nucleo64-test/application/stm32f4xx_it.c<|end_filename|>

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
#include "main.h"

/******************************************************************************/
/*            Cortex-M4 Processor Exceptions Handlers                         */
/******************************************************************************/

///@brief  This function handles NMI exception.
void NMI_Handler(void)
{
}

///@brief  This function handles Hard Fault exception.
void HardFault_Handler(void);

///@brief  This function handles Memory Manage exception.
void MemManage_Handler(void);

///@brief  This function handles Bus Fault exception.
void BusFault_Handler(void);

///@brief  This function handles Usage Fault exception.
void UsageFault_Handler(void);

///@brief  This function handles SVCall exception.
void SVC_Handler(void)
{
}

/// @brief  This function handles Debug Monitor exception.
void DebugMon_Handler(void)
{
}


//@brief  This function handles PendSVC exception.
//void PendSV_Handler(void)
//{
//}
//< defined in ucosii\os_cpu_a.asm

/// @brief  This function handles SysTick Handler.
void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}
//#include "ucos_ii.h"
//void SysTick_Handler(void)
//{
//	if (OSRunning == OS_TRUE) {
//		OSIntEnter();
//		OSTimeTick();        
//		OSIntExit();
//	}
//}
//< use as os tick, if would like to run os

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f4xx.s).                                               */
/******************************************************************************/

///@brief  This function handles PPP interrupt request.
/*void PPP_IRQHandler(void)*/


<|start_filename|>firmware/LD2-PWM/LD2pwm.h<|end_filename|>
/**
  @file    LD2pwm.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   interface of pwm output on LD2.
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LD2PWM_H
#define __LD2PWM_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#ifndef pwm_arr
	#define pwm_arr 100
#endif
#define pwm_LD2 (TIM2->CCR1)
#define pwm_range(x) ((x)>=pwm_arr?pwm_arr-1:(x)<0?0:x) /* danger tri.. */
/* Exported functions ------------------------------------------------------- */
void GPIO_init_4_LD2_PWM (void);

#ifdef __cplusplus
}
#endif

#endif /* __LD2PWM_H */


<|start_filename|>firmware/BTN-EXTI/btn_exti.h<|end_filename|>
/**
  @file    btn_exti.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170724
  @brief   a header file about the button triggers an external interrupt.
           B1 - PC13 - EXTI13
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BTN_EXTI_H
#define __BTN_EXTI_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"   
#include "ucos_ii.h"
#include "stm32f4xx_exti.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void GPIO_init_4_BTN_EXTI (void);
void EXTI15_10_IRQHandler (void);

#ifdef __cplusplus
}
#endif

#endif /* __BTN_EXTI_H */


<|start_filename|>project/p10-ANO/application/Attitude.c<|end_filename|>

#include "inv_mpu.h"
#include "gpio_hmc5883.h"
#include "Attitude.h"
#include "math.h"

// #define nihetuoqiu
/* extern variables ---------------------------------------------------- */
#define cn 10
#define deg2rad(d) ((float)(d)/180.f*3.1415926f)
#define rad2deg(r) ((float)(r)/3.1415926f*180.f)
short gyro[3], accel[3], mag[3];        //九轴原始数据
short mag_mid[3] = {80, -379, 55};      //陀螺仪水平旋转校准数据 (特定系统)
float yaw, pitch, roll;                 //姿态角

void Attitude(void)
{
    // 函数内部把六轴原始数据放在全局变量 gyro 以及 accel 中
    while (mpu_dmp_get_data(&pitch, &roll, &yaw));

    // 获取电子罗盘原始数据，并做校准
    updateHMC5883(mag);
#ifndef nihetuoqiu
    mag[0] -= mag_mid[0];
    mag[1] -= mag_mid[1];
    mag[2] -= mag_mid[2];

    mag[0] /= 479/5000.f;
    mag[1] /= 483/5000.f;
    mag[2] /= 412/5000.f;

    // 用磁力计数据计算YAW角
    float rad_roll = deg2rad(roll);
    float cos_roll = cosf(rad_roll);
    float sin_roll = sinf(rad_roll);
    float rad_pitch = deg2rad(pitch);
    float cos_pitch = cosf(rad_pitch);
    float sin_pitch = sinf(rad_pitch);
    float sin_absroll = roll > 0 ? sin_roll : -sin_roll;
    float sin_abspitch = pitch > 0 ? sin_pitch : -sin_pitch;
    yaw = - rad2deg(
                atan2f(mag[1]*cos_roll  - mag[2]*sin_roll,
                       mag[0]*cos_pitch + mag[1]*sin_absroll*sin_abspitch + mag[2]*cos_roll*sin_pitch
                )
            ); // -180˚~180˚
#endif /* nihetuoqiu */

#if 0
    // 对陀螺仪数据做滑动窗口滤波
    static int gx_c, gy_c, gz_c;
    static short gx_w[cn], gy_w[cn], gz_w[cn];
    static int wid;
    gx_c -= gx_w[wid];
    gy_c -= gy_w[wid];
    gz_c -= gz_w[wid];

    gx_w[wid] = gyro[0];
    gy_w[wid] = gyro[1];
    gz_w[wid] = gyro[2];

    gx_c += gx_w[wid];
    gy_c += gy_w[wid];
    gz_c += gz_w[wid];

    if (++wid == cn) wid = 0;
    gyro[0] = gx_c/cn;
    gyro[1] = gy_c/cn;
    gyro[2] = gz_c/cn;
#endif
}


<|start_filename|>firmware/Nucleo64-User/button.c<|end_filename|>
/**
  @file    button.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   This file provides firmware functions to user botton on nucleo64.

  B1 - PC13

*/
#include <stm32f4xx.h>
#include <button.h>

void GPIO_init_4_B1 (void)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
	// 默认浮空输入
}


<|start_filename|>ucosii/os_cpu_c_tick.c<|end_filename|>
/**
  @file    main.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   define tick-isr, which call OSTimeTick().
*/

#include "ucos_ii.h"
void SysTick_Handler (void)
{
    if (OSRunning == OS_TRUE) {
        OSIntEnter();
        OSTimeTick();
        OSIntExit();
    }
}


<|start_filename|>utility/tterm/tterm.c<|end_filename|>
/*
    an easy POSIX series program.
    author: (C)tjua, ES-SS-UESTC, 171129.
    without any lisence.
*/

#ifndef static_Band
#error static_Band should be defined
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>

#define exit_ifn(x) ((void)((x)||(fprintf(stderr, "%s line %d:  ", argv[0], __LINE__), perror(""), exit(EXIT_FAILURE), 0)))

int main(int argc, char *argv[])
{
    int fd;
    struct termios st;
    char buf[1000];
    fd_set readfds;

#ifndef static_termfile
#define termfile_path argv[1]
    if (argc != 2) {
        puts("usage: ./tterm path");
        return 0;
    }
#else
#define termfile_path static_termfile
#endif

    {/* 打开串口并初始化 */
        exit_ifn(-1 != (fd = open(termfile_path, O_RDWR)));

        tcgetattr(fd, &st);

        cfsetispeed(&st, B38400);
        cfsetospeed(&st, B38400);
        st.c_cflag &= ~CSTOPB&~PARENB;
        st.c_lflag &= ~ICANON&~ECHO&~ECHOE&~ISIG;

        tcsetattr(fd, TCSANOW, &st);
    }

    /* 死循环+多路复用 */
    FD_ZERO(&readfds);
    for (;;) {
        int flags = 0;
        FD_SET(0, &readfds);
        FD_SET(fd, &readfds);
        exit_ifn(-1 != select(fd+1, &readfds, NULL, NULL, NULL));

        if (FD_ISSET(0, &readfds)) {
            exit_ifn(read(0, buf, 1) == 1);
            write(fd, buf, 1);
            flags = 1;
            FD_CLR(0, &readfds);
        }
        if (FD_ISSET(fd, &readfds)) {
            exit_ifn(read(fd, buf, 1) == 1);
            write(1, buf, 1);
            flags = 1;
            FD_CLR(fd, &readfds);
        }
        exit_ifn(flags);
    }
}


<|start_filename|>firmware/FW7-PWM-RCV/PWM-RCV.c<|end_filename|>
/**
  @file    PWM-RCV.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20171113
  @brief   获取接收机PWM的占空比。
*/

/* Includes ------------------------------------------------------------------*/
#include "PWM-RCV.h"

/* Private macro ------------------------------------------------------------*/
// 变量名宏定义：接收机通道 到 定时器通道的映射
#define u16Tim3IC3 u16Rcvr_ch4
#define u16Tim3IC4 u16Rcvr_ch3
#define u16Tim3IC1 u16Rcvr_ch2
#define u16Tim3IC2 u16Rcvr_ch1

/* Exported variables ---------------------------------------------------------*/
uint16_t u16Tim3IC1 = 0;
uint16_t u16Tim3IC2 = 0;
uint16_t u16Tim3IC3 = 0;
uint16_t u16Tim3IC4 = 0;

/* Exported functions ------------------------------------------------------- */
/**
  * @brief  init TIM & GPIO
    |==========|==============|======|
    |   GPIO   |    F411RE    | AFxx |
    |==========|==============|======|
    | PC[8:9]  | TIM3_CH[3:4] | AF02 |
    | PA[6:7]  | TIM3_CH[1:2] | AF02 |
    |==========|==============|======|
  */
void RCV_IC_init (void) {

    /* Configuration PC[8:9]  | TIM3_CH[3:4] | AF02
                     PA[6:7]  | TIM3_CH[1:2] | AF02  */

        /* TIM3 clock enable */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

        {
            TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
            TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 15.25HZ 只要高电平时间不超过33ms 就不会 
            TIM_TimeBaseStructure.TIM_Prescaler = 100; // 1MHZ
            TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
            TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
            /// In upcounting mode, the counter counts from 0 to the auto-reload value (content of the TIMx_ARR register), then restarts from 0 and generates a counter overflow event.
            TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
        }

        /* GPIOA&C clock enable */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
        
        {
            GPIO_InitTypeDef GPIO_InitStructure;
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
            GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
            GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
            GPIO_Init(GPIOA, &GPIO_InitStructure);

            /* Connect TIM pins to AF2 */
            GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
            GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM3);
        }

        {
            GPIO_InitTypeDef GPIO_InitStructure;
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
            GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
            GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
            GPIO_Init(GPIOC, &GPIO_InitStructure);

            /* Connect TIM pins to AF2 */
            GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM3);
            GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3);
        }

        /* Enable the TIM3 global Interrupt */
        {
            NVIC_InitTypeDef NVIC_InitStructure;
            NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
            // TIM1_CC_IRQn 高级定时器与通用定时器的区别 中断号上 misc.h + stm32f4xx.h
            NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
            NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
            NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
            NVIC_Init(&NVIC_InitStructure);
        }

        /* TIM3 configuration: Input Capture mode */
        {
            TIM_ICInitTypeDef TIM_ICInitStructure;
            // TIM_ICInitStructure.TIM_Channel = TIM_Channel_1 | TIM_Channel_2 | TIM_Channel_3 | TIM_Channel_4;
                // 自己看实现，虽然通道值设计允许 | 但是函数实现不允许 函数实现是if-else-if
            TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
            TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI,
            TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
            TIM_ICInitStructure.TIM_ICFilter = 0x0;

            TIM_ICInitStructure.TIM_Channel = TIM_Channel_1,
                TIM_ICInit(TIM3, &TIM_ICInitStructure);
            TIM_ICInitStructure.TIM_Channel = TIM_Channel_2,
                TIM_ICInit(TIM3, &TIM_ICInitStructure);
            TIM_ICInitStructure.TIM_Channel = TIM_Channel_3,
                TIM_ICInit(TIM3, &TIM_ICInitStructure);
            TIM_ICInitStructure.TIM_Channel = TIM_Channel_4,
                TIM_ICInit(TIM3, &TIM_ICInitStructure);
        }
        /* TIM enable counter */
        TIM_Cmd(TIM3, ENABLE);

        /* Enable the CC Interrupt Request */
        TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

}

void TIM3_IRQHandler(void)
{ 
    if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == SET)
    {
        static uint16_t ReadNO = 1;
        static uint16_t ReadValue1 = 0;
        static uint16_t ReadValue2 = 0;
        /* Clear TIM3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
        if (ReadNO == 1)
        {
            /* Get the Input Capture value */
            ReadValue1 = TIM_GetCapture1(TIM3);
            ReadNO = 2;
            TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Falling);
        }
        else /* ReadNO == 2 */
        {
            /* Get the Input Capture value */
            ReadValue2 = TIM_GetCapture1(TIM3);
            
            /* Capture computation */
            #if 0
                    if (ReadValue2 >= ReadValue1)
                    {
                        u16Tim3IC1 = (ReadValue2 - ReadValue1); 
                    }
                    else if (ReadValue2 < ReadValue1)
                    {
                        u16Tim3IC1 = ((0x10000 - ReadValue1) + ReadValue2); 
                    }
            // or
                    u16Tim3IC1=(ReadValue2-ReadValue1+0x10000)%0x10000; // C99/向零截断 %与a同号
            #endif
            u16Tim3IC1=ReadValue2-ReadValue1; // 无符号数截断
            ReadNO = 1;
            TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising);
        }
    }
    if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET) /***/
    {
        static uint16_t ReadNO = 1;
        static uint16_t ReadValue1 = 0;
        static uint16_t ReadValue2 = 0;
        /* Clear TIM3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2); /***/
        if (ReadNO == 1)
        {
            /* Get the Input Capture value */
            ReadValue1 = TIM_GetCapture2(TIM3); /***/
            ReadNO = 2;
            TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling); /***/
        }
        else /* ReadNO == 2 */
        {
            /* Get the Input Capture value */
            ReadValue2 = TIM_GetCapture2(TIM3); /***/
            
            /* Capture computation */
            u16Tim3IC2=ReadValue2-ReadValue1;
            ReadNO = 1;
            TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising);
        }
    }
    if(TIM_GetITStatus(TIM3, TIM_IT_CC3) == SET) /***/
    {
        static uint16_t ReadNO = 1;
        static uint16_t ReadValue1 = 0;
        static uint16_t ReadValue2 = 0;
        /* Clear TIM3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC3); /***/
        if (ReadNO == 1)
        {
            /* Get the Input Capture value */
            ReadValue1 = TIM_GetCapture3(TIM3); /***/
            ReadNO = 2;
            TIM_OC3PolarityConfig(TIM3, TIM_ICPolarity_Falling); /***/
        }
        else /* ReadNO == 2 */
        {
            /* Get the Input Capture value */
            ReadValue2 = TIM_GetCapture3(TIM3); /***/
            
            /* Capture computation */
            u16Tim3IC3=ReadValue2-ReadValue1;
            ReadNO = 1;
            TIM_OC3PolarityConfig(TIM3, TIM_ICPolarity_Rising);
        }
    }
    if(TIM_GetITStatus(TIM3, TIM_IT_CC4) == SET) /***/
    {
        static uint16_t ReadNO = 1;
        static uint16_t ReadValue1 = 0;
        static uint16_t ReadValue2 = 0;
        /* Clear TIM3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC4); /***/
        if (ReadNO == 1)
        {
            /* Get the Input Capture value */
            ReadValue1 = TIM_GetCapture4(TIM3); /***/
            ReadNO = 2;
            TIM_OC4PolarityConfig(TIM3, TIM_ICPolarity_Falling); /***/
        }
        else /* ReadNO == 2 */
        {
            /* Get the Input Capture value */
            ReadValue2 = TIM_GetCapture4(TIM3); /***/
            
            /* Capture computation */
            u16Tim3IC4=ReadValue2-ReadValue1;
            ReadNO = 1;
            TIM_OC4PolarityConfig(TIM3, TIM_ICPolarity_Rising);
        }
    }
}


<|start_filename|>project/p8-GPIO-IIC/application/main.c<|end_filename|>
/**
    @file    main.c
    @author  tjua @ ES-SS-UESTC © 2017
    @version V1.0
    @date    20171113
    @brief   define main entry.
*/

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "gpio_mpu6050.h"


/* Private macro -------------------------------------------------------------*/
#define printf_(s, ...) printf("file:%s\tline:%d\t" s, __FILE__, __LINE__, __VA_ARGS__)


/* Private functions ---------------------------------------------------------*/

int main(void)
{

 /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function,
       refer to system_stm32f4xx.c file */
    delayinit();
    uart_init(38400);
    MPU_Init();

    for (int c=0;;c++) {
        delay(1000);

        acc_correct();
        gyro_correct();

        printf("%d\r\n", c);
        printf("\tax_c = %d \r\n", ax_cc);
        printf("\tay_c = %d \r\n", ay_cc);
        printf("\taz_c = %d \r\n", az_cc);
        printf("\tgx_c = %d \r\n", gx_cc);
        printf("\tgy_c = %d \r\n", gy_cc);
        printf("\tgz_c = %d \r\n", gz_cc);
    }
}


<|start_filename|>project/p7-PWM-RCV/application/main.c<|end_filename|>
/**
  @file    main.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20171113
  @brief   define main entry.
*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "PWM-RCV.h"
#include "delay.h"
#include "usart.h"
#include "motor-PWM.h"


/* Private macro -------------------------------------------------------------*/
#define printf_(s, ...) printf("file:%s\tline:%d\t" s, __FILE__, __LINE__, __VA_ARGS__)

/* Private functions ---------------------------------------------------------*/

int main(void)
{
    
 /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */
    delayinit();
    motor_pwm_init();
    motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_4 = motor_pwm_max;
    delay(2000);
    motor_pwm_4 = motor_pwm_min;
    delay(1100);
    motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_min;
    // delay(5000);
    uart_init(38400);
    RCV_IC_init();

    for (int c=0;;c++) {
        delay(1000);
    printf("%d\r\n", c);
    printf("\tu16Rcvr_ch1 = %d \r\n", u16Rcvr_ch1);
    printf("\tu16Rcvr_ch2 = %d \r\n", u16Rcvr_ch2);
    printf("\tu16Rcvr_ch3 = %d \r\n", u16Rcvr_ch3);
    printf("\tu16Rcvr_ch4 = %d \r\n", u16Rcvr_ch4);
    printf("\tTIM3->CCR1 = %d \r\n", TIM3->CCR1);
    printf("\tTIM3->CCR2 = %d \r\n", TIM3->CCR2);
    printf("\tTIM3->CCR3 = %d \r\n", TIM3->CCR3);
    printf("\tTIM3->CCR4 = %d \r\n", TIM3->CCR4);

    }
}


<|start_filename|>firmware/FW8-gpio-iic-mpu6050-rawdata/gpio_i2c.c<|end_filename|>
#include "gpio_i2c.h"
#include "gpio_sys.h"

// GPIO方向设置
#define SDA_IN()   do {GPIOB->MODER&=~(3<<(5*2));GPIOB->MODER|=0<<5*2;} while(0) //PB5输入模式
#define SDA_OUT()  do {GPIOB->MODER&=~(3<<(5*2));GPIOB->MODER|=1<<5*2;} while(0) //PB5输出模式

#define IIC_SCL    PBout(4)
#define IIC_SDA    PBout(5)
#define READ_SDA   PBin(5)

static void delay_us(volatile u32 nus)
{
  for (; nus > 0; nus--);
}

/* GPIO B4,B5 init */
void IIC_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  IIC_SCL=1;
  IIC_SDA=1; // 空闲状态
}

void IIC_Start(void)
{
    SDA_OUT();
    IIC_SDA=1; // 不信任调用者? 还是别的比如协议的原因
    IIC_SCL=1;
    delay_us(4);

    IIC_SDA=0; // START: when CLK is high, DATA change form high to low
    delay_us(4);
    IIC_SCL=0; // 钳住I2C总线，准备发送或接收数据
    delay_us(4);
}

void IIC_Stop(void)
{
    SDA_OUT();
    IIC_SCL=0;
    delay_us(4);

    IIC_SDA=0;
    delay_us(4);
    IIC_SCL=1;
    delay_us(4);
    IIC_SDA=1; // STOP: when CLK is high DATA change form low to high
    delay_us(4);
}

uint8_t IIC_Wait_Ack(void)
{
    uint8_t ucErrTime=0;

    SDA_IN();
    IIC_SDA=1;
    delay_us(4);

    IIC_SCL=1;
    delay_us(4);
    while(READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL=0;
    delay_us(4);
    return 0;
}

void IIC_Ack(void)
{
    SDA_OUT();
    IIC_SCL=0;
    delay_us(2);

    IIC_SDA=0;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
    delay_us(2);
}

void IIC_NAck(void)
{
    IIC_SCL=0;
    SDA_OUT();
    delay_us(2);

    IIC_SDA=1;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
    delay_us(2);
}

void IIC_Send_Byte(uint8_t txd)
{
    uint8_t t;
    SDA_OUT();
    IIC_SCL=0; // 拉低时钟开始数据传输
    delay_us(2);
    for(t=0;t<8;t++)
    {
        IIC_SDA=txd>>7;
        txd<<=1;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
        delay_us(2);
    }
}

uint8_t IIC_Read_Byte(uint8_t ack)
{
    unsigned char i,receive=0;
    SDA_IN();IIC_SCL=0; /// 0?
    for(i=0;i<8;i++ )
    {
        delay_us(2);
        IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;
        delay_us(2);
        IIC_SCL=0;
        delay_us(2);
    }
    if (!ack)
        IIC_NAck();
    else
        IIC_Ack();
    return receive;
}


<|start_filename|>project/p10-ANO/application/gpio_hmc5883.h<|end_filename|>
#ifndef __GPIO_HMC5883_H
#define __GPIO_HMC5883_H

#include <stdint.h>

uint8_t InitHMC5883(void);
void updateHMC5883(short mag[3]);

#endif /* __GPIO_HMC5883_H */


<|start_filename|>firmware/FW6-motor-PWM/motor-PWM.h<|end_filename|>
/**
  @file    motor-PWM.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20171111
  @brief   a header file declares the interface of motor control.
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __motor_PWM_H
#define __motor_PWM_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <inttypes.h>
#include <stdint.h>


/* Exported constants --------------------------------------------------------*/
#define motor_pwm_arr (2500-1)
#define motor_pwm_max 2000 // 不能给满 要留余量
#define motor_pwm_min 1000 // 电调和接收机都是这样的



/* Exported macro ------------------------------------------------------------*/
#define motor_pwm_1 (*(int32_t*)&TIM1->CCR1)
#define motor_pwm_2 (*(int32_t*)&TIM1->CCR2)
#define motor_pwm_3 (*(int32_t*)&TIM1->CCR3)
#define motor_pwm_4 (*(int32_t*)&TIM1->CCR4)


/* Exported functions ------------------------------------------------------- */
/**
  * @brief  keep CCR in [0, ARR).
  */
inline uint32_t motor_pwm_range (int32_t x) { // boom warning!! (x)<0
	return ((x)>motor_pwm_max ? motor_pwm_max : (x)<motor_pwm_min ? motor_pwm_min : (x)) ;
}

/**
  * @brief  init TIM1_CH[1:4] & GPIOA[8:11](AF01).
  */
void motor_pwm_init (void);

#ifdef __cplusplus
}
#endif


#endif /* __motor_PWM_H */


<|start_filename|>project/p10-ANO/application/USARTx_IRQHANDLER.c<|end_filename|>
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "EVAL_define.h"
#include "data_transfer.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define USARTx_IRQHANDLER   USART2_IRQHandler

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t *aTxBuffer;
static uint32_t ubNbrOfDataToTransfer;
static uint32_t ubTxCounter;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f40xx.s/startup_stm32f427x.s).                         */
/******************************************************************************/

/**
    * @brief  This function handles USARTx global interrupt request.
    * @param  None
    * @retval None
    */
void USARTx_IRQHANDLER(void) /// NVIC 中断版本的收发
{
    if(USART_GetITStatus(MY_COM1, USART_IT_RXNE) != RESET)
    {
        /* Read one byte from the receive data register */
        ANO_DT_Data_Receive_Prepare(USART_ReceiveData(MY_COM1)); /// 之前这里有一个 & 0x7F：应该是用来处理 7O2 的，因为只有7个数据位，加上串口是LSB先发送，当时没有发现，理论上是要删掉的，当时由于只用
    }

    if(USART_GetITStatus(MY_COM1, USART_IT_TXE) != RESET)
    {
        /* Write one byte to the transmit data register */
        USART_SendData(MY_COM1, aTxBuffer[ubTxCounter]);

        if(++ubTxCounter == ubNbrOfDataToTransfer)
        {
            /* Disable the MY_COM1 Transmit interrupt */
            USART_ITConfig(MY_COM1, USART_IT_TXE, DISABLE);
        }
    }
}

void Usart2_Send(uint8_t *data_to_send, uint32_t length) {
    /* Wait until MY_COM1 send the TxBuffer */
    while (ubTxCounter < ubNbrOfDataToTransfer); // if os -> swi(控制资源) // 50*9/38400 = 0.0117s ...虽然是在自旋，但是可以被其他优先级更高的任务抢占
    /* The software must wait until TC=1. The TC flag remains cleared during all data
             transfers and it is set by hardware at the last frame’s end of transmission*/
    // while (USART_GetFlagStatus(MY_COM1, USART_FLAG_TC) == RESET);
    // USART_ClearFlag(MY_COM1, USART_FLAG_TC);

    aTxBuffer = data_to_send;
    ubNbrOfDataToTransfer = length;
    ubTxCounter = 0;
    /* Enable the MY_COM1 Transmit interrupt: this interrupt is generated when the
         MY_COM1 transmit data register is empty */
    USART_ITConfig(MY_COM1, USART_IT_TXE, ENABLE);
}

static u8 *RxBuf;
static uint32_t RxLen;
void my1_ANO_DT_Data_Receive_Anl(u8 *RxBuffer, uint32_t length) {
    if (!RxLen && !!length) {
        RxBuf = RxBuffer;
        RxLen = length;
        USART_ITConfig(MY_COM1, USART_IT_RXNE, DISABLE);
    } else ; // ignore this RxBuf
}
void my2_ANO_DT_Data_Receive_Anl() {
    if (RxLen) {
        ANO_DT_Data_Receive_Anl(RxBuf, RxLen);
        RxLen=0;
        USART_ITConfig(MY_COM1, USART_IT_RXNE, ENABLE);
    }
}


<|start_filename|>firmware/FW8-gpio-iic-mpu6050-rawdata/gpio_mpu6050.h<|end_filename|>
#ifndef __GPIO_MPU6050_H
#define __GPIO_MPU6050_H
#include <stdint.h> // u8 define in stm32f4xx.h for legacy

uint8_t MPU_Init(void);

uint8_t MPU_Write_Byte(uint8_t reg, uint8_t data);  // IIC写一个字节
uint8_t MPU_Read_Byte(uint8_t reg);                 // IIC读一个字节
uint8_t MPU_Write_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf); // IIC连续写
uint8_t MPU_Read_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf);  // IIC连续读

#endif /* __GPIO_MPU6050_H */


<|start_filename|>firmware/FW7-PWM-RCV/PWM-RCV.h<|end_filename|>
/**
  @file    PWM-RCV.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20171113
  @brief   获取接收机PWM的占空比。
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __PWM_RCV_H
#define __PWM_RCV_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <stdint.h>


/* Exported variable ---------------------------------------------------------*/
extern uint16_t u16Rcvr_ch1;
extern uint16_t u16Rcvr_ch2;
extern uint16_t u16Rcvr_ch3;
extern uint16_t u16Rcvr_ch4;

/* Exported functions ------------------------------------------------------- */
/**
  * @brief  init TIM & GPIO
	|==========|==============|======|
	|   GPIO   |    F411RE    | AFxx |
	|==========|==============|======|
	| PC[6:9]  | TIM3_CH[1:4] | AF02 |
	| PA[6:7]  | TIM3_CH[1:2] | AF02 |
	|==========|==============|======|
  */
void RCV_IC_init (void);
void TIM3_IRQHandler(void);

#ifdef __cplusplus
}
#endif

#endif /* __PWM_RCV_H */


<|start_filename|>project/p10-ANO/application/EVAL_define.c<|end_filename|>
#include "stm32f4xx.h"
#include "EVAL_define.h"


USART_TypeDef* COM_USART[COMn] = {MY_COM1}; 

GPIO_TypeDef* COM_TX_PORT[COMn] = {MY_COM1_TX_GPIO_PORT};
 
GPIO_TypeDef* COM_RX_PORT[COMn] = {MY_COM1_RX_GPIO_PORT};

const uint32_t COM_USART_CLK[COMn] = {MY_COM1_CLK};

const uint32_t COM_TX_PORT_CLK[COMn] = {MY_COM1_TX_GPIO_CLK};
 
const uint32_t COM_RX_PORT_CLK[COMn] = {MY_COM1_RX_GPIO_CLK};

const uint16_t COM_TX_PIN[COMn] = {MY_COM1_TX_PIN};

const uint16_t COM_RX_PIN[COMn] = {MY_COM1_RX_PIN};
 
const uint16_t COM_TX_PIN_SOURCE[COMn] = {MY_COM1_TX_SOURCE};

const uint16_t COM_RX_PIN_SOURCE[COMn] = {MY_COM1_RX_SOURCE};
 
const uint16_t COM_TX_AF[COMn] = {MY_COM1_TX_AF};
 
const uint16_t COM_RX_AF[COMn] = {MY_COM1_RX_AF};


/**
    * @brief  Configures COM port.
    * @param  COM: Specifies the COM port to be configured.
    *   This parameter can be one of following parameters:    
    *     @arg COM1
    *     @arg COM2  
    * @param  USART_InitStruct: pointer to a USART_InitTypeDef structure that
    *   contains the configuration information for the specified USART peripheral.
    * @retval None
    */
void MY_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable GPIO clock */
    RCC_AHB1PeriphClockCmd(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM], ENABLE);

    if (COM == COM1)
    {
        /* Enable UART clock */
        RCC_APB1PeriphClockCmd(COM_USART_CLK[COM], ENABLE);
    }

    /* Connect PXx to USARTx_Tx*/
    GPIO_PinAFConfig(COM_TX_PORT[COM], COM_TX_PIN_SOURCE[COM], COM_TX_AF[COM]);

    /* Connect PXx to USARTx_Rx*/
    GPIO_PinAFConfig(COM_RX_PORT[COM], COM_RX_PIN_SOURCE[COM], COM_RX_AF[COM]);

    /* Configure USART Tx as alternate function  */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Pin = COM_TX_PIN[COM];
    GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
    GPIO_Init(COM_TX_PORT[COM], &GPIO_InitStructure);

    /* Configure USART Rx as alternate function  */
    GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM];
    GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure);

    /* USART configuration */
    USART_Init(COM_USART[COM], USART_InitStruct);
        
    /* Enable USART */
    USART_Cmd(COM_USART[COM], ENABLE);
}


<|start_filename|>project/p4-button-EXTI/application/main.h<|end_filename|>
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */

#endif /* __MAIN_H */


<|start_filename|>project/p10-ANO/application/data_transfer.h<|end_filename|>
#ifndef _DATA_TRANSFER_H
#define _DATA_TRANSFER_H

#include "stm32f4xx.h"

typedef struct {
    u8 send_version;
    u8 send_status;
    u8 send_senser;
    u8 send_pid1;
    u8 send_pid2;
    u8 send_pid3;
    u8 send_pid4;
    u8 send_pid5;
    u8 send_pid6;
    u8 send_rcdata;
    u8 send_offset;
    u8 send_motopwm;
    u8 send_power;
    u8 send_F1;
    u8 send_F2;
    u8 send_F3;
    u8 send_F4;
} dt_flag_t;

extern dt_flag_t f;

void ANO_DT_Data_Exchange(uint16_t times, uint16_t time);
void ANO_DT_Data_Receive_Prepare(u8 data);
void ANO_DT_Data_Receive_Anl(u8 *data_buf,u8 num);
void ANO_DT_Send_Version(u8 hardware_type, u16 hardware_ver,u16 software_ver,u16 protocol_ver,u16 bootloader_ver);
void ANO_DT_Send_Status(float angle_rol, float angle_pit, float angle_yaw, s32 alt, u8 fly_model, u8 armed);
void ANO_DT_Send_Senser(s16 a_x,s16 a_y,s16 a_z,s16 g_x,s16 g_y,s16 g_z,s16 m_x,s16 m_y,s16 m_z,s32 bar);
void ANO_DT_Send_RCData(u16 thr,u16 yaw,u16 rol,u16 pit,u16 aux1,u16 aux2,u16 aux3,u16 aux4,u16 aux5,u16 aux6);
void ANO_DT_Send_Power(u16 votage, u16 current);
void ANO_DT_Send_MotoPWM(u16 m_1,u16 m_2,u16 m_3,u16 m_4,u16 m_5,u16 m_6,u16 m_7,u16 m_8);
void ANO_DT_Send_PID(u8 group,float p1_p,float p1_i,float p1_d,float p2_p,float p2_i,float p2_d,float p3_p,float p3_i,float p3_d);
// void ANO_DT_Send_Fx_pid_ans(u8 Fx, float rcver_rol, float rcver_pit, float rcver_yaw,
//                     float error_rol, float error_pit, float error_yaw,
//                     float react_rol, float react_pit, float react_yaw);
// void ANO_DT_Send_Fx_pid_part(u8 Fx, float P_Output_rol, float P_Output_pit, float P_Output_yaw,
//                              float I_Output_rol, float I_Output_pit, float I_Output_yaw,
//                              float D_Output_rol, float D_Output_pit, float D_Output_yaw);
void ANO_DT_Send_Fx_9float(u8 buf[], u8 Fx,
                    float _f1, float _f2, float _f3,
                    float _f4, float _f5, float _f6,
                    float _f7, float _f8, float _f9);

#endif /* _DATA_TRANSFER_H */



<|start_filename|>firmware/uart-nucleo/usart.c<|end_filename|>
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用
#endif
//////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用，未经作者许可，不得用于其它任何用途
//ALIENTEK STM32F4探索者开发板
//串口2初始化
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2014/6/10
//版本：V1.5
//版权所有，盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART2_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
//////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
	int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
	x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
	while((USART2->SR&0X40)==0);//循环发送,直到发送完毕  --  发送不用中断
	USART2->DR = (u8) ch;
	return ch;
}
#endif

//#if EN_USART2_RX   //如果使能了接收
//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15，	接收完成标志
//bit14，	接收到0x0d
//bit13~0，	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记

//初始化IO 串口2

//bound:波特率
void uart_init(u32 bound){
   //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟

	//串口2对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2

	//USART2端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2与GPIOA3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA2，PA3

   //USART2 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART2, &USART_InitStructure); //初始化串口2

  USART_Cmd(USART2, ENABLE);  //使能串口2

	//USART_ClearFlag(USART2, USART_FLAG_TC);

#if EN_USART2_RX
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断

	//Usart2 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//串口2中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、

#endif

}


void USART2_IRQHandler(void)                	//串口2中断服务程序
{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
	OSIntEnter();
#endif
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  ///接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Res =USART_ReceiveData(USART2);//(USART2->DR);	//读取接收到的数据

		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000, USART_RX_BUF[USART_RX_STA&0X3FFF]=0;	//接收完成了
			}
			else //还没收到0X0D
			{
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-2))USART_RX_STA=0;//接收数据错误,重新开始接收
				}
			}
		}
    }
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真，则需要支持OS.
	OSIntExit();
#endif
}
//#endif


<|start_filename|>project/p10-ANO/application/EVAL_define.h<|end_filename|>
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __EVAL_DEFINE_H
#define __EVAL_DEFINE_H

#include "stm32f4xx.h"

typedef enum 
{
    COM1 = 0
} COM_TypeDef;

#define COMn                             1

#define MY_COM1                        USART2
#define MY_COM1_CLK                    RCC_APB1Periph_USART2
#define MY_COM1_TX_PIN                 GPIO_Pin_2
#define MY_COM1_TX_GPIO_PORT           GPIOA
#define MY_COM1_TX_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define MY_COM1_TX_SOURCE              GPIO_PinSource2
#define MY_COM1_TX_AF                  GPIO_AF_USART2
#define MY_COM1_RX_PIN                 GPIO_Pin_3
#define MY_COM1_RX_GPIO_PORT           GPIOA
#define MY_COM1_RX_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define MY_COM1_RX_SOURCE              GPIO_PinSource3
#define MY_COM1_RX_AF                  GPIO_AF_USART2
#define MY_COM1_IRQn                   USART2_IRQn

void MY_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct);

#endif /* __EVAL_DEFINE_H */


<|start_filename|>project/p2-led-pwm/application/main.c<|end_filename|>
/**
  @file    main.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   define main entry.
*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "LD2pwm.h"
#include "delay.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Main program
  */
int main(void)
{
	delayinit();
	GPIO_init_4_LD2_PWM();
  while (1) {
		for (int i = 1; i<99; i++) 
		{
			pwm_LD2 = i;
			delay(20);
		}
		for (int i = 99; i>1; i--)
		{
			pwm_LD2 = i;
			delay(10);
		}
	}
}


<|start_filename|>stdperiph/Driver/src/stm32f4xx_conf.c<|end_filename|>
/**
  @file    main.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   define assert_failed.
*/

#include "stm32f4xx_conf.h"

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  for (;;);
}
#endif


<|start_filename|>firmware/Nucleo64-User/button.h<|end_filename|>
/**
  @file    button.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   This file contains all the functions prototypes for the botton firmware library.

  B1 - PC13

*/
#ifndef __BUTTON_H
#define __BUTTON_H
#include <stm32f4xx.h>

void GPIO_init_4_B1 (void);

#define get_B1 GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)
/* 替换/扩展型宏 */

/* 位带 */

#endif


<|start_filename|>firmware/delay/delay.h<|end_filename|>
/**
  @file    delay.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   used systick to delay ms.
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DELAY_H
#define __DELAY_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"   

extern volatile uint32_t msTimerCounter;
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void delay (uint32_t ticks);
void delayinit (void);


#ifdef __cplusplus
}
#endif

#endif /* __DELAY_H */


<|start_filename|>project/p10-ANO/application/Attitude.h<|end_filename|>
#ifndef _ATTITUDE_H
#define _ATTITUDE_H

/* extern variables ---------------------------------------------------- */
extern short gyro[3], accel[3], mag[3];  // 六轴原始数据
extern float yaw, pitch, roll;           // 姿态角
extern short mag_mid[3];                 //陀螺仪校准数据

void Attitude(void);

#endif /* _ATTITUDE_H */


<|start_filename|>project/p10-ANO/application/pid.c<|end_filename|>
#include "delay.h"
#include "pid.h"
#include "inv_mpu.h"
#include "Attitude.h"
#include "PWM-RCV.h"
#include "motor-PWM.h"
#include "math.h"


#define max_angle_pr 5
#define max_rate_pr  20
#define I_limit_init 20
#define DMP_GYRO_SCALE 16.4f    // 2000deg/s , 31276/2000=16.4f


PID_Typedef pitch_angle_PID;    // pitch角度PID
PID_Typedef roll_angle_PID;
PID_Typedef yaw_angle_PID;

PID_Typedef pitch_rate_PID;
PID_Typedef roll_rate_PID;
PID_Typedef yaw_rate_PID;

extern float yaw, pitch, roll; // 观测角度，解算出来的

/**
    * @brief  PID初始化
    * @param  None
    * @retval None
    */

void PID_init(void)
{
    pitch_angle_PID.P = 3.2;
    pitch_angle_PID.I = 0.5;
    pitch_angle_PID.D = 0;
    pitch_angle_PID.iLimit = I_limit_init;

    roll_angle_PID.P = 4;
    roll_angle_PID.I = 0.7;
    roll_angle_PID.D = 0;
    roll_angle_PID.iLimit = I_limit_init;

    yaw_angle_PID.P = 8;
    yaw_angle_PID.I = 4;
    yaw_angle_PID.D = 0;
    yaw_angle_PID.iLimit = I_limit_init;

    pitch_rate_PID.P = 1.2;
    pitch_rate_PID.I = 0.5;
    pitch_rate_PID.D = 0;
    pitch_rate_PID.iLimit = I_limit_init;

    roll_rate_PID.P = 1.2;
    roll_rate_PID.I = 0.5;
    roll_rate_PID.D = 0;
    roll_rate_PID.iLimit = I_limit_init;

    yaw_rate_PID.P = 2;
    yaw_rate_PID.I = 0;
    yaw_rate_PID.D = 0;
    yaw_rate_PID.iLimit = I_limit_init;
}

/**
    * @brief  位置式PID：输入期望值、观测值，得到输出值
    * @param  PID_Typedef * PID： PID结构体
              float target：      期望值
              float measure：     观测值
              uint32_t dertT：     时间间隔，用于计算积分
    * @retval None
    */
static void PID_postion_cal(PID_Typedef * PID, float measure, uint32_t dertT)
{
    // 计算误差 = 期望值 - 观测值
    PID->Error = PID->Desired - measure;
    // 计算积分
    PID->Integ += (double)PID->Error * dertT / 1000.0;
    // 积分限制
    if (PID->Integ > PID->iLimit) PID->Integ = PID->iLimit;
    if (PID->Integ < -PID->iLimit) PID->Integ = -PID->iLimit;
    // 计算微分
    PID->Deriv = PID->Error - PID->PreError;
    // 计算输出
    PID->Output = PID->P * PID->Error + PID->I * PID->Integ + PID->D * PID->Deriv;
    // 保留上一次误差
    PID->PreError = PID->Error;
}

static float range_trans(uint16_t Rcvr_ch, uint16_t max_angle)
{
    // 此函数要求通道捕获值为1000～2000
    if (Rcvr_ch<=5)    Rcvr_ch = 1500; // ==0 接收机上电但是没有遥控器信号
    if (Rcvr_ch<=1000) Rcvr_ch = 1001;
    if (Rcvr_ch>=2000) Rcvr_ch = 1999;
    if (Rcvr_ch<=1510 && Rcvr_ch>=1490) Rcvr_ch = 1500; // 死区
    return (Rcvr_ch-1500)/500.f*max_angle;
}

static inline uint16_t range_pwm(float motor_pwm, uint16_t thr)
{
    thr += motor_pwm;
    if (thr<=1000) thr = 1001;
    if (thr>=2000) thr = 1999;
    return thr;
}

static inline uint16_t range_thr(uint16_t thr)
{
    return 600 + 0.6 * thr;
}

// 外环角度PID
void CtrlAttiAng(void)
{
    static uint32_t told = 0;

    uint32_t tnow = msTimerCounter;
    roll_angle_PID.Desired  = range_trans(u16Rcvr_ch1, max_angle_pr);       // f(u16Rcvr_ch1) +
    pitch_angle_PID.Desired = range_trans(u16Rcvr_ch2, max_angle_pr);       // f(u16Rcvr_ch2) +
    yaw_angle_PID.Desired  += range_trans(3000-u16Rcvr_ch4, max_rate_pr)*(tnow-told)/1000.f;   /// Question

    if (yaw_angle_PID.Desired > +180.f) yaw_angle_PID.Desired -= 360.f;
    if (yaw_angle_PID.Desired < -180.f) yaw_angle_PID.Desired += 360.f; // keep Desired in -180~180
    if (yaw_angle_PID.Desired - yaw > +180.f) yaw_angle_PID.Desired -= 360.f;
    if (yaw_angle_PID.Desired - yaw < -180.f) yaw_angle_PID.Desired += 360.f; // keep error smallest
    // abs(error) > max_angle_pr ? Desired = yaw :  ;
    if (fabs(yaw_angle_PID.Desired - yaw) > max_angle_pr) yaw_angle_PID.Desired = yaw + copysignf(max_angle_pr, yaw_angle_PID.Desired - yaw);
    PID_postion_cal(&roll_angle_PID,  roll,  tnow-told);
    PID_postion_cal(&pitch_angle_PID, pitch, tnow-told);
    PID_postion_cal(&yaw_angle_PID,   yaw,   tnow-told);
    told = tnow;
}

// 内环角速度PID
void CtrlAttiRate(void)
{
    static uint32_t told = 0;

    roll_rate_PID.Desired  = roll_angle_PID.Output ;
    pitch_rate_PID.Desired = pitch_angle_PID.Output;
    yaw_rate_PID.Desired   = yaw_angle_PID.Output  ;

    //roll_rate_PID.Desired  = range_trans(u16Rcvr_ch1, 100);
    //pitch_rate_PID.Desired = range_trans(u16Rcvr_ch2, 100);
    //yaw_rate_PID.Desired   = range_trans(3000-u16Rcvr_ch4, 60);

    uint32_t tnow = msTimerCounter;
    PID_postion_cal(&roll_rate_PID,  gyro[0] / DMP_GYRO_SCALE, tnow-told); // DMP_GYRO_SCALE
    PID_postion_cal(&pitch_rate_PID, gyro[1] / DMP_GYRO_SCALE, tnow-told);
    PID_postion_cal(&yaw_rate_PID,   gyro[2] / DMP_GYRO_SCALE, tnow-told);
    told = tnow;
}

void CtrlMotorSpeed(void)
{
    // 获取输出值
    uint16_t Thr = u16Rcvr_ch3; /// 不用转换量程，因为通道捕获和电调输出都是1000～2000
    float Pitch  = pitch_rate_PID.Output;
    float Roll   = roll_rate_PID.Output;
    float Yaw    = yaw_rate_PID.Output;

    // 输出值融合到四个电机
    if (Thr > 1100) { // 是否锁定状态
        motor_pwm_1 = range_pwm( - Pitch - Roll - Yaw, range_thr(Thr));
        motor_pwm_2 = range_pwm( + Pitch - Roll + Yaw, range_thr(Thr));
        motor_pwm_3 = range_pwm( + Pitch + Roll - Yaw, range_thr(Thr));
        motor_pwm_4 = range_pwm( - Pitch + Roll + Yaw, range_thr(Thr));
    } else {
        motor_pwm_1 = motor_pwm_min;
        motor_pwm_2 = motor_pwm_min;
        motor_pwm_3 = motor_pwm_min;
        motor_pwm_4 = motor_pwm_min;
    }
}


<|start_filename|>firmware/FW8-gpio-iic-mpu6050-rawdata/gpio_i2c.h<|end_filename|>
#ifndef __GPIO_IIC_H
#define __GPIO_IIC_H

#include <stdint.h>

/// @brief GPIO初始化
void IIC_Init(void);


/// @brief 产生IIC起始信号
void IIC_Start(void);
/// @brief 产生IIC停止信号
void IIC_Stop(void);


/** 等待应答信号到来
    @retval int(_bool会不会更好)
            1 接收应答失败
            0 接收应答成功
*/
uint8_t IIC_Wait_Ack(void);
/// @brief 产生ACK应答
void IIC_Ack(void);
/// @brief 不产生ACK应答
void IIC_NAck(void);


/** @brief IIC发送一个字节.
    @param 要发送的字节数据
    @notes 不等待应答信号（没有调用IIC_Wait_Ack）
*/
void IIC_Send_Byte(uint8_t txd);


/** @brief 读1个字节，并发送ack/nack
    @param ack=1时，发送ACK，ack=0，发送nACK
*/
uint8_t IIC_Read_Byte(uint8_t ack);


#endif /* __GPIO_IIC_H */


<|start_filename|>project/Templates-without-OS/application/template.h<|end_filename|>
/**
  @file    template.h
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   a header file template.
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TEMPLATE_H
#define __TEMPLATE_H

#ifdef __cplusplus
 extern "C" {
#endif 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"   
#include "ucos_ii.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */

#ifdef __cplusplus
}
#endif

#endif /* __TEMPLATE_H */


<|start_filename|>ucosii/os_cpu_a.asm<|end_filename|>
;/*********************** (C) COPYRIGHT 2010 Libraworks *************************
;* File Name    : os_cpu_a.asm
;* Author       : Librae
;* Version      : V1.0
;* Date         : 06/10/2010
;* Description  : μCOS-II asm port  for STM32
;*******************************************************************************/

        IMPORT  OSRunning               ; External references
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy
        IMPORT  OSTCBCur
        IMPORT  OSTCBHighRdy
        IMPORT  OSIntNesting
        IMPORT  OSIntExit
        IMPORT  OSTaskSwHook

        EXPORT  OSStartHighRdy
        EXPORT  OSCtxSw
        EXPORT  OSIntCtxSw
        EXPORT  OS_CPU_SR_Save                                      ; Functions declared in this file
        EXPORT  OS_CPU_SR_Restore
        EXPORT  PendSV_Handler


NVIC_INT_CTRL       EQU     0xE000ED04  ; 中断控制寄存器
NVIC_SYSPRI2        EQU     0xE000ED22  ; 系统优先级寄存器(2)
NVIC_PENDSV_PRI     EQU         0xFFFF  ; PendSV中断和系统节拍中断
                                        ; (都为最低，0xff).
NVIC_PENDSVSET      EQU     0x10000000  ; 触发软件中断的值.


        PRESERVE8

        AREA    |.text|, CODE, READONLY
        THUMB



;********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU's status register.
;
; Prototypes :     OS_CPU_SR  OS_CPU_SR_Save(void);
;                  void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             /* cpu_sr = OS_CPU_SaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              /* OS_CPU_RestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;********************************************************************************************************

OS_CPU_SR_Save
    MRS     R0, PRIMASK     ;读取PRIMASK到R0,R0为返回值
    CPSID   I               ;PRIMASK=1,关中断(NMI和硬件FAULT可以响应)
    BX      LR              ;返回

OS_CPU_SR_Restore
    MSR     PRIMASK, R0     ;读取R0到PRIMASK中,R0为参数
    BX      LR              ;返回


;/**************************************************************************************
;* 函数名称: OSStartHighRdy
;*
;* 功能描述: 使用调度器运行第一个任务
;*
;* 参    数: None
;*
;* 返 回 值: None
;**************************************************************************************/

OSStartHighRdy
        LDR     R4, =NVIC_SYSPRI2      ; set the PendSV exception priority
        LDR     R5, =NVIC_PENDSV_PRI
        STR     R5, [R4]

        MOV     R4, #0                 ; set the PSP to 0 for initial context switch call
        MSR     PSP, R4

        LDR     R4, =OSRunning         ; OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]

                                       ;切换到最高优先级的任务
        LDR     R4, =NVIC_INT_CTRL     ;rigger the PendSV exception (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]

        CPSIE   I                      ;enable interrupts at processor level
OSStartHang
        B       OSStartHang            ;should never get here

;/**************************************************************************************
;* 函数名称: OSCtxSw
;*
;* 功能描述: 任务级上下文切换
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

OSCtxSw
        PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL      ;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
        POP     {R4, R5}
        BX      LR

;/**************************************************************************************
;* 函数名称: OSIntCtxSw
;*
;* 功能描述: 中断级任务切换
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

OSIntCtxSw
        PUSH    {R4, R5}
        LDR     R4, =NVIC_INT_CTRL      ;触发PendSV异常 (causes context switch)
        LDR     R5, =NVIC_PENDSVSET
        STR     R5, [R4]
        POP     {R4, R5}
        BX      LR
        NOP

;/**************************************************************************************
;* 函数名称: OSPendSV
;*
;* 功能描述: OSPendSV is used to cause a context switch.
;*
;* 参    数: None
;*
;* 返 回 值: None
;***************************************************************************************/

PendSV_Handler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                             ; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈-白菜注
    CBZ     R0, PendSV_Handler_Nosave                           ; Skip register save the first time

    ;Is the task using the FPU context? If so, push high vfp registers.
    TST     R14, #0x10
    IT      EQ
    VSTMDBEQ R0!, {S16-S31}

    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur                                       ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

                                                                ; At this point, entire context of process has been saved
PendSV_Handler_Nosave
    PUSH    {R14}                                               ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, =OSTCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20

    ;Is the task using the FPU context? If so, push high vfp registers.
    TST     R14, #0x10
    IT      EQ
    VLDMIAEQ R0!, {S16-S31}

    MSR     PSP, R0                                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                                  ; Exception return will restore remaining context
    NOP
    end


<|start_filename|>project/p10-ANO/application/HMC5883.c<|end_filename|>
#include "gpio_hmc5883.h"
#include "gpio_mpu6050.h"
#include "gpio_i2c.h"
#include "delay.h"

#define  HMC5883_Addr   0x1E

static uint8_t HMC_Write_Byte(uint8_t reg, uint8_t data)
{
    IIC_Start();
    IIC_Send_Byte((HMC5883_Addr<<1)|0);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    IIC_Send_Byte(data);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Stop();
    return 0;
}

uint8_t InitHMC5883(void)
{
    // 主控制器的I2C与MPU6050的AUXI2C直通。控制器可以直接访问GY-86上的HMC5883L。即MPU6050不是AUXI2C线的主机。
    if (!MPU_Write_Byte(0X37, 0x82)) return 0;
    delay(20);
    return HMC_Write_Byte(0x00, 0x78) && HMC_Write_Byte(0x01, 0xE0) && HMC_Write_Byte(0x02, 0x01);
                        // 0 11 110 00                 111 00000                        单一测量模式
                        // 75Hz + 8次均值滤波           量程 +-8.1Ga ~ -2048~+2047 
                                                        // 230 Counts/Ga
}

void updateHMC5883(short mag[3])
{
    uint8_t buf[6];

    IIC_Start();
    IIC_Send_Byte((HMC5883_Addr<<1)|1);
    IIC_Wait_Ack();
    buf[0]=IIC_Read_Byte(1);
    buf[1]=IIC_Read_Byte(1);
    buf[2]=IIC_Read_Byte(1);
    buf[3]=IIC_Read_Byte(1);
    buf[4]=IIC_Read_Byte(1);
    buf[5]=IIC_Read_Byte(0);
    IIC_Stop();

    mag[0] = (buf[0] << 8) | buf[1]; // Combine MSB and LSB of X Data output register
    mag[1] = (buf[4] << 8) | buf[5]; // Combine MSB and LSB of Y Data output register
    mag[2] = (buf[2] << 8) | buf[3]; // Combine MSB and LSB of Z Data output register

    HMC_Write_Byte(0x02, 0x01);
}


<|start_filename|>project/p6-PWM-motor/application/main.c<|end_filename|>
#include "stm32f4xx_conf.h"
#include "usart.h"
#include "delay.h"
#include "motor-PWM.h"

/* Private typedef -----------------------------------------------------------*/
#define printf_(s, ...) printf("file:%s\tline:%d\t" s, __FILE__, __LINE__, __VA_ARGS__)
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @retval None
  */
int main(void)
{
	
 /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       files before to branch to application main.
       To reconfigure the default setting of SystemInit() function, 
       refer to system_stm32f4xx.c file */
	delayinit();
  /* Add your application code here */
	motor_pwm_init();
	motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_4 = motor_pwm_max;
	delay(2000);
	motor_pwm_4 = motor_pwm_min;
	delay(1100);
	motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_min;
	delay(5000);
	motor_pwm_1 = motor_pwm_2 = motor_pwm_3 = motor_pwm_4 = motor_pwm_max;//motor_pwm_range(motor_pwm_min+300);
	
	int c = 0;
	uart_init(38400);
	for (;;) {
		delay(1000);
		printf_("c = %d \r\n", c++);
		printf_("TIM1->CNT = %d \r\n", TIM1->CNT);
	}

  /* Infinite loop */
  //for (;;);
}


<|start_filename|>firmware/BTN-EXTI/btn_exti.c<|end_filename|>
/**
  @file    btn_exti.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170724
  @brief   a source file about the button triggers an external interrupt.
           B1 - PC13.
*/

/* Includes ------------------------------------------------------------------*/
#include "btn_exti.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

#include "stm32f4xx_conf.h"

void GPIO_init_4_BTN_EXTI (void)
{
  EXTI_InitTypeDef   EXTI_InitStructure;
  GPIO_InitTypeDef   GPIO_InitStructure;
  NVIC_InitTypeDef   NVIC_InitStructure;

  /* Enable GPIOC clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  /* Enable SYSCFG clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  
  /* Configure PC13 pin as input floating */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  GPIO_Init(GPIOC, &GPIO_InitStructure); /* fixed #1 in 6513ab08c8a3d9be2c0de274092e8cfb35b52814 */

  /* Connect EXTI Line13 to PC13 pin */
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13);

  /* Configure EXTI Line13 */
  EXTI_InitStructure.EXTI_Line = EXTI_Line13;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

  /* Enable and set EXTI Line13 Interrupt to the lowest priority */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}


<|start_filename|>firmware/FW8-gpio-iic-mpu6050-rawdata/gpio_mpu6050.c<|end_filename|>
#include "gpio_mpu6050.h"
#include "gpio_i2c.h"
#include "delay.h"

#define windows_fliter

////////////////////////////////////////////////////////////////////////////////


/* MPU6050 寄存器地址 */

#define MPU_SELF_TESTX_REG      0X0D    // 自检寄存器X
#define MPU_SELF_TESTY_REG      0X0E    // 自检寄存器Y
#define MPU_SELF_TESTZ_REG      0X0F    // 自检寄存器Z
#define MPU_SELF_TESTA_REG      0X10    // 自检寄存器A
#define MPU_SAMPLE_RATE_REG     0X19    // 采样频率分频器
#define MPU_CFG_REG             0X1A    // 配置寄存器
#define MPU_GYRO_CFG_REG        0X1B    // 陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG       0X1C    // 加速度计配置寄存器
#define MPU_MOTION_DET_REG      0X1F    // 运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG         0X23    // FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG     0X24    // IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG    0X25    // IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG         0X26    // IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG    0X27    // IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG    0X28    // IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG         0X29    // IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG    0X2A    // IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG    0X2B    // IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG         0X2C    // IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG    0X2D    // IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG    0X2E    // IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG         0X2F    // IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG    0X30    // IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG    0X31    // IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG         0X32    // IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG      0X33    // IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG    0X34    // IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG      0X35    // IIC从机4读数据寄存器

#define MPU_I2CMST_STA_REG      0X36    // IIC主机状态寄存器
#define MPU_INTBP_CFG_REG       0X37    // 中断/旁路设置寄存器
#define MPU_INT_EN_REG          0X38    // 中断使能寄存器
#define MPU_INT_STA_REG         0X3A    // 中断状态寄存器

#define MPU_ACCEL_XOUTH_REG     0X3B    // 加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG     0X3C    // 加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG     0X3D    // 加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG     0X3E    // 加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG     0X3F    // 加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG     0X40    // 加速度值,Z轴低8位寄存器

#define MPU_TEMP_OUTH_REG       0X41    // 温度值高八位寄存器
#define MPU_TEMP_OUTL_REG       0X42    // 温度值低8位寄存器

#define MPU_GYRO_XOUTH_REG      0X43    // 陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG      0X44    // 陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG      0X45    // 陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG      0X46    // 陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG      0X47    // 陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG      0X48    // 陀螺仪值,Z轴低8位寄存器

#define MPU_I2CSLV0_DO_REG      0X63    // IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG      0X64    // IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG      0X65    // IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG      0X66    // IIC从机3数据寄存器

#define MPU_I2CMST_DELAY_REG    0X67    // IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG     0X68    // 信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG    0X69    // 运动检测控制寄存器
#define MPU_USER_CTRL_REG       0X6A    // 用户控制寄存器
#define MPU_PWR_MGMT1_REG       0X6B    // 电源管理寄存器1
#define MPU_PWR_MGMT2_REG       0X6C    // 电源管理寄存器2
#define MPU_FIFO_CNTH_REG       0X72    // FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG       0X73    // FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG         0X74    // FIFO读写寄存器
#define MPU_DEVICE_ID_REG       0X75    // 器件ID寄存器

#define MPU_ADDR                0X68    // AD0接地,IIC地址为0X68(不包含最低位).


////////////////////////////////////////////////////////////////////////////////


/* MPU6050 控制接口，更底层是 IIC + GPIO */

static uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr);
static uint8_t MPU_Set_Accel_Fsr(uint8_t fsr);

static uint8_t MPU_Set_LPF(uint16_t lpf);
static uint8_t MPU_Set_Rate(uint16_t rate);
static uint8_t MPU_Set_Fifo(uint8_t sens);

static short   MPU_Get_Temperature(void);
static uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz);
static uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az);


////////////////////////////////////////////////////////////////////////////////


/* 量程相关函数 */

/** @brief 设置 MPU6050 陀螺仪传感器满量程范围.
    @param fsr: 
        0, ±250dps;
        1, ±500dps;
        2, ±1000dps;
        3, ±2000dps(°/sec)
    @retval int
            0,      设置成功
            others, 设置失败
*/

uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
{
    return MPU_Write_Byte(MPU_GYRO_CFG_REG, fsr<<3); // 设置陀螺仪满量程范围
}

/** @brief 设置 MPU6050 加速度传感器满量程范围.
    @param fsr:
        0, ±2g;
        1, ±4g;
        2, ±8g;
        3, ±16g(重力加速度)
    @retval int
            0,      设置成功
            others, 设置失败
    @notes 2^15 = 32768
*/
uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
{
    return MPU_Write_Byte(MPU_ACCEL_CFG_REG, fsr<<3); // 设置加速度传感器满量程范围
}


////////////////////////////////////////////////////////////////////////////////


/** @brief 设置MPU6050的数字低通滤波器.
    @param lpf: 数字低通滤波频率(Hz)
    @retval int
            0,      设置成功
            others, 设置失败
*/
uint8_t MPU_Set_LPF(uint16_t lpf)
{
    uint8_t 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);//设置数字低通滤波器
}


/** @brief 设置MPU6050的采样率(假定Fs=1KHz)
    @param rate: 4~1000(Hz)
    @retval int
            0,      设置成功
            others, 设置失败
*/
uint8_t MPU_Set_Rate(uint16_t rate)
{
    uint8_t data;
    if(rate>1000)rate=1000;
    if(rate<4)rate=4;
    data = 1000/rate-1;

    /* 设置采样率 以及 设置数字低通滤波器频率为采样率的一半 */
    return MPU_Write_Byte(MPU_SAMPLE_RATE_REG, data) || MPU_Set_LPF(rate/2);
}


////////////////////////////////////////////////////////////////////////////////


/* 获取重要的数据寄存器的值 */

/** @brief 获取MPU6050温度.
    @retval 温度寄存器的值
*/
short MPU_Get_Temperature(void)
{
    uint8_t buf[2];
    MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG, 2, buf);
    short raw = ((uint16_t)buf[0]<<8)|buf[1];
    float temp = 36.53+((double)raw)/340;
    return temp*100;
}

/** @brief 得到陀螺仪值(原始值).
    @param gx, gy, gz: 陀螺仪三轴的原始读数(带符号)
    @retval int
            0,      读取成功
            others, 读取失败
*/
uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz)
{
    uint8_t buf[6], res;
    if ((res = MPU_Read_Len(MPU_ADDR, MPU_GYRO_XOUTH_REG, 6, buf)) == 0) {
        *gx=(((uint16_t)buf[0]<<8)|buf[1]);;
        *gy=(((uint16_t)buf[2]<<8)|buf[3]);;
        *gz=(((uint16_t)buf[4]<<8)|buf[5]);;
    }
    return res;
}

/** @brief 得到加速度值(原始值).
    @param gx, gy, gz: 加速度三轴的原始读数(带符号)
    @retval int
            0,      读取成功
            others, 读取失败
*/
uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az)
{
    uint8_t buf[6], res;
    if((res = MPU_Read_Len(MPU_ADDR, MPU_ACCEL_XOUTH_REG, 6, buf)) == 0) {
        *ax=((uint16_t)buf[0]<<8)|buf[1];
        *ay=((uint16_t)buf[2]<<8)|buf[3];
        *az=((uint16_t)buf[4]<<8)|buf[5];
    }
    return res;
}


////////////////////////////////////////////////////////////////////////////////


/* MPU6050的IIC读写时序 */


/** @brief IIC连续写.
    @param  addr: 器件地址
            reg:  寄存器地址
            len:  写入长度
            buf:  数据区
    @retval int
            1 成功
            0 失败
*/
uint8_t MPU_Write_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
    uint8_t i;
    IIC_Start();
    IIC_Send_Byte((addr<<1)|0);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    for(i=0;i<len;i++)
    {
        IIC_Send_Byte(buf[i]);
        if(IIC_Wait_Ack())
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_Stop();
    return 0;
}


/** @brief IIC连续读.
    @param 
        addr: 器件地址
        reg: 要读取的寄存器地址
        len: 要读取的长度
        buf: 读取到的数据存储区
    @retval int
            1 成功
            0 失败
*/
uint8_t MPU_Read_Len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
    IIC_Start();
    IIC_Send_Byte((addr<<1)|0);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte((addr<<1)|1);
    IIC_Wait_Ack();
    while(len)
    {
        if(len==1)*buf=IIC_Read_Byte(0);
        else *buf=IIC_Read_Byte(1);
        len--;
        buf++;
    }
    IIC_Stop();
    return 0;
}


/** @brief IIC写一个字节.
    @param 
        reg: 寄存器地址
        data: 数据
    @retval int
            1 成功
            0 失败
*/
uint8_t MPU_Write_Byte(uint8_t reg, uint8_t data)
{
    IIC_Start();
    IIC_Send_Byte((MPU_ADDR<<1)|0);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    IIC_Send_Byte(data);
    if(IIC_Wait_Ack())
    {
        IIC_Stop();
        return 1;
    }
    IIC_Stop();
    return 0;
}


/** @brief IIC读一个字节.
    @param 
        reg: 寄存器地址
    @retval uint8_t 读到的数据
*/
uint8_t MPU_Read_Byte(uint8_t reg)
{
    uint8_t res;
    IIC_Start();
    IIC_Send_Byte((MPU_ADDR<<1)|0);
    IIC_Wait_Ack();
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte((MPU_ADDR<<1)|1);
    IIC_Wait_Ack();
    res = IIC_Read_Byte(0);
    IIC_Stop();
    return res;
}


////////////////////////////////////////////////////////////////////////////////


/* 函数接口 */


/** @brief 通过IIC初始化MPU6050.
    @retval uint8_t
            0 初始化正常
            1 初始化失败
    @notes  这里是通过什么检查的呢，感觉这里的错误反馈都是假的
            不正常运行也不知道为什么
*/
uint8_t MPU_Init(void)
{
    /* 初始化IIC总线 */
    IIC_Init();
    /* 复位MPU6050 */
    MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X80);
    delay(100);

    /* 唤醒MPU6050 */
    MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00);

    /* 设置量程和采样率 */
    MPU_Set_Gyro_Fsr(3);                      /* 陀螺仪传感器, ±2000dps 16.4C */
    MPU_Set_Accel_Fsr(2);                     /* 加速度传感器, ±8g 4096 */
    MPU_Set_Rate(125);                        /* 设置采样率125Hz */

    /* 关闭各种无用模式功能，不用MPU */
    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引脚低电平有效 */

    /* 检查器件ID */ // 为什么在这里
    if (MPU_Read_Byte(MPU_DEVICE_ID_REG) != MPU_ADDR)
        return 1; /* 器件ID不正确，直接返回 */

    MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); /* 设置CLKSEL, PLL X轴为参考 */
    MPU_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); /* 加速度与陀螺仪都工作 */
    MPU_Set_Rate(250);                       /* 设置采样率为50Hz */
    return 0;
}


<|start_filename|>firmware/Nucleo64-User/LED.h<|end_filename|>
/**
  @file    button.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   This file contains all the functions prototypes for the LED firmware library.

  LD2 - PA5 - TIM2_CH1

*/
#ifndef __LED_H
#define __LED_H
#include <stm32f4xx.h>

void GPIO_init_4_LD2 (void);

#define set_LD2(s) GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)(s))
/* 扩展型宏 */


/* 位带 */

#endif


<|start_filename|>project/Templates-without-OS/application/main.c<|end_filename|>
/**
  @file    main.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   define main entry.
*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Main program
  */
int main(void)
{
  for (;;);
}


<|start_filename|>firmware/LD2-PWM/LD2pwm.c<|end_filename|>
/**
  @file    LD2pwm.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   interface of pwm output on LD2.
*/

/* Includes ------------------------------------------------------------------*/
#include "LD2pwm.h"
#include "stm32f4xx_conf.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

void GPIO_init_4_LD2_PWM (void)
{
	/* PA5=TIM2_CH1*/
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  
	{
		GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);
		GPIO_InitTypeDef r1 = {GPIO_Pin_5, GPIO_Mode_AF, GPIO_High_Speed, GPIO_OType_PP, GPIO_PuPd_NOPULL};
		GPIO_Init(GPIOA, &r1);
	}
	
	{
		TIM_TimeBaseInitTypeDef r1 = {
			.TIM_CounterMode = TIM_CounterMode_Up,
			.TIM_ClockDivision = TIM_CKD_DIV1,
			.TIM_Prescaler = 0,
			.TIM_Period = pwm_arr //100M->1M
		};
		TIM_TimeBaseInit(TIM2, &r1);
	}
	
	{
		TIM_OCInitTypeDef r1 = {
			r1.TIM_OCMode = TIM_OCMode_PWM1,
			r1.TIM_OCPolarity = TIM_OCPolarity_High,
			r1.TIM_OutputState = TIM_OutputState_Enable
		};
		TIM_OC1Init(TIM2, &r1);
	}
	
	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); 
	
	TIM_Cmd(TIM2, ENABLE);
	/*
  -@- If the corresponding interrupt or DMA request are needed, the user should:
        (+@) Enable the NVIC (or the DMA) to use the TIM interrupts (or DMA requests). 
        (+@) Enable the corresponding interrupt (or DMA request) using the function 
             TIM_ITConfig(TIMx, TIM_IT_CCx) (or TIM_DMA_Cmd(TIMx, TIM_DMA_CCx))  
	*/
}



<|start_filename|>firmware/delay/delay.c<|end_filename|>
/**
  @file    delay.c
  @author  tjua @ ES-SS-UESTC © 2017
  @version V1.0
  @date    20170720
  @brief   used systick to delay ms.
*/

#include "delay.h"

static __IO uint32_t uwTimingDelay;
volatile uint32_t msTimerCounter;
/* 
__IO的说明
定义在 "core_cm4.h"
__IO __I __O -> volatile -> 防止多任务(OS/IRQ)使用的资源被优化
不是指针的参数以及返回值就不要用这个修饰了
*/

/// @brief  Inserts a delay time.
/// @param  nTime: specifies the delay time length, in milliseconds.
void delay (uint32_t ticks)
{ 
  uwTimingDelay = ticks;

  while(uwTimingDelay != 0);
}

/// @brief  Decrements the TimingDelay variable.
static void TimingDelay_Decrement (void)
{
  if (uwTimingDelay != 0x00)
  { 
    uwTimingDelay--;
  }
  msTimerCounter++;
}

/// @brief  This function handles SysTick Handler.
void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}


void delayinit (void)
{
  /* SysTick end of count event each 1ms */
  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);
  SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // 见19/20/21讲笔记
}

