博主在项目中接触到海泰电机作为控制器件,是博主第一次接触RS485通信的电机,写下博客供跟博主一样的小白进行学习,拿到电机的第一时间,首先可以发现通信有RS485和CAN通信两种
基于项目需要我们采取RS485通信,但是我们使用的32单片机没有485通信口,所以采取了串口转485的方式进行电机的控制,PS:此方法最开始我心里也悬,问官方官方也说不建议,还好最后调试成功了。
模块不多做赘述,在某宝上面搜索就有,具体接法记住,与平常的串口通信不同,是需要直连的,RS485模块的458A接电机的485A,B接B,串口那边,RX接RX,TX接TX,这样进行控制,在代码中我们使用了一个串口进行通信一个进行串口打印,所以是双串口使能,分别是串口1和串口4,代码如下:
/**
****************************************************************************************************
* @file usart.c
* @author ÕýµãÔ×ÓÍŶÓ(ALIENTEK)
* @version V1.0
* @date 2021-10-14
* @brief ´®¿Ú³õʼ»¯´úÂë(Ò»°ãÊÇ´®¿Ú1)£¬Ö§³Öprintf
* @license Copyright (c) 2020-2032, ¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾
****************************************************************************************************
* @attention
*
* ʵÑéÆ½Ì¨:ÕýµãÔ×Ó Ì½Ë÷Õß F407¿ª·¢°å
* ÔÚÏßÊÓÆµ:www.yuanzige.com
* ¼¼ÊõÂÛ̳:www.openedv.com
* ¹«Ë¾ÍøÖ·:www.alientek.com
* ¹ºÂòµØÖ·:openedv.taobao.com
*
* ÐÞ¸Ä˵Ã÷
* V1.0 20211014
* µÚÒ»´Î·¢²¼
*
****************************************************************************************************
*/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
/* Èç¹ûʹÓÃos,Ôò°üÀ¨ÏÂÃæµÄÍ·Îļþ¼´¿É */
#if SYS_SUPPORT_OS
#include "os.h" /* os ʹÓà */
#endif
/******************************************************************************************/
/* ¼ÓÈëÒÔÏ´úÂë, Ö§³Öprintfº¯Êý, ¶ø²»ÐèҪѡÔñuse MicroLIB */
#if 1
#if (__ARMCC_VERSION >= 6010050) /* ʹÓÃAC6±àÒëÆ÷ʱ */
__asm(".global __use_no_semihosting\n\t"); /* ÉùÃ÷²»Ê¹ÓðëÖ÷»úģʽ */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6ÏÂÐèÒªÉùÃ÷mainº¯ÊýΪÎÞ²ÎÊý¸ñʽ£¬·ñÔò²¿·ÖÀý³Ì¿ÉÄܳöÏÖ°ëÖ÷»úģʽ */
#else
/* ʹÓÃAC5±àÒëÆ÷ʱ, ÒªÔÚÕâÀﶨÒå__FILE ºÍ ²»Ê¹ÓðëÖ÷»úģʽ */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* ²»Ê¹ÓðëÖ÷»úģʽ£¬ÖÁÉÙÐèÒªÖØ¶¨Òå_ttywrch\_sys_exit\_sys_command_stringº¯Êý,ÒÔͬʱ¼æÈÝAC6ºÍAC5ģʽ */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* ¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE ÔÚ stdio.hÀïÃæ¶¨Òå. */
FILE __stdout;
/* ÖØ¶¨Òåfputcº¯Êý, printfº¯Êý×îÖÕ»áͨ¹ýµ÷ÓÃfputcÊä³ö×Ö·û´®µ½´®¿Ú */
int fputc(int ch, FILE *f)
{
while ((UART4->SR & 0X40) == 0); /* µÈ´ýÉÏÒ»¸ö×Ö·û·¢ËÍÍê³É */
UART4->DR = (uint8_t)ch; /* ½«Òª·¢Ë͵Ä×Ö·û ch дÈëµ½DR¼Ä´æÆ÷ */
return ch;
}
#endif
/***********************************************END*******************************************/
#if USART_EN_RX /* Èç¹ûʹÄÜÁ˽ÓÊÕ */
/* ½ÓÊÕ»º³å, ×î´óUSART_REC_LEN¸ö×Ö½Ú. */
uint8_t g_usart_rx_buf[USART_REC_LEN];
/* ½ÓÊÕ״̬
* bit15£¬ ½ÓÊÕÍê³É±êÖ¾
* bit14£¬ ½ÓÊÕµ½0x0d
* bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
*/
uint16_t g_usart_rx_sta = 0;
uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL¿âʹÓõĴ®¿Ú½ÓÊÕ»º³å */
UART_HandleTypeDef g_uart4_handle; /* UART¾ä±ú */
/**
* @brief ´®¿ÚX³õʼ»¯º¯Êý
* @param baudrate: ²¨ÌØÂÊ, ¸ù¾Ý×Ô¼ºÐèÒªÉèÖò¨ÌØÂÊÖµ
* @note ×¢Òâ: ±ØÐëÉèÖÃÕýÈ·µÄʱÖÓÔ´, ·ñÔò´®¿Ú²¨ÌØÂʾͻáÉèÖÃÒì³£.
* ÕâÀïµÄUSARTµÄʱÖÓÔ´ÔÚsys_stm32_clock_init()º¯ÊýÖÐÒѾÉèÖùýÁË.
* @retval ÎÞ
*/
void usart_init(uint32_t baudrate)
{
g_uart4_handle.Instance = USART_UX; /* UART4 */
g_uart4_handle.Init.BaudRate = baudrate; /* ²¨ÌØÂÊ */
g_uart4_handle.Init.WordLength = UART_WORDLENGTH_8B; /* ×Ö³¤Îª8λÊý¾Ý¸ñʽ */
g_uart4_handle.Init.StopBits = UART_STOPBITS_1; /* Ò»¸öֹͣλ */
g_uart4_handle.Init.Parity = UART_PARITY_NONE; /* ÎÞÆæÅ¼Ð£Ñéλ */
g_uart4_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* ÎÞÓ²¼þÁ÷¿Ø */
g_uart4_handle.Init.Mode = UART_MODE_TX_RX; /* ÊÕ·¢Ä£Ê½ */
HAL_UART_Init(&g_uart4_handle); /* HAL_UART_Init()»áʹÄÜUART1 */
/* ¸Ãº¯Êý»á¿ªÆô½ÓÊÕÖжϣº±ê־λUART_IT_RXNE£¬²¢ÇÒÉèÖýÓÊÕ»º³åÒÔ¼°½ÓÊÕ»º³å½ÓÊÕ×î´óÊý¾ÝÁ¿ */
HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}
/**
* @brief UARTµ×²ã³õʼ»¯º¯Êý
* @param huart: UART¾ä±úÀàÐÍÖ¸Õë
* @note ´Ëº¯Êý»á±»HAL_UART_Init()µ÷ÓÃ
* Íê³ÉʱÖÓʹÄÜ£¬Òý½ÅÅäÖã¬ÖжÏÅäÖÃ
* @retval ÎÞ
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
if(huart->Instance == USART_UX) /* Èç¹ûÊÇ´®¿Ú1£¬½øÐд®¿Ú1 MSP³õʼ»¯ */
{
USART_UX_CLK_ENABLE(); /* UART4 ʱÖÓʹÄÜ */
USART_TX_GPIO_CLK_ENABLE(); /* ·¢ËÍÒý½ÅʱÖÓʹÄÜ */
USART_RX_GPIO_CLK_ENABLE(); /* ½ÓÊÕÒý½ÅʱÖÓʹÄÜ */
gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* TXÒý½Å */
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 = USART_TX_GPIO_AF; /* ¸´ÓÃΪUART4 */
HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* ³õʼ»¯·¢ËÍÒý½Å */
gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* RXÒý½Å */
gpio_init_struct.Alternate = USART_RX_GPIO_AF; /* ¸´ÓÃΪUART4 */
HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* ³õʼ»¯½ÓÊÕÒý½Å */
#if USART_EN_RX
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* ʹÄÜUART4ÖжÏͨµÀ */
HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* ÇÀÕ¼ÓÅÏȼ¶3£¬×ÓÓÅÏȼ¶3 */
#endif
}
}
/**
* @brief Rx´«Ê仨µ÷º¯Êý
* @param huart: UART¾ä±úÀàÐÍÖ¸Õë
* @retval ÎÞ
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART_UX) /* Èç¹ûÊÇ´®¿Ú1 */
{
if((g_usart_rx_sta & 0x8000) == 0) /* ½ÓÊÕδÍê³É */
{
if(g_usart_rx_sta & 0x4000) /* ½ÓÊÕµ½ÁË0x0d */
{
if(g_rx_buffer[0] != 0x0a)
{
g_usart_rx_sta = 0; /* ½ÓÊÕ´íÎó,ÖØÐ¿ªÊ¼ */
}
else
{
g_usart_rx_sta |= 0x8000; /* ½ÓÊÕÍê³ÉÁË */
}
}
else /* »¹Ã»ÊÕµ½0X0D */
{
if(g_rx_buffer[0] == 0x0d)
{
g_usart_rx_sta |= 0x4000;
}
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
g_usart_rx_sta++;
if(g_usart_rx_sta > (USART_REC_LEN - 1))
{
g_usart_rx_sta = 0; /* ½ÓÊÕÊý¾Ý´íÎó,ÖØÐ¿ªÊ¼½ÓÊÕ */
}
}
}
}
}
}
/**
* @brief ´®¿Ú1ÖжϷþÎñº¯Êý
* @param ÎÞ
* @retval ÎÞ
*/
void USART_UX_IRQHandler(void)
{
uint32_t timeout = 0;
uint32_t maxDelay = 0x1FFFF;
#if SYS_SUPPORT_OS /* ʹÓÃOS */
OSIntEnter();
#endif
HAL_UART_IRQHandler(&g_uart4_handle); /* µ÷ÓÃHAL¿âÖжϴ¦Àí¹«Óú¯Êý */
timeout = 0;
while (HAL_UART_GetState(&g_uart4_handle) != HAL_UART_STATE_READY) /* µÈ´ý¾ÍÐ÷ */
{
timeout++; /* ³¬Ê±´¦Àí */
if(timeout > maxDelay)
{
break;
}
}
timeout=0;
/* Ò»´Î´¦ÀíÍê³ÉÖ®ºó£¬ÖØÐ¿ªÆôÖжϲ¢ÉèÖÃRxXferCountΪ1 */
while (HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)
{
timeout++; /* ³¬Ê±´¦Àí */
if (timeout > maxDelay)
{
break;
}
}
#if SYS_SUPPORT_OS /* ʹÓÃOS */
OSIntExit();
#endif
}
#endif
博主认为,最麻烦的是控制命令的编写,虽说有文档,但是需要十进制到十六进制的转换,并且最后进行CRC冗余算法才能得出最后两位,在命令不多的时候我支持自己算出来写出命令,推荐一个计算网站: CRC在线计算
在算出命令值后再进行串口命令的发送,即可实现控制: HAL_UART_Transmit(&huart1,lvjing1,sizeof(lvjing1),0xffff);
最后实现的功能是串口4接串口助手,串口1接电机,串口4发送0,1,2,3分别实现设置原点,前进,返回原点,调速等操作,博主的资源链接如下: https://download.csdn.net/download/weixin_43955009/88374177