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

相关文章

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3

Mysql虚拟列的使用场景

《Mysql虚拟列的使用场景》MySQL虚拟列是一种在查询时动态生成的特殊列,它不占用存储空间,可以提高查询效率和数据处理便利性,本文给大家介绍Mysql虚拟列的相关知识,感兴趣的朋友一起看看吧... 目录1. 介绍mysql虚拟列1.1 定义和作用1.2 虚拟列与普通列的区别2. MySQL虚拟列的类型2

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

关于@MapperScan和@ComponentScan的使用问题

《关于@MapperScan和@ComponentScan的使用问题》文章介绍了在使用`@MapperScan`和`@ComponentScan`时可能会遇到的包扫描冲突问题,并提供了解决方法,同时,... 目录@MapperScan和@ComponentScan的使用问题报错如下原因解决办法课外拓展总结@

mysql数据库分区的使用

《mysql数据库分区的使用》MySQL分区技术通过将大表分割成多个较小片段,提高查询性能、管理效率和数据存储效率,本文就来介绍一下mysql数据库分区的使用,感兴趣的可以了解一下... 目录【一】分区的基本概念【1】物理存储与逻辑分割【2】查询性能提升【3】数据管理与维护【4】扩展性与并行处理【二】分区的

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学