1、修改电机驱动PWM源为TIMER4 U;启用缓启动缓停止。

This commit is contained in:
cui635
2025-09-15 16:15:51 +08:00
parent f296a8eb48
commit 6f7e999350
7 changed files with 366 additions and 73 deletions
@@ -14,7 +14,7 @@ volatile uint16_t g_accelTimer = 0;
static uint16_t accelCounter = 0;
static uint8_t DcMotorDispEn = true;
static uint8_t DcMotorDispEn = false;
#define DCMOTOR_DBG_LOG(...) { if(DcMotorDispEn) DBG_LOG(__VA_ARGS__);}
#define DCMOTOR_DBG_ARRAY(ARRAY, SIZE) { if(DcMotorDispEn) {DBG_ARRAY(ARRAY,SIZE)}}
@@ -25,12 +25,174 @@ void DCMOTORDBGOnOff(uint8_t OnOff)
{
DcMotorDispEn = OnOff;
if(OnOff)
DBG_LOG("\r\nKey Display Enable!\r\n");
DBG_LOG("\r\nDcMotor Display Enable!\r\n");
else
DBG_LOG("\r\nKey Display Disable!\r\n");
DBG_LOG("\r\nDcMotor Display Disable!\r\n");
}
/* Timer4 CNT */
#define TIMER4_UNIT (M4_TMR41)
#define TIMER4_CNT_CYCLE_VAL (10000u) /* Timer4 counter cycle value */
/* Timer4 OCO */
#define TIMER4_OCO_HIGH_CH (Timer4OcoOuh) /* only Timer4OcoOuh Timer4OcoOvh Timer4OcoOwh */
/* Timer4 PWM */
#define TIMER4_PWM_CH (Timer4PwmU) /* only Timer4PwmU Timer4PwmV Timer4PwmW */
/* Define port and pin for Timer4Pwm */
#define TIMER4_PWM_H_PORT (PortA) /* TIM4_1_OUH_B:PE9 TIM4_1_OVH_B:PE11 TIM4_1_OWH_B:PE13 */
#define TIMER4_PWM_H_PIN (Pin08)
#define TIMER4_PWM_L_PORT (PortB) /* TIM4_1_OUL_B:PE8 TIM4_1_OVL_B:PE10 TIM4_1_OWL_B:PE12 */
#define TIMER4_PWM_L_PIN (Pin13)
void Timer41_Init(uint8_t dir)
{
uint8_t E_OC_Port = 0;
uint8_t E_PWM_OS = 0;
stc_timer4_cnt_init_t stcCntInit;
stc_timer4_oco_init_t stcOcoInit;
stc_timer4_pwm_init_t stcPwmInit;
stc_oco_low_ch_compare_mode_t stcLowChCmpMode;
stc_oco_high_ch_compare_mode_t stcHighChCmpMode;
uint16_t u8OcoOccrVal = TIMER4_CNT_CYCLE_VAL/10u;
en_timer4_oco_ch_t enOcoLowCh = (en_timer4_oco_ch_t)(TIMER4_OCO_HIGH_CH + 1);
/* Clear structures */
MEM_ZERO_STRUCT(stcCntInit);
MEM_ZERO_STRUCT(stcOcoInit);
MEM_ZERO_STRUCT(stcLowChCmpMode);
MEM_ZERO_STRUCT(stcHighChCmpMode);
MEM_ZERO_STRUCT(stcPwmInit);
if(dir == 0)
{
E_OC_Port = OcPortLevelLow;
E_PWM_OS = PwmHReversePwmLHold;
}
else
{
E_OC_Port = OcPortLevelHigh;
E_PWM_OS = PwmHReversePwmLHold;
}
/* Enable peripheral clock */
PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM41 | PWC_FCG2_PERIPH_TIM42 | PWC_FCG2_PERIPH_TIM43, Enable);
/* Timer4 CNT : Initialize CNT configuration structure */
stcCntInit.enBufferCmd = Disable;
stcCntInit.enClk = Timer4CntPclk;
stcCntInit.enClkDiv = Timer4CntPclkDiv4; /* CNT clock divide */
stcCntInit.u16Cycle = TIMER4_CNT_CYCLE_VAL;
stcCntInit.enCntMode = Timer4CntTriangularWave;
stcCntInit.enZeroIntCmd = Disable;
stcCntInit.enPeakIntCmd = Disable;
stcCntInit.enZeroIntMsk = Timer4CntIntMask1;
stcCntInit.enPeakIntMsk = Timer4CntIntMask1;
TIMER4_CNT_Init(TIMER4_UNIT, &stcCntInit); /* Initialize CNT */
/* Timer4 OCO : Initialize OCO configuration structure */
stcOcoInit.enOccrBufMode = OccrBufTrsfByCntZero;
stcOcoInit.enOcmrBufMode = OcmrBufTrsfByCntZero;
stcOcoInit.enPortLevel = E_OC_Port; /*输出低电平到OC端口*/
stcOcoInit.enOcoIntCmd = Disable;
TIMER4_OCO_Init(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, &stcOcoInit); /* Initialize OCO high channel */
TIMER4_OCO_Init(TIMER4_UNIT, enOcoLowCh, &stcOcoInit); /* Initialize OCO low channel */
if (!(TIMER4_OCO_HIGH_CH % 2))
{
/* ocmr[15:0] = 0x0FFF */
stcHighChCmpMode.enCntZeroMatchOpState = OcoOpOutputReverse;
stcHighChCmpMode.enCntZeroNotMatchOpState = OcoOpOutputHold;
stcHighChCmpMode.enCntUpCntMatchOpState = OcoOpOutputReverse;
stcHighChCmpMode.enCntPeakMatchOpState = OcoOpOutputReverse;
stcHighChCmpMode.enCntPeakNotMatchOpState = OcoOpOutputHold;
stcHighChCmpMode.enCntDownCntMatchOpState = OcoOpOutputReverse;
stcHighChCmpMode.enCntZeroMatchOcfState = OcoOcfSet;
stcHighChCmpMode.enCntUpCntMatchOcfState = OcoOcfSet;
stcHighChCmpMode.enCntPeakMatchOcfState = OcoOcfSet;
stcHighChCmpMode.enCntDownCntMatchOcfState = OcoOcfSet;
stcHighChCmpMode.enMatchConditionExtendCmd = Disable;
TIMER4_OCO_SetHighChCompareMode(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, &stcHighChCmpMode); /* Set OCO high channel compare mode */
}
/*************Timer4 OCO ocmr1[31:0] = 0x0FF0 0FFF*****************************/
if (enOcoLowCh % 2)
{
/* OCMR[31:0] Ox 0FF0 0FFF 0000 1111 1111 0000 0000 1111 1111 1111 */
stcLowChCmpMode.enCntZeroLowMatchHighMatchLowChOpState = OcoOpOutputReverse; /* bit[27:26] 11 */
stcLowChCmpMode.enCntZeroLowMatchHighNotMatchLowChOpState = OcoOpOutputReverse; /* bit[11:10] 11 */
stcLowChCmpMode.enCntZeroLowNotMatchHighMatchLowChOpState = OcoOpOutputHold; /* bit[31:30] 00 */
stcLowChCmpMode.enCntZeroLowNotMatchHighNotMatchLowChOpState = OcoOpOutputHold; /* bit[15:14] 00 */
stcLowChCmpMode.enCntUpCntLowMatchHighMatchLowChOpState = OcoOpOutputReverse; /* bit[25:24] 11 */
stcLowChCmpMode.enCntUpCntLowMatchHighNotMatchLowChOpState = OcoOpOutputReverse; /* bit[9:8] 11 */
stcLowChCmpMode.enCntUpCntLowNotMatchHighMatchLowChOpState = OcoOpOutputHold; /* bit[19:18] 00 */
stcLowChCmpMode.enCntPeakLowMatchHighMatchLowChOpState = OcoOpOutputReverse; /* bit[23:22] 11 */
stcLowChCmpMode.enCntPeakLowMatchHighNotMatchLowChOpState = OcoOpOutputReverse; /* bit[7:6] 11 */
stcLowChCmpMode.enCntPeakLowNotMatchHighMatchLowChOpState = OcoOpOutputHold; /* bit[29:28] 00 */
stcLowChCmpMode.enCntPeakLowNotMatchHighNotMatchLowChOpState = OcoOpOutputHold; /* bit[13:12] 00 */
stcLowChCmpMode.enCntDownLowMatchHighMatchLowChOpState = OcoOpOutputReverse; /* bit[21:20] 11 */
stcLowChCmpMode.enCntDownLowMatchHighNotMatchLowChOpState = OcoOpOutputReverse; /* bit[5:4] 11 */
stcLowChCmpMode.enCntDownLowNotMatchHighMatchLowChOpState = OcoOpOutputHold; /* bit[17:16] 00 */
stcLowChCmpMode.enCntZeroMatchOcfState = OcoOcfSet; /* bit[3] 1 */
stcLowChCmpMode.enCntUpCntMatchOcfState = OcoOcfSet; /* bit[2] 1 */
stcLowChCmpMode.enCntPeakMatchOcfState = OcoOcfSet; /* bit[1] 1 */
stcLowChCmpMode.enCntDownCntMatchOcfState = OcoOcfSet; /* bit[0] 1 */
TIMER4_OCO_SetLowChCompareMode(TIMER4_UNIT, enOcoLowCh, &stcLowChCmpMode); /* Set OCO low channel compare mode */
}
/* Set OCO compare value */
TIMER4_OCO_WriteOccr(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, u8OcoOccrVal);
TIMER4_OCO_WriteOccr(TIMER4_UNIT, enOcoLowCh, u8OcoOccrVal);
/* Enable OCO */
if(dir == 0)
{
// TIMER4_OCO_OutputCompareCmd(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, Enable);
TIMER4_OCO_OutputCompareCmd(TIMER4_UNIT, enOcoLowCh, Enable);
}
else
{
TIMER4_OCO_OutputCompareCmd(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, Enable);
}
/* Initialize PWM I/O */
PORT_SetFunc(TIMER4_PWM_H_PORT, TIMER4_PWM_H_PIN, Func_Tim4, Disable);
PORT_SetFunc(TIMER4_PWM_L_PORT, TIMER4_PWM_L_PIN, Func_Tim4, Disable);
/* Timer4 PWM: Initialize PWM configuration structure */
stcPwmInit.enRtIntMaskCmd = Enable;
stcPwmInit.enClkDiv = PwmPlckDiv1;
stcPwmInit.enOutputState = E_PWM_OS; /*输出PWMH信号不改变电平,输出PWML信号反转*/
stcPwmInit.enMode = PwmThroughMode;
TIMER4_PWM_Init(TIMER4_UNIT, TIMER4_PWM_CH, &stcPwmInit); /* Initialize timer4 pwm */
/* Clear && Start CNT */
TIMER4_CNT_ClearCountVal(TIMER4_UNIT);
TIMER4_CNT_Start(TIMER4_UNIT);
}
void Timer61A_Init(void)
{
uint16_t u16Period;
@@ -225,7 +387,13 @@ void dcmotor_start(void)
*/
void dcmotor_stop(void)
{
#if(TIMER == TIMER6)
Timer6_StopCount(M4_TMR61);
#endif
#if(TIMER == TIMER4)
TIMER4_CNT_Stop(TIMER4_UNIT);
#endif
}
/**
@@ -236,6 +404,7 @@ void dcmotor_stop(void)
*/
void dcmotor_dir(uint8_t para)
{
#if(TIMER == TIMER6)
Timer6_StopCount(M4_TMR61);
Timer6_DeInit(M4_TMR61);
@@ -252,7 +421,21 @@ void dcmotor_dir(uint8_t para)
}
dcmotor_start();
Timer6_StartCount(M4_TMR61);
#endif
#if(TIMER == TIMER4)
if (para == 0) /* 正转 */
{
Timer41_Init(1);
}
else if (para == 1) /* 反转 */
{
Timer41_Init(0);
}
#endif
}
/**
@@ -266,23 +449,47 @@ void dcmotor_speed(uint16_t para)
if (g_motorSpeed == 0) {
g_motorDirection = DIR_STOPPED;
#if(TIMER == TIMER6)
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, g_motorSpeed);
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, g_motorSpeed);
#endif
#if(TIMER == TIMER4)
TIMER4_OCO_WriteOccr(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, TIMER4_CNT_CYCLE_VAL - g_motorSpeed); //正转
TIMER4_OCO_WriteOccr(TIMER4_UNIT, Timer4OcoOul, TIMER4_CNT_CYCLE_VAL - g_motorSpeed); //反转
#endif
dcmotor_stop();
return;
}
if(Motor_GetDirection() == DIR_REVERSE) //反转
{
#if(TIMER == TIMER6)
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, g_motorSpeed); //Set General Compare RegisterA Value
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareC, g_motorSpeed); //Set General Compare RegisterC Value as buffer register of GCMAR
DBG_LOG("REVERSE\tnewSpeed = %d\r\n", g_motorSpeed);
#endif
#if(TIMER == TIMER4)
// TIMER4_OCO_WriteOccr(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, TIMER4_CNT_CYCLE_VAL - g_motorSpeed); //正转
// TIMER4_OCO_WriteOccr(TIMER4_UNIT, Timer4OcoOul, TIMER4_CNT_CYCLE_VAL - g_motorSpeed); //反转
TIMER4_OCO_WriteOccr(TIMER4_UNIT, Timer4OcoOul, g_motorSpeed); //反转
#endif
DCMOTOR_DBG_LOG("REVERSE\tnewSpeed = %d\r\n", g_motorSpeed);
}
else if(Motor_GetDirection() == DIR_FORWARD) //正转
{
#if(TIMER == TIMER6)
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, 10000-g_motorSpeed); //Set General Compare RegisterA Value
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareC, 10000-g_motorSpeed); //Set General Compare RegisterC Value as buffer register of GCMAR
DBG_LOG("FORWARD\tnewSpeed = %d\r\n", g_motorSpeed);
#endif
#if(TIMER == TIMER4)
TIMER4_OCO_WriteOccr(TIMER4_UNIT, TIMER4_OCO_HIGH_CH, g_motorSpeed); //正转
// TIMER4_OCO_WriteOccr(TIMER4_UNIT, Timer4OcoOul, TIMER4_CNT_CYCLE_VAL - g_motorSpeed); //反转
#endif
DCMOTOR_DBG_LOG("FORWARD\tnewSpeed = %d\r\n", g_motorSpeed);
}
}
@@ -306,13 +513,25 @@ void motor_pwm_set(float para)
{
g_motorDirection = DIR_FORWARD;
dcmotor_dir(0); /* 正转 */
#if(TIMER == TIMER6)
dcmotor_speed(10000-val);
#endif
#if(TIMER == TIMER4)
dcmotor_speed(val);
#endif
}
else
{
g_motorDirection = DIR_REVERSE;
dcmotor_dir(1); /* 反转 */
#if(TIMER == TIMER6)
dcmotor_speed(-val);
#endif
#if(TIMER == TIMER4)
dcmotor_speed(-val);
#endif
}
DCMOTOR_DBG_LOG("dcmotor_speed:%d\r\n", val);
}
@@ -335,21 +554,10 @@ void Motor_SetDirection(uint8_t dir) {
}
uint8_t KeyASta;
uint8_t KeyBSta;
uint8_t RunSta;
// 电机控制接口
void Motor_Control(MotorCommand cmd) {
g_motorCmd = cmd;
if(cmd == MOTOR_CMD_REVERSE)
KeyASta =true;
else if(cmd == MOTOR_CMD_FORWARD)
KeyBSta = true;
else
{
KeyASta = false;
KeyBSta = false;
}
}
// 获取电机当前方向
@@ -399,11 +607,13 @@ void Dcmotor1msRoutine(void)
uint8_t KeyASta;
uint8_t KeyBSta;
uint8_t RunSta;
void DcmotorLoopHandler(void)
{
#if(1)
#if(0)
if((RunSta == false) && (KeyASta == true) && (KeyBSta == false))
@@ -427,7 +637,7 @@ void DcmotorLoopHandler(void)
{
RunSta = true;
Timer61B_Init();
g_motorSpeed = 9500;
g_motorSpeed = MAX_SPEED;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, g_motorSpeed);
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareC, g_motorSpeed);
Timer6_StartCount(M4_TMR61);
@@ -439,7 +649,7 @@ void DcmotorLoopHandler(void)
{
RunSta = true;
Timer61A_Init();
g_motorSpeed = 9500;
g_motorSpeed = MAX_SPEED;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, g_motorSpeed);
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareC, g_motorSpeed);
Timer6_StartCount(M4_TMR61);
@@ -455,7 +665,7 @@ void DcmotorLoopHandler(void)
#endif
#if(0)
#if(1)
if((RunSta == false) && (KeyASta == true) && (KeyBSta == false))
@@ -501,6 +711,8 @@ void DcmotorLoopHandler(void)
// Motor_SetSpeed(ACCEL_STEP); // 初始速度
// motor_pwm_set(ACCEL_STEP);
dcmotor_speed(ACCEL_STEP);
TIMER4_CNT_ClearCountVal(TIMER4_UNIT);
TIMER4_CNT_Start(TIMER4_UNIT);
}
break;
@@ -560,3 +772,9 @@ void DcmotorLoopHandler(void)
#endif
}
@@ -5,12 +5,16 @@
#include "hc32_ddl.h"
#define TIMER4 0
#define TIMER6 1
#define TIMER TIMER4
// 电机控制参数
#define PWM_PERIOD TIM_PERIOD // PWM周期值 (ARR)
#define MAX_SPEED 9900 // 最大速度(PWM占空比)
#define ACCEL_STEP 100 // 加速步进值
#define DECEL_STEP 100 // 减速步进值
#define ACCEL_INTERVAL 5 // 加减速间隔(ms)
#define ACCEL_INTERVAL 2 // 加减速间隔(ms)
@@ -74,19 +78,3 @@ void DcmotorLoopHandler(void);
#endif
@@ -93,10 +93,10 @@ extern "C"
#define DDL_SRAM_ENABLE (DDL_ON)
#define DDL_SWDT_ENABLE (DDL_ON)
#define DDL_TIMER0_ENABLE (DDL_OFF)
#define DDL_TIMER4_CNT_ENABLE (DDL_OFF)
#define DDL_TIMER4_CNT_ENABLE (DDL_ON)
#define DDL_TIMER4_EMB_ENABLE (DDL_OFF)
#define DDL_TIMER4_OCO_ENABLE (DDL_OFF)
#define DDL_TIMER4_PWM_ENABLE (DDL_OFF)
#define DDL_TIMER4_OCO_ENABLE (DDL_ON)
#define DDL_TIMER4_PWM_ENABLE (DDL_ON)
#define DDL_TIMER4_SEVT_ENABLE (DDL_OFF)
#define DDL_TIMER6_ENABLE (DDL_ON)
#define DDL_TIMERA_ENABLE (DDL_OFF)
+40 -2
View File
@@ -7,6 +7,7 @@
#include "Debug.h"
#include "main.h"
#include "bsp.h"
#include "dc_motor.h"
#if (USE_DEBUG != 0)
#define DEBUG_CMD_CNT 8
@@ -213,6 +214,7 @@ void DebugCmdHelp(int argc, char *argv[])
DBG_LOG("Debug Cmd:\r\n\
disp task on/off -->Open the task display.\r\n\
help\
dcmotor\
");
}
@@ -265,13 +267,49 @@ void DebugCmdHelp(int argc, char *argv[])
// TimeSync(num);
//}
extern uint8_t KeyASta;
extern uint8_t KeyBSta;
extern uint8_t RunSta;
void MotorSwitch(int argc, char *argv[])
{
// 如果参数个数小于2,则返回
if(argc < 2)
return;
// 如果第一个参数为?,则打印帮助信息
if(strcmp(argv[1], "?") == 0)
{
DBG_LOG("DCMotor Cmd:\r\n\
motor F/R/S -->Turn the motor on or off.\r\n");
return;
}
// 如果第一个参数为on,则开启SonarWork
if(strcmp(argv[1], "R") == 0)
{
KeyASta = true;
Motor_Control(MOTOR_CMD_REVERSE);
DBG_LOG("Motor FORWARD\r\n");
}
// 如果第一个参数为off,则关闭SonarWork
else if(strcmp(argv[1], "F") == 0)
{
KeyBSta = true;
Motor_Control(MOTOR_CMD_FORWARD);
DBG_LOG("Motor REVERSE\r\n");
}
else if(strcmp(argv[1], "S") == 0)
{
KeyASta = false;
KeyBSta = false;
Motor_Control(MOTOR_CMD_STOP);
DBG_LOG("Motor OFF\r\n");
}
}
const DBGFunType DebugFun[DEBUG_CMD_CNT] = {
"help", DebugCmdHelp,
// "TimeSync", (void*)TimeSync,
// "SetTime", SetTime,
"motor", MotorSwitch,
};
#endif