can是一种异步通信,具有CAN—HIGH和CAN—LOW两条信号线,其差分输出的信号模式,提高了其传递的抗干扰性能。

stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_CAN


stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_yz_aim_02


stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_CAN_03


stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_stm32_04


CAN通信的显性和隐形,还有逻辑电平的1和0很容易混淆,可以这样理解,CAN是通过CAN-HIGH和CAH-LOW的电压差来实现逻辑转换的,二者都为2.5v时,电压差是0,称之为隐性,对应为逻辑1. HIGH3.5v,LOW为1.5v,压差是2,称之为显性,对应逻辑0.

CAN是半双工异步通信方式,

can的协议层

can的位时序和同步:

位时序的组成:包含4段,ss, pts,pbs1,pbs2,将这四段加一起就是一个can数据位的长度。分解后的最小时间单位是tq,一个完整的位由8到25个Tq组成。

stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_stm32_05


stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程_arm_06

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "yz_aim.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t ret1=0;
uint16_t ret2=0;
/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
MX_CAN2_Init();
/* USER CODE BEGIN 2 */
// HAL_Delay(200);
// motor_stop(YZ_MOTOR_0);
// HAL_Delay(10);
// motor_stop(YZ_MOTOR_1);
// HAL_Delay(200);
// motor_relative_position_init(YZ_MOTOR_0);
// HAL_Delay(10);
// motor_set_trapezoidal_speed(YZ_MOTOR_0, 700); // 梯形速度写入 1500RPM
// HAL_Delay(10);
// motor_relative_position_init(YZ_MOTOR_1);
// HAL_Delay(10);
// motor_set_trapezoidal_speed(YZ_MOTOR_1, 200); // 梯形速度写入 500RPM
// HAL_Delay(10);
/* 设置找原点模式 */

motor_test_find_the_origin();
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
ret1 = motor_get_state_word(YZ_MOTOR_0);
if (ret1 != 0xFFFF)
{
if ((ret1 >> 12) & 0x01)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
}
else
{

}
}
HAL_Delay(10);
ret2 = motor_get_state_word(YZ_MOTOR_1);
if (ret2 != 0xFFFF)
{
if ((ret2 >> 12) & 0x01)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
else
{
HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin);
}
}
HAL_Delay(500);
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/********************************************************************************
* @file yz_aim.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-05-05
* @brief NULL
********************************************************************************/

/*******************************************
CANopen 地址说明:
一个完整的 CANopen 地址格式为:60400010(控制字),
[6040]0010: Index(16 位地址)。
6040[00]10:Subindex(8 位子地址)形式表示寄存器寻址,
604000[10]:位数 0x08 表示此寄存器将存放的数据长度为 1 个 Byte,位数 0x10 表示存放的数据长度为 2 个
Byte,位数 0x20 表示存放的数据长度为 4 个 Byte,
R: 可读,W: 可写,S:可保存,M: 可映射,
*******************************************/

/*******************************************
* CAN 标识符 DLC(数据段长度) 1 (2 3) 4 5 6 7 8
* 0x600 + device_ID 0x08 CS 命令符 对象索引 子索引 写入的数据
* 高位在[3],底位在[2] 高位在[8]
* CS 命令符: 0x2F=写1byte 0x2B=写2byte 0x23=写4byte
* 0x40=读取
*******************************************/

/*******************************************
* 控制字(6040H)的位定义如下:
* 位: 15:9 8 7 6 5 4 3 2 1 0
* 定义: 无 停止 故障复位 0:绝对位置 位置立即生效 执行新设置点 允许操作 允许急停 电压输出 启动
* 1:相位位置
*
* Bit0:置 1 后,外部脉冲控制无效。
* Bit4:每写入一次 1,就运行到新位置值。执行新位置值后自动置 0;
* Bit8:值为 1 时,电机急停,但是电机仍然是自锁状态。
*******************************************/

/*******************************************
* 状态字(6041H)的位定义如下:
* 位: 7 6 5 4 3 2 1 0
* 定义: 无 无 允许急停 电压输出 伺服报警 允许操作 启动 准备启动
*
* 位: 15 14 13 12 11 10 9 8
* 定义: 无 无 找原点错误 找原点完成 无 目标达到 无 无
*
* 从机回复读命令符: 0x4F=读回复一个字节。 0x4B=读回复两个字节。0x43=读回复四个字节
*******************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>

#include "can.h"
#include "yz_aim.h"

/* Private define ------------------------------------------------------------*/
#define MOTOR1_ID 0x601
#define MOTOR2_ID 0x601

/* Private variables ---------------------------------------------------------*/


/* Private function prototypes -----------------------------------------------*/
/***********************************基础层*************************************/
/**
* @brief 设置状态字
* @param motor_id: 电机编号
* @param data: 状态字值
* @retval None
*/
static void motor_set_control_word(yz_motor_t motor_id, uint16_t data)
{
uint8_t buff[8] = {0x2B, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(data & 0x00ff);
buff[5] = (uint8_t)((data & 0xff00) >> 8);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 获取状态字
* @param motor_id: 电机编号
* @retval 状态字值
*/
uint16_t motor_get_state_word(yz_motor_t motor_id)
{
uint16_t i = 0xffff;
uint8_t buff[8] = {0x40, 0x41, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
// 死等读取,后期如果上os后,可以换成os延时
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == 0x41 && (can1_recv_msg.data)[2] == 0x60)
{
return (buff[4]) | (buff[5] << 8);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == 0x41 && (can2_recv_msg.data)[2] == 0x60)
{
return (buff[4]) | (buff[5] << 8);
}
}
}
return 0xFFFF;
}

/**
* @brief 电机启动
* @param motor_id: 电机编号
* @param opt: 操作值[4:8]bit,支持混写
* @retval 状态字值
*/
void motor_start(yz_motor_t motor_id, uint16_t opt)
{
uint16_t data = 0;

data = CONTROL_WORD_START | CONTROL_WORD_VOLTAGE_OUTPUT | CONTROL_WORD_EMERGENCY_STOP_EN | CONTROL_WORD_OPERATION_EN;

data |= opt;

motor_set_control_word(motor_id, data);
}

/**
* @brief 电机停止
* @param motor_id: 电机编号
* @retval None
*/
void motor_stop(yz_motor_t motor_id)
{
motor_set_control_word(motor_id, 0x00);
}

