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

2023-12-08 23:59

本文主要是介绍stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、简介
  • 二、特性
  • 三、示例代码

一、简介

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)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组成。

在这里插入图片描述
在这里插入图片描述

二、特性

  1. 隔离CAN通信(EasyCan协议,简易,快速上手,速率1M)。支持轮廓位置模式,和,周期同步模式。
  2. 15位绝对编码器,一圈脉冲高达32768。
  3. 多圈绝对值(需配电池)。脉冲模式:重新上电自动回断电位置。
    通信模式:可断电记录位置。
  4. 多级DD马达结构,大扭力输出。
  5. 一体化伺服,简化接线,体积超小。
  6. 低噪音,低振动,高速定位,高可靠性。
  7. FOC场定向矢量控制,支持位置/速度闭环。
  8. 可工作在零滞后给定脉冲状态,跟随零滞后。
  9. 16位电子齿轮功能。
  10. 提供串口上位机,可监测电机状态和修改参数。
  11. 位置模式,支持脉冲+方向信号,编码器跟随
  12. 速度模式,支持PWM占空比信号调速
  13. 具有堵转,过流保护,过压保护。

三、示例代码

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; 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); // 梯形速度写入 500RPMHAL_Delay(10);motor_set_trapezoidal_acceleration(motor_id, 65000); // 梯形加减速写入 60000RPM/SHAL_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

代码下载:https://download.csdn.net/download/qq_29246181/70668701

这篇关于stm32f407 双CAN通信 cubemx 使用yz_aim电机作为历程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/471762

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud