#include "board.h" #include "debug.h" #include "lock_resource.h" // 使用定时器14,13 // PF7,8,9 是输出口 // 使用PF7来产生脉冲,PF8来改变方向 // PI6 是输入口 // 使用PI6来捕获到位中断 typedef struct{ int tick; int step; int fre; int fre_max; int fre_min; int up_tick; }ctrl_fre; typedef struct{ TIM_HandleTypeDef htim; TIM_HandleTypeDef htim2; EXTI_HandleTypeDef hexti; int count_all; int count_past; int fre; ctrl_fre cfre; void (*end_irq)(void *t); void *t; }self_def; static self_def g_self; static void Exti14FallingCb(void); static int init(pwm_def *p) { self_def *s=&g_self; if(p->private_data) return 0; p->private_data=s; s->cfre.step=320; s->cfre.fre_min=1100; s->htim.Instance = TIM14; s->htim.Init.Prescaler = 209-1; s->htim.Init.CounterMode = TIM_COUNTERMODE_UP; s->htim.Init.Period = 31-1; s->htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; s->htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&s->htim) != HAL_OK) { DBG_ERR("time init failed."); return -1; } s->htim2.Instance = TIM13; s->htim2.Init.Prescaler = 209-1; s->htim2.Init.CounterMode = TIM_COUNTERMODE_UP; s->htim2.Init.Period = 1000-1; s->htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; s->htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&s->htim2) != HAL_OK) { DBG_ERR("time init failed."); return -1; } GPIO_InitTypeDef init={0}; __HAL_RCC_GPIOF_CLK_ENABLE(); init.Mode = GPIO_MODE_OUTPUT_PP; init.Pull = GPIO_NOPULL; init.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; PERIPH_LOCK(GPIOF); HAL_GPIO_Init(GPIOF, &init); PERIPH_UNLOCK(GPIOF); __HAL_RCC_GPIOI_CLK_ENABLE(); init.Mode = GPIO_MODE_INPUT; init.Pull = GPIO_NOPULL; init.Pin = GPIO_PIN_6; PERIPH_LOCK(GPIOI); HAL_GPIO_Init(GPIOI, &init); PERIPH_UNLOCK(GPIOI); EXTI_ConfigTypeDef init2={0}; init2.Line = EXTI_LINE_14; init2.Trigger = EXTI_TRIGGER_FALLING; init2.GPIOSel = EXTI_GPIOA; init2.Mode = EXTI_MODE_C2_INTERRUPT; PERIPH_LOCK(EXTI); HAL_EXTI_SetConfigLine(&s->hexti, &init2); PERIPH_UNLOCK(EXTI); /* Register callback to treat Exti interrupts in user Exti14FallingCb function */ HAL_EXTI_RegisterCallback(&s->hexti, HAL_EXTI_FALLING_CB_ID, Exti14FallingCb); /* Enable and set line 14 Interrupt to the lowest priority */ HAL_NVIC_SetPriority(EXTI6_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI6_IRQn); return 0; } static int deinit(pwm_def *p) { return 0; } static int start(pwm_def *p,int step_count) { param_check(p); param_check(p->private_data); self_def *self=p->private_data; if(step_count==0) return 0; if((HAL_GPIO_ReadPin(GPIOI,6)==GPIO_PIN_RESET)&&(step_count<0)) { // 到达零点后不能继续上升 if(self->end_irq) self->end_irq(self->t); return -1; } if(step_count>0) HAL_GPIO_WritePin(GPIOF,8,GPIO_PIN_RESET); else{ step_count=-step_count; HAL_GPIO_WritePin(GPIOF,8,GPIO_PIN_SET); } 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(); HAL_TIM_Base_Start_IT(&self->htim); HAL_TIM_Base_Start_IT(&self->htim2); return 0; } static inline void self_stop__(self_def *self); static int stop(pwm_def *p) { param_check(p); param_check(p->private_data); self_def *self=p->private_data; self_stop__(self); return 0; } static inline void self_set_fre(self_def *self,int fre) { // 两个定时器溢出为一个翻转周期,这里重装载值要除2 __HAL_TIM_SET_AUTORELOAD(&self->htim,1000000/2/fre); __HAL_TIM_SET_COUNTER(&self->htim,0); } // 设置频率,最低8hz,最高16000hz // 如果设置fre为0,则自动运行 static int set_fre(pwm_def *p,int fre) { param_check(p); param_check(p->private_data); self_def *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_def *self=p->private_data; irq_disable(); self->end_irq=fun; self->t=t; irq_enable(); return 0; } static inline void self_stop__(self_def *self) { HAL_TIM_Base_Stop_IT(&self->htim); HAL_TIM_Base_Stop_IT(&self->htim2); if(self->end_irq) self->end_irq(self->t); } pwm_init_export(pwm,init,deinit,start,stop,set_fre,set_irq_fun,0) static inline void self_irq(self_def *self) { rt_interrupt_enter(); HAL_GPIO_TogglePin(GPIOF,7); 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_def *self) { ctrl_fre *cfre=&self->cfre; if(self->count_pastcount_all/2) { if(cfre->frefre_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->frefre_min) cfre->fre=cfre->fre_min; } static int calc_fre(self_def *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_def *self) { rt_interrupt_enter(); if(self->fre==0) self_set_fre(self,calc_fre(self)); rt_interrupt_leave(); } static inline void self_stop_irq(self_def *self) { rt_interrupt_enter(); irq_disable(); self->count_past=0; self->count_all=0; irq_enable(); self_stop__(self); rt_interrupt_leave(); } static void Exti14FallingCb(void) { self_def *s=&g_self; self_stop_irq(s); } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { self_def *s=&g_self; //DBG_LOG("timer updata."); if(htim==&s->htim) { self_irq(s); } else if(htim==&s->htim2) { self_irq2(s); } } void HAL_TIMEx_Break2Callback(TIM_HandleTypeDef *htim) { } void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim) { } void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim) { } void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim) { } void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma) { } void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma) { } void TIM14_IRQHandler(void) { self_def *s=&g_self; HAL_TIM_IRQHandler(&s->htim); } void TIM13_IRQHandler(void) { self_def *s=&g_self; HAL_TIM_IRQHandler(&s->htim2); } void EXTI6_IRQHandler(void) { self_def *s=&g_self; HAL_EXTI_IRQHandler(&s->hexti); }