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

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti