Files
checker_m4/source/interface/if_pwm.c
2023-06-27 18:16:46 +08:00

324 lines
6.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}