第二家公司测试工装代码

main.h

/**
  ******************************************************************************
  * @file           : main.h
  * @brief          : Header for main.c file.
  *                   This file contains the common defines of the application.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

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

/* Includes ------------------------------------------------------------------*/

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/

#define PushMotorPWM_Pin GPIO_PIN_0
#define PushMotorPWM_GPIO_Port GPIOA
#define PushMotorIN1_Pin GPIO_PIN_1
#define PushMotorIN1_GPIO_Port GPIOA
#define PushMotorIN2_Pin GPIO_PIN_2
#define PushMotorIN2_GPIO_Port GPIOA
#define Knob3_1_Pin GPIO_PIN_5
#define Knob3_1_GPIO_Port GPIOA
#define Knob3_2_Pin GPIO_PIN_6
#define Knob3_2_GPIO_Port GPIOA
#define Knob3_3_Pin GPIO_PIN_7
#define Knob3_3_GPIO_Port GPIOA
#define StepMotorPul_Pin GPIO_PIN_0
#define StepMotorPul_GPIO_Port GPIOB
#define StepMotorDir_Pin GPIO_PIN_1
#define StepMotorDir_GPIO_Port GPIOB
#define StepMotorEna_Pin GPIO_PIN_2
#define StepMotorEna_GPIO_Port GPIOB
#define LED_RED_Pin GPIO_PIN_11
#define LED_RED_GPIO_Port GPIOB
#define LED_GREEN_Pin GPIO_PIN_12
#define LED_GREEN_GPIO_Port GPIOB
#define PushMotor2IN1_Pin GPIO_PIN_13
#define PushMotor2IN1_GPIO_Port GPIOB
#define PushMotor2IN2_Pin GPIO_PIN_14
#define PushMotor2IN2_GPIO_Port GPIOB
#define PushMotor2PWM_Pin GPIO_PIN_8
#define PushMotor2PWM_GPIO_Port GPIOA
#define Proximity1_Pin GPIO_PIN_5
#define Proximity1_GPIO_Port GPIOB
#define Proximity1_EXTI_IRQn EXTI9_5_IRQn
#define proximity2_Pin GPIO_PIN_6
#define proximity2_GPIO_Port GPIOB
#define proximity2_EXTI_IRQn EXTI9_5_IRQn
#define Switch_Pin GPIO_PIN_7
#define Switch_GPIO_Port GPIOB
#define Switch_EXTI_IRQn EXTI9_5_IRQn

/* ########################## Assert Selection ############################## */
/**
  * @brief Uncomment the line below to expanse the "assert_param" macro in the 
  *        HAL drivers code
  */
/* #define USE_FULL_ASSERT    1U */

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

#ifdef __cplusplus
 extern "C" {
#endif
void _Error_Handler(char *, int);

#define Error_Handler() _Error_Handler(__FILE__, __LINE__)
#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

main.c


/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_hal.h"
#include "iwdg.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */
#include "StepMotor.h"
#include "debug.h"
#include "app.h"
#include "sys.h"
#include "mytype.h"
#include "list.h"
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
void LED_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_RED_Pin|LED_GREEN_Pin, GPIO_PIN_SET);


  /*Configure GPIO pins : PBPin PBPin */
  GPIO_InitStruct.Pin = LED_RED_Pin|LED_GREEN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  *
  * @retval None
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
	LED_GPIO_Init();
	for(int i=0;i<15;i++)
	{
		LED_Toggel(-1);
		HAL_Delay(100);
	}
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  //MX_IWDG_Init();
  MX_TIM4_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
	
	printf("start\r\n");
	HAL_UART_Receive_IT(&huart1,&byTmpData,1);
	//App1_Func();
	switch(Get_Mod())
	{
		case 1:
			printf("mod1\r\n");
			App1_Func();
			break;
		case 2:
			printf("mod2\r\n");
			App2_Func();
			break;
		case 3:
			printf("mod3\r\n");
			App3_Func();
			break;
		default:
			printf("moderr\r\n");
			break;
	}
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
		HAL_Delay(10);
  }
  /* USER CODE END 3 */

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void _Error_Handler(char *file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#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 CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

PushMotor.h

#ifndef __PUSHMOTOR_H__
#define __PUSHMOTOR_H__

#include "stm32f1xx.h"
#include "main.h"
#include "tim.h"

#define PUSHMOTORPER_10US		10

extern uint16_t PushMotor_10us;
extern volatile uint32_t PM_Max_Counter;
extern volatile uint32_t PM_Counter;

extern uint16_t PushMotor2_10us;
extern volatile uint32_t PM2_Max_Counter;
extern volatile uint32_t PM2_Counter;

int8_t PushMotor_Control(int8_t speed,uint32_t time_off,uint8_t flag_break);
int8_t PushMotor2_Control(int8_t speed,uint32_t time_off,uint8_t flag_break);
void PushMotor1_irq_cb(void);
void PushMotor2_irq_cb(void);

#endif

PushMotor.c

#include "PushMotor.h"
#include "debug.h"

#define PushMotor2TIM		TIM1
#define PushMotorTIM		TIM2

uint16_t PushMotor_10us=0;
volatile uint32_t PM_Max_Counter=0;
volatile uint32_t PM_Counter=0;

uint16_t PushMotor2_10us=0;
volatile uint32_t PM2_Max_Counter=0;
volatile uint32_t PM2_Counter=0;

/*推杆电机控制函数
speed:速度
				0		锁死
				正数
				负数
timout:运动时间
*/
int8_t PushMotor_Control(int8_t speed,uint32_t time_off,uint8_t flag_break)
{
	/*判断是否需要打断之前的运行*/
	if(flag_break!=0)//打断当前运行
	{
		debug("打断\r\n");
	}
	else
	{
		if(PushMotor_10us!=0)//电机正在运行
		{
			debug("定时器正在运行\r\n");
			return -1;
		}
		else
		{
			
		}
	}
	
	/*需要打断或者上次运行已经结束*/
	PushMotor_10us=speed<0?0-speed:speed;
	if(speed<0)
	{
		HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_RESET);
	}
	else if(speed>0)
	{
		HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_RESET);
		HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
		return 0;
	}
	PushMotorTIM->CNT=0;
	PushMotorTIM->CCR1=PushMotor_10us;
	
	/*转动时间控制,当time_off为0时一直转动*/
	PushMotorTIM->SR&=0x00;
	if(time_off==0)
	{
		debug("时间为0\r\n");
		PushMotorTIM->DIER&=0x00;
	}
	else
	{
		PM_Counter=0;
		PM_Max_Counter=time_off;
		PushMotorTIM->DIER|=0x01;
	}
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
	
	return 0;
}

int8_t PushMotor2_Control(int8_t speed,uint32_t time_off,uint8_t flag_break)
{
	/*判断是否需要打断之前的运行*/
	if(flag_break!=0)//打断当前运行
	{
		debug("打断\r\n");
	}
	else
	{
		if(PushMotor2_10us!=0)//电机正在运行
		{
			debug("定时器正在运行\r\n");
			return -1;
		}
		else
		{
			
		}
	}
	
	/*需要打断或者上次运行已经结束*/
	PushMotor2_10us=speed<0?0-speed:speed;
	if(speed<0)
	{
		HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_RESET);
	}
	else if(speed>0)
	{
		HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_SET);
	}
	else
	{
		HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_RESET);
		HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
		return 0;
	}
	PushMotor2TIM->CNT=0;
	PushMotor2TIM->CCR1=PushMotor2_10us;
	
	/*转动时间控制,当time_off为0时一直转动*/
	PushMotor2TIM->SR&=0x00;
	if(time_off==0)
	{
		debug("时间为0\r\n");
		PushMotor2TIM->DIER&=0x00;
	}
	else
	{
		PM2_Counter=0;
		PM2_Max_Counter=time_off;
		PushMotor2TIM->DIER|=0x01;
	}
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
	
	return 0;
}

void PushMotor1_irq_cb()
{
	PM_Counter++;
	if(PM_Counter>=PM_Max_Counter)
	{
		PM_Counter=0;
		debug("over\r\n");
		PushMotor_Control(0,0,1);
	}
}

void PushMotor2_irq_cb()
{
	PM2_Counter++;
	if(PM2_Counter>=PM2_Max_Counter)
	{
		PM2_Counter=0;
		debug("over\r\n");
		PushMotor2_Control(0,0,1);
	}
}

StepMotor.h

#ifndef __STEPMOTOR_H__
#define __STEPMOTOR_H__

#include "stm32f1xx.h"
#include "main.h"
#include "tim.h"

extern uint16_t StepMotor_10us;

int8_t StepMotor_Control(int16_t speed,uint16_t angle,uint8_t flag_break);
void StepMotor_irq_cb(void);

#endif

StepMotor.c

#include "StepMotor.h"
#include "debug.h"

#define StepMotorTIM		TIM3
#define SlaveMotorTIM		TIM4

uint16_t StepMotor_10us=0;

/*步进电机控制函数
speed:速度
				0		锁死
				正数
				负数
angle:运动角度
*/
int8_t StepMotor_Control(int16_t speed,uint16_t angle,uint8_t flag_break)
{
	/*判断是否需要打断之前的运行*/
	if(flag_break!=0)//打断当前运行
	{
		debug("打断\r\n");
	}
	else
	{
		/*检测电机是否正在运行*/
		//if(StepMotorTIM->CR1&0x00000001)//电机正在运行
		if(StepMotor_10us!=0)
		{
			debug("定时器正在运行\r\n");
			return -1;
		}
		else
		{
			
		}
	}
	
	/*需要打断或者上次运行已经结束*/
	StepMotor_10us=speed<0?0-speed:speed;
	if(speed<0)
	{
		HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(StepMotorDir_GPIO_Port,StepMotorDir_Pin,GPIO_PIN_RESET);
	}
	else if(speed>0)
	{
		HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(StepMotorDir_GPIO_Port,StepMotorDir_Pin,GPIO_PIN_SET);
	}
	else
	{
		//锁死步进电机
		HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
		HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3);
		return 0;
	}
	StepMotorTIM->CNT = 0;
	StepMotorTIM->ARR = StepMotor_10us;
	StepMotorTIM->CCR3 = StepMotor_10us/2;
	
	/*转动角度控制,当angle为0时一直转动*/
	SlaveMotorTIM->SR&=0x00;
	if(angle==0)
	{
		debug("角度为0\r\n");
		HAL_TIM_Base_Stop_IT(&htim4);
	}
	else
	{
		SlaveMotorTIM->CNT=0;
		SlaveMotorTIM->ARR=angle-1;
		HAL_TIM_Base_Start_IT(&htim4);
	}
	
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
	
	return 0;
}