/**
* @brief 设置电机工作模式
* @param motor_id: 电机编号
* @param mode: 电机工作模式
* @retval None
*/
void motor_set_work_mode(yz_motor_t motor_id, motor_work_mode_t mode)
{
uint8_t buff[8] = {0x2F, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(mode & 0xff);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 设置电机位置缓存
* @param motor_id: 电机编号
* @param val: 位置缓存值
* @retval None
*/
void motor_set_location_cache(yz_motor_t motor_id, uint32_t val)
{
uint8_t buff[8] = {0x23, 0x7A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(val & 0x000000ff);
buff[5] = (uint8_t)((val & 0x0000ff00) >> 8);
buff[6] = (uint8_t)((val & 0x00ff0000) >> 16);
buff[7] = (uint8_t)((val & 0xff000000) >> 24);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 设置电机转速
* @param motor_id: 电机编号
* @param val: 范围0~3000r/min
* @retval None
*/
void motor_set_trapezoidal_speed(yz_motor_t motor_id, uint32_t val)
{
uint8_t buff[8] = {0x23, 0x81, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(val & 0x000000ff);
buff[5] = (uint8_t)((val & 0x0000ff00) >> 8);
buff[6] = (uint8_t)((val & 0x00ff0000) >> 16);
buff[7] = (uint8_t)((val & 0xff000000) >> 24);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 设置电机加速度
* @param motor_id: 电机编号
* @param val: 0~65535(r/min)/s 参数小于 60000 时,驱动器内部产生加减速曲线,
* 参数大于60000 时,驱动器内部不产生加减速脉冲
* @retval None
*/
void motor_set_trapezoidal_acceleration(yz_motor_t motor_id, uint32_t val)
{
uint8_t buff[8] = {0x23, 0x83, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(val & 0x000000ff);
buff[5] = (uint8_t)((val & 0x0000ff00) >> 8);
buff[6] = (uint8_t)((val & 0x00ff0000) >> 16);
buff[7] = (uint8_t)((val & 0xff000000) >> 24);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 获取电机当前位置
* @param motor_id: 电机编号
* @retval 电机当前的实际位置
*/
uint32_t motor_get_current_location(yz_motor_t motor_id)
{
uint16_t i = 0xffff;
uint8_t buff[8] = {0x40, 0x64, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
// 死等读取,后期如果上os后,可以换成os延时
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == 0x64 && (can1_recv_msg.data)[2] == 0x60)
{
return (buff[4]) | (buff[5] << 8) | (buff[6] << 16) | (buff[7] << 24);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == 0x64 && (can2_recv_msg.data)[2] == 0x60)
{
return (buff[4]) | (buff[5] << 8) | (buff[6] << 16) | (buff[7] << 24);
}
}
}
return 0;
}

/**
* @brief 设置电机回原点方法
* @param type: 找原点方法 [17:22]
* @retval 0--成功 1--错误
*/
uint8_t motor_set_find_origin_mode(yz_motor_t motor_id, uint8_t type)
{
uint8_t buff[8] = {0x2f, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

if (type > 22 || type < 17)
{
return 1;
}

buff[4] = type;

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
return 0;
}

/**
* @brief 设置电机最大允许电流
* @param motor_id: 电机编号
* @param max_val: 最大工作允许电流 [0-10000]mA
* @param keep_time: 最大电流持续多长时间才报警[0-9]s
* @retval None
*/
void motor_set_max_electric(yz_motor_t motor_id, uint32_t val, uint8_t keep_time)
{
uint8_t buff[8] = {0x23, 0x83, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};

buff[4] = (uint8_t)(val & 0x000000ff);
buff[5] = (uint8_t)((val & 0x0000ff00) >> 8);
buff[6] = (uint8_t)((val & 0x00ff0000) >> 16);
buff[7] = (uint8_t)((val & 0xff000000) >> 24);

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
}

/**
* @brief 设置电机相对角度
* @param motor_id: 电机编号
* @param degree: 角度
* @retval None
*/
void motor_set_relative_degree(yz_motor_t motor_id, int16_t degree)
{
motor_set_location_cache(motor_id, ((32768 * 80) / 360) * degree);
}

/**
* @brief 得到厂家ID
* @param motor_id: 电机编号
* @retval None
*/
uint32_t motor_get_manufacturer_id(yz_motor_t motor_id)
{
uint8_t buff[8] = {0x40, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00};
uint32_t i = 0xffff;

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == 0x18 && (can1_recv_msg.data)[2] == 0x10)
{
return (buff[4]) | (buff[5] << 8) | (buff[6] << 16) | (buff[7] << 24);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == 0x18 && (can2_recv_msg.data)[2] == 0x10)
{
return (buff[4]) | (buff[5] << 8) | (buff[6] << 16) | (buff[7] << 24);
}
}
}
return 0xFFFF;
}

/**
* @brief 得到系统电压
* @param motor_id: 电机编号
* @retval None
*/
uint16_t motor_get_sys_vcc(yz_motor_t motor_id)
{
uint8_t buff[8] = {0x40, 0x79, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00};
uint16_t i = 0xffff;

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == buff[1] && (can1_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == buff[1] && (can2_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
}
return 0xFFFF;
}

/**
* @brief 得到系统温度
* @param motor_id: 电机编号
* @retval None
*/
uint16_t motor_get_sys_temp(yz_motor_t motor_id)
{
uint8_t buff[8] = {0x40, 0x12, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00};
uint16_t i = 0xffff;

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == buff[1] && (can1_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == buff[1] && (can2_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
}
return 0xFFFF;
}

/**
* @brief 得到系统温度
* @param motor_id: 电机编号
* @retval None
*/
uint16_t motor_get_sys_pwm(yz_motor_t motor_id)
{
uint8_t buff[8] = {0x40, 0x13, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00};
uint16_t i = 0xffff;

if (motor_id == YZ_MOTOR_0)
{
can1_transmit(MOTOR1_ID, (uint8_t *)buff);
}
else if (motor_id == YZ_MOTOR_1)
{
can2_transmit(MOTOR2_ID, (uint8_t *)buff);
}
while (1)
{
i--;
if (i == 0)
{
break;
}
if (motor_id == YZ_MOTOR_0)
{
if ((can1_recv_msg.data)[1] == buff[1] && (can1_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
else if (motor_id == YZ_MOTOR_1)
{
if ((can2_recv_msg.data)[1] == buff[1] && (can2_recv_msg.data)[2] == buff[2])
{
return (buff[4]) | (buff[5] << 8);
}
}
}
return 0xFFFF;
}

/***********************************应用层*************************************/

/**
* @brief 初始化为相对位移模式
* @param motor_id: 电机编号
* @retval None
*/
void motor_relative_position_init(yz_motor_t motor_id)
{
motor_start(motor_id, 0x00); // 启动+电压输出+允许急停+允许操作
HAL_Delay(10);
motor_set_work_mode(motor_id, LOCATION_MODE); // 工作模式设置为位置模式
HAL_Delay(10);
motor_set_location_cache(motor_id, 50000); // 位置缓存写入 50000 脉冲
HAL_Delay(10);
motor_set_trapezoidal_speed(motor_id, 500); // 梯形速度写入 500RPM
HAL_Delay(10);
motor_set_trapezoidal_acceleration(motor_id, 65000); // 梯形加减速写入 60000RPM/S
HAL_Delay(10);
motor_start(motor_id, CONTROL_WORD_RELATIVE_POSITION); // 相对位置控制模式
HAL_Delay(10);
motor_start(motor_id, CONTROL_WORD_RELATIVE_POSITION | CONTROL_WORD_EXECUTE_NEW_SET_POINT); // 相对位置控制模式 + 走到新的位置点
HAL_Delay(10);
}

/**
* @brief 设置相对位移位置缓存
* @param motor_id: 电机编号
* @retval None
*/
void motor_set_relative_position(yz_motor_t motor_id, uint32_t new_location_cache)
{
motor_set_location_cache(motor_id, new_location_cache); // 位置缓存写入脉冲
HAL_Delay(10);
motor_start(motor_id, CONTROL_WORD_RELATIVE_POSITION | CONTROL_WORD_EXECUTE_NEW_SET_POINT); // 相对位置控制模式 + 走到新的位置点
HAL_Delay(10);
}

/***********************************测试层*************************************/
/**
* @brief 测试电机正反转
* @retval None
*/
void motor_test_positive_inversion(void)
{
uint8_t i = 0;
uint8_t flag = 0;

while (1)
{
if (flag == 0)
{
motor_set_relative_position(YZ_MOTOR_0, 1800000);
motor_set_relative_position(YZ_MOTOR_1, 1800000);
HAL_Delay(2000);
}
else
{
motor_set_relative_position(YZ_MOTOR_0, 0xFFE488BF);
motor_set_relative_position(YZ_MOTOR_1, 0xFFE488BF);
HAL_Delay(2000);
}
i++;
if (i == 10)
{
i = 0;
motor_set_relative_position(YZ_MOTOR_0, 0);
motor_set_relative_position(YZ_MOTOR_1, 0);
HAL_Delay(1000);
if (flag == 0)
{
flag = 1;
}
else
{
flag = 0;
}
}
}
}

/**
* @brief 测试电机找原点模式
* @retval None
*/
void motor_test_find_the_origin(void)
{
HAL_Delay(10);
motor_stop(YZ_MOTOR_0);
HAL_Delay(10);
motor_stop(YZ_MOTOR_1);
HAL_Delay(200);
motor_set_find_origin_mode(YZ_MOTOR_0, 17);
HAL_Delay(10);
motor_set_find_origin_mode(YZ_MOTOR_1, 17);
HAL_Delay(10);
motor_set_work_mode(YZ_MOTOR_0, FIND_ORIGIN_MODE);
HAL_Delay(10);
motor_set_work_mode(YZ_MOTOR_1, FIND_ORIGIN_MODE);
}
/********************************************************************************
* @file yz_aim.h
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-05-05
* @brief
********************************************************************************/

#ifndef __YZ_AIM_H
#define __YZ_AIM_H

#include <stdint.h>

#define CONTROL_WORD_START (1<<0)
#define CONTROL_WORD_VOLTAGE_OUTPUT (1<<1)
#define CONTROL_WORD_EMERGENCY_STOP_EN (1<<2)
#define CONTROL_WORD_OPERATION_EN (1<<3)
#define CONTROL_WORD_EXECUTE_NEW_SET_POINT (1<<4)
#define CONTROL_WORD_LOCATION_START (1<<5)

#define CONTROL_WORD_ABSOLUTE_POSITION (0<<6)
#define CONTROL_WORD_RELATIVE_POSITION (1<<6)

#define CONTROL_WORD_FAULT_RESET_EN (1<<7)
#define CONTROL_WORD_STOP (1<<8)

typedef enum
{
YZ_MOTOR_0 = 0,
YZ_MOTOR_1
} yz_motor_t;

typedef enum
{
LOCATION_MODE = 1,
SPEED_MODE = 3,
FIND_ORIGIN_MODE = 6,
MOVEMENT_MODE = 7
} motor_work_mode_t;

uint16_t motor_get_state_word(yz_motor_t motor_id);
void motor_start(yz_motor_t motor_id, uint16_t opt);
void motor_stop(yz_motor_t motor_id);

void motor_set_work_mode(yz_motor_t motor_id, motor_work_mode_t mode);
void motor_set_location_cache(yz_motor_t motor_id, uint32_t val);
void motor_set_trapezoidal_speed(yz_motor_t motor_id, uint32_t val);
void motor_set_trapezoidal_acceleration(yz_motor_t motor_id, uint32_t val);
uint32_t motor_get_current_location(yz_motor_t motor_id);
uint8_t motor_set_find_origin_mode(yz_motor_t motor_id, uint8_t type);

void motor_set_max_electric(yz_motor_t motor_id, uint32_t val, uint8_t keep_time);

void motor_set_relative_degree(yz_motor_t motor_id, int16_t degree);

uint32_t motor_get_manufacturer_id(yz_motor_t motor_id);
uint16_t motor_get_sys_vcc(yz_motor_t motor_id);
uint16_t motor_get_sys_temp(yz_motor_t motor_id);
uint16_t motor_get_sys_pwm(yz_motor_t motor_id);

void motor_relative_position_init(yz_motor_t motor_id);
void motor_set_relative_position(yz_motor_t motor_id, uint32_t new_location_cache);

void motor_test_positive_inversion(void);
void motor_test_find_the_origin(void);

#endif