diff --git a/ReadMe.txt b/ReadMe.txt index 70ae6ec..d22ff29 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -2,4 +2,7 @@ 建立工程,成功创建两个虚拟串口与主机通信 2023.6.25 使用rt-thread - 电机控制、按键、ADC在M4上实现 \ No newline at end of file + 电机控制、按键、ADC在M4上实现 +2023.6.27 + 在m4上使用定时器,实现pwm控制的时候没有找到光感输入脚 + 如果发现程序不能运行,检查RTE文件 \ No newline at end of file diff --git a/checker_m4.uvoptx b/checker_m4.uvoptx index 717bfbe..c8d4262 100644 --- a/checker_m4.uvoptx +++ b/checker_m4.uvoptx @@ -1130,7 +1130,7 @@ ::Compiler - 0 + 1 0 0 1 diff --git a/checker_m4.uvprojx b/checker_m4.uvprojx index 35b99df..54b15a7 100644 --- a/checker_m4.uvprojx +++ b/checker_m4.uvprojx @@ -606,6 +606,11 @@ stm32mp1xx_hal_fdcan.c 1 .\source\stm32lib\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_fdcan.c + + + stm32mp1xx_hal_tim.c + 1 + .\source\stm32lib\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim.c 2 @@ -658,11 +663,6 @@ - - stm32mp1xx_hal_tim.c - 1 - .\source\stm32lib\STM32MP1xx_HAL_Driver\Src\stm32mp1xx_hal_tim.c - @@ -772,6 +772,57 @@ if_pwm.c 1 .\source\interface\if_pwm.c + + + 2 + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + diff --git a/debug.ini b/debug.ini new file mode 100644 index 0000000..ffa5283 --- /dev/null +++ b/debug.ini @@ -0,0 +1 @@ +LOAD %L NOCODE INCREMENTAL \ No newline at end of file diff --git a/source/interface/if_pwm.c b/source/interface/if_pwm.c index b92073b..fc16f6d 100644 --- a/source/interface/if_pwm.c +++ b/source/interface/if_pwm.c @@ -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_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(); + 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<dtb->gpio_zero_pin)){ + irq_disable(); + self->count_past=0; + self->count_all=0; + irq_enable(); + self_stop__(self); + EXTI_ClearFlag(1<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); +} diff --git a/source/main/main.c b/source/main/main.c index f67cee9..1036317 100644 --- a/source/main/main.c +++ b/source/main/main.c @@ -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 */