7. 步进电机

7.1. 介绍

步进电机又称为脉冲电机,基于最基本的电磁铁原理,它是一种可以自由回转的电磁铁,其动作原理是依靠气隙磁导的变化来产生电磁转矩。 由于步进电机是一个可以把电脉冲转换成机械运动的装置,具有很好的数据控制特性,因此,计算机成为步进电机的理想驱动源, 随着微电子和计算机技术的发展,软硬件结合的控制方式成为了主流,即通过程序产生控制脉冲,驱动硬件电路。单片机通过软件来控制步进电机, 更好地挖掘出了电机的潜力。在不超载的情况下电机的转速和停止位置只取决于脉冲信号的频率和数量; 并且步进电机的脉冲与步进旋转的角度成正比,脉冲的频率与步进的转速成正比,所以可以很好的从源头控制信号的输出; 且步进电机只有周期性的误差,使得在速度、位置等控制领域用步进电机来控制变的非常的简单。话虽如此,想要玩转步进也不是件容易的事情。

../../_images/step_motor_pic.png

混合式步进电机拆解图

7.2. 工作原理

通常步进电机的转子为永磁体,当电流流过定子绕组时,定子绕组产生一矢量磁场。磁场会带动转子旋转一定的角度, 使得转子的一对磁场方向与定子的磁场方向一致。当定子的矢量磁场旋转一个角度。转子也随着该磁场转步距角。 每输入一个电脉冲,电动机转动一个角度前进一步。它输出的角位移与输入的脉冲数成正比、转速与脉冲频率成正比。 改变绕组通电的顺序,电机就会反转。所以可用控制脉冲数量、频率及电动机各相绕组的通电顺序来控制步进电机的转动。具体看下图:

../../_images/step_dingzi.png

步进电机横截图

7.2.1. 步进电机极性区分

步进电机又分为单极性的步进电机和双极性的步进电机;具体简易图如下图所示:

../../_images/unipolar.png

其中左侧为单极性步进电机,右侧为双极性的步进电机,从上图中不难看出区别是什么。单双极性是指一个步进电机里面有几种电流的流向, 左侧的五线四相步进电机就是单极性的步进电机,图中的红色箭头为电流的走向,四根线的电流走向汇总到公共线,所以称之为单极性电机; 但是右侧则不同,电机中有两个电流的回路,两个电流的回路自然就是双极性,所以称之为双极性电机。

单极性绕组

单极性步进电机使用的是单极性绕组。其一个电极上有两个绕组,这种联接方式为当一个绕组通电时,产生一个北极磁场; 另一个绕组通电,则产生一个南极磁场。因为从驱动器到线圈的电流不会反向,所以可称其为单极绕组。

双极性绕组

双极性步进电机使用的是双极性绕组。每相用一个绕组,通过将绕组中电流反向,电磁极性被反向。 典型的两相双极驱动的输出步骤在电气原理图和下图中的步进顺序中进一步阐述。 按图所示,转换只利用绕组简单地改变电流的方向,就能改变该组的极性。

../../_images/Field_polarity.png

永磁步进电机包括一个永磁转子、线圈绕组和导磁定子,只要将线圈通电根据电磁铁的原理就会产生磁场,分为南北极,见上图所示; 通过改变步进电机定子的磁场,转子就会因磁场的变化而发生转动,同理,依次改变通电的顺序就可以使得电机转动起来。

7.2.2. 双极性步进电机驱动原理

下图是一个双极性的步进电机整步,步进顺序。 在第一步中:将A相通电,根据电磁铁原理,产生磁性,并且因异性相吸,所以磁场将转子固定在第一步的位置; 第二步:当A相关闭,B相通电时,转子会旋转90°; 第三步:B相关闭、A相通电,但极性与第1步相反,这促使转子再次旋转90°。 在第四步中:A相关闭、B相通电,极性与第2步相反。重复该顺序促使转子按90°的步距角顺时针旋转。

../../_images/Bipolar_pacing.png

