324 lines
6.2 KiB
C
324 lines
6.2 KiB
C
#include "board.h"
|
||
#include "debug.h"
|
||
#include "lock_resource.h"
|
||
|
||
// 使用定时器14
|
||
|
||
// PF7,8,9 是输出口
|
||
// 使用PF7来产生脉冲,PF8来改变方向
|
||
|
||
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;
|
||
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 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_INPUT;
|
||
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);
|
||
|
||
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((*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();
|
||
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();
|
||
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_def *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_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();
|
||
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_def *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 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
||
{
|
||
//DBG_LOG("timer updata.");
|
||
}
|
||
|
||
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
|