单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
原理图:



单极性整步驱动,图示中有 5 根线,分别是 A、
B、C、D 以及公共端,公共端是一直通电的,ABCD 相是交替得电的。
第一步:A 相通电,通过电磁原理,电生磁,然后通过磁力把转子吸引到 A 处;
第二步:A 相关闭,B 相通电,转子就会旋转 90°到 B 处;第三步 B 相关闭,C 相通电,
转子会再次旋转 90°,到 C 处,接着第四步:C 相关闭,D 相通电,就会旋转到 D 处,重
复该顺序就可以以 90°的步距角顺时针旋转起来。这种属于单相激励步进,意思就是每步进
一步都只受到了一个磁场的力。

同时两相一起通电,它与上
一种驱动方式的区别是固定在两相中间位置,因为两相同时通入相同的电流此时磁力矢量在
两相中间就会把转子吸引到两相的中间位置,还有一个区别就是这种方式它是受到了两个磁
场的力所以他的输出力矩相对上一种会更大。接着我们看下它的通电顺序:AB---BC---CD---
DA,重复该顺序就可以使电机顺时针旋转起来。像这种方式,相邻的线圈的角度为 90°,
然后转子直接一步到位旋转 90°的方式称为整步驱动。

每步步进的距离为 45°,我们来看下它的通电顺
序:A---AB---B---BC---C---CD---D---DA,重复该步骤,电机就可以以 45°的步距角顺时针
旋转了,同理想要逆时针旋转的话就将通电顺序反过来即可。

电流可以从 A+进去也可以从
A-进去,B 相同理。我们看下它的通电顺序第一步:A 相通电,此时 A+方向接电源正极,
A-接电源负极,那么此时根据电磁原理,产生磁场,异性相吸,就会将转子吸引到第一步的
位置;接着第二步:A 相关闭,B 相通电(B+接正,B-接负),就会吸引转子旋转 90°;第
三步:B 相关闭,A 相通电但是极性与第一步相反(A+接负,A-接正),此时就会吸引转子
继续旋转 90°;第四步:A 相关闭,B 相通电,极性与第 2 步相反,重复该步骤就可以使其
以 90°的步距角顺时针旋转了。

力矩相较于单相会更大,它的通电顺序为:
AB(A+B+接正)---AB(A-B+接正)---AB(A-B-接正)---AB(A+B-接正)重复该顺序即
可顺时针旋转起来。

通电顺序:
第一步:A 相通电(A+接正),B 相不通电;
第二步:AB 相通电(A+B+接正),通入相同电流,产生磁力相同;
第三步:B 相通电(B+接正),A 相不通电
第四步:AB 相通电(A-B+接正),通入相同电流,产生磁力相同;
第五步:A 相通电(A-接正),B 相不通电;
第六步:AB 相通电(A-B-接正),通入相同电流,产生磁力相同;
第七步:B 相通电(B-接正),A 相不通电
第八步:AB 相通电(A+B-接正)通入相同电流,产生磁力相同;
重复上面步骤就可以以 45°的步距角顺时针旋转,与整步相比半步的驱动方式旋转起来
更加的顺滑。

