427 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			427 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include "stm32f4xx.h"
							 | 
						|||
| 
								 | 
							
								#include "board.h"
							 | 
						|||
| 
								 | 
							
								#include "if_pwm.h"
							 | 
						|||
| 
								 | 
							
								#include "math.h"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// PE0 PWM 输出脚
							 | 
						|||
| 
								 | 
							
								// PE0,PE1,PE2,PE4,都不是定时器输出脚
							 | 
						|||
| 
								 | 
							
								// 只能使用普通方式
							 | 
						|||
| 
								 | 
							
								// PB7==0时到达上升零点
							 | 
						|||
| 
								 | 
							
								// tim2用于调速
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#define GPIO_Initer() {.GPIO_Mode=GPIO_Mode_OUT,\
							 | 
						|||
| 
								 | 
							
								  .GPIO_Speed=GPIO_Speed_100MHz,\
							 | 
						|||
| 
								 | 
							
								  .GPIO_OType=GPIO_OType_PP,\
							 | 
						|||
| 
								 | 
							
								  .GPIO_PuPd=GPIO_PuPd_UP \
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// 重装载值设为31us,引脚翻转一个周期是62us
							 | 
						|||
| 
								 | 
							
								#define TIMER_Initer(){\
							 | 
						|||
| 
								 | 
							
									.TIM_Period = 31-1,\
							 | 
						|||
| 
								 | 
							
									.TIM_Prescaler= 84-1,\
							 | 
						|||
| 
								 | 
							
									.TIM_CounterMode=TIM_CounterMode_Up,\
							 | 
						|||
| 
								 | 
							
									.TIM_ClockDivision=TIM_CKD_DIV1,\
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#define NVIC_Initer() {0}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#define EXTI_Initer() {\
							 | 
						|||
| 
								 | 
							
								  .EXTI_Mode=EXTI_Mode_Interrupt,\
							 | 
						|||
| 
								 | 
							
								  .EXTI_Trigger=EXTI_Trigger_Falling,\
							 | 
						|||
| 
								 | 
							
								  .EXTI_LineCmd=ENABLE,\
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								typedef struct{
							 | 
						|||
| 
								 | 
							
								  char *name;
							 | 
						|||
| 
								 | 
							
								  TIM_TypeDef *tim;
							 | 
						|||
| 
								 | 
							
								  void (*tim_clock_fun)(uint32_t,FunctionalState);
							 | 
						|||
| 
								 | 
							
								  uint32_t tim_rcc;
							 | 
						|||
| 
								 | 
							
								  int irq_channel;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  TIM_TypeDef *tim2;
							 | 
						|||
| 
								 | 
							
								  void (*tim2_clock_fun)(uint32_t,FunctionalState);
							 | 
						|||
| 
								 | 
							
								  uint32_t tim2_rcc;
							 | 
						|||
| 
								 | 
							
								  int irq2_channel;
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								  void (*gpio_tx_clock_fun)(uint32_t,FunctionalState);
							 | 
						|||
| 
								 | 
							
								  uint32_t gpio_tx_rcc;
							 | 
						|||
| 
								 | 
							
								  GPIO_TypeDef *gpio_tx_base;
							 | 
						|||
| 
								 | 
							
								  uint16_t gpio_tx_pin;
							 | 
						|||
| 
								 | 
							
								  volatile uint32_t *bitmap_pin;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  void (*gpio_dir_clock_fun)(uint32_t,FunctionalState);
							 | 
						|||
| 
								 | 
							
								  uint32_t gpio_dir_rcc;
							 | 
						|||
| 
								 | 
							
								  GPIO_TypeDef *gpio_dir_base;
							 | 
						|||
| 
								 | 
							
								  uint16_t gpio_dir_pin;
							 | 
						|||
| 
								 | 
							
								  volatile uint32_t *bitmap_pin_dir;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  void (*gpio_zero_clock_fun)(uint32_t,FunctionalState);
							 | 
						|||
| 
								 | 
							
								  uint32_t gpio_zero_rcc;
							 | 
						|||
| 
								 | 
							
								  GPIO_TypeDef *gpio_zero_base;
							 | 
						|||
| 
								 | 
							
								  uint16_t gpio_zero_pin;
							 | 
						|||
| 
								 | 
							
								  volatile uint32_t *bitmap_pin_zero;
							 | 
						|||
| 
								 | 
							
								  int zero_irq_channel;
							 | 
						|||
| 
								 | 
							
								  uint8_t exti_src_port;
							 | 
						|||
| 
								 | 
							
								}pwm_dtb;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// 可以基于定时器2345
							 | 
						|||
| 
								 | 
							
								static const pwm_dtb g_pwmdtb[]={
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    .name="pwm1",
							 | 
						|||
| 
								 | 
							
								    .tim=TIM2,
							 | 
						|||
| 
								 | 
							
								    .tim_clock_fun=RCC_APB1PeriphClockCmd,
							 | 
						|||
| 
								 | 
							
								    .tim_rcc=RCC_APB1Periph_TIM2,
							 | 
						|||
| 
								 | 
							
								    .irq_channel=TIM2_IRQn,
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    .tim2=TIM3,
							 | 
						|||
| 
								 | 
							
								    .tim2_clock_fun=RCC_APB1PeriphClockCmd,
							 | 
						|||
| 
								 | 
							
								    .tim2_rcc=RCC_APB1Periph_TIM3,
							 | 
						|||
| 
								 | 
							
								    .irq2_channel=TIM3_IRQn,
							 | 
						|||
| 
								 | 
							
								    
							 | 
						|||
| 
								 | 
							
								    .gpio_tx_clock_fun=RCC_AHB1PeriphClockCmd,
							 | 
						|||
| 
								 | 
							
								    .gpio_tx_rcc=RCC_AHB1Periph_GPIOE,
							 | 
						|||
| 
								 | 
							
								    .gpio_tx_base=GPIOE,
							 | 
						|||
| 
								 | 
							
								    .gpio_tx_pin=0,
							 | 
						|||
| 
								 | 
							
								    .bitmap_pin=&PINOUT(E,0),
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    .gpio_dir_clock_fun=RCC_AHB1PeriphClockCmd,
							 | 
						|||
| 
								 | 
							
								    .gpio_dir_rcc=RCC_AHB1Periph_GPIOE,
							 | 
						|||
| 
								 | 
							
								    .gpio_dir_base=GPIOE,
							 | 
						|||
| 
								 | 
							
								    .gpio_dir_pin=1,
							 | 
						|||
| 
								 | 
							
								    .bitmap_pin_dir=&PINOUT(E,1),
							 | 
						|||
| 
								 | 
							
								    
							 | 
						|||
| 
								 | 
							
								    .gpio_zero_clock_fun=RCC_AHB1PeriphClockCmd,
							 | 
						|||
| 
								 | 
							
								    .gpio_zero_rcc=RCC_AHB1Periph_GPIOB,
							 | 
						|||
| 
								 | 
							
								    .gpio_zero_base=GPIOB,
							 | 
						|||
| 
								 | 
							
								    .gpio_zero_pin=7,
							 | 
						|||
| 
								 | 
							
								    .bitmap_pin_zero=&PININ(B,7),
							 | 
						|||
| 
								 | 
							
								    .zero_irq_channel=EXTI9_5_IRQn,
							 | 
						|||
| 
								 | 
							
								    .exti_src_port=EXTI_PortSourceGPIOB,
							 | 
						|||
| 
								 | 
							
								  },
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								typedef struct{
							 | 
						|||
| 
								 | 
							
								  int tick;
							 | 
						|||
| 
								 | 
							
								  int step;
							 | 
						|||
| 
								 | 
							
								  int fre;
							 | 
						|||
| 
								 | 
							
								  int fre_max;
							 | 
						|||
| 
								 | 
							
								  int fre_min;
							 | 
						|||
| 
								 | 
							
								  int up_tick;
							 | 
						|||
| 
								 | 
							
								}ctrl_fre;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								typedef struct{
							 | 
						|||
| 
								 | 
							
								  const pwm_dtb *dtb;
							 | 
						|||
| 
								 | 
							
								  int count_all;
							 | 
						|||
| 
								 | 
							
								  int count_past;
							 | 
						|||
| 
								 | 
							
								  int fre;
							 | 
						|||
| 
								 | 
							
								  ctrl_fre cfre;
							 | 
						|||
| 
								 | 
							
								  void (*end_irq)(void *t);
							 | 
						|||
| 
								 | 
							
								  void *t;
							 | 
						|||
| 
								 | 
							
								}self_data;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static self_data g_self[LENGTH(g_pwmdtb)];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								def_find_fun(pwm_dtb,g_pwmdtb)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static int init(pwm_def *p)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  if(p->private_data) return 0;
							 | 
						|||