上图中显示的步进顺序是单相激励步进,也可以理解为每次通电产生磁性的相只有一个,要么A相,要么B相; 但是更常用的是双相激励,但是在转换时,一次只能换相一次,具体详见下图:

../../_images/Bipolar_half_step.png

上图是两相同时通电的旋转顺序,与单相激励不同的是,单相通电后被固定在了与定子正对着的绕组极性, 但是双相同时激励时转子却被固定在两个绕阻的极性中间;此时通电顺序就变成了AB相同时通电即可。

在双相激励的过程中,也可以在装换相位时加一个关闭相位的状态而产生走半步的现象,这将步进电机的整个步距角一分为二, 例如,一个90°的步进电机将每半步移动45°,具体见下图。

../../_images/Biphasic_excitation_half_step.png
  1. A相通电,B相不通电

  2. A、B相全部通电,且电流相同,产生相同磁性

  3. B相通电,A断电

  4. B相通电,A相通电,且电流相等,产生相同磁性

  5. A相通电,B断电

  6. A、B相全部通电,且电流相同,产生相同磁性

  7. B相通电,A断电

  8. B相通电,A相通电,且电流相等,产生相同磁性

其中1~4步与5~8步的电流方向相反(电流相反,电磁的极性就相反)这样就产生了顺时针旋转,同理逆时针是 将通电顺序反过来即可。

7.2.3. 单极性步进电机驱动原理

单极性与双极性步进电机驱动类似,都可以分为整步与半步的驱动方式,不同的是,双极性的步进电机可以通过改变 电流的方向来改变每相的磁场方向,但是单极性的就不可以了,它有一个公共端,这就直接决定了,电流方向。具体旋转顺序详见下图:

../../_images/Unipolar_pacing.png

上图是单极性步进电机整步旋转的过程,其中,在图示中分为5根线,分别为A、B、C、D和公共端(+),公共端需要一直通电, 剩下ABCD相中只要有一个相通电,即可形成回路产生磁场,图中的通电顺序为A->B->C->D,即可完成上图中的顺时针旋转, 如果想要逆时针旋转只需要将其倒序即可。

以上是单相通电产生的整步旋转,两相通电也可以产生,两个相邻的相通电,这样相邻的两个相就都产生了回路,也就产生了磁场, 图中的通电顺序为AB->BC->CD->DA,同理逆时针旋转的顺序为逆序。具体看下图:

../../_images/Unipolar_half_step.png

上面两张图清晰的描述了单极性步进电机的通电顺序与旋转的过程,综合这两张图就是单极性步进电机半步的通电顺序,具体看下图:

../../_images/Unipolar_step_half_step.png

上图兼容了前两张图的所有特点,也可以说前两张图是这张图的子集,图中的通电顺序为:A->AB->B->BC->C->CD->D->DA 转子每次只走半步45度,所以这也被称为半步驱动,与整步相比半步的旋转方式旋转起来更加的顺滑。

7.2.4. 细分器驱动原理

对于细分驱动的原理,不分单双极步进电机,下图以单极为例:

../../_images/Principle_current_subdivision.png

在上图中均为双相激励;其中图(a)为A相电流很大,B相的电流极其微弱,接近0; 图(C)为A相和B相的电流相同,电流决定磁场,所以说A相和B相的磁场也是相同的,(a)和(c)可以是极限特殊的情况, 再看图(b)和图(d)这两个是由于A相和B相的电流不同产生位置情况;由此可以得出改变定子的电流比例就可以使得转子在任意角度停住。 细分的原理就是:通过改变定子的电流比例,改变转子在一个整步中的不同位置,可以将一个整步分成多个小步来运行。

在上图中就是一个整步分成了4步来跑,从(a)~(d)是A相的电流逐渐减小,B相电流逐渐增大的过程,如果驱动器的细分能力很强, 可以将其分成32细分、64细分等;这不仅提高了步进电机旋转的顺畅度而且提高了每步的精度。

7.3. 技术指标术语