void StepMotor_irq_cb()
{
	debug("over\r\n");
	StepMotor_Control(0,0,1);
}

dubug.h

#ifndef _DEBUG_H
#define _DEBUG_H

#include "stdio.h"
#include "stm32f1xx.h"
#include "main.h"
#include "usart.h"

#define MKIMAGE_DEBUG

#ifdef MKIMAGE_DEBUG
#define debug(fmt,args...)	printf (fmt ,##args)
#else
#define debug(fmt,args...)
#endif /* MKIMAGE_DEBUG */

extern uint8_t byTmpData;

void debug_analyze(void);

#endif /* DEBUG_H */

debug.c

#include "debug.h"
#include "string.h"
#include "StepMotor.h"
#include "PushMotor.h"

//#define RX_SHOW		//处理器速度不够请不要打开这个,72M主频也不够

#define DEBUG_BUFF_SIZE  36

uint8_t byDebugBuff[DEBUG_BUFF_SIZE];

uint8_t byTmpData;
static uint8_t byCurrentDebugCursor = 0;
int dwTmpPara[6];
int i;

/**
 * @brief DEBUG 常量文本索引
 */
enum
{
    DEBUG_TEXT_INFO,                                    /* debug信息 */
    DEBUG_TEXT_CMD_TOO_LONG,                            /* 命令过长 */
    DEBUG_TEXT_BACK,                                    /* 退格 */
    DEBUG_TEXT_INPUT_HEAD,                              /* 输入前置打印 */
    DEBUG_TEXT_HELP,                                    /* help 命令打印 */
    DEBUG_TEXT_CMD_UNKNOWN,                              /* 未知命令类型 */
};

static const char *pDebugText[] =
{
//    [DEBUG_TEXT_INFO] = 
        "\r\n======================================================================"
        "\r\n=              (C) COPYRIGHT 2020 STMicroelectronics                 ="
        "\r\n=                                                                    ="
        "\r\n=        STM32F4xx Application For Motion (Version xxxxx)            ="
        "\r\n=                                                                    ="
        "\r\n=                                                  By Alight Team    ="
        "\r\n======================================================================\r\n",
//     [DEBUG_TEXT_CMD_TOO_LONG] = 
    	"\r\nCommand is too long\r\n",
//     [DEBUG_TEXT_BACK] = 
     	"\b \b",
//	 [DEBUG_TEXT_INPUT_HEAD] = 
	 	">",
//	 [DEBUG_TEXT_HELP] = 
	 	"\r\nCommand List :"
	 	"\r\nreboot          reset mcu"
	 	"\r\nsm     step motor control(speed angle break)"
		"\r\npm     push motor control(speed time break)"
	 	"\r\nhelp            show command info\r\n",
//	 [DEBUG_TEXT_CMD_UNKNOWN] =
	 "\r\nCommand unknown\r\n"
};

/*
*********************************************************************************************************
*	函 数 名: debug_analyze
*	功能说明: DEBUG数据解析
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void debug_analyze(void)
{
		if('\b' == byTmpData)
		{
			if(byCurrentDebugCursor <= 0)
			{
				byCurrentDebugCursor = 0;
			}
			else
			{
				printf("%s", pDebugText[DEBUG_TEXT_BACK]);
				byCurrentDebugCursor--;
			}
			return;
		}
	
		if('\r' == byTmpData || '\n' == byTmpData)
		{
			byDebugBuff[byCurrentDebugCursor] = '\0';

			if(0 == byCurrentDebugCursor)
			{
				printf("\r\n");
			}
			else if(strcmp("reboot", (const char *)byDebugBuff) == 0)
			{
				HAL_NVIC_SystemReset();
				printf("\r\nreset mcu\r\n");
			}
			else if(strncmp("sm", (const char *)byDebugBuff,strlen("sm")) == 0)
			{
					sscanf((const char *)byDebugBuff, "sm %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
					printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
					StepMotor_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
			}
			else if(strncmp("pm1", (const char *)byDebugBuff,strlen("pm1")) == 0)
			{
					sscanf((const char *)byDebugBuff, "pm1 %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
					printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
					PushMotor_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
			}
			else if(strncmp("pm2", (const char *)byDebugBuff,strlen("pm2")) == 0)
			{
					sscanf((const char *)byDebugBuff, "pm2 %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
					printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
					PushMotor2_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
			}
			else if(strncmp("get app1", (const char *)byDebugBuff,strlen("get app1")) == 0)
			{
					
			}
			else if(strncmp("set app1", (const char *)byDebugBuff,strlen("set app1")) == 0)
			{
					sscanf((const char *)byDebugBuff, "set app1 %d",&dwTmpPara[0]);
					printf("\r\n%d\r\n",dwTmpPara[0]);
					
			}
			else if(strcmp("help", (const char *)byDebugBuff) == 0)
			{
				printf("%s",pDebugText[DEBUG_TEXT_HELP]);
			}
			else
			{
				printf("%s",pDebugText[DEBUG_TEXT_CMD_UNKNOWN]);
			}
			
			byCurrentDebugCursor = 0;
			printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
		}
		else
		{
#ifdef RX_SHOW
			HAL_UART_Transmit(&huart1,&byTmpData,1,0xff);	
#endif
			byDebugBuff[byCurrentDebugCursor] = byTmpData;
			byCurrentDebugCursor++;
			
			if(byCurrentDebugCursor >= DEBUG_BUFF_SIZE)
			{
				byCurrentDebugCursor = 0;
				printf("%s", pDebugText[DEBUG_TEXT_CMD_TOO_LONG]);
				printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
			}
		}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  UNUSED(huart);

  debug_analyze();
	
	HAL_UART_Receive_IT(&huart1,&byTmpData,1);
}

/*添加了GNU extensions后会默认定义__GNUC__,使得printf不正确,所以这里去掉该定义*/
#undef __GNUC__
#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
	
PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
 
  return ch;
}

sys.h

#ifndef __SYS_H__
#define __SYS_H__

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "timer.h"

typedef void (*VOID_FUNC)(void);	

typedef struct RA
{
	VOID_FUNC func;
	
	uint32_t tickstart;//起始时间
	uint32_t wait_HZ;//等待时间
	uint32_t cycle_index;//循环次数
	
}RA_st;

typedef struct IC
{
	VOID_FUNC func;
	uint32_t cycle_index;//循环次数
}IC_st;

typedef struct IC_Tab
{
	IC_st **IC_table;
	uint8_t tabsize;
	uint8_t counter;//注册个数计数
}IC_Tab_st;

extern HAL_TickFreqTypeDef uwTickFreq;

int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_HZ,uint8_t index,uint32_t cycle_index);
int8_t Run_Aftertimer_release(uint8_t index);
void RA_Task(void);

int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index);
int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index);
int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize);
int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab);
void IC_Task(IC_Tab_st *IC_Tab);

#endif

sys.c

#include "sys.h"
#include <stdlib.h>
#include "debug.h"
#include "timer.h"
#include "string.h"

/*******************************Run_Aftertimer*********************************/
#define RA_MAX_DELAY HAL_MAX_DELAY

#define RA_TABLE_SIZE	5
RA_st *RA_table[RA_TABLE_SIZE]={NULL};

int8_t Run_Aftertimer_register(RA_st *ra,uint8_t index)
{
	/*index为0时自动分配index*/
	if(index==0)
	{
		debug("自动分配RA\r\n");
		for(int i=1;i<RA_TABLE_SIZE;i++)
		{
			if(RA_table[i]==NULL)
			{
				index=i;
			}
			if(i>=RA_TABLE_SIZE)
			{
				if(ra!=NULL)
				{
					free(ra);
					ra=NULL;
				}
				debug("RA自动分配失败,无可用\r\n");
				return -1;
			}
		}
	}
	
	if(RA_table[index]!=NULL)
	{
		if(ra!=NULL)
		{
			free(ra);
			ra=NULL;
		}
		debug("RA reg该位置已被占用\r\n");
		return -1;
	}
	
	RA_table[index]=ra;
	RA_table[index]->tickstart = jiffies;
	
	/* Add a freq to guarantee minimum wait */
	if (RA_table[index]->wait_HZ < RA_MAX_DELAY)
  {
    RA_table[index]->wait_HZ += 1;
  }
	else
	{
		debug("RA延时时间过长\r\n");
		return -1;
	}
	
	return index;
}

int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_HZ,uint8_t index,uint32_t cycle_index)
{
	uint8_t need_heap_size=0;
	
	if(RA_table[index]!=NULL)
	{
		debug("RA该位置已被占用 %d\r\n",index);
		return -1;
	}
	need_heap_size=sizeof(RA_st);
	RA_st *ra=malloc(need_heap_size);
	if(ra==NULL)
	{
		debug("RA分配内存失败\r\n");
		return -1;
	}
	memset((uint8_t *)ra,0,need_heap_size);
	ra->func=func;
	ra->wait_HZ=wait_HZ;
	ra->cycle_index=cycle_index;
	return Run_Aftertimer_register(ra,index);
}

int8_t Run_Aftertimer_release(uint8_t index)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
	if(RA_table[index]==NULL)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		debug("释放的RA为NULL\r\n");
		return -1;
	}
	/*释放内存*/
	if(RA_table[index]!=NULL)
	{
		free(RA_table[index]);
		RA_table[index]=NULL;
	}
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

