stm32HAL库通过MODBUS,RS485,控制伺服电机(已实现验证)
本文章主要讲解使用stm32驱动AIMtor的伺服电机(自带驱动器版本),北京时代超群电机厂产
基础必备知识
在讲解之前,首先得明白MODBUS和RS485到底是啥东西:
如果你了解了这俩东西之后去驱动这个就很简单啦,也就是说单片机只需要输出一个串口信号,给伺服电机发信息就行。
硬件选择
只需要去网上购买一个TTL转RS485的转换模块即可,这里尤为注意!!!
1,不要购买野火的那个模块,那个模块的接收和发送需要你自己去通过IO口控制,正常我们去控制伺服电机是不会这样控制的,所以没有这个特别需求的话,千万不要买!!!
2,看清模块手册,有的模块手册比如野火的这款,左边是TX接TX!!!!一定要看清!!!

编程
DMA+空闲中断
好,在搞清上述两点之后,我们就可以去编程控制了,博主采用了CUMX+keil的编程方式去控制
串口部分采用DMA转运加空闲中断的方式去发送和接收伺服电机的HEX数据包,初始化设置的教程参考
STM32串口通信的三种方式———HAL库实现_stm32 hal 串口-CSDN博客
文章最后一个大节,直接照抄即可。
CRC实现
MODBUS.C
`#include "MODBUS.h"
size_t size;
uint16_t crc_16;
uint8_t crc_8[2];
/*
* @name MODBUS_Sent
* @brief MODBUS数据发送
* @param data->数组指针,size->长度
*/
void MODBUS_Sent(uint8_t *data,uint8_t size)
{
// size=sizeof(data)/sizeof(data[0]);
crc_16=CRC_Check(data,size);
crc_8[1]=crc_16&0xff;
crc_8[0]=(crc_16>>8)&0xff;
HAL_UART_Transmit_DMA(&huart1,data,size);
while(huart1.gState!=HAL_UART_STATE_READY)
{
HAL_Delay(1);
}
HAL_UART_Transmit_DMA(&huart1,crc_8,sizeof(crc_8));
}
/*
* @name CRC_Check
* @brief CRC校验
* @param CRC_Ptr->数组指针,LEN->长度
* @retval CRC校验值
*/
uint16_t CRC_Check(uint8_t *CRC_Ptr,uint8_t LEN)
{
uint16_t CRC_Value = 0;
uint8_t i = 0;
uint8_t j = 0;
CRC_Value = 0xffff;
for(i=0;i<LEN;i++) //LEN为数组长度
{
CRC_Value ^= *(CRC_Ptr+i);
for(j=0;j<8;j++)
{
if(CRC_Value & 0x00001)
CRC_Value = (CRC_Value >> 1) ^ 0xA001;
else
CRC_Value = (CRC_Value >> 1);
}
}
CRC_Value = ((CRC_Value >> 8) + (CRC_Value << 8)); //交换高低字节
return CRC_Value;
}
`
上述代码实现了CRC校验+发送的功能,前提是你已经跟着上面的链接完成了DMA转运+空闲中断的基本配置并成功实现。
MODBUS.h
#ifndef __MODBUS_H
#define __MODBUS_H
#include "main.h"
void MODBUS_Sent(uint8_t *data,uint8_t size);
uint16_t CRC_Check(uint8_t *CRC_Ptr,uint8_t LEN);
void MODBUS_Moter_Command(void);
#endif
主要代码就这些,后面的话就是博主自己写的一些交互功能,比如按键控制电机使能或失能
这里展出一些博主通过上位机的发送函数以及自己的研究记录后,自己记录的一些功能命令包

可以直接添加到你们自己的工程中,通过单片机直接发送,注意一点哦,这些是我加过CRC校验的,单片机中的代码在发送时只需要发送内容即可,CRC校验位单片机可以自己计算并发送。
一些插曲
值得一提的是,在发送代码段中两个HAL_UART_Transmit_DMA挨在一块会出问题
HAL_UART_Transmit_DMA(&huart1,data,size);
while(huart1.gState!=HAL_UART_STATE_READY)
{
HAL_Delay(1);
}
HAL_UART_Transmit_DMA(&huart1,crc_8,sizeof(crc_8));
这一段实际上困扰了一段时间,因为我发现在两个HAL_UART_Transmit_DMA之间如果不加任何延时等待的话,会出现第二个发送函数没法发送出去的情况,针对于此我查找了
这篇博客给了多种方案,我试过之后,经验证,博主用的这个应该是很稳的,至少目前没出错
获取方式:qq群1079267694
浙公网安备 33010602011771号