7.3.1. 静态指标术语

  • 相数:产生不同对极N、S磁场的激磁线圈对数,也可以理解为步进电机中线圈的组数,其中两相步进电机步距角为1.8°, 三相的步进电机步距角为1.5°,相数越多的步进电机,其步距角就越小。

  • 拍数:完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例, 有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即 A-AB-B-BC-C-CD-D-DA-A。

  • 步距角:一个脉冲信号所对应的电机转动的角度,可以简单理解为一个脉冲信号驱动的角度,电机上都有写,一般42步进电机的步距角为1.8°

  • 定位转矩:电机在不通电状态下,电机转子自身的锁定力矩(由磁场齿形的谐波以及机械误差造成的)。

  • 静转矩:电机在额定静态电压作用下,电机不作旋转运动时,电机转轴的锁定力矩。此力矩是衡量电机体积的标准,与驱动电压及驱动电源等无关。

7.3.2. 动态指标术语

  • 步距角精度:步进电机转动一个步距角度的理论值与实际值的误差。用百分比表示:误差/步距角*100%。

  • 失步:电机运转时运转的步数,不等于理论上的步数。也可以叫做丢步,一般都是因负载太大或者是频率过快。

  • 失调角:转子齿轴线偏移定子齿轴线的角度,电机运转必存在失调角,由失调角产生的误差,采用细分驱动是不能解决的。

  • 最大空载起动频率:在不加负载的情况下,能够直接起动的最大频率。

  • 最大空载的运行频率:电机不带负载的最高转速频率。

  • 运行转矩特性:电机的动态力矩取决于电机运行时的平均电流(而非静态电流),平均电流越大,电机输出力矩越大,即电机的频率特性越硬。

  • 电机正反转控制:通过改变通电顺序而改变电机的正反转。

7.4. 主要特点

  1. 步进电机的精度大概为步距角的3-5%,且不会积累

  2. 步进电机的外表允许的最高温度:一般步进电机会因外表温度过高而产生磁性减小,从而会导致力矩较小, 一般来说磁性材料的退磁点都在摄氏130度以上,有的甚至高达摄氏200度以上,所以步进电机外表温度在摄氏80-90度完全正常。

  3. 步进电机的转矩与速度成反比,速度越快力矩越小。

  4. 低速时步进电机可以正常启动,高速时不会启动,并伴有啸叫声。步进电机的空载启动频率是固定的, 如果高于这个频率电机不能被启动并且会产生丢步或者堵转。

7.5. 驱动器简介

步进电机必须要有控制器和驱动器才可以使电机正常工作,控制器是瑞萨RA或者其它型号的MCU了,驱动器就是步进电机驱动器了。 为什么要使用驱动器呢?驱动器起到将控制器信号放大或者转换的作用,如下图所示,控制器输出方向信号和脉冲信号来控制步进电机驱动器, 驱动器将其功率放大然后作用到步进电机上。

../../_images/xifenqi.png

7.5.1. 野火步进电机细分器介绍

BHMSD4805是野火科技推出的一款智能步进电机驱动器。它是一款以双极恒流PWM驱动输出控制电机的驱动器,驱动电压范围DC12V~48V, 适合外径为42mm、 57mm、86mm系列,驱动电流在5A以下的所有两相混合式步进电机。 根据驱动器提供的8位拨码开关可以轻松的实现对不同电机电流及不同细分步数的精确控制。带有自动半流技术, 可以大大降低电机的功耗及发热量,输入信号都经过光耦隔离,具有很强的抗干扰能力,能适应恶劣的工作环境,下图为产品实物图。

../../_images/step_xifen.png

驱动器性能表

参数

说明

额定电压

直流:

12V~48V

额定电流

0.75A~5.0A

驱动方式

双极恒流PWM驱动输出

工作温度

0℃~80℃

结构尺寸

118*75.5*33

单位mm

应用领域

数控设备、雕刻机等设备

7.5.2. 模块引脚说明

驱动器右侧分别是电源及故障指示灯、控制信号接口、参数设定拨码开关、电源驱动接口,在其端子的正,上方是对应引脚名称的丝印。

控制信号引脚如下表所示:

序号

引脚名称

引脚定义

1

ENA-(ENA)

输出使能负端

2

ENA+(5V)

输出使能正端

3

DIR-(DIR)

方向控制负端

4

DIR+(5V)

方向控制正端

5

PUL-(PLU)

脉冲控制负端

6

PUL+(5V)

脉冲控制正端

  • ENA功能说明:控制器的输出是通过该组信号使能,又称脱机信号。当此信号有效时,输出关闭,电机绕组电流为零, 电机为无力矩状态,可以自由转动电机,适合需要手动调整电机的场合。

  • DIR功能说明:电机的方向控制信号,当此信号有效时,电机顺时针转动,当此信号无效时,电机逆时针旋转。

  • PUL功能说明:电机的转动控制信号,驱动器接收到的脉冲信号电机就会按照既定的方向旋转。电机的角位移与脉冲的数量成正比, 速度与脉冲的频率成正比。通常脉冲的有效宽度>=5us,频率<=125KHz。

拨码开关引脚如下表所示:

序号

引脚名称

引脚定义

1

SW1~SW4

细分设定

2

SW5~SW8

电流设定

细分参数设置

驱动器的细分设置由拨码开关的SW1~SW4来设定,默认为100细分,一般的两相四线制步进电机的步进角都是1.8°, 因此电机旋转一圈需要360° /1.8° =200个脉冲,这里100细分转一圈 需要的脉冲数为200*100=20000个。具体详见下表:

细分

脉冲

SW1

SW2

SW3

SW4

2

400

ON

ON

ON

ON

4

800

OFF

ON

ON

ON

8

1600

ON

OFF

ON

ON

16

3200

OFF

OFF

ON

ON

32

6400

ON

ON

OFF

ON

64

12800

OFF

ON

OFF

ON

128

25600

ON

OFF

OFF

ON

3

600

OFF

OFF

OFF

ON

6

1200

ON

ON

ON

OFF

12

2400

OFF

ON

ON

OFF

36

7200

ON

OFF

ON

OFF

5

1000

OFF

OFF

ON

OFF

10

2000

ON

ON

OFF

OFF

20

4000

OFF

ON

OFF

OFF

50

10000

ON

OFF

OFF

OFF

100

20000

OFF

OFF

OFF

OFF

电流参数设置

驱动器的电流设置由拨码开关的SW5~SW8来设定,默认为1.5A。这个电流值需要根据步进电机的额定电流来设定。 一般建议驱动器的输出电流设定和电机额定电流差不多或者小一点,详细设定见下表:

电流

SW5

SW6

SW7

SW8

0.75A

OFF

OFF

OFF

ON

1.00A

ON

OFF

OFF

ON

1.25A

OFF

ON

OFF

ON

1.50A

OFF

OFF

OFF

OFF

1.75A

OFF

OFF

ON

ON

2.00A

ON

OFF

OFF

OFF

2.25A

OFF

ON

ON

ON

2.50A

OFF

ON

OFF

OFF

3.00A

ON

ON

OFF

OFF

3.50A

OFF

OFF

ON

OFF

4.00A

ON

OFF

ON

OFF

4.50A

OFF

ON

ON

OFF

5.00A

ON

ON

ON

OFF

接线方式

驱动器与控制器共有两种接线方式,分别为共阴极接法和供阳极接法:

共阴极接法如图所示:

../../_images/jiefa1.png

共阳极接法如图所示:

../../_images/jiefa2.png

驱动器引脚

电机绕组接线

A+

黑色

A-

绿色

B+

红色

B-

蓝色

当输入信号高于5V时,可根据需要外接限流电阻。

7.6. 步进电机基础旋转控制

在本章前几个小节对步进电机的工作原理、特点以及驱动器的进行了详细的讲解, 本小节将使用 PWM 对最基本的控制方法,包括电机的启动、停止、转向、加减速等。

7.6.1. 硬件设计

介绍步进电机的电路与接线方法

隔离电路

步进电机光耦隔离部分电路

../../_images/Stepper_motor_interface_isolation.png