void RA_Task()
{
	for(int i=1;i<RA_TABLE_SIZE;i++)
	{
		if(RA_table[i]==NULL)
			continue;
		
		if (time_after_eq(jiffies, (RA_table[i]->tickstart+RA_table[i]->wait_HZ))) 
		{
			RA_table[i]->func();
			
			if(RA_table[i]->cycle_index==1)
			{
				/*释放内存*/
				
				if(RA_table[i]!=NULL)
				{
					free(RA_table[i]);
					RA_table[i]=NULL;
				}
				continue;
			}
			
			RA_table[i]->tickstart = jiffies;
			if(RA_table[i]->cycle_index!=0)
			{
				RA_table[i]->cycle_index--;
			}
		}
		
	}
}

/*******************************中断任务*********************************/
int8_t Interrupt_Callback_register(IC_Tab_st *IC_Tab,IC_st *ic,uint8_t index)
{
/*错误判断*/
	/*index为0时自动分配index*/
	if(index==0)
	{
		debug("自动分配IC\r\n");
		for(int i=1;i<IC_Tab->tabsize;i++)
		{
			if(IC_Tab->IC_table[i]==NULL)
			{
				index=i;
			}
			if(i>=IC_Tab->tabsize)
			{
				if(ic!=NULL)
				{
					free(ic);
					ic=NULL;
				}
				debug("IC自动分配失败,无可用\r\n");
				return -1;
			}
		}
	}
	/*该位置已被使用*/
	if(IC_Tab->IC_table[index]!=NULL)
	{
		if(ic!=NULL)
		{
			free(ic);
			ic=NULL;
		}
		debug("IC reg该位置已被占用\r\n");
		return -1;
	}
/*正文*/	
	IC_Tab->counter++;
	IC_Tab->IC_table[index]=ic;
	
	return index;
}

int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index)
{
	uint8_t need_heap_size=0;
	
/*错误判断*/
	/*Tab未创建*/
	if(IC_Tab->IC_table==NULL)
	{
		debug("IC TAB未创建\r\n");
		return -1;
	}
	/*该位置已被使用*/
	if(IC_Tab->IC_table[index]!=NULL)
	{
		debug("IC该位置已被占用 %d\r\n",index);
		return -1;
	}
/*正文*/
	need_heap_size=sizeof(IC_st);
	IC_st *ic=malloc(need_heap_size);
	if(ic==NULL)
	{
		debug("IC分配内存失败\r\n");
		return -1;
	}
	memset((uint8_t *)ic,0,need_heap_size);
	ic->func=func;
	ic->cycle_index=cycle_index;
	
	return Interrupt_Callback_register(IC_Tab,ic,index);
}

int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
/*错误判断*/
	/*该位置为NULL不用释放*/
	if(IC_Tab->IC_table[index]==NULL)
	{
		debug("释放的IC为NULL\r\n");
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
	/*index为0(不支持一次释放全部)*/
	if(index==0)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		debug("index为0,不支持一次释放全部\r\n");
		return -1;
	}
/*正文*/
	/*释放内存*/
	IC_Tab->counter--;
	if(IC_Tab->IC_table[index]!=NULL)
	{
		free(IC_Tab->IC_table[index]);
		IC_Tab->IC_table[index]=NULL;
	}
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize)
{
	uint8_t need_heap_size=0;
	
/*错误判断*/
	/*Tab已经创建*/
	if(IC_Tab->IC_table!=NULL)
	{
		debug("IC TAB已经创建\r\n");
		return -1;
	}
	/*tabsize不满足要求*/
	if(tabsize==0)
	{
		debug("tabsize不满足要求\r\n");
		return -1;
	}
/*正文*/	
	tabsize+=1;
	IC_Tab->tabsize=tabsize;
	need_heap_size=tabsize*sizeof(IC_st *);
	IC_Tab->IC_table=malloc(need_heap_size);
	if(IC_Tab->IC_table==NULL)
	{
		debug("IC TAB分配内存失败\r\n");
		return -1;
	}
	memset((uint8_t *)IC_Tab->IC_table,0,need_heap_size);
	
	return tabsize;
}

int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
/*错误判断*/
	/*未创建Tab或重复释放*/
	if(IC_Tab->IC_table==NULL)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		debug("释放的IC TAB为NULL\r\n");
		return -1;
	}
	/*Tab中还有未释放的项目*/
	if(IC_Tab->counter!=0)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		debug("IC TAB中还有未释放的项目\r\n");
		return -1;
	}
/*正文*/	
	/*释放内存*/
	if(IC_Tab->IC_table!=NULL)
	{
		free(IC_Tab->IC_table);
		IC_Tab->IC_table=NULL;
	}
	IC_Tab->tabsize=0;
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

void IC_Task(IC_Tab_st *IC_Tab)
{
	for(int i=1;i<IC_Tab->tabsize;i++)
	{
		if(IC_Tab->IC_table[i]==NULL)
			continue;

		IC_Tab->IC_table[i]->func();
		
		if(IC_Tab->IC_table[i]->cycle_index==1)
		{
			/*释放内存*/
			if(IC_Tab->IC_table[i]!=NULL)
			{
				free(IC_Tab->IC_table[i]);
				IC_Tab->IC_table[i]=NULL;
			}
			continue;
		}
		
		if(IC_Tab->IC_table[i]->cycle_index!=0)
		{
			IC_Tab->IC_table[i]->cycle_index--;
		}
	}
}

app.h

#ifndef __APP_H__
#define __APP_H__

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "sys.h"

#define READ	0
#define WRITE	1

typedef enum Status
{
	Init_StepMotor,
	Init_PushMotor,
	Creat_LED_RA,
	Start_StepMotor,
	Start_PushMotor__,
	Start_PushMotor_,
	Init_Monitor_Proximity,
	Monitor_Proximitying,
	Status_Delay,
	Start_Delay_Long,
	Delaying_Long,
	Start_Delay_Short,
	Delaying_Short,
	Status_Stop,
}Status_en;

extern IC_Tab_st Proximity1_IC_Tab;
extern IC_Tab_st Proximity2_IC_Tab;

int8_t Get_Mod(void);
void App1_Func(void);
void App2_Func(void);
void App3_Func(void);
void LED_Toggel(int led);
int8_t Flag_App_Start(uint8_t rw,int8_t parameter);

#endif

app.c

#include "app.h"
#include "StepMotor.h"
#include "PushMotor.h"
#include "iwdg.h"

const struct env_t
{
	uint32_t crc32;
	uint32_t app1_long_time;
	uint32_t app1_short_time;
	uint32_t app2_long_time;
	uint32_t app2_short_time;
	uint32_t app3_long_time;
	uint32_t app3_short_time;
}env __attribute__((at(0x0800fc00)));

volatile Status_en status=Status_Stop;

IC_Tab_st Proximity1_IC_Tab={NULL};
IC_Tab_st Proximity2_IC_Tab={NULL};

int8_t Get_Mod()
{
	static uint8_t counter=1;
	static int8_t mod=1;
	uint8_t f1=0,f2=0;
	
	if(counter==0)
	{
		return mod;
	}
	counter--;
	
	if(HAL_GPIO_ReadPin(Knob3_2_GPIO_Port,Knob3_2_Pin)==GPIO_PIN_RESET)
	{
		f1=1;
	}
	if(HAL_GPIO_ReadPin(Knob3_3_GPIO_Port,Knob3_3_Pin)==GPIO_PIN_RESET)
	{
		f2=1;
	}
	
	if((f1==1)&&(f2==0))
	{
		mod=1;
	}
	else if((f1==0)&&(f2==0))
	{
		mod=2;
	}
	else if((f1==0)&&(f2==1))
	{
		mod=3;
	}
	else{return -1;}
	
	return mod;
}

void App1_Proximity1_callback1()
{
	if(status!=Monitor_Proximitying)
		return;
	printf("App1_Proximity1_callback1\r\n");
	StepMotor_Control(0,0,1);
	PushMotor_Control(4,0,1);
	status=Start_Delay_Short;
}

void App1_Proximity2_callback1()
{
	if(status!=Monitor_Proximitying)
		return;
	printf("App1_Proximity2_callback1\r\n");
	StepMotor_Control(0,0,1);
	PushMotor_Control(-4,0,1);
	status=Start_Delay_Long;
}

void LED_Toggel(int led)
{
	if(led<0)
	{
		HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
		HAL_GPIO_TogglePin(LED_RED_GPIO_Port,LED_RED_Pin);
	}
	else
	{
		HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
		HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);
	}
}

void LED_Toggel_RA_func()
{

		HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
		HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);
}

void App1_Func()
{
	uint32_t start_time;
	int8_t ret;
	static uint8_t dir=2;
	uint32_t num=0;
	
	ret=Interrupt_Callback_Tab_creat(&Proximity1_IC_Tab,2);if(ret<0){goto ERR;}
	ret=Interrupt_Callback_Tab_creat(&Proximity2_IC_Tab,2);if(ret<0){goto ERR;}
	
	while(1)
	{
		if(Flag_App_Start(READ,0))
		{
			switch(status)
			{
				case Status_Stop:
					status=Init_StepMotor;
					break;
				case Init_StepMotor:
					printf("Init_StepMotor\r\n");
					StepMotor_Control(0,0,1);
					status=Init_Monitor_Proximity;
					break;
				case Init_Monitor_Proximity:
					printf("Init_Monitor_Proximity\r\n");
					ret=Interrupt_Callback_creat(&Proximity1_IC_Tab,App1_Proximity1_callback1,1,0);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_creat(&Proximity2_IC_Tab,App1_Proximity2_callback1,1,0);if(ret<0){goto ERR;}
					status=Creat_LED_RA;
					break;
				case Creat_LED_RA:
					ret=Run_Aftertimer_creat(LED_Toggel_RA_func,0.1*HZ,4,0);if(ret<0){goto ERR;}
					status=Start_StepMotor;
					break;
				case Start_StepMotor:
					printf("Start_StepMotor");
					StepMotor_Control(150,0,0);
					status=Monitor_Proximitying;
					break;
				case Monitor_Proximitying:
					break;
				case Start_Delay_Long:
					printf("Start_Delay_Long");
					start_time=HAL_GetTick();
					status=Delaying_Long;
					break;
				case Delaying_Long:
					if(HAL_GetTick()-start_time>18000)
					{
						status=Start_StepMotor;
					}
					break;
				case Start_Delay_Short:
					printf("Start_Delay_Short");
					start_time=HAL_GetTick();
					status=Delaying_Short;
					break;
				case Delaying_Short:
					if(HAL_GetTick()-start_time>1000)
					{
						status=Start_StepMotor;
					}
					break;
				default:
					break;
			}
		}
		else
		{
			HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
			HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_RESET);
			switch(status)
			{
				case Status_Stop:
					break;
				default:
					status=Status_Stop;
					StepMotor_Control(0,0,1);
					PushMotor_Control(0,0,1);
					ret=Run_Aftertimer_release(4);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_release(&Proximity1_IC_Tab,1);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_release(&Proximity2_IC_Tab,1);if(ret<0){goto ERR;}
					break;
			}
		}
		//HAL_IWDG_Refresh(&hiwdg);
	}
	ret=Interrupt_Callback_Tab_release(&Proximity1_IC_Tab);if(ret<0){goto ERR;}
	ret=Interrupt_Callback_Tab_release(&Proximity2_IC_Tab);if(ret<0){goto ERR;}
	
	ERR:
	printf("err\r\n");
	while(1)
	{
		HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_RESET);
		//HAL_IWDG_Refresh(&hiwdg);
		HAL_Delay(50);
	}
}

void App2_Func()
{
	App1_Func();
	while(1)
	{
		
	}
}

void App3_Proximity2_callback1()
{
	if(status!=Monitor_Proximitying)
		return;
	printf("App3_Proximity2_callback1\r\n");
	PushMotor2_Control(0,0,1);
	PushMotor_Control(4,0,1);
	status=Start_Delay_Short;
}

void App3_Proximity1_callback1()
{
	if(status!=Monitor_Proximitying)
		return;
	printf("App3_Proximity1_callback1\r\n");
	PushMotor2_Control(0,0,1);
	PushMotor_Control(-4,0,1);
	status=Start_Delay_Long;
}

void App3_Func()
{
	uint32_t start_time;
	int8_t ret;
	static uint8_t dir=2;
	uint32_t num=0;
	
	ret=Interrupt_Callback_Tab_creat(&Proximity1_IC_Tab,2);if(ret<0){goto ERR;}
	ret=Interrupt_Callback_Tab_creat(&Proximity2_IC_Tab,2);if(ret<0){goto ERR;}
	
	while(1)
	{
		if(Flag_App_Start(READ,0))
		{
			switch(status)
			{
				case Status_Stop:
					status=Init_PushMotor;
					break;
				case Init_PushMotor:
					printf("Init_PushMotor\r\n");
					PushMotor2_Control(0,0,1);
					status=Init_Monitor_Proximity;
					break;
				case Init_Monitor_Proximity:
					printf("Init_Monitor_Proximity\r\n");
					ret=Interrupt_Callback_creat(&Proximity1_IC_Tab,App3_Proximity1_callback1,1,0);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_creat(&Proximity2_IC_Tab,App3_Proximity2_callback1,1,0);if(ret<0){goto ERR;}
					status=Creat_LED_RA;
					break;
				case Creat_LED_RA:
					ret=Run_Aftertimer_creat(LED_Toggel_RA_func,0.1*HZ,4,0);if(ret<0){goto ERR;}
					if(HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin)==GPIO_PIN_RESET)
						status=Start_PushMotor__;
					else
						status=Start_PushMotor_;
					break;
				case Start_PushMotor__:
					printf("Start_PushMotor__");
					PushMotor2_Control(-4,105000,0);
					status=Monitor_Proximitying;
					break;
				case Start_PushMotor_:
					printf("Start_PushMotor_");
					PushMotor2_Control(4,0,0);
					status=Monitor_Proximitying;
					break;
				case Monitor_Proximitying:
					break;
				case Start_Delay_Long:
					printf("Start_Delay_Long");
					start_time=HAL_GetTick();
					status=Delaying_Long;
					break;
				case Delaying_Long:
					if(HAL_GetTick()-start_time>5000)
					{
						status=Start_PushMotor__;
					}
					break;
				case Start_Delay_Short:
					printf("Start_Delay_Short");
					start_time=HAL_GetTick();
					status=Delaying_Short;
					break;
				case Delaying_Short:
					if(HAL_GetTick()-start_time>2000)
					{
						status=Start_PushMotor_;
					}
					break;
				default:
					break;
			}
		}
		else
		{
			HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
			HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_RESET);
			switch(status)
			{
				case Status_Stop:
					break;
				default:
					status=Status_Stop;
					PushMotor2_Control(0,0,1);
					PushMotor_Control(0,0,1);
					ret=Run_Aftertimer_release(4);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_release(&Proximity1_IC_Tab,1);if(ret<0){goto ERR;}
					ret=Interrupt_Callback_release(&Proximity2_IC_Tab,1);if(ret<0){goto ERR;}
					break;
			}
		}
		//HAL_IWDG_Refresh(&hiwdg);
	}
	ret=Interrupt_Callback_Tab_release(&Proximity1_IC_Tab);if(ret<0){goto ERR;}
	ret=Interrupt_Callback_Tab_release(&Proximity2_IC_Tab);if(ret<0){goto ERR;}
	
	ERR:
	printf("err\r\n");
	while(1)
	{
		HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
		HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_RESET);
		//HAL_IWDG_Refresh(&hiwdg);
		HAL_Delay(50);
	}
}

int8_t Flag_App_Start(uint8_t rw,int8_t parameter)
{
	static uint8_t flag=0;
	
	switch(rw)
	{
		case READ:
			break;
		case WRITE:
			flag=parameter;
			break;
		default:
			return -1;
	}
	return flag;
}

gpio.h

gpio.c

/**
  ******************************************************************************
  * File Name          : gpio.c
  * Description        : This file provides code for the configuration
  *                      of all used GPIO pins.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
#include "sys.h"
#include "app.h"
/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure GPIO                                                             */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, PushMotorIN1_Pin|PushMotorIN2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, StepMotorDir_Pin|StepMotorEna_Pin|PushMotor2IN1_Pin|PushMotor2IN2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_RED_Pin|LED_GREEN_Pin, GPIO_PIN_SET);

  /*Configure GPIO pins : PAPin PAPin */
  GPIO_InitStruct.Pin = PushMotorIN1_Pin|PushMotorIN2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PAPin PAPin PAPin */
  GPIO_InitStruct.Pin = Knob3_1_Pin|Knob3_2_Pin|Knob3_3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin PBPin PBPin */
  GPIO_InitStruct.Pin = StepMotorDir_Pin|StepMotorEna_Pin|PushMotor2IN1_Pin|PushMotor2IN2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin */
  GPIO_InitStruct.Pin = LED_RED_Pin|LED_GREEN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin PBPin */
  GPIO_InitStruct.Pin = Proximity1_Pin|proximity2_Pin|Switch_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

}

/* USER CODE BEGIN 2 */
void Proximity1_RA_func()
{
	static GPIO_PinState status=GPIO_PIN_SET;
	
	if(HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin)==status)
	{
		EXTI->IMR|=(0x01<<5);
		return;
	}
	
	status=HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin);
	if(status==GPIO_PIN_RESET)
	{
		printf("Proximity1 reset\r\n");
		IC_Task(&Proximity1_IC_Tab);
	}
	else
	{
		printf("Proximity1 set\r\n");
	}
	EXTI->IMR|=(0x01<<5);
}

void Proximity2_RA_func()
{
	static GPIO_PinState status=GPIO_PIN_SET;
	
	if(HAL_GPIO_ReadPin(proximity2_GPIO_Port,proximity2_Pin)==status)
	{
		EXTI->IMR|=(0x01<<6);
		return;
	}
	
	status=HAL_GPIO_ReadPin(proximity2_GPIO_Port,proximity2_Pin);
	if(status==GPIO_PIN_RESET)
	{
		printf("Proximity2 reset\r\n");
		IC_Task(&Proximity2_IC_Tab);
	}
	else
	{
		printf("Proximity2 set\r\n");
	}
	EXTI->IMR|=(0x01<<6);
}

void Switch_RA_func()
{
	static GPIO_PinState status=GPIO_PIN_SET;
	
	if(HAL_GPIO_ReadPin(Switch_GPIO_Port,Switch_Pin)==status)
	{
		EXTI->IMR|=(0x01<<7);
		return;
	}
	
	status=HAL_GPIO_ReadPin(Switch_GPIO_Port,Switch_Pin);
	if(status==GPIO_PIN_RESET)
	{
		Flag_App_Start(WRITE,1);
		printf("Switch reset\r\n");
	}
	else
	{
		Flag_App_Start(WRITE,0);
		printf("Switch set\r\n");
	}
	EXTI->IMR|=(0x01<<7);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == Proximity1_Pin)
  {
		EXTI->IMR&=(~(0x01<<5));
    int8_t ret=Run_Aftertimer_creat(Proximity1_RA_func,0.002*HZ,1,1);
  }
	else if(GPIO_Pin == proximity2_Pin)
	{
		EXTI->IMR&=(~(0x01<<6));
		int8_t ret=Run_Aftertimer_creat(Proximity2_RA_func,0.002*HZ,2,1);
	}
	else if(GPIO_Pin == Switch_Pin)
	{
		EXTI->IMR&=(~(0x01<<7));
		int8_t ret=Run_Aftertimer_creat(Switch_RA_func,0.1*HZ,3,1);
	}
	else
	{
		printf("err\r\n");
	}
}
/* USER CODE END 2 */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

tim.h

/**
  ******************************************************************************
  * File Name          : TIM.h
  * Description        : This file provides code for the configuration
  *                      of the TIM instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __tim_H
#define __tim_H
#ifdef __cplusplus
 extern "C" {
#endif

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

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

extern void _Error_Handler(char *, int);

void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
void MX_TIM3_Init(void);
void MX_TIM4_Init(void);
                    
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
                                                

/* USER CODE BEGIN Prototypes */

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ tim_H */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

tim.c

/**
  ******************************************************************************
  * File Name          : TIM.c
  * Description        : This file provides code for the configuration
  *                      of the TIM instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

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

/* USER CODE BEGIN 0 */
#include "StepMotor.h"
#include "PushMotor.h"
/* USER CODE END 0 */

TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;

/* TIM1 init function */
void MX_TIM1_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 720-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = PUSHMOTORPER_10US;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = PushMotor2_10us;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim1);

}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 720-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = PUSHMOTORPER_10US;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = PushMotor_10us;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim2);

}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 720-1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = StepMotor_10us;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = StepMotor_10us/2;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim3);

}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 0;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
  sSlaveConfig.InputTrigger = TIM_TS_ITR2;
  if (HAL_TIM_SlaveConfigSynchronization(&htim4, &sSlaveConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{

  if(tim_pwmHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */

  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();

    /* TIM1 interrupt Init */
    HAL_NVIC_SetPriority(TIM1_UP_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
  /* USER CODE BEGIN TIM1_MspInit 1 */

  /* USER CODE END TIM1_MspInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspInit 0 */

  /* USER CODE END TIM2_MspInit 0 */
    /* TIM2 clock enable */
    __HAL_RCC_TIM2_CLK_ENABLE();

    /* TIM2 interrupt Init */
    HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  /* USER CODE BEGIN TIM2_MspInit 1 */

  /* USER CODE END TIM2_MspInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspInit 0 */

  /* USER CODE END TIM3_MspInit 0 */
    /* TIM3 clock enable */
    __HAL_RCC_TIM3_CLK_ENABLE();
  /* USER CODE BEGIN TIM3_MspInit 1 */

  /* USER CODE END TIM3_MspInit 1 */
  }
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM4)
  {
  /* USER CODE BEGIN TIM4_MspInit 0 */

  /* USER CODE END TIM4_MspInit 0 */
    /* TIM4 clock enable */
    __HAL_RCC_TIM4_CLK_ENABLE();

    /* TIM4 interrupt Init */
    HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM4_IRQn);
  /* USER CODE BEGIN TIM4_MspInit 1 */

  /* USER CODE END TIM4_MspInit 1 */
  }
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(timHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspPostInit 0 */

  /* USER CODE END TIM1_MspPostInit 0 */
    /**TIM1 GPIO Configuration    
    PA8     ------> TIM1_CH1 
    */
    GPIO_InitStruct.Pin = PushMotor2PWM_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(PushMotor2PWM_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM1_MspPostInit 1 */

  /* USER CODE END TIM1_MspPostInit 1 */
  }
  else if(timHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspPostInit 0 */

  /* USER CODE END TIM2_MspPostInit 0 */
  
    /**TIM2 GPIO Configuration    
    PA0-WKUP     ------> TIM2_CH1 
    */
    GPIO_InitStruct.Pin = PushMotorPWM_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(PushMotorPWM_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM2_MspPostInit 1 */

  /* USER CODE END TIM2_MspPostInit 1 */
  }
  else if(timHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspPostInit 0 */

  /* USER CODE END TIM3_MspPostInit 0 */
  
    /**TIM3 GPIO Configuration    
    PB0     ------> TIM3_CH3 
    */
    GPIO_InitStruct.Pin = StepMotorPul_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(StepMotorPul_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM3_MspPostInit 1 */

  /* USER CODE END TIM3_MspPostInit 1 */
  }

}

void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{

  if(tim_pwmHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspDeInit 0 */

  /* USER CODE END TIM1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM1_CLK_DISABLE();

    /* TIM1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM1_UP_IRQn);
  /* USER CODE BEGIN TIM1_MspDeInit 1 */

  /* USER CODE END TIM1_MspDeInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM2)
  {
  /* USER CODE BEGIN TIM2_MspDeInit 0 */

  /* USER CODE END TIM2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM2_CLK_DISABLE();

    /* TIM2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM2_IRQn);
  /* USER CODE BEGIN TIM2_MspDeInit 1 */

  /* USER CODE END TIM2_MspDeInit 1 */
  }
  else if(tim_pwmHandle->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspDeInit 0 */

  /* USER CODE END TIM3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM3_CLK_DISABLE();
  /* USER CODE BEGIN TIM3_MspDeInit 1 */

  /* USER CODE END TIM3_MspDeInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{

  if(tim_baseHandle->Instance==TIM4)
  {
  /* USER CODE BEGIN TIM4_MspDeInit 0 */

  /* USER CODE END TIM4_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM4_CLK_DISABLE();

    /* TIM4 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM4_IRQn);
  /* USER CODE BEGIN TIM4_MspDeInit 1 */

  /* USER CODE END TIM4_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == htim4.Instance)
	{
		StepMotor_irq_cb();
	}
	else if (htim->Instance == htim2.Instance)
	{
		PushMotor1_irq_cb();
	}
	else if (htim->Instance == htim1.Instance)
	{
		PushMotor2_irq_cb();
	}
}
/* USER CODE END 1 */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

stm32f1xx_it.c

/**
  ******************************************************************************
  * @file    stm32f1xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "stm32f1xx.h"
#include "stm32f1xx_it.h"

/* USER CODE BEGIN 0 */
#include "sys.h"
#include "timer.h"
/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim4;
extern UART_HandleTypeDef huart1;

/******************************************************************************/
/*            Cortex-M3 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */
	printf("hard fault\r\n");
  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
  /* USER CODE BEGIN HardFault_IRQn 1 */

  /* USER CODE END HardFault_IRQn 1 */
}

/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
  /* USER CODE BEGIN MemoryManagement_IRQn 1 */

  /* USER CODE END MemoryManagement_IRQn 1 */
}

/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
  /* USER CODE BEGIN BusFault_IRQn 1 */

  /* USER CODE END BusFault_IRQn 1 */
}

/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
  /* USER CODE BEGIN UsageFault_IRQn 1 */

  /* USER CODE END UsageFault_IRQn 1 */
}

/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
  /* USER CODE BEGIN SysTick_IRQn 1 */
	static uint8_t ctr=0;
	if(ctr<(1000/HZ))
	{
		ctr++;
	}
	if(ctr>=(1000/HZ))
	{
		ctr=0;
		jiffies_64+=1;
		RA_Task();
#ifdef USE_KERNEL_TIMER
		timer_update(&timer_base);
#endif
	}
  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
* @brief This function handles EXTI line[9:5] interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */

  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

/**
* @brief This function handles TIM1 update interrupt.
*/
void TIM1_UP_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_IRQn 0 */

  /* USER CODE END TIM1_UP_IRQn 0 */
  HAL_TIM_IRQHandler(&htim1);
  /* USER CODE BEGIN TIM1_UP_IRQn 1 */

  /* USER CODE END TIM1_UP_IRQn 1 */
}

/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

/**
* @brief This function handles TIM4 global interrupt.
*/
void TIM4_IRQHandler(void)
{
  /* USER CODE BEGIN TIM4_IRQn 0 */

  /* USER CODE END TIM4_IRQn 0 */
  HAL_TIM_IRQHandler(&htim4);
  /* USER CODE BEGIN TIM4_IRQn 1 */

  /* USER CODE END TIM4_IRQn 1 */
}

/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

timer.h

#ifndef _LINUX_TIMER_H
#define _LINUX_TIMER_H

#include "list.h"
#include "typecheck.h"

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"

//#define USE_KERNEL_TIMER

#define HZ	1000

#define time_after(a,b)		\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(b) - (long)(a) < 0))
#define time_before(a,b)	time_after(b,a)

#define time_after_eq(a,b)	\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b)	time_after_eq(b,a)

#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)

#define CONFIG_BASE_SMALL 0
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)

struct timer_list {
	struct list_head entry;//用于把一组定时器组成一个链表
	unsigned long expires;//指出了该定时器的到期时刻,也就是期望定时器到期时刻的jiffies计数值
	struct tvec_base *base;//每个cpu拥有一个自己的用于管理定时器的tvec_base结构,该字段指向该定时器所属的cpu所对应tvec_base结构
	void (*function)(unsigned long);//指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数
	unsigned long data;//data域则被内核用作function函数的调用参数
};

struct tvec {
	struct list_head vec[TVN_SIZE];
};

struct tvec_root {
	struct list_head vec[TVR_SIZE];
};

struct tvec_base {
	//spinlock_t lock;
	struct timer_list *running_timer;//指向当前cpu正在处理的定时器所对应的timer_list结构
	unsigned long timer_jiffies;//表示当前cpu定时器所经历过的jiffies数,大多数情况下,该值和jiffies计数值相等,当cpu的idle状态连续持续了多个jiffies时间时,当退出idle状态时,jiffies计数值就会大于该字段,在接下来的tick中断后,定时器系统会让该字段的值追赶上jiffies值
	unsigned long next_timer;//指向该cpu下一个即将到期的定时器
	struct tvec_root tv1;
	struct tvec tv2;
	struct tvec tv3;
	struct tvec tv4;
	struct tvec tv5;
};
	 
#define TIMER_INITIALIZER(_function, _expires, _data) {.entry = { .prev = NULL },.function = _function,.expires = _expires,.data = _data,.base = &timer_base}
#define DEFINE_TIMER(_name, _function, _expires, _data) struct timer_list _name = TIMER_INITIALIZER(_function, _expires, _data)

static inline void set_running_timer(struct tvec_base *base,
					struct timer_list *timer)
{
	base->running_timer = timer;
}