通过改变定子的电流比例,进而控制转子在一个整步中的不同位置,
即可以将一个整步分成多个小步来运行。
一、基础驱动PWM模式
主函数
int main(void)
{
uint8_t key,t,id = 1;
char buf[32];
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
// stepper_init(1000 - 1, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
stepper_init(50000 - 1, 16800 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 5s,方便万用表测试*/
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* LCD显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:ID + +",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:start",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:stop",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
printf("按下KEY0 选择控制哪个步进电机\r\n"); /* 串口打印提示信息 */
printf("按下KEY1 开启步进电机\r\n");
printf("按下KEY2 关闭步进电机\r\n");
printf("当前控制步进电机接口%d\r\n",id);
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES)
{
id++;
if(id > 4)
{
id = 1;
}
printf("当前控制步进电机接口%d\r\n",id); /* 串口打印提示信息 */
sprintf(buf,"Stepper ID: %1d",id); /* 按下KEY0:选择控制哪个步进电机,并显示当前ID */
lcd_show_string(10,90,200,16,16,buf,g_point_color);
}
else if(key == KEY1_PRES) /* 按下KEY1开启电机 */
{
stepper_star(id);
printf("开启步进电机\r\n");
}
else if(key == KEY2_PRES) /* 按下KEY2关闭电机 */
{
stepper_stop(id);
printf("关闭步进电机\r\n");
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
电机配置
/* 步进电机引脚定义*/
#define STEPPER_MOTOR_1 1 /* 步进电机接口序号 */
#define STEPPER_MOTOR_2 2
#define STEPPER_MOTOR_3 3
#define STEPPER_MOTOR_4 4
/* 步进电机方向引脚定义 */
#define STEPPER_DIR1_GPIO_PIN GPIO_PIN_14
#define STEPPER_DIR1_GPIO_PORT GPIOF
#define STEPPER_DIR1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define STEPPER_DIR2_GPIO_PIN GPIO_PIN_12
#define STEPPER_DIR2_GPIO_PORT GPIOF
#define STEPPER_DIR2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define STEPPER_DIR3_GPIO_PIN GPIO_PIN_2
#define STEPPER_DIR3_GPIO_PORT GPIOB
#define STEPPER_DIR3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
#define STEPPER_DIR4_GPIO_PIN GPIO_PIN_2
#define STEPPER_DIR4_GPIO_PORT GPIOH
#define STEPPER_DIR4_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* PH口时钟使能 */
/* 步进电机脱机引脚定义 */
#define STEPPER_EN1_GPIO_PIN GPIO_PIN_15
#define STEPPER_EN1_GPIO_PORT GPIOF
#define STEPPER_EN1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define STEPPER_EN2_GPIO_PIN GPIO_PIN_13
#define STEPPER_EN2_GPIO_PORT GPIOF
#define STEPPER_EN2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define STEPPER_EN3_GPIO_PIN GPIO_PIN_11
#define STEPPER_EN3_GPIO_PORT GPIOF
#define STEPPER_EN3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define STEPPER_EN4_GPIO_PIN GPIO_PIN_3
#define STEPPER_EN4_GPIO_PORT GPIOH
#define STEPPER_EN4_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* PH口时钟使能 */
/*----------------------- 方向引脚控制 -----------------------------------*/
/* 由于我们使用的是共阳极解法,并且硬件对电平做了取反操作,所以当 x = 1有效,x = 0时无效*/
#define ST1_DIR(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_DIR1_GPIO_PORT, STEPPER_DIR1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_DIR1_GPIO_PORT, STEPPER_DIR1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST2_DIR(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_DIR2_GPIO_PORT, STEPPER_DIR2_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_DIR2_GPIO_PORT, STEPPER_DIR2_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST3_DIR(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_DIR3_GPIO_PORT, STEPPER_DIR3_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_DIR3_GPIO_PORT, STEPPER_DIR3_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST4_DIR(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_DIR4_GPIO_PORT, STEPPER_DIR4_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_DIR4_GPIO_PORT, STEPPER_DIR4_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
/*----------------------- 脱机引脚控制 -----------------------------------*/
/* 由于我们使用的是共阳极解法,并且硬件对电平做了取反操作,所以当 x = 1有效,x = 0时无效*/
#define ST1_EN(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_EN1_GPIO_PORT, STEPPER_EN1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_EN1_GPIO_PORT, STEPPER_EN1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST2_EN(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_EN2_GPIO_PORT, STEPPER_EN2_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_EN2_GPIO_PORT, STEPPER_EN2_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST3_EN(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_EN3_GPIO_PORT, STEPPER_EN3_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_EN3_GPIO_PORT, STEPPER_EN3_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define ST4_EN(x) do{ x ? \
HAL_GPIO_WritePin(STEPPER_EN4_GPIO_PORT, STEPPER_EN4_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(STEPPER_EN4_GPIO_PORT, STEPPER_EN4_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
void stepper_star(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_2 :
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_3 :
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_4 :
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4); /* 开启对应PWM通道 */
break;
}
default : break;
}
}
void stepper_stop(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_2 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_3 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_4 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4); /* 关闭对应PWM通道 */
break;
}
default : break;
}
}
定时器配置:
#define ATIM_TIMX_PWM_CH1_GPIO_PORT GPIOI
#define ATIM_TIMX_PWM_CH1_GPIO_PIN GPIO_PIN_5
#define ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOI_CLK_ENABLE(); }while(0) /* PI口时钟使能 */
#define ATIM_TIMX_PWM_CH2_GPIO_PORT GPIOI
#define ATIM_TIMX_PWM_CH2_GPIO_PIN GPIO_PIN_6
#define ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOI_CLK_ENABLE(); }while(0) /* PI口时钟使能 */
#define ATIM_TIMX_PWM_CH3_GPIO_PORT GPIOI
#define ATIM_TIMX_PWM_CH3_GPIO_PIN GPIO_PIN_7
#define ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOI_CLK_ENABLE(); }while(0) /* PI口时钟使能 */
#define ATIM_TIMX_PWM_CH4_GPIO_PORT GPIOC
#define ATIM_TIMX_PWM_CH4_GPIO_PIN GPIO_PIN_9
#define ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口时钟使能 */
#define ATIM_TIMX_PWM_CHY_GPIO_AF GPIO_AF3_TIM8
#define ATIM_TIMX_PWM TIM8
#define ATIM_TIMX_PWM_IRQn TIM8_UP_TIM13_IRQn
#define ATIM_TIMX_PWM_IRQHandler TIM8_UP_TIM13_IRQHandler
#define ATIM_TIMX_PWM_CH1 TIM_CHANNEL_1 /* 通道1 */
#define ATIM_TIMX_PWM_CH2 TIM_CHANNEL_2 /* 通道2 */
#define ATIM_TIMX_PWM_CH3 TIM_CHANNEL_3 /* 通道3 */
#define ATIM_TIMX_PWM_CH4 TIM_CHANNEL_4 /* 通道4 */
#define ATIM_TIMX_PWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM8_CLK_ENABLE(); }while(0) /* TIM8 时钟使能 */
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_PWM_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_atimx_oc_chy_handle.Pulse = arr/2;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE(); /* IO时钟使能 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道x的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN;
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN;
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
}
}
测试结果:

PI5输出方波。
二、基础驱动翻转模式
主函数
int main(void)
{
uint8_t key,t,id = 1;
char buf[32];
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
// stepper_init(0xFFFF, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
stepper_init(0xFFFF, 16800 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:ID + +",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:start",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:stop",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
printf("按下KEY0 选择控制哪个步进电机\r\n"); /* 串口打印提示信息 */
printf("按下KEY1 开启步进电机\r\n");
printf("按下KEY2 关闭步进电机\r\n");
printf("当前控制步进电机接口%d\r\n",id);
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES)
{
id++;
if(id > 4)
{
id = 1;
}
printf("当前控制步进电机接口%d\r\n",id); /* 串口打印提示信息 */
sprintf(buf,"Stepper ID: %1d",id); /* 按下KEY0:选择控制哪个步进电机,并显示当前ID */
lcd_show_string(10,90,200,16,16,buf,g_point_color);
}
else if(key == KEY1_PRES) /* 按下KEY1开启电机 */
{
stepper_star(id);
printf("开启步进电机\r\n");
}
else if(key == KEY2_PRES) /* 按下KEY2关闭电机 */
{
stepper_stop(id);
printf("关闭步进电机\r\n");
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
电机配置
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
void stepper_star(uint8_t motor_num)
{
switch(motor_num)
{
/* 开启对应PWM通道 */
case STEPPER_MOTOR_1 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
void stepper_stop(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
/* 关闭对应PWM通道 */
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
定时器配置
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_OC_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_TOGGLE; /* 翻转模式 */
g_atimx_oc_chy_handle.Pulse = 0;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_LOW;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
HAL_TIM_Base_Start(&g_atimx_handle);
}
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE();
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE();
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE();
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
HAL_NVIC_SetPriority(ATIM_TIMX_INT_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(ATIM_TIMX_INT_IRQn);
}
}
void ATIM_TIMX_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_atimx_handle); /* 定时器共用处理函数 */
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
/*获取当前计数*/
g_count_val = __HAL_TIM_GET_COUNTER(&g_atimx_handle);
/*设置比较数值*/
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH1, (g_count_val + 500)%0XFFFF);
printf("Tim\n");
}
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH2, (g_count_val + 500)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH3, (g_count_val + 500)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH4, (g_count_val + 500)%0XFFFF);
}
测试结果:

/*设置比较数值*/
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH1, (g_count_val + 5000)%0XFFFF);
printf("Tim\n");
}

三、变速控制PWM模式
主函数
int main(void)
{
uint8_t key,t,flag = 0;
uint16_t set_speed;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
stepper_init(1000 - 1, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:start/stop",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:speed +",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:speed -",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
printf("KEY0翻转电机状态,开启/关闭\r\n");
printf("KEY1加速电机\r\n");
printf("KEY2减速电机\r\n");
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES) /* 电机状态翻转 */
{
flag = !flag;
if(flag)
{
stepper_star(STEPPER_MOTOR_1);
}
else
{
stepper_stop(STEPPER_MOTOR_1);
}
}
else if(key == KEY1_PRES) /* 加速 */
{
set_speed -= 50;
if(set_speed <= 50)
{
set_speed = 100;
}
stepper_pwmt_speed(set_speed,ATIM_TIMX_PWM_CH1);
}
else if(key == KEY2_PRES) /* 减速 */
{
set_speed += 100;
if(set_speed >= 2000)
{
set_speed = 2000;
}
stepper_pwmt_speed(set_speed,ATIM_TIMX_PWM_CH1);
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
电机配置
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
void stepper_star(uint8_t motor_num)
{
switch(motor_num)
{
/* 开启对应PWM通道 */
case STEPPER_MOTOR_1 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
void stepper_stop(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
/* 关闭对应PWM通道 */
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
void stepper_pwmt_speed(uint16_t speed,uint32_t Channel)
{
__HAL_TIM_SetAutoreload(&g_atimx_handle,speed);
__HAL_TIM_SetCompare(&g_atimx_handle,Channel,__HAL_TIM_GET_AUTORELOAD(&g_atimx_handle)>>1);
}
定时器配置
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_PWM_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_atimx_oc_chy_handle.Pulse = arr/2;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE(); /* IO时钟使能 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
}
}
测试结果:

四、变速控制翻转模式
主函数
int main(void)
{
uint8_t key,t,flag = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
// stepper_init(0xFFFF-1, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
stepper_init(0xFFFF-1, 16800 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:start/stop",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:speed +",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:speed -",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
printf("KEY0翻转电机状态,开启/关闭\r\n");
printf("KEY1加速电机\r\n");
printf("KEY2减速电机\r\n");
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES) /* 电机状态翻转 */
{
flag = !flag;
if(flag)
{
stepper_star(STEPPER_MOTOR_1);
printf("start\r\n");
}
else
{
stepper_stop(STEPPER_MOTOR_1);
printf("stop\r\n");
}
}
else if(key == KEY1_PRES) /* 加速 */
{
g_ccr_val -= 20;
if(g_ccr_val <= 20)
{
g_ccr_val = 20;
}
printf("val=%d\r\n",g_ccr_val);
}
else if(key == KEY2_PRES) /* 减速 */
{
g_ccr_val += 20;
if(g_ccr_val >= 1000)
{
g_ccr_val = 1000;
}
printf("val=%d\r\n",g_ccr_val);
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
电机配置
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
void stepper_star(uint8_t motor_num)
{
switch(motor_num)
{
/* 开启对应PWM通道 */
case STEPPER_MOTOR_1 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
void stepper_stop(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
/* 关闭对应PWM通道 */
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
定时器配置
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_OC_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_TOGGLE; /* 翻转模式 */
g_atimx_oc_chy_handle.Pulse = 0;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_LOW;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
HAL_TIM_Base_Start(&g_atimx_handle);
}
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE(); /* IO时钟使能 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
HAL_NVIC_SetPriority(ATIM_TIMX_INT_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(ATIM_TIMX_INT_IRQn);
}
}
void ATIM_TIMX_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_atimx_handle); /* 定时器共用处理函数 */
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
/*获取当前计数*/
g_count_val = __HAL_TIM_GET_COUNTER(&g_atimx_handle);
/*设置比较数值*/
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH1, (g_count_val + g_ccr_val)%0XFFFF);
printf("g_count_val=%d\r\n",g_count_val);
}
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH2, (g_count_val + g_ccr_val)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH3, (g_count_val + g_ccr_val)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH4, (g_count_val + g_ccr_val)%0XFFFF);
}
测试结果:


五、定位控制PWM模式
主函数
int main(void)
{
uint8_t key,t;
int angle = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
stepper_init(1000 - 1, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:angle ++",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:angle --",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:start",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
/* 打印提示信息 */
printf("KEY0往正方向增加旋转角度,每次加90°\r\n");
printf("KEY1往反方向增加旋转角度,每次加90°\r\n");
printf("KEY2开启电机\r\n");
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES) /* 按下KEY0增加旋转角度 */
{
if(g_run_flag == 0)
{
angle += 90;
if(angle >= 0)
{
g_stepper.angle = angle;
g_stepper.dir = CW;
}else
{
g_stepper.angle = -angle;
g_stepper.dir = CCW;
}
printf("旋转的角度为:%d\r\n",angle);
}
}
else if(key == KEY1_PRES) /* 按下KEY1增加旋转角度 */
{
if(g_run_flag == 0)
{
angle -= 90;
if(angle >= 0)
{
g_stepper.angle = angle;
g_stepper.dir = CW;
}else
{
g_stepper.angle = -angle;
g_stepper.dir = CCW;
}
printf("旋转的角度为:%d\r\n",angle);
}
}
else if(key == KEY2_PRES) /* 按下KEY2开启电机 */
{
if(g_run_flag == 0)
{
angle = 0; /* 角度清0,以便下次设置 */
stepper_set_angle(g_stepper.angle, g_stepper.dir, STEPPER_MOTOR_1); /* 开启旋转 */
printf("开启旋转\r\n");
}
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
电机
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
void stepper_star(uint8_t motor_num, uint8_t dir)
{
HAL_TIM_Base_Start_IT(&g_atimx_handle);
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
ST1_DIR(dir);
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_2 :
{
ST2_DIR(dir);
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_3 :
{
ST3_DIR(dir);
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3); /* 开启对应PWM通道 */
break;
}
case STEPPER_MOTOR_4 :
{
ST4_DIR(dir);
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4); /* 开启对应PWM通道 */
break;
}
default : break;
}
}
void stepper_stop(uint8_t motor_num)
{
HAL_TIM_Base_Stop_IT(&g_atimx_handle);
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_2 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_3 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3); /* 关闭对应PWM通道 */
break;
}
case STEPPER_MOTOR_4 :
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4); /* 关闭对应PWM通道 */
break;
}
default : break;
}
}
void stepper_set_angle(uint16_t angle, uint8_t dir,uint8_t motor_num)
{
g_stepper.pulse_count = angle / MAX_STEP_ANGLE;
if(g_stepper.pulse_count == 0)
{
stepper_stop(motor_num);
}
else stepper_star(motor_num,dir);
}
定时器
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_PWM_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_atimx_oc_chy_handle.Pulse = arr/2;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE(); /* IO时钟使能 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
HAL_NVIC_SetPriority(ATIM_TIMX_UP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ATIM_TIMX_UP_IRQn);
}
}
void ATIM_TIMX_UP_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_atimx_handle); /* 定时器共用处理函数 */
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM8)
{
g_run_flag = 1; /* 标志位置一 */
g_stepper.pulse_count--; /* 每一个完整的脉冲就-- */
if(g_stepper.dir == CW)
{
g_stepper.add_pulse_count++; /* 绝对位置++ */
}else
{
g_stepper.add_pulse_count--; /* 绝对位置-- */
}
if(g_stepper.pulse_count<=0) /* 当脉冲数等于0的时候 代表需要发送的脉冲个数已完成,停止定时器输出 */
{
printf("累计旋转的角度:%d\r\n",(int)(g_stepper.add_pulse_count*MAX_STEP_ANGLE)); /* 打印累计转动了多少角度 */
stepper_stop(STEPPER_MOTOR_1); /* 停止接口一输出 */
g_run_flag = 0;
}
}
}
测试结果:

六、定位控制翻转模式
主函数
int main(void)
{
uint8_t key,t;
int angle = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
stepper_init(0xFFFF, 168 - 1); /* 168 000 000 / 168 = 1000 000 1Mhz的计数频率 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Stepper Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:angle ++",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:angle --",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:start",g_point_color);
lcd_show_string(10,90,200,16,16,"Stepper ID: 1",g_point_color);
printf("KEY0往正方向增加旋转角度,每次加90°\r\n");
printf("KEY1往反方向增加旋转角度,每次加90°\r\n");
printf("KEY2开启电机\r\n");
while (1)
{
key = key_scan(0);
if(key == KEY0_PRES) /* 按下KEY0增加旋转角度 */
{
if(g_run_flag == 0)
{
angle += 90;
if(angle >= 0)
{
g_stepper.angle = angle;
g_stepper.dir = CW;
}else
{
g_stepper.angle = -angle;
g_stepper.dir = CCW;
}
printf("旋转的角度为:%d\r\n",angle);
}
}
else if(key == KEY1_PRES) /* 按下KEY1增加旋转角度 */
{
if(g_run_flag == 0)
{
angle -= 90;
if(angle >= 0)
{
g_stepper.angle = angle;
g_stepper.dir = CW;
}else
{
g_stepper.angle = -angle;
g_stepper.dir = CCW;
}
printf("旋转的角度为:%d\r\n",angle);
}
}
else if(key == KEY2_PRES) /* 按下KEY2关闭电机 */
{
if(g_run_flag == 0)
{
angle = 0; /* 角度清0,以便下次设置 */
stepper_set_angle(g_stepper.angle, g_stepper.dir, STEPPER_MOTOR_1); /* 开启旋转 */
printf("开启旋转\r\n");
}
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /*LED0(红灯) 翻转*/
}
delay_ms(10);
}
}
电机
void stepper_init(uint16_t arr, uint16_t psc)
{
GPIO_InitTypeDef gpio_init_struct;
STEPPER_DIR1_GPIO_CLK_ENABLE(); /* DIR1时钟使能 */
STEPPER_DIR2_GPIO_CLK_ENABLE(); /* DIR2时钟使能 */
STEPPER_DIR3_GPIO_CLK_ENABLE(); /* DIR3时钟使能 */
STEPPER_DIR4_GPIO_CLK_ENABLE(); /* DIR4时钟使能 */
STEPPER_EN1_GPIO_CLK_ENABLE(); /* EN1时钟使能 */
STEPPER_EN2_GPIO_CLK_ENABLE(); /* EN2时钟使能 */
STEPPER_EN3_GPIO_CLK_ENABLE(); /* EN3时钟使能 */
STEPPER_EN4_GPIO_CLK_ENABLE(); /* EN4时钟使能 */
gpio_init_struct.Pin = STEPPER_DIR1_GPIO_PIN; /* DIR1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; /* 低速 */
HAL_GPIO_Init(STEPPER_DIR1_GPIO_PORT, &gpio_init_struct); /* 初始化DIR1引脚 */
gpio_init_struct.Pin = STEPPER_DIR2_GPIO_PIN; /* DIR2引脚 */
HAL_GPIO_Init(STEPPER_DIR2_GPIO_PORT, &gpio_init_struct); /* 初始化DIR2引脚 */
gpio_init_struct.Pin = STEPPER_DIR3_GPIO_PIN; /* DIR3引脚 */
HAL_GPIO_Init(STEPPER_DIR3_GPIO_PORT, &gpio_init_struct); /* 初始化DIR3引脚 */
gpio_init_struct.Pin = STEPPER_DIR4_GPIO_PIN; /* DIR4引脚 */
HAL_GPIO_Init(STEPPER_DIR4_GPIO_PORT, &gpio_init_struct); /* 初始化DIR4引脚 */
/* 脱机引脚初始化 */
gpio_init_struct.Pin = STEPPER_EN1_GPIO_PIN; /* EN1引脚 */
HAL_GPIO_Init(STEPPER_EN1_GPIO_PORT, &gpio_init_struct); /* 初始化EN1引脚 */
gpio_init_struct.Pin = STEPPER_EN2_GPIO_PIN; /* EN2引脚 */
HAL_GPIO_Init(STEPPER_EN2_GPIO_PORT, &gpio_init_struct); /* 初始化EN2引脚 */
gpio_init_struct.Pin = STEPPER_EN3_GPIO_PIN; /* EN3引脚 */
HAL_GPIO_Init(STEPPER_EN3_GPIO_PORT, &gpio_init_struct); /* 初始化EN3引脚 */
gpio_init_struct.Pin = STEPPER_EN4_GPIO_PIN; /* EN4引脚 */
HAL_GPIO_Init(STEPPER_EN4_GPIO_PORT, &gpio_init_struct); /* 初始化EN4引脚 */
atim_timx_oc_chy_init(arr, psc); /* 初始化PUL引脚,以及脉冲模式等 */
}
/**
* @brief 开启步进电机
* @param motor_num: 步进电机接口序号
* @param dir : 步进电机旋转方向
* @retval 无
*/
void stepper_star(uint8_t motor_num, uint8_t dir)
{
switch(motor_num)
{
/* 开启对应PWM通道 */
case STEPPER_MOTOR_1 :
{
ST1_DIR(dir);
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
ST2_DIR(dir);
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
ST3_DIR(dir);
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
ST4_DIR(dir);
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Start(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Start_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
/**
* @brief 关闭步进电机
* @param motor_num: 步进电机接口序号
* @retval 无
*/
void stepper_stop(uint8_t motor_num)
{
switch(motor_num)
{
case STEPPER_MOTOR_1 :
{
/* 关闭对应PWM通道 */
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH1);
}
break;
}
case STEPPER_MOTOR_2 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH2);
}
break;
}
case STEPPER_MOTOR_3 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH3);
}
break;
}
case STEPPER_MOTOR_4 :
{
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM1||g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_PWM2)
{
HAL_TIM_PWM_Stop(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
if(g_atimx_oc_chy_handle.OCMode == TIM_OCMODE_TOGGLE)
{
HAL_TIM_OC_Stop_IT(&g_atimx_handle, ATIM_TIMX_PWM_CH4);
}
break;
}
default : break;
}
}
/**
* @brief 将需要转动的角度转换成脉冲数
* @param angle : 需要转动的角度值
* @param dir : 旋转方向
* @param motor_num: 步进电机接口序号
* @retval 无
*/
void stepper_set_angle(uint16_t angle, uint8_t dir,uint8_t motor_num)
{
g_stepper.pulse_count = angle / MAX_STEP_ANGLE;
if(g_stepper.pulse_count == 0)
{
stepper_stop(motor_num);
}
else stepper_star(motor_num,dir);
}
定时器
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /* 使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_OC_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_TOGGLE; /* 翻转模式 */
g_atimx_oc_chy_handle.Pulse = 0;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_LOW;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
HAL_TIM_OC_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH4); /* 配置TIMx通道y */
HAL_TIM_Base_Start(&g_atimx_handle);
}
/**
* @brief 定时器底层驱动,时钟使能,引脚配置
此函数会被HAL_TIM_OC_Init()调用
* @param htim:定时器句柄
* @retval 无
*/
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启通道y的GPIO时钟 */
ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* IO时钟使能 */
ATIM_TIMX_PWM_CH4_GPIO_CLK_ENABLE(); /* IO时钟使能 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = ATIM_TIMX_PWM_CH4_GPIO_PIN; /* 通道y的GPIO口 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CH4_GPIO_PORT, &gpio_init_struct);
HAL_NVIC_SetPriority(ATIM_TIMX_INT_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(ATIM_TIMX_INT_IRQn);
}
}
/**
* @brief 高级定时器TIMX NPWM中断服务函数
* @param 无
* @retval 无
*/
void ATIM_TIMX_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_atimx_handle); /* 定时器共用处理函数 */
}
/**
* @brief 定时器比较中断
* @param htim:定时器句柄指针
* @note 无
* @retval 无
*/
uint8_t i = 0;
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
i++;
if(i % 2 == 0)
{
i = 0;
g_run_flag = 1;
g_stepper.pulse_count --; /* 每一个完整的脉冲就-- */
if(g_stepper.dir == CW) /* 正转 */
{
g_stepper.add_pulse_count++; /* 绝对位置++ */
}else
{
g_stepper.add_pulse_count--; /* 绝对位置-- */
}
if(g_stepper.pulse_count <= 0) /* 当脉冲数等于0的时候 代表需要发送的脉冲个数已完成,停止定时器输出 */
{
printf("累计旋转的角度:%d\r\n",(int)(g_stepper.add_pulse_count*MAX_STEP_ANGLE)); /* 打印累计转动了多少角度 */
stepper_stop(STEPPER_MOTOR_1); /* 停止接口一输出 */
g_run_flag = 0;
}
}
/*获取当前计数*/
g_count_val = __HAL_TIM_GET_COUNTER(&g_atimx_handle);
/*设置比较数值*/
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH1, (g_count_val + g_ccr_val)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH2, (g_count_val + g_ccr_val)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH3, (g_count_val + g_ccr_val)%0XFFFF);
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
__HAL_TIM_SET_COMPARE(&g_atimx_handle, ATIM_TIMX_PWM_CH4, (g_count_val + g_ccr_val)%0XFFFF);
}
测试结果:
