新手向:使用STM32通过RS485通信接口控制步进电机
准备工作
本文使用的STM32芯片是STM32F407ZGTx,使用的电机是57步进电机,驱动器是用的是时代超群的RS485总线一体化步进电机驱动器(42 型:ZD-M42P-485)。使用到的其他设备有:MOXA盒(串口调试),ST-LINK/V2(下程序),另外电源、电源线以及其他电子设备等忽略不计。
使用到的软件有:Keil uVision5,STM32CubeMX,SSCOM v5.10a(串口调试助手),M42P-S-Too(封装好的直接发串口数据控制电机的软件)
硬件调试
先放一个硬件接口图

最开始的时候,对板子还不太熟悉,我们想先确认一下电机的运动状态,以及驱动器的串口指令等等。因此,采用计算机直接发送串口指令到MOXA盒,再将串口数据传入RS485驱动器,最后再驱动电机。
计算机直接发送串口指令可以使用M42P-S-Too(封装好的直接发串口数据控制电机的软件),直接控制电机。并且软件底部会有对应的串口的指令。

RS485驱动器电气结构图:
RS485串口通讯的相关原理可以参考以下链接:
通过以上方法,可以让电机初步转起来。
软件调试
这里讲一个关键的点。在面对不同的STM32的芯片的时候,在我经过了两天的尝试之后发现,建立工程最好的办法就是借助STM32CubeMX。如果是自己按照以前正点原子的教程自己来添加文件夹一步步设置的话,面对不同的库(正点原子的是标准库,这里使用的是HAL库)不同的芯片,很容易出现其他问题。当然STM32CubeMX生成的工程文档也是基于HAL库来的。

设置好需要用的端口,通信接口,引脚之后,点击右上角GENERATE CODE,即可直接生成工程文件。
这里的ioc文件就是CubeMX的工程,下次可以直接从这里打开。
点击MDK-ARM文件夹,里面的.uvprojx格式的文件,就是Keil所需的工程文件。

打开Keil,在main函数中直接可以开始编写程序,CubeMX生成的工程文档使用起来会比较方便。
这里给一个新建工程文档的教程参考:
如何使用STM32CubeMX快速配置工程【简单入门】_哔哩哔哩_bilibili
我在调试电机的时候,先将要传入RS485的控制电机的数据传入RS422的端口,这样可以通过MOXA盒,用串口助手来验证我的通信。
c
// 电机控制指令数组
const uint8_t resetCmd[] = {0x01, 0x06, 0x07, 0xD0, 0x00, 0x01, 0x48, 0x87}; // 复位指令
const uint8_t forwardCmd[] = {0x01, 0x10, 0x07, 0xD4, 0x00, 0x02, 0x04,
0x00, 0x00, 0x03, 0xE8, 0xD9, 0x8E}; // 正转1000步
const uint8_t reverseCmd[] = {0x01, 0x10, 0x07, 0xD6, 0x00, 0x02, 0x04,
0x00, 0x00, 0x03, 0xE8, 0x58, 0x57}; // 反转1000步
void timer_1Hz_callback(void *p_arg) // 电机控制任务
{
OS_ERR err;
p_arg = p_arg;
static uint8_t initFlag = 0; // 初始化标志
static uint8_t direction = 0; // 电机方向:0=正转, 1=反转
while(1) {
OSTimeDly(4000, OS_OPT_TIME_PERIODIC, &err); // 4秒延时
if(initFlag == 0) {
// 首次执行:发送复位指令
HAL_UART_Transmit(&huart1, (uint8_t*)resetCmd, sizeof(resetCmd), 100);
initFlag = 1;
direction = 0;
continue; // 跳过本次循环剩余部分
}
if(direction == 0) {
// 正转指令
HAL_UART_Transmit(&huart1, (uint8_t*)forwardCmd, sizeof(forwardCmd), 100);
OSTimeDly(5000, OS_OPT_TIME_DLY, &err); // 延时5秒[5](@ref)
HAL_UART_Transmit(&huart1, (uint8_t*)resetCmd, sizeof(resetCmd), 100);
direction = 1; // 下次反转
} else {
// 反转指令
HAL_UART_Transmit(&huart1, (uint8_t*)reverseCmd, sizeof(reverseCmd), 100);
OSTimeDly(5000, OS_OPT_TIME_DLY, &err); // 延时5秒[5](@ref)
HAL_UART_Transmit(&huart1, (uint8_t*)resetCmd, sizeof(resetCmd), 100);
direction = 0; // 下次正转
}
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9); // 翻转LED1
}
}
串口助手SSCOM v5.10a中会收到这个以下代码:

然后将该部分代码改写之后,从RS485通信接口输出即可。但是需要注意,RS485通信跟RS422通信不同,RS485需要通过频繁的切发送/接收来完成通信。
c
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET); // 485切发送模式
/*xxxxx(这里补充你要发送的代码)*/
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET); // 485切接收模式
结语
本文的需求是控制步进电机的运动,来控制吊舱的转动,是一个角动量守恒的一个科普展演。需求很简单,但由于博主研究方向并不是嵌入式软件,所以不太熟悉,仅限于新手向参考。欢迎跟各位多多交流!