static inline void detach_timer(struct timer_list *timer,
				int clear_pending)
{
	struct list_head *entry = &timer->entry;

	//debug_deactivate(timer);

	__list_del(entry->prev, entry->next);
	if (clear_pending)
		entry->next = NULL;
	entry->prev = LIST_POISON2;
}

#define jiffies		*pjiffies
extern unsigned long jiffies;
extern uint64_t jiffies_64;
extern uint32_t sys_start_rtc_time;

extern struct tvec_base timer_base;

void init_timers(void);
void timer_update(struct tvec_base *base);

#define init_timer(timer)\
	init_timer_key((timer), NULL)
void init_timer_key(struct timer_list *timer,
		    const char *name);
int mod_timer(struct timer_list *timer, unsigned long expires);
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list * timer);

static inline void setup_timer_key(struct timer_list * timer,
				const char *name,
				void (*function)(unsigned long),
				unsigned long data)
{
	timer->function = function;
	timer->data = data;
	init_timer_key(timer, name);
}
#define setup_timer(timer, fn, data)\
	setup_timer_key((timer), NULL, (fn), (data))

#endif

timer.c

/*默认情况下,没有使能CONFIG_BASE_SMALL,TVR_SIZE的大小是256,TVN_SIZE的大小则是64,当需要节省内存空间时,也可以使能CONFIG_BASE_SMALL,这时TVR_SIZE的大小是64,TVN_SIZE的大小则是16,以下的讨论我都是基于没有使能CONFIG_BASE_SMALL的情况。当有一个新的定时器要加入时,系统根据定时器到期的jiffies值和timer_jiffies字段的差值来决定该定时器被放入tv1至tv5中的哪一个数组中*/
#include "timer.h"
//#define USE_RTC
#ifdef USE_RTC
#include "rtc.h"
#endif

#ifndef __ARMEB__
unsigned long *pjiffies=((unsigned long *)(&jiffies_64));
#else
unsigned long *pjiffies=((unsigned long *)(&jiffies_64))+4;
#endif

uint64_t jiffies_64=0;
struct tvec_base timer_base;

#ifdef USE_RTC
uint32_t sys_start_rtc_time;
static struct timer_list rtc_timer;

/**
  * @brief  Read the time counter available in RTC_CNT registers.
  * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
  *                the configuration information for RTC.
  * @retval Time counter
  */
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
{
  uint16_t high1 = 0U, high2 = 0U, low = 0U;
  uint32_t timecounter = 0U;

  high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
  low   = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
  high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);

  if (high1 != high2)
  { /* In this case the counter roll over during reading of CNTL and CNTH registers, 
       read again CNTL register then return the counter value */
    timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
  }
  else
  { /* No counter roll over during reading of CNTL and CNTH registers, counter 
       value is equal to first value of CNTL and CNTH */
    timecounter = (((uint32_t) high1 << 16U) | low);
  }

  return timecounter;
}
#endif

void init_timers()
{
#ifdef USE_RTC
	//读取RTC
	sys_start_rtc_time=RTC_ReadTimeCounter(&hrtc);
#endif

#ifdef USE_KERNEL_TIMER
	for(int i=0;i<TVR_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv1.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv2.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv3.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv4.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv5.vec[i]));
	}
#endif
}

static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
			  unsigned long data)
{
	fn(data);
}

//确定要插入的链表数组以及数组的哪一项链表中
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
	unsigned long expires = timer->expires;
	unsigned long idx = expires - base->timer_jiffies;//也即timer->expires-base->timer_jiffies,差值范围可以大致判断属于哪一个分组
	struct list_head *vec;

	if (idx < TVR_SIZE) {																													//tv1
		int i = expires & TVR_MASK;
		vec = base->tv1.vec + i;
	} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {																//tv2
		int i = (expires >> TVR_BITS) & TVN_MASK;
		vec = base->tv2.vec + i;
	} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {														//tv3
		int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
		vec = base->tv3.vec + i;
	} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {														//tv4
		int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
		vec = base->tv4.vec + i;
	} else if ((signed long) idx < 0) {//异常处理,随机取了一个0~255之间的数值
		/*
		 * Can happen if you add a timer with expires == jiffies,
		 * or you set a timer to go off in the past
		 */
		vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
	} else {
		int i;
		/* If the timeout is larger than 0xffffffff on 64-bit
		 * architectures then we use the maximum timeout:
		 */
		if (idx > 0xffffffffUL) {
			idx = 0xffffffffUL;
			expires = idx + base->timer_jiffies;
		}
		i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
		vec = base->tv5.vec + i;																											//tv5
	}
	/*
	 * Timers are FIFO:
	 */
	list_add_tail(&timer->entry, vec);//相同vec的timer采取FIFO策略
}

//定时器的到期时的迁移代码
//参数index为事先计算好的高一级tv的需要迁移的数组索引
static int cascade(struct tvec_base *base, struct tvec *tv, int index)
{
	/* cascade all the timers from tv up one level */
	struct timer_list *timer, *tmp;
	struct list_head tv_list;

	list_replace_init(tv->vec + index, &tv_list);//用tv_list替换tv->vec+index表头,将tv->vec+index重新初始化,即为空,链表不会有timer存在。

	/*
	 * We are removing _all_ timers from the list, so we
	 * don't have to detach them individually.
	 */
	list_for_each_entry_safe(timer, tmp, &tv_list, entry) {//遍历刚取出的tv_list里的timer
		//BUG_ON(tbase_get_base(timer->base) != base);
		internal_add_timer(base, timer);//重新加入到定时器系统中,实际上将会迁移到下一级的tv数组中
	}

	return index;
}

static inline void __run_timers(struct tvec_base *base)
{
	struct timer_list *timer;

	//spin_lock_irq(&base->lock);
	while (time_after_eq(jiffies, base->timer_jiffies)) {//同步jiffies,在NO_HZ情况下,base->timer_jiffies可能落后不止一个tick
		struct list_head work_list;
		struct list_head *head = &work_list;
		int index = base->timer_jiffies & TVR_MASK;//计算到期定时器链表在tv1中的索引

		/*
		 * Cascade timers:
		 */
		if (!index &&																				//index为0时,表示有进位到tv2
			(!cascade(base, &(base->tv2), INDEX(0))) &&					//返回为0时,表示有进位到tv3
				(!cascade(base, &(base->tv3), INDEX(1))) &&				//返回为0时,表示有进位到tv4
					!cascade(base, &(base->tv4), INDEX(2)))					//返回为0时,表示有进位到tv5
			cascade(base, &(base->tv5), INDEX(3));							//从低位到高位逐级进位的迁移,在进位时将高位timer_list插入到低位
		
		++base->timer_jiffies;//该cpu定时器系统运行时间递增一个tick
		list_replace_init(base->tv1.vec + index, &work_list);//取出到期的定时器链表
		
		while (!list_empty(head)) {//遍历所有的到期定时器
			void (*fn)(unsigned long);
			unsigned long data;

			timer = list_first_entry(head, struct timer_list,entry);
			fn = timer->function;
			data = timer->data;

			set_running_timer(base, timer);//标记正在处理的定时器
			detach_timer(timer, 1);

			//spin_unlock_irq(&base->lock);
			call_timer_fn(timer, fn, data);//调用定时器的回调函数
			//spin_lock_irq(&base->lock);
		}
	}
	set_running_timer(base, NULL);
	//spin_unlock_irq(&base->lock);
}

void timer_update(struct tvec_base *base)
{
	if (time_after_eq(jiffies, base->timer_jiffies)) 
			__run_timers(base); 
}

static void __init_timer(struct timer_list *timer,
			 const char *name)
{
	timer->entry.next = NULL;
	timer->base = &timer_base;
}

void init_timer_key(struct timer_list *timer,
		    const char *name)
{
	__init_timer(timer, name);
}

static inline int timer_pending(const struct timer_list * timer)
{
	return timer->entry.next != NULL;
}

static inline int
__mod_timer(struct timer_list *timer, unsigned long expires)
{
	struct tvec_base *base;
	int ret = 0;

	base=timer->base;
	
	if (timer_pending(timer)) {
		detach_timer(timer, 0);
		if (timer->expires == base->next_timer)
			base->next_timer = base->timer_jiffies;
		ret = 1;
	} else {}

	timer->expires = expires;
	if (time_before(timer->expires, base->next_timer))
		base->next_timer = timer->expires;
	internal_add_timer(base, timer);

	return ret;
}

int mod_timer(struct timer_list *timer, unsigned long expires)
{
	/*
	 * This is a common optimization triggered by the
	 * networking code - if the timer is re-modified
	 * to be the same thing then just return:
	 */
	if (timer_pending(timer) && timer->expires == expires)
		return 1;

	return __mod_timer(timer, expires);
}

void add_timer(struct timer_list *timer)
{
	mod_timer(timer, timer->expires);
}

/**
 * del_timer - deactive a timer.
 * @timer: the timer to be deactivated
 *
 * del_timer() deactivates a timer - this works on both active and inactive
 * timers.
 *
 * The function returns whether it has deactivated a pending timer or not.
 * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
 * active timer returns 1.)
 */
int del_timer(struct timer_list *timer)
{
	struct tvec_base *base;
	int ret = 0;

	if (timer_pending(timer)) {
		detach_timer(timer, 1);
		if (timer->expires == base->next_timer)
			base->next_timer = base->timer_jiffies;
		ret = 1;
	}

	return ret;
}

list.h

/*此代码移植自linux kernel*/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H

#include "mytype.h"

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"

#define LIST_POISON1  NULL
#define LIST_POISON2  NULL

#define prefetch(x)		x

/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */

struct list_head {
	struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next);
#endif

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}


/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 */
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif

/**
 * list_replace - replace old entry by new one
 * @old : the element to be replaced
 * @new : the new element to insert
 *
 * If @old was empty, it will be overwritten.
 */