上图为原理图中的隔离电路,其中主要用到的是高速的光耦进行隔离,在这里隔离不仅可以防止外部电流倒灌, 损坏芯片,还有增强驱动能力的作用;并且在开发板这端已经默认为共阳极接法了,可以将步进电机的所有线按照对应的顺序接在端子上, 也可以在驱动器一端实现共阴或者共阳的接法。

接线方法

接线的方法可以查看 模块引脚说明 章节,里面有详细的介绍。

7.6.2. 软件设计

7.6.2.1. 新建工程

我们直接在串口章节的 “003_Basic_UART_Receive_Send” 例程的基础上修改程序。

对于 e2 studio 开发环境:

拷贝一份我们之前的 e2s 工程 “003_Basic_UART_Receive_Send”, 然后将工程文件夹重命名为 “300_Motor_Stepper_PWM_Control”,最后再将它导入到我们的 e2 studio 工作空间中。

对于 Keil 开发环境:

拷贝一份我们之前的 Keil 工程 “003_Basic_UART_Receive_Send”, 然后将工程文件夹重命名为 “300_Motor_Stepper_PWM_Control”,并进入该文件夹里面双击 Keil 工程文件,打开该工程。

工程新建好之后,在工程根目录的 “src” 文件夹下面新建 “motor_controls” 文件夹, 再进入 “motor_controls” 文件夹里面新建源文件和头文件:“bsp_motor_control.c” 和 “bsp_motor_control.h”。 工程文件结构如下。

文件结构
300_Motor_Stepper_PWM_Control
├─ ......
└─ src
   ├─ beep
   │  ├─ bsp_beep.c
   │  └─ bsp_beep.h
   ├─ debug_uart
   │  ├─ bsp_debug_uart.c
   │  └─ bsp_debug_uart.h
   ├─ key
   │  ├─ bsp_key_irq.c
   │  └─ bsp_key_irq.h
   ├─ led
   │  ├─ bsp_led.c
   │  └─ bsp_led.h
   ├─ motor_controls
   │  ├─ bsp_motor_control.c   //新建文件
   │  └─ bsp_motor_control.h   //新建文件
   └─ hal_entry.c

7.6.2.2. FSP配置

下面以野火启明6T2开发板为例来讲解相关的 FSP 配置。

本节实验中,使用步进电机驱动接口1来进行实验,关于引脚部分已经在硬件设计中展示。

需要先在“Pins”配置页中,将 C08E12 引脚设置为输出模式。 接下来为 GPT 配置引脚,我们将 GPT7 的 GTIOC7B 信号输出连接到 PE13 引脚,如下图所示。

图

然后在“Stacks”配置页中添加 GPT 模块,并对其作如下图所示的配置。

图

上图中框起来的部分是需要我们去修改的区域,其他的配置属性按照默认即可。 图中需要更改的一部分配置如下:

  • Pin Output Support:这一项配置允许输出 PWM 信号到引脚,我们改为使能引脚输出。

  • NameChannel:这两项分别设置 GPT 模块名字为 “step_pwm” 和选择第 7 个 GPT 定时器(第7个通道)。

  • Mode:配置 GPT 的工作模式为周期 PWM 输出模式。

  • PeriodPeriod Unit:我们将PWM频率设为 10 KHz,这里只是随意设置,之后在程序中需要进行修改。

  • GTIOCB Output Enabled:使能 GTIOCB 输出。

  • GTIOCB Stop Level:设置定时器停止时 GTIOCB 输出的电平为低电平。

  • GTIOC7A:选择连接到 PE13 引脚,这个软件会自动设置的,我们只要确认了就好。

7.6.2.3. 定时器初始化函数

代码清单7-1:定时器初始化函数
/* 定时器初始化函数 */
void initMotor(void)
{
    fsp_err_t err = FSP_SUCCESS;
    /* 初始化 GPT 模块 */
    err = R_GPT_Open(&step_pwm_ctrl, &step_pwm_cfg);
    assert(FSP_SUCCESS == err);

    /* 启动 GPT 定时器 */
    err = R_GPT_Start(&step_pwm_ctrl);
    assert(FSP_SUCCESS == err);
}

