Files
checker_m4/source/interface/if_pwm.c
2023-06-30 14:23:54 +08:00

359 lines
6.9 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,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_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();
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);
}