static inline void list_replace(struct list_head *old,
				struct list_head *new)
{
	new->next = old->next;
	new->next->prev = new;
	new->prev = old->prev;
	new->prev->next = new;
}

static inline void list_replace_init(struct list_head *old,
					struct list_head *new)
{
	list_replace(old, new);
	INIT_LIST_HEAD(old);
}

/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}

/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
				  struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add_tail(list, head);
}

/**
 * list_is_last - tests whether @list is the last entry in list @head
 * @list: the entry to test
 * @head: the head of the list
 */
static inline int list_is_last(const struct list_head *list,
				const struct list_head *head)
{
	return list->next == head;
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

/**
 * list_empty_careful - tests whether a list is empty and not being modified
 * @head: the list to test
 *
 * Description:
 * tests whether a list is empty _and_ checks that no other CPU might be
 * in the process of modifying either member (next or prev)
 *
 * NOTE: using list_empty_careful() without synchronization
 * can only be safe if the only activity that can happen
 * to the list entry is list_del_init(). Eg. it cannot be used
 * if another CPU could re-list_add() it.
 */
static inline int list_empty_careful(const struct list_head *head)
{
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

/**
 * list_rotate_left - rotate the list to the left
 * @head: the head of the list
 */
static inline void list_rotate_left(struct list_head *head)
{
	struct list_head *first;

	if (!list_empty(head)) {
		first = head->next;
		list_move_tail(first, head);
	}
}

/**
 * list_is_singular - tests whether a list has just one entry.
 * @head: the list to test.
 */
static inline int list_is_singular(const struct list_head *head)
{
	return !list_empty(head) && (head->next == head->prev);
}

static inline void __list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	struct list_head *new_first = entry->next;
	list->next = head->next;
	list->next->prev = list;
	list->prev = entry;
	entry->next = list;
	head->next = new_first;
	new_first->prev = head;
}

/**
 * list_cut_position - cut a list into two
 * @list: a new list to add all removed entries
 * @head: a list with entries
 * @entry: an entry within head, could be the head itself
 *	and if so we won't cut the list
 *
 * This helper moves the initial part of @head, up to and
 * including @entry, from @head to @list. You should
 * pass on @entry an element you know is on @head. @list
 * should be an empty list or a list you do not care about
 * losing its data.
 *
 */
static inline void list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	if (list_empty(head))
		return;
	if (list_is_singular(head) &&
		(head->next != entry && head != entry))
		return;
	if (entry == head)
		INIT_LIST_HEAD(list);
	else
		__list_cut_position(list, head, entry);
}

static inline void __list_splice(const struct list_head *list,
				 struct list_head *prev,
				 struct list_head *next)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

	first->prev = prev;
	prev->next = first;

	last->next = next;
	next->prev = last;
}

/**
 * list_splice - join two lists, this is designed for stacks
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(const struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head, head->next);
}

/**
 * list_splice_tail - join two lists, each list being a queue
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice_tail(struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head->prev, head);
}

/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list,
				    struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head, head->next);
		INIT_LIST_HEAD(list);
	}
}

/**
 * list_splice_tail_init - join two lists and reinitialise the emptied list
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * Each of the lists is a queue.
 * The list at @list is reinitialised
 */
static inline void list_splice_tail_init(struct list_head *list,
					 struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head->prev, head);
		INIT_LIST_HEAD(list);
	}
}

/**
 * list_entry - get the struct for this entry
 * @ptr:	the &struct list_head pointer.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

/**
 * list_first_entry - get the first element from a list
 * @ptr:	the list head to take the element from.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_first_entry(ptr, type, member) \
	list_entry((ptr)->next, type, member)

/**
 * list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each(pos, head) \
	for (pos = (head)->next; prefetch(pos->next), pos != (head); \
        	pos = pos->next)

/**
 * __list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 *
 * This variant differs from list_for_each() in that it's the
 * simplest possible list iteration code, no prefetching is done.
 * Use this for code that knows the list to be very short (empty
 * or 1 entry) most of the time.
 */
#define __list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * list_for_each_prev	-	iterate over a list backwards
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
        	pos = pos->prev)

/**
 * list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)

/**
 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_prev_safe(pos, n, head) \
	for (pos = (head)->prev, n = pos->prev; \
	     prefetch(pos->prev), pos != (head); \
	     pos = n, n = pos->prev)

/**
 * list_for_each_entry	-	iterate over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)				\
	for (pos = list_entry((head)->next, typeof(*pos), member);	\
	     prefetch(pos->member.next), &pos->member != (head); 	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_reverse - iterate backwards over list of given type.
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_reverse(pos, head, member)			\
	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
	     prefetch(pos->member.prev), &pos->member != (head); 	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
 * @pos:	the type * to use as a start point
 * @head:	the head of the list
 * @member:	the name of the list_struct within the struct.
 *
 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
 */
#define list_prepare_entry(pos, head, member) \
	((pos) ? : list_entry(head, typeof(*pos), member))

/**
 * list_for_each_entry_continue - continue iteration over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Continue to iterate over list of given type, continuing after
 * the current position.
 */
#define list_for_each_entry_continue(pos, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
	     prefetch(pos->member.next), &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_continue_reverse - iterate backwards from the given point
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Start to iterate over list of given type backwards, continuing after
 * the current position.
 */
#define list_for_each_entry_continue_reverse(pos, head, member)		\
	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
	     prefetch(pos->member.prev), &pos->member != (head);	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
 * list_for_each_entry_from - iterate over list of given type from the current point
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing from current position.
 */
#define list_for_each_entry_from(pos, head, member) 			\
	for (; prefetch(pos->member.next), &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_continue - continue list iteration safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing after current point,
 * safe against removal of list entry.
 */
#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
		n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_from - iterate over list from current point safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type from current point, safe against
 * removal of list entry.
 */
#define list_for_each_entry_safe_from(pos, n, head, member) 			\
	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate backwards over list of given type, safe against removal
 * of list entry.
 */
#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
		n = list_entry(pos->member.prev, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))

/**
 * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
 * @pos:	the loop cursor used in the list_for_each_entry_safe loop
 * @n:		temporary storage used in list_for_each_entry_safe
 * @member:	the name of the list_struct within the struct.
 *
 * list_safe_reset_next is not safe to use in general if the list may be
 * modified concurrently (eg. the lock is dropped in the loop body). An
 * exception to this is if the cursor element (pos) is pinned in the list,
 * and list_safe_reset_next is called after re-taking the lock and before
 * completing the current iteration of the loop body.
 */
#define list_safe_reset_next(pos, n, member)				\
	n = list_entry(pos->member.next, typeof(*pos), member)

/*
 * Double linked lists with a single pointer list head.
 * Mostly useful for hash tables where the two pointer list head is
 * too wasteful.
 * You lose the ability to access the tail in O(1).
 */

struct hlist_head {
	struct hlist_node *first;
};

struct hlist_node {
	struct hlist_node *next, **pprev;
};

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
	h->next = NULL;
	h->pprev = NULL;
}

static inline int hlist_unhashed(const struct hlist_node *h)
{
	return !h->pprev;
}

static inline int hlist_empty(const struct hlist_head *h)
{
	return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
	struct hlist_node *next = n->next;
	struct hlist_node **pprev = n->pprev;
	*pprev = next;
	if (next)
		next->pprev = pprev;
}

static inline void hlist_del(struct hlist_node *n)
{
	__hlist_del(n);
	n->next = LIST_POISON1;
	n->pprev = LIST_POISON2;
}

static inline void hlist_del_init(struct hlist_node *n)
{
	if (!hlist_unhashed(n)) {
		__hlist_del(n);
		INIT_HLIST_NODE(n);
	}
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
	struct hlist_node *first = h->first;
	n->next = first;
	if (first)
		first->pprev = &n->next;
	h->first = n;
	n->pprev = &h->first;
}

/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
					struct hlist_node *next)
{
	n->pprev = next->pprev;
	n->next = next;
	next->pprev = &n->next;
	*(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n,
					struct hlist_node *next)
{
	next->next = n->next;
	n->next = next;
	next->pprev = &n->next;

	if(next->next)
		next->next->pprev  = &next->next;
}

/*
 * Move a list from one list head to another. Fixup the pprev
 * reference of the first entry if it exists.
 */
static inline void hlist_move_list(struct hlist_head *old,
				   struct hlist_head *new)
{
	new->first = old->first;
	if (new->first)
		new->first->pprev = &new->first;
	old->first = NULL;
}

#define hlist_entry(ptr, type, member) container_of(ptr,type,member)

#define hlist_for_each(pos, head) \
	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
	     pos = pos->next)

#define hlist_for_each_safe(pos, n, head) \
	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
	     pos = n)

/**
 * hlist_for_each_entry	- iterate over list of given type
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry(tpos, pos, head, member)			 \
	for (pos = (head)->first;					 \
	     pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_continue(tpos, pos, member)		 \
	for (pos = (pos)->next;						 \
	     pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_from(tpos, pos, member)			 \
	for (; pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @n:		another &struct hlist_node to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
	for (pos = (head)->first;					 \
	     pos && ({ n = pos->next; 1; }) && 				 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = n)

#endif

mytype.h

#ifndef __MYTYPE_H__
#define __MYTYPE_H__

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

#endif

typecheck.h

#ifndef TYPECHECK_H_INCLUDED
#define TYPECHECK_H_INCLUDED

/*
 * Check at compile time that something is of a particular type.
 * Always evaluates to 1 so you may use it easily in comparisons.
 */
#define typecheck(type,x) \
({	type __dummy; \
	typeof(x) __dummy2; \
	(void)(&__dummy == &__dummy2); \
	1; \
})

/*
 * Check at compile time that 'function' is a certain type, or is a pointer
 * to that type (needs to use typedef for the function type.)
 */
#define typecheck_fn(type,function) \
({	typeof(type) __tmp = function; \
	(void)__tmp; \
})

#endif		/* TYPECHECK_H_INCLUDED */