| 
								 | 
							
								  GPIO_InitTypeDef init=GPIO_Initer();
							 | 
						|||
| 
								 | 
							
									TIM_TimeBaseInitTypeDef init2=TIMER_Initer();
							 | 
						|||
| 
								 | 
							
								  NVIC_InitTypeDef init3=NVIC_Initer();
							 | 
						|||
| 
								 | 
							
								  EXTI_InitTypeDef init4=EXTI_Initer();
							 | 
						|||
| 
								 | 
							
								  int index;
							 | 
						|||
| 
								 | 
							
								  const pwm_dtb *dtb=find(p->name,&index);
							 | 
						|||
| 
								 | 
							
								  self_data *self=&g_self[index];
							 | 
						|||
| 
								 | 
							
								  self->dtb=dtb;
							 | 
						|||
| 
								 | 
							
								  self->cfre.step=320;
							 | 
						|||
| 
								 | 
							
								  self->cfre.fre_min=1100;
							 | 
						|||
| 
								 | 
							
								  p->private_data=self;
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
									dtb->tim_clock_fun(dtb->tim_rcc,ENABLE);
							 | 
						|||
| 
								 | 
							
									TIM_TimeBaseInit(dtb->tim,&init2);
							 | 
						|||
| 
								 | 
							
								  TIM_ITConfig(dtb->tim,TIM_IT_Update,ENABLE);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  init2.TIM_Period=1000-1;
							 | 
						|||
| 
								 | 
							
									dtb->tim2_clock_fun(dtb->tim2_rcc,ENABLE);
							 | 
						|||
| 
								 | 
							
									TIM_TimeBaseInit(dtb->tim2,&init2);
							 | 
						|||
| 
								 | 
							
								  TIM_ITConfig(dtb->tim2,TIM_IT_Update,ENABLE);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  dtb->gpio_tx_clock_fun(dtb->gpio_tx_rcc,ENABLE);
							 | 
						|||
| 
								 | 
							
									init.GPIO_Pin = 1<<dtb->gpio_tx_pin;	 
							 | 
						|||
| 
								 | 
							
									GPIO_Init(dtb->gpio_tx_base, &init);	
							 | 
						|||
| 
								 | 
							
								  dtb->gpio_dir_clock_fun(dtb->gpio_dir_rcc,ENABLE);
							 | 
						|||
| 
								 | 
							
									init.GPIO_Pin = 1<<dtb->gpio_dir_pin;	 
							 | 
						|||
| 
								 | 
							
									GPIO_Init(dtb->gpio_dir_base, &init);	
							 | 
						|||
| 
								 | 
							
								  dtb->gpio_zero_clock_fun(dtb->gpio_zero_rcc,ENABLE);
							 | 
						|||
| 
								 | 
							
									init.GPIO_Pin = 1<<dtb->gpio_zero_pin;	
							 | 
						|||
| 
								 | 
							
								  init.GPIO_Mode=GPIO_Mode_IN;
							 | 
						|||
| 
								 | 
							
									GPIO_Init(dtb->gpio_zero_base, &init);	
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannel = dtb->irq_channel;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelPreemptionPriority=0;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelSubPriority =0;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelCmd = ENABLE;
							 | 
						|||
| 
								 | 
							
								  NVIC_Init(&init3);
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannel = dtb->irq2_channel;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelPreemptionPriority=1;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelSubPriority =1;
							 | 
						|||
| 
								 | 
							
								  NVIC_Init(&init3);
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								  init4.EXTI_Line=1<<dtb->gpio_zero_pin;
							 | 
						|||
| 
								 | 
							
								  EXTI_Init(&init4);
							 | 
						|||
| 
								 | 
							
								  SYSCFG_EXTILineConfig(dtb->exti_src_port,dtb->gpio_zero_pin);
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannel = dtb->zero_irq_channel;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelPreemptionPriority=0;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelSubPriority =0;
							 | 
						|||
| 
								 | 
							
								  init3.NVIC_IRQChannelCmd = ENABLE;
							 | 
						|||
| 
								 | 
							
								  NVIC_Init(&init3);
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static int deinit(pwm_def *p)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  if(p->private_data==0) return 0;
							 | 
						|||
| 
								 | 
							
								  NVIC_InitTypeDef init3=NVIC_Initer();
							 | 
						|||
| 
								 | 
							
								  const pwm_dtb *dtb=find(p->name,0);
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    TIM_Cmd(dtb->tim, DISABLE);	
							 | 
						|||
| 
								 | 
							
								    dtb->tim_clock_fun(dtb->tim_rcc,DISABLE);
							 | 
						|||
| 
								 | 
							
								    dtb->gpio_tx_clock_fun(dtb->gpio_tx_rcc,DISABLE);
							 | 
						|||
| 
								 | 
							
								    init3.NVIC_IRQChannelCmd = DISABLE;
							 | 
						|||
| 
								 | 
							
								    NVIC_Init(&init3);
							 | 
						|||
| 
								 | 
							
								    TIM_ITConfig(dtb->tim,TIM_IT_Update,DISABLE);
							 | 
						|||
| 
								 | 
							
								    p->private_data=0;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// step_count有方向,向下为正
							 | 
						|||
| 
								 | 
							
								static int start(pwm_def *p,int step_count)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  param_check(p->private_data);
							 | 
						|||
| 
								 | 
							
								  self_data *self=p->private_data;
							 | 
						|||
| 
								 | 
							
								  if(step_count==0) return 0;
							 | 
						|||
| 
								 | 
							
								  if((*self->dtb->bitmap_pin_zero==0)&&(step_count<0))
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    // 到达零点后不能继续上升
							 | 
						|||
| 
								 | 
							
								    if(self->end_irq)
							 | 
						|||
| 
								 | 
							
								      self->end_irq(self->t);
							 | 
						|||
| 
								 | 
							
								    return -1;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  if(step_count>0)
							 | 
						|||
| 
								 | 
							
								    *self->dtb->bitmap_pin_dir=0;
							 | 
						|||
| 
								 | 
							
								  else{
							 | 
						|||
| 
								 | 
							
								    step_count=-step_count;
							 | 
						|||
| 
								 | 
							
								    *self->dtb->bitmap_pin_dir=1;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  if(self->fre==0)
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    ctrl_fre *cfre=&self->cfre;
							 | 
						|||
| 
								 | 
							
								    memset(cfre,0,sizeof(ctrl_fre));
							 | 
						|||
| 
								 | 
							
								    int max_count=0;
							 | 
						|||
| 
								 | 
							
								    cfre->tick=0;
							 | 
						|||
| 
								 | 
							
								    cfre->step=320;
							 | 
						|||
| 
								 | 
							
								    cfre->fre_max=16000;
							 | 
						|||
| 
								 | 
							
								    cfre->fre_min=1100;
							 | 
						|||
| 
								 | 
							
								    cfre->up_tick=0;
							 | 
						|||
| 
								 | 
							
								    cfre->fre=cfre->fre_min;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  irq_disable();
							 | 
						|||
| 
								 | 
							
								  if(step_count>0)
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    self->count_all=step_count;
							 | 
						|||
| 
								 | 
							
								  }else{
							 | 
						|||
| 
								 | 
							
								    self->count_all=0;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  self->count_past=0;
							 | 
						|||
| 
								 | 
							
								  irq_enable();
							 | 
						|||
| 
								 | 
							
								  TIM_Cmd(self->dtb->tim, ENABLE);	
							 | 
						|||
| 
								 | 
							
								  TIM_Cmd(self->dtb->tim2, ENABLE);	
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void self_stop__(self_data *self);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static int stop(pwm_def *p)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  param_check(p->private_data);
							 | 
						|||
| 
								 | 
							
								  self_data *self=p->private_data;
							 | 
						|||
| 
								 | 
							
								  self_stop__(self);
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void self_set_fre(self_data *self,int fre)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  // 两个定时器溢出为一个翻转周期,这里重装载值要除2
							 | 
						|||
| 
								 | 
							
								  TIM_SetAutoreload(self->dtb->tim,1000000/2/fre);
							 | 
						|||
| 
								 | 
							
								  TIM_SetCounter(self->dtb->tim,0);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// 设置频率,最低8hz,最高16000hz
							 | 
						|||
| 
								 | 
							
								// 如果设置fre为0,则自动运行
							 | 
						|||
| 
								 | 
							
								static int set_fre(pwm_def *p,int fre)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  param_check(p->private_data);
							 | 
						|||
| 
								 | 
							
								  self_data *self=p->private_data;
							 | 
						|||
| 
								 | 
							
								  if(fre==0)
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    self->fre=fre;
							 | 
						|||
| 
								 | 
							
								    return 0;
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  if((fre<8)||(fre>16000)) return -1;
							 | 
						|||
| 
								 | 
							
								  self->fre=fre;
							 | 
						|||
| 
								 | 
							
								  self_set_fre(self,fre);
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// 设置中断回调
							 | 
						|||
| 
								 | 
							
								static int set_irq_fun(pwm_def *p,void (*fun)(void *t),void *t)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  param_check(p);
							 | 
						|||
| 
								 | 
							
								  param_check(p->private_data);
							 | 
						|||
| 
								 | 
							
								  self_data *self=p->private_data;
							 | 
						|||
| 
								 | 
							
								  irq_disable();
							 | 
						|||
| 
								 | 
							
								  self->end_irq=fun;
							 | 
						|||
| 
								 | 
							
								  self->t=t;
							 | 
						|||
| 
								 | 
							
								  irq_enable();
							 | 
						|||
| 
								 | 
							
								  return 0;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void self_stop__(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  TIM_Cmd(self->dtb->tim, DISABLE);	
							 | 
						|||
| 
								 | 
							
								  TIM_Cmd(self->dtb->tim2, DISABLE);	
							 | 
						|||
| 
								 | 
							
								  if(self->end_irq)
							 | 
						|||
| 
								 | 
							
								    self->end_irq(self->t);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void self_irq(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									rt_interrupt_enter();
							 | 
						|||
| 
								 | 
							
								  volatile uint32_t *pin=self->dtb->bitmap_pin;
							 | 
						|||
| 
								 | 
							
								  if(TIM_GetFlagStatus(self->dtb->tim,TIM_FLAG_Update))
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    TIM_ClearFlag(self->dtb->tim,TIM_FLAG_Update);
							 | 
						|||
| 
								 | 
							
								    *pin=!(*pin);
							 | 
						|||
| 
								 | 
							
								    irq_disable();
							 | 
						|||
| 
								 | 
							
								    self->count_past++;
							 | 
						|||
| 
								 | 
							
								    irq_enable();
							 | 
						|||
| 
								 | 
							
								    if(self->count_all>0&&(self->count_all<=self->count_past))
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								      self_stop__(self);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
									rt_interrupt_leave();
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void calc_up(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  ctrl_fre *cfre=&self->cfre;
							 | 
						|||
| 
								 | 
							
								  if(self->count_past<self->count_all/2)
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    if(cfre->fre<cfre->fre_max)
							 | 
						|||
| 
								 | 
							
								      cfre->fre+=cfre->step;
							 | 
						|||
| 
								 | 
							
								    else
							 | 
						|||
| 
								 | 
							
								      cfre->up_tick++;
							 | 
						|||
| 
								 | 
							
								  }else{
							 | 
						|||
| 
								 | 
							
								    if(cfre->up_tick>0)
							 | 
						|||
| 
								 | 
							
								      cfre->up_tick--;
							 | 
						|||
| 
								 | 
							
								    else{
							 | 
						|||
| 
								 | 
							
								      cfre->fre-=cfre->step;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
								  // 防止速度减到0,永远不停止
							 | 
						|||
| 
								 | 
							
								  if(cfre->fre<cfre->fre_min)
							 | 
						|||
| 
								 | 
							
								    cfre->fre=cfre->fre_min;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static int calc_fre(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  ctrl_fre *cfre=&self->cfre;
							 | 
						|||
| 
								 | 
							
								  int fre=0;
							 | 
						|||
| 
								 | 
							
								  calc_up(self);
							 | 
						|||
| 
								 | 
							
								  fre=cfre->fre;
							 | 
						|||
| 
								 | 
							
								  // 会每1ms更新一次频率,因此频率必须大于1000
							 | 
						|||
| 
								 | 
							
								  param_check(fre>1000);
							 | 
						|||
| 
								 | 
							
								  cfre->tick++;
							 | 
						|||
| 
								 | 
							
								  return fre;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								static inline void self_irq2(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									rt_interrupt_enter();
							 | 
						|||
| 
								 | 
							
								  volatile uint32_t *pin=self->dtb->bitmap_pin;
							 | 
						|||
| 
								 | 
							
								  if(TIM_GetFlagStatus(self->dtb->tim2,TIM_FLAG_Update))
							 | 
						|||
| 
								 | 
							
								  {
							 | 
						|||
| 
								 | 
							
								    TIM_ClearFlag(self->dtb->tim2,TIM_FLAG_Update);
							 | 
						|||
| 
								 | 
							
								    if(self->fre==0)
							 | 
						|||
| 
								 | 
							
								      self_set_fre(self,calc_fre(self));
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
									rt_interrupt_leave();
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								static inline void self_stop_irq(self_data *self)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									rt_interrupt_enter();
							 | 
						|||
| 
								 | 
							
								  if(EXTI_GetFlagStatus(1<<self->dtb->gpio_zero_pin)){
							 | 
						|||
| 
								 | 
							
								    irq_disable();
							 | 
						|||
| 
								 | 
							
								    self->count_past=0;
							 | 
						|||
| 
								 | 
							
								    self->count_all=0;
							 | 
						|||
| 
								 | 
							
								    irq_enable();
							 | 
						|||
| 
								 | 
							
								    self_stop__(self);
							 | 
						|||
| 
								 | 
							
								    EXTI_ClearFlag(1<<self->dtb->gpio_zero_pin);
							 | 
						|||
| 
								 | 
							
								  }
							 | 
						|||
| 
								 | 
							
									rt_interrupt_leave();
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								void TIM2_IRQHandler(void)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  self_data *self=&g_self[0];
							 | 
						|||
| 
								 | 
							
								  self_irq(self);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								void TIM3_IRQHandler(void)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  self_data *self=&g_self[0];
							 | 
						|||
| 
								 | 
							
								  self_irq2(self);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								void EXTI9_5_IRQHandler(void)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								  self_data *self=&g_self[0];
							 | 
						|||
| 
								 | 
							
								  self_stop_irq(self);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								pwm_init_export(pwm1,init,deinit,start,stop,set_fre,set_irq_fun,0)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 |