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 */