test.ioc(stm32cubemx文件)

#MicroXplorer Configuration settings - do not modify
File.Version=6
IWDG.IPParameters=Reload
IWDG.Reload=1000
KeepUserPlacement=false
Mcu.Family=STM32F1
Mcu.IP0=IWDG
Mcu.IP1=NVIC
Mcu.IP2=RCC
Mcu.IP3=SYS
Mcu.IP4=TIM1
Mcu.IP5=TIM2
Mcu.IP6=TIM3
Mcu.IP7=TIM4
Mcu.IP8=USART1
Mcu.IPNb=9
Mcu.Name=STM32F103C(8-B)Tx
Mcu.Package=LQFP48
Mcu.Pin0=PD0-OSC_IN
Mcu.Pin1=PD1-OSC_OUT
Mcu.Pin10=PB2
Mcu.Pin11=PB11
Mcu.Pin12=PB12
Mcu.Pin13=PB13
Mcu.Pin14=PB14
Mcu.Pin15=PA8
Mcu.Pin16=PA9
Mcu.Pin17=PA10
Mcu.Pin18=PA13
Mcu.Pin19=PA14
Mcu.Pin2=PA0-WKUP
Mcu.Pin20=PB5
Mcu.Pin21=PB6
Mcu.Pin22=PB7
Mcu.Pin23=VP_IWDG_VS_IWDG
Mcu.Pin24=VP_SYS_VS_Systick
Mcu.Pin25=VP_TIM4_VS_ControllerModeClock
Mcu.Pin26=VP_TIM4_VS_ClockSourceITR
Mcu.Pin3=PA1
Mcu.Pin4=PA2
Mcu.Pin5=PA5
Mcu.Pin6=PA6
Mcu.Pin7=PA7
Mcu.Pin8=PB0
Mcu.Pin9=PB1
Mcu.PinsNb=27
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F103C8Tx
MxCube.Version=4.26.1
MxDb.Version=DB.4.0.261
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.EXTI9_5_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_2
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.TIM1_UP_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.TIM4_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false
PA0-WKUP.GPIOParameters=GPIO_Label
PA0-WKUP.GPIO_Label=PushMotorPWM
PA0-WKUP.Signal=S_TIM2_CH1_ETR
PA1.GPIOParameters=GPIO_Label
PA1.GPIO_Label=PushMotorIN1
PA1.Locked=true
PA1.Signal=GPIO_Output
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA2.GPIOParameters=GPIO_Label
PA2.GPIO_Label=PushMotorIN2
PA2.Locked=true
PA2.Signal=GPIO_Output
PA5.GPIOParameters=GPIO_PuPd,GPIO_Label
PA5.GPIO_Label=Knob3_1
PA5.GPIO_PuPd=GPIO_PULLUP
PA5.Locked=true
PA5.Signal=GPIO_Input
PA6.GPIOParameters=GPIO_PuPd,GPIO_Label
PA6.GPIO_Label=Knob3_2
PA6.GPIO_PuPd=GPIO_PULLUP
PA6.Locked=true
PA6.Signal=GPIO_Input
PA7.GPIOParameters=GPIO_PuPd,GPIO_Label
PA7.GPIO_Label=Knob3_3
PA7.GPIO_PuPd=GPIO_PULLUP
PA7.Locked=true
PA7.Signal=GPIO_Input
PA8.GPIOParameters=GPIO_Label
PA8.GPIO_Label=PushMotor2PWM
PA8.Locked=true
PA8.Signal=S_TIM1_CH1
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB0.GPIOParameters=GPIO_Label
PB0.GPIO_Label=StepMotorPul
PB0.Signal=S_TIM3_CH3
PB1.GPIOParameters=GPIO_Label
PB1.GPIO_Label=StepMotorDir
PB1.Locked=true
PB1.Signal=GPIO_Output
PB11.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PB11.GPIO_Label=LED_RED
PB11.GPIO_PuPd=GPIO_PULLUP
PB11.Locked=true
PB11.PinState=GPIO_PIN_SET
PB11.Signal=GPIO_Output
PB12.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PB12.GPIO_Label=LED_GREEN
PB12.GPIO_PuPd=GPIO_PULLUP
PB12.Locked=true
PB12.PinState=GPIO_PIN_SET
PB12.Signal=GPIO_Output
PB13.GPIOParameters=GPIO_Label
PB13.GPIO_Label=PushMotor2IN1
PB13.Locked=true
PB13.Signal=GPIO_Output
PB14.GPIOParameters=GPIO_Label
PB14.GPIO_Label=PushMotor2IN2
PB14.Locked=true
PB14.Signal=GPIO_Output
PB2.GPIOParameters=GPIO_Label
PB2.GPIO_Label=StepMotorEna
PB2.Locked=true
PB2.Signal=GPIO_Output
PB5.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB5.GPIO_Label=Proximity1
PB5.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB5.GPIO_PuPd=GPIO_PULLUP
PB5.Locked=true
PB5.Signal=GPXTI5
PB6.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB6.GPIO_Label=proximity2
PB6.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB6.GPIO_PuPd=GPIO_PULLUP
PB6.Locked=true
PB6.Signal=GPXTI6
PB7.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB7.GPIO_Label=Switch
PB7.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB7.GPIO_PuPd=GPIO_PULLUP
PB7.Locked=true
PB7.Signal=GPXTI7
PCC.Checker=false
PCC.Line=STM32F103
PCC.MCU=STM32F103C(8-B)Tx
PCC.PartNumber=STM32F103C8Tx
PCC.Seq0=0
PCC.Series=STM32F1
PCC.Temperature=25
PCC.Vdd=3.3
PD0-OSC_IN.Mode=HSE-External-Oscillator
PD0-OSC_IN.Signal=RCC_OSC_IN
PD1-OSC_OUT.Mode=HSE-External-Oscillator
PD1-OSC_OUT.Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=true
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32F103C8Tx
ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.6.1
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x200
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=0
ProjectManager.MainLocation=Src
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=test.ioc
ProjectManager.ProjectName=test
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=MDK-ARM V5
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_TIM2_Init-TIM2-false-HAL-true,4-MX_TIM3_Init-TIM3-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true,6-MX_IWDG_Init-IWDG-false-HAL-true,7-MX_TIM4_Init-TIM4-false-HAL-true,8-MX_TIM1_Init-TIM1-false-HAL-true
RCC.ADCFreqValue=36000000
RCC.AHBFreq_Value=72000000
RCC.APB1CLKDivider=RCC_HCLK_DIV2
RCC.APB1Freq_Value=36000000
RCC.APB1TimFreq_Value=72000000
RCC.APB2Freq_Value=72000000
RCC.APB2TimFreq_Value=72000000
RCC.FCLKCortexFreq_Value=72000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=72000000
RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,VCOOutput2Freq_Value
RCC.MCOFreq_Value=72000000
RCC.PLLCLKFreq_Value=72000000
RCC.PLLMCOFreq_Value=36000000
RCC.PLLMUL=RCC_PLL_MUL9
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
RCC.SYSCLKFreq_VALUE=72000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.TimSysFreq_Value=72000000
RCC.USBFreq_Value=72000000
RCC.VCOOutput2Freq_Value=8000000
SH.GPXTI5.0=GPIO_EXTI5
SH.GPXTI5.ConfNb=1
SH.GPXTI6.0=GPIO_EXTI6
SH.GPXTI6.ConfNb=1
SH.GPXTI7.0=GPIO_EXTI7
SH.GPXTI7.ConfNb=1
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
SH.S_TIM1_CH1.ConfNb=1
SH.S_TIM2_CH1_ETR.0=TIM2_CH1,PWM Generation1 CH1
SH.S_TIM2_CH1_ETR.ConfNb=1
SH.S_TIM3_CH3.0=TIM3_CH3,PWM Generation3 CH3
SH.S_TIM3_CH3.ConfNb=1
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM1.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Period,Pulse-PWM Generation1 CH1,OCPolarity_1
TIM1.IPParametersWithoutCheck=Pulse-PWM Generation1 CH1,Period
TIM1.OCPolarity_1=TIM_OCPOLARITY_LOW
TIM1.Period=PUSHMOTORPER_10US
TIM1.Prescaler=720-1
TIM1.Pulse-PWM\ Generation1\ CH1=PushMotor2_10us
TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM2.IPParameters=Prescaler,Period,Channel-PWM Generation1 CH1,Pulse-PWM Generation1 CH1,OCPolarity_1
TIM2.IPParametersWithoutCheck=Pulse-PWM Generation1 CH1,Pulse-PWM Generation2 CH2,Period
TIM2.OCPolarity_1=TIM_OCPOLARITY_LOW
TIM2.Period=PUSHMOTORPER_10US
TIM2.Prescaler=720-1
TIM2.Pulse-PWM\ Generation1\ CH1=PushMotor_10us
TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
TIM3.IPParameters=Prescaler,Period,TIM_MasterSlaveMode,TIM_MasterOutputTrigger,Channel-PWM Generation3 CH3,Pulse-PWM Generation3 CH3,OCPolarity_3
TIM3.IPParametersWithoutCheck=Pulse-PWM Generation3 CH3,Period,Pulse-Output Compare3 CH3
TIM3.OCPolarity_3=TIM_OCPOLARITY_LOW
TIM3.Period=StepMotor_10us
TIM3.Prescaler=720-1
TIM3.Pulse-PWM\ Generation3\ CH3=StepMotor_10us/2
TIM3.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
TIM3.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_ENABLE
TIM4.IPParameters=Period,TIM_MasterOutputTrigger
TIM4.Period=0
TIM4.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM4_VS_ClockSourceITR.Mode=TriggerSource_ITR2
VP_TIM4_VS_ClockSourceITR.Signal=TIM4_VS_ClockSourceITR
VP_TIM4_VS_ControllerModeClock.Mode=Clock Mode
VP_TIM4_VS_ControllerModeClock.Signal=TIM4_VS_ControllerModeClock
board=custom

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值