使用定时器

This commit is contained in:
ranchuan
2023-06-27 18:16:46 +08:00
parent cdad432f8a
commit edd3010a20
6 changed files with 338 additions and 9 deletions

View File

@@ -1,15 +1,35 @@
#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;
@@ -18,11 +38,13 @@ 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 = 65535;
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)
@@ -30,16 +52,257 @@ static int init(pwm_def *p)
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)
{
}
@@ -50,6 +313,11 @@ 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);
}

View File

@@ -25,6 +25,7 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "debug.h"
#include "board.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -139,6 +140,11 @@ int main(void)
{
Error_Handler();
}
pwm_def *pwm=dev_get("pwm");
pwm->init(pwm);
DBG_LOG("pwm start.");
pwm->start(pwm,1);
/* USER CODE END 2 */
/* Infinite loop */