7.6.2.4. 宏定义操作函数

该例程使用了一系列宏定义来实现步进电机的控制。首先, STEP_ENABLEDSTEP_DISABLED 宏定义用来控制步进电机的启用和禁用,通过设置相应的引脚电平来实现。 STEP_CWSTEP_CCW 宏定义用于设置电机的旋转方向,分别控制电机的顺时针和逆时针转动。

为了方便反转电机的状态和方向,定义了 STEP_STATE_TOGGLESTEP_DIRECTION_TOGGLE 宏,它们能够通过切换相应的引脚电平来改变电机的使能状态和旋转方向。 这样可以快速实现电机状态的切换和方向的反转。

此外, Hz_Set(frequency_hz) 宏定义根据给定的目标频率计算定时器的周期值。 通过调整PWM频率,控制单位时间内的脉冲数,从而精确控制电机的转速。 具体来说,电机在32细分模式下,每一圈需要6400个脉冲,这个宏定义确保在需要的频率下能够生成正确的脉冲数,从而保证电机的精准控制。 通过这些宏定义,不仅提高了代码的可读性,还能够方便地调整电机的各项控制参数。

代码清单6-3:电机初始化函数
/* 步进电机使能控制 */
#define STEP_ENABLED       R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_13_PIN_12, BSP_IO_LEVEL_LOW)   // 步进电机使能
#define STEP_DISABLED      R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_13_PIN_12, BSP_IO_LEVEL_HIGH)  // 步进电机禁用

/* 步进电机方向控制 */
#define STEP_CW            R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_14_PIN_10, BSP_IO_LEVEL_HIGH)  // 设置步进电机顺时针方向
#define STEP_CCW           R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_14_PIN_10, BSP_IO_LEVEL_LOW)   // 设置步进电机逆时针方向

/* 步进电机状态及方向反转 */
#define STEP_STATE_TOGGLE      R_PORT13->PODR ^= 1 << (BSP_IO_PORT_13_PIN_12 & 0xFF)  // 切换步进电机的使能状态
#define STEP_DIRECTION_TOGGLE  R_PORT14->PODR ^= 1 << (BSP_IO_PORT_14_PIN_10 & 0xFF)  // 切换步进电机的方向

/* 定时器时钟频率 */
#define TIMER_CLK_FREQ       120000000  // 定时器时钟频率为 120 MHz

/* 计算目标频率对应的定时器周期值 */
#define Hz_Set(frequency_hz) ((TIMER_CLK_FREQ / (frequency_hz)) - 1)  // 根据目标频率计算周期值

/* 电机单圈参数 */
#define STEP_ANGLE           1.8f                        // 步进电机步距角(单位:度)
#define FSPR                 (360.0f / STEP_ANGLE)       // 电机一圈所需步数(无细分)

#define MICRO_STEP           32                          // 细分数
#define SPR                  ((uint32_t)(FSPR * MICRO_STEP))  // 细分后电机一圈所需脉冲数
#define QUARTER_SPR          (SPR / 4)                   // 细分后四分之一圈所需脉冲数

/* 步进电机 PWM 参数 */
#define PWM_MAX_FREQUENCY    19200  // 步进电机最大频率
#define PWM_MIN_FREQUENCY    1600   // 步进电机最小频率

7.6.2.5. 电机控制函数

该代码段提供了完整的步进电机控制功能,包括启动、停止、反转方向和设置速度。以下是对每个函数的简要说明:

  • Motor_Control_Start:启动电机,使能电机并启用定时器PWM输出,以开始控制步进电机。

  • Motor_Control_Stop:停止电机,禁用电机并停止定时器PWM输出,从而停止电机的运动。

  • Motor_Control_Reverse:反转电机方向,通过切换控制引脚的状态来改变电机的旋转方向。

  • Motor_Control_SetSpeed:控制电机速度,通过调整定时器的周期来设置步进电机的速度, speed_hz 是目标速度,单位是 Hz,调用 R_GPT_PeriodSet 来设置定时器周期。

代码清单7-电机控制函数
/**
* @brief  启动电机
*/
void Motor_Control_Start(void)
{
   STEP_ENBLED; // 使能电机
   R_GPT_Start(&step_pwm_ctrl);// 使能定时器7的PWM输出

}

/**
* @brief  停止电机
*/
void Motor_Control_Stop(void)
{
   STEP_DISENBLED;              // 禁用电机
   R_GPT_Stop(&step_pwm_ctrl);  // 禁用定时器7的PWM输出
}

/**
* @brief  反转电机方向
*/
void Motor_Control_Reverse(void)
{
   motor_dir = !motor_dir;      // 切换电机方向
   STEP_DIRECTION_TOGGLE;      // 切换电机方向控制引脚
}

/**
* @brief  控制电机速度
* @param[in] speed_hz 目标速度,单位:Hz
* @retval 无
*/
void Motor_Control_SetSpeed(uint32_t speed_hz)
{
   // 使用 R_GPT_PeriodSet 来设置定时器周期,从而控制 PWM 输出频率
   R_GPT_PeriodSet(&step_pwm_ctrl, Hz_Set(speed_hz));
}

7.6.2.6. 串口接收控制函数

本届实验中,使用了串口来调试电机,所以还要在 bsp_debug_uart.c 文件中进行修改。

代码清单6-5:串口接收控制函数
// 定义 Order 变量,初始化为空字符
char Order = '\0';

/* 串口中断回调 */
void debug_uart9_callback (uart_callback_args_t * p_args)
{
    switch (p_args->event)
    {
        case UART_EVENT_RX_CHAR:
        {
            // 将接收到的的值转换为 char 类型,并赋值给 Order
            Order = (char)(p_args->data);
            break;
        }
        case UART_EVENT_TX_COMPLETE:
        {
            uart_send_complete_flag = true;
            break;
        }
        default:
            break;
    }
}

7.6.2.7. 命令处理函数

在这个函数中,Process_Motor_Command 用于根据用户输入的命令执行相应的电机控制操作。各个命令的具体功能如下:

  • ‘S’:启动电机,调用 Motor_Control_Start 启动电机,并输出启动信息。

  • ‘P’:停止电机,调用 Motor_Control_Stop 停止电机,并输出停止信息。

  • ‘U’:增加电机速度,如果当前频率已接近最大值,则将其设置为最大频率,否则以 0.25 转/秒加速电机(增加 PWM 频率),并设置定时器周期以更新电机速度。

  • ‘D’:减少电机速度,如果当前频率已接近最小值,则将其设置为最小频率,否则以 0.25 转/秒减速电机(减少 PWM 频率),并设置定时器周期以更新电机速度。

  • ‘R’:反转电机方向,调用 Motor_Control_Reverse 反转电机方向,并输出当前的旋转方向(正向或反向)。

  • default:无效命令,命令被清空。

在每个命令的执行过程中,都会清空当前命令并对电机进行相应的控制操作。 MOTOR_PRINT 用于打印电机状态,帮助用户了解当前电机的运行情况。

代码清单:命令处理函数
/**
* @brief 处理用户输入的命令,执行相应的电机控制操作
*
* @return 无
*/
void Process_Motor_Command(void)
{
   switch (Order) {
      case 'S':  // 启动电机
            Clear_Order;// 命令被处理后清空
            Motor_Control_Start();  // 调用电机启动函数
            MOTOR_PRINT("电机启动\r\n");
            break;

      case 'P':  // 停止电机
            Clear_Order;// 命令被处理后清空
            Motor_Control_Stop();  // 调用电机停止函数
            MOTOR_PRINT("************电机关闭************\r\n");
            break;

      case 'U':
            Clear_Order;// 命令被处理后清空
            if (Hz >= (PWM_MAX_FREQUENCY - 1600)) {
               Hz = PWM_MAX_FREQUENCY;  // 限制最大频率
               Motor_Control_SetSpeed(Hz); // 设置定时器周期
               MOTOR_PRINT("已到达电机所能承受最大频率,当前频率 = %ld Hz\r\n", Hz);
            } else {
               Hz += QUARTER_SPR;//电机加速(+0.25转/秒)(PWM频率+1600Hz)
               R_GPT_PeriodSet(&step_pwm_ctrl, Hz_Set(Hz)); // 设置定时器周期
               MOTOR_PRINT("电机加速,新的频率 = %ld Hz\r\n", Hz);
            }
            break;

      case 'D':
            Clear_Order;// 命令被处理后清空
            if (Hz <= PWM_MIN_FREQUENCY) {
               Hz = PWM_MIN_FREQUENCY;  // 限制最小频率
               Motor_Control_SetSpeed(Hz); // 设置定时器周期
               MOTOR_PRINT("已到达程序最小频率,当前频率 = %ld Hz\r\n", Hz);
            } else {
               Hz -= QUARTER_SPR;//电机减速(-0.25转/秒)(PWM频率+1600Hz)
               R_GPT_PeriodSet(&step_pwm_ctrl, Hz_Set(Hz)); // 设置定时器周期
               MOTOR_PRINT("电机减速,新的频率 = %ld Hz\r\n", Hz);
            }
            break;

      case 'R':  // 反转电机旋转方向
            Clear_Order;// 命令被处理后清空
            Motor_Control_Reverse();  // 调用电机方向反转函数
            if (motor_dir == true) {
               MOTOR_PRINT("电机方向翻转,当前旋转方向:正向\n");
            } else {
               MOTOR_PRINT("电机方向翻转,当前旋转方向:反向\n");
            }
            break;

      default:  // 无效命令
            Clear_Order;// 命令被处理后清空
            break;
   }
}

7.6.2.8. hal_entry入口函数

hal_entry 函数中,首先初始化了系统所需的外设,包括 LED 和串口,用于状态显示和调试。 接下来,初始化电机控制的定时器,并通过 Motor_Control_SetSpeed(Hz) 设置电机的初始速度,其中 Hz 定义为电机一圈所需的脉冲数( SPR)。 所以电机初始运行速度应该为 1转/秒。 然后,打印控制指令,指导用户如何使用串口助手发送命令控制电机的运行。 进入主循环后,调用 Process_Motor_Command() 以处理来自用户的输入命令,并根据不同的命令执行相应的电机操作。这样能够确保电机的状态根据用户指令实时变化。

代码清单6_4:hal_entry入口函数
//PWM频率值
uint32_t Hz = SPR;

void hal_entry(void)
{
   /* TODO: add your own code here */
   LED_Init(); // LED 初始化
   Debug_UART9_Init();//调试串口初始化

   Motor_Control_Init();        //初始化电机定时器

   MOTOR_PRINT("这是一个步进电机基础控制示例\r\n");
   MOTOR_PRINT("打开串口助手发送以下指令,可控制电机运行状态:\r\n");
   MOTOR_PRINT("S----------------电机开始旋转\r\n");
   MOTOR_PRINT("P----------------电机停止旋转\r\n");
   MOTOR_PRINT("U----------------电机加速(+0.25转/秒)(PWM频率+1600Hz)\r\n");
   MOTOR_PRINT("D----------------电机减速(-0.25转/秒)(PWM频率-1600Hz)\r\n");
   MOTOR_PRINT("R----------------电机反向旋转\r\n");

   Motor_Control_SetSpeed(Hz); // 设置定时器周期

   while(1)
   {
      //处理用户输入的命令,执行相应的电机控制操作
      Process_Motor_Command();
   }

#if BSP_TZ_SECURE_BUILD
   /* Enter non-secure code */
   R_BSP_NonSecureEnter();
#endif
}

7.6.3. 下载验证

编译并下载程序后,复位开发板使程序重新运行,打开串口调试助手,连接开发板,可以看到对电机的控制方法,我们可以通过野火多功能调试助手中的多项发送来控制电机,如下图所示:

串口输出情况

在确定串口打印正确后,就可以接上电机验证程序了。