TMC2660驱动及调试记录

news2024/9/28 9:31:04

TMC2660

一款优秀的电机驱动芯片,驱动简单。
理论就看这篇:TMC260/TMC2660/TMC262步进电机驱动
或者直接看手册,手册也不复杂。

  • 使用SPI通信,通过SPI配置参数。
  • 支持直接使用SPI和Step/Dir方式控制两种控制步进电机的方式。

TMC2660驱动

1、原理图

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

在这里插入图片描述
需要驱动两个步进电机,两个步进电机连接一样,使用同一个SPI接口通信 —— SPI2

2、编写驱动

2.1 SPI驱动

SPI驱动直接STM32CubeMX配置即可,容易得很。
需要注意的是查看手册SPI通信时序就知道,时钟极性选择SPI_POLARITY_HIGH,时钟相位选择SPI_PHASE_2EDGE

void MX_SPI2_Init(void)
{
  ...
  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
  ...
}

2.2 TMC2660驱动代码

bsp_tmc2660.h:

#ifndef _BSP_TMC2660_H_
#define _BSP_TMC2660_H_

// #include <stdint.h>
typedef unsigned char uint8_t;

#define TMC2660_M1 0
#define TMC2660_M2 1
typedef uint8_t enTCM2660Def;

#define TMC2660_Disable  1
#define TMC2660_Enable   0
typedef uint8_t enTCM2660EnDisableDef;

#define TMC2660_CW   0
#define TMC2660_CCW  1
typedef uint8_t enTMC2660DirDef;

/* 细分步数 register value 用于Step/DIR模式 */
#define	TMC2660_MICROSTEP_256		0x00
#define	TMC2660_MICROSTEP_128		0x01
#define	TMC2660_MICROSTEP_64		0x02
#define	TMC2660_MICROSTEP_32		0x03
#define	TMC2660_MICROSTEP_16		0x04
#define	TMC2660_MICROSTEP_8			0x05
#define	TMC2660_MICROSTEP_4			0x06
#define	TMC2660_MICROSTEP_2			0x07    /* Half Step */
#define	TMC2660_MICROSTEP_1			0x08    /* Full Step */
typedef uint8_t microstep_t;

#define TMC2660_SG2_THRESHOLD_VAL (val)  (val << 8)

void BSP_TMC2660_Init(void);
void BSP_TMC2660_DirectSet(enTCM2660Def t, enTMC2660DirDef dir);
void BSP_TMC2660_Enable(enTCM2660Def t, enTCM2660EnDisableDef state);
microstep_t BSP_TMC2660_MicrostepSet(enTCM2660Def t, microstep_t microstep);
uint8_t  BSP_TMC2660_TorqueSet(enTCM2660Def t, uint8_t torque);

#endif /* _BSP_TMC2660_H_ */

bsp_tmc2660.c:

#include <stdio.h>
#include "spi.h"
#include "bsp_tmc2660.h"
#include "bsp_cfg.h"


/* tmc2660 register */
#define		REG_DRVCTRL			0x00000000
#define		REG_CHOPCONF		0x00080000
#define		REG_SMARTEN			0x000A0000
#define		REG_SGCSCONF		0x000C0000
#define		REG_DRVCONF			0x000E0000

#define DRVCTRL_SPI_PHA    (1 << 17)
/* 
 * 使用SPI模式需要设置DRVCONF寄存器的SDOFF位(bit7),
 *  0: Enable STEP and DIR interface. 
 *   1: Disable STEP and DIR interface. SPI interface is used 
 *   to move motor. 
*/

/* 默认配置 */
#define		SCG_DEFAULT			0x10000

/* spi chip select */
#define		TMC2660_M1_PORT_CS		GPIOB
#define		TMC2660_M1_GPIO_CS		GPIO_PIN_12		

/* Step motor enable */
#define		TMC2660_M1_PORT_EN		GPIOA			
#define		TMC2660_M1_GPIO_EN		GPIO_PIN_8

/* step pulse */
#define		TMC2660_M1_PORT_STEP	GPIOC			
#define		TMC2660_M1_GPIO_STEP	GPIO_PIN_8

/* direction */
#define		TMC2660_M1_PORT_DIR	    GPIOC			
#define		TMC2660_M1_GPIO_DIR	    GPIO_PIN_7	

/* spi chip select */
#define		TMC2660_M2_PORT_CS		GPIOC
#define		TMC2660_M2_GPIO_CS		GPIO_PIN_6		

/* Step motor enable */
#define		TMC2660_M2_PORT_EN		GPIOD			
#define		TMC2660_M2_GPIO_EN		GPIO_PIN_2

/* step pulse */
#define		TMC2660_M2_PORT_STEP	GPIOB			
#define		TMC2660_M2_GPIO_STEP	GPIO_PIN_9

/* direction */
#define		TMC2660_M2_PORT_DIR	    GPIOC			
#define		TMC2660_M2_GPIO_DIR	    GPIO_PIN_10	

static uint32_t tmc2660_SPI_Xfer(uint32_t wdata)
{
    uint8_t wbuf[3] = {0};
    uint8_t rbuf[3] = {0};

    wbuf[0] = (wdata>>16) & 0xff;
    wbuf[1] = (wdata>>8) & 0xff;
    wbuf[2] = (wdata&0xff);

    HAL_SPI_TransmitReceive(&hspi2, (uint8_t *)&wbuf, rbuf, 3, HAL_MAX_DELAY);
    uint32_t ret = (rbuf[0]<<16 | rbuf[1]<<8 | rbuf[2]);
    return ret;
}

#define LEVEL_SW(level)    ((level) > 0 ? GPIO_PIN_SET : GPIO_PIN_RESET)

static void tmc2660_SPI_CS(enTCM2660Def t, uint8_t level)
{
    if (t == TMC2660_M1)
    {
        HAL_GPIO_WritePin(TMC2660_M2_PORT_CS, TMC2660_M2_GPIO_CS, LEVEL_SW(1));  /* cancel M2 chip select */
        HAL_GPIO_WritePin(TMC2660_M1_PORT_CS, TMC2660_M1_GPIO_CS, LEVEL_SW(level));
    }
    else if (t == TMC2660_M2)
    {
        HAL_GPIO_WritePin(TMC2660_M1_PORT_CS, TMC2660_M1_GPIO_CS, LEVEL_SW(1));  /* cancel M1 chip select */
        HAL_GPIO_WritePin(TMC2660_M2_PORT_CS, TMC2660_M2_GPIO_CS, LEVEL_SW(level));
    }
}


static void tmc2660Enable(enTCM2660Def t, uint8_t level)
{
    if (t == TMC2660_M1)
    {
        HAL_GPIO_WritePin(TMC2660_M1_PORT_EN, TMC2660_M1_GPIO_EN, LEVEL_SW(level));
    }
    else
    {
        HAL_GPIO_WritePin(TMC2660_M2_PORT_EN, TMC2660_M2_GPIO_EN, LEVEL_SW(level));
    }
}

static void tmc2660GPIOConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
   
      /*Configure GPIO pin : TMC2660_M1 */
    GPIO_InitStruct.Pin = TMC2660_M1_GPIO_CS;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(TMC2660_M1_PORT_CS, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = TMC2660_M1_GPIO_EN;
    HAL_GPIO_Init(TMC2660_M1_PORT_EN, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = TMC2660_M1_GPIO_DIR;
    HAL_GPIO_Init(TMC2660_M1_PORT_DIR, &GPIO_InitStruct);   

    /*Configure GPIO pin : TMC2660_M2 */
    GPIO_InitStruct.Pin = TMC2660_M2_GPIO_CS;
    HAL_GPIO_Init(TMC2660_M2_PORT_CS, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = TMC2660_M2_GPIO_EN;
    HAL_GPIO_Init(TMC2660_M2_PORT_EN, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = TMC2660_M2_GPIO_DIR;
    HAL_GPIO_Init(TMC2660_M2_PORT_DIR, &GPIO_InitStruct);

    HAL_GPIO_WritePin(TMC2660_M1_PORT_CS, TMC2660_M1_GPIO_CS, LEVEL_SW(1));
    HAL_GPIO_WritePin(TMC2660_M1_PORT_EN, TMC2660_M1_GPIO_EN, LEVEL_SW(1));
    HAL_GPIO_WritePin(TMC2660_M1_PORT_DIR, TMC2660_M1_GPIO_DIR, LEVEL_SW(0));

    HAL_GPIO_WritePin(TMC2660_M2_PORT_CS, TMC2660_M2_GPIO_CS, LEVEL_SW(1));
    HAL_GPIO_WritePin(TMC2660_M2_PORT_EN, TMC2660_M2_GPIO_EN, LEVEL_SW(1));
    HAL_GPIO_WritePin(TMC2660_M2_PORT_DIR, TMC2660_M2_GPIO_DIR, LEVEL_SW(0));
}

#define BSP_TMC2660_MODE_SPI  1
#define BSP_TMC2660_MODE_STEP_DIR 0

#define BSP_TMC2660_MODE  BSP_TMC2660_MODE_SPI

static void tmc2660ParamInit(void)
{
    uint32_t ret;
//Device Initialization from Datasheet
/* 1- spi, 0 - step/dir */
#if BSP_TMC2660_MODE == BSP_TMC2660_MODE_SPI  /* SPI Mode */
#define		INIT_DRVCTRL		0x00000000
#define		INIT_CHOPCONF		0x000901B4
#define		INIT_SMARTEN		0x000A8202
#define		INIT_SGCSCONF		0x000D0010
#define		INIT_DRVCONF		0x000E0090
#elif BSP_TMC2660_MODE == BSP_TMC2660_MODE_STEP_DIR  /* Step/DIR Mode*/
#define		INIT_DRVCTRL		0x00000000
#define		INIT_CHOPCONF		0x000901B4
#define		INIT_SMARTEN		0x000A8202
#define		INIT_SGCSCONF		0x000D0010//0x000D001F
#define		INIT_DRVCONF		0x000EF010
#endif 

    tmc2660_SPI_CS(TMC2660_M2, 0);
    ret = tmc2660_SPI_Xfer(REG_DRVCTRL | INIT_DRVCTRL | TMC2660_MICROSTEP_32);
    tmc2660_SPI_CS(TMC2660_M2, 1);
    printf("reg %08lx\r\n", ret);

    tmc2660_SPI_CS(TMC2660_M2, 0);
	ret = tmc2660_SPI_Xfer(REG_CHOPCONF | INIT_CHOPCONF);
    tmc2660_SPI_CS(TMC2660_M2, 1);
    printf("reg %08lx\r\n", ret);

    tmc2660_SPI_CS(TMC2660_M2, 0);
	ret = tmc2660_SPI_Xfer(REG_SMARTEN | INIT_SMARTEN);
    tmc2660_SPI_CS(TMC2660_M2, 1);
    printf("reg %08lx\r\n", ret);

    tmc2660_SPI_CS(TMC2660_M2, 0);
	ret = tmc2660_SPI_Xfer(REG_SGCSCONF | INIT_SGCSCONF);
    tmc2660_SPI_CS(TMC2660_M2, 1);
    printf("reg %08lx\r\n", ret);

    tmc2660_SPI_CS(TMC2660_M2, 0);
    ret = tmc2660_SPI_Xfer(REG_DRVCONF | INIT_DRVCONF);
    tmc2660_SPI_CS(TMC2660_M2, 1);
    printf("reg %08lx\r\n", ret);
}

void BSP_TMC2660_Init(void)
{
    MX_SPI2_Init();

    tmc2660GPIOConfig();

    tmc2660ParamInit();
    
    BSP_TMC2660_Enable(TMC2660_M1, TMC2660_Disable);
    BSP_TMC2660_Enable(TMC2660_M2, TMC2660_Enable);
}

/**
 * @brief:  Set Motor direction(设置电机方向)
 * @retval:  
 * @note:  
 */
void BSP_TMC2660_DirectSet(enTCM2660Def t, enTCM2660EnDisableDef dir)
{
    if (t == TMC2660_M1)
    {
        HAL_GPIO_WritePin(TMC2660_M1_PORT_DIR, TMC2660_M1_GPIO_DIR, LEVEL_SW(dir));
    }
    else if (t == TMC2660_M2)
    {
        HAL_GPIO_WritePin(TMC2660_M2_PORT_DIR, TMC2660_M2_GPIO_DIR, LEVEL_SW(dir));
    }
}

void BSP_TMC2660_Enable(enTCM2660Def t, enTCM2660EnDisableDef state)
{
    if (t == TMC2660_M1)
    {
        HAL_GPIO_WritePin(TMC2660_M1_PORT_EN, TMC2660_M1_GPIO_EN, LEVEL_SW(state));
    }
    else if (t == TMC2660_M2)
    {
        HAL_GPIO_WritePin(TMC2660_M2_PORT_EN, TMC2660_M2_GPIO_EN, LEVEL_SW(state));
    }
}

/**
 * @brief:  Set Motor microstep (设置tmc2660细分步数)
 * @retval: return microstep 
 * @note:  
 */
microstep_t BSP_TMC2660_MicrostepSet(enTCM2660Def t, microstep_t microstep)
{
	uint32_t cmd = 0;

    if (microstep > TMC2660_MICROSTEP_1 || microstep  < TMC2660_MICROSTEP_256)
    {
        microstep = TMC2660_MICROSTEP_16;
    }

	cmd = REG_DRVCTRL | INIT_DRVCTRL | microstep;    

    tmc2660_SPI_CS(t, 0);
    uint32_t ret = tmc2660_SPI_Xfer(cmd);
    tmc2660_SPI_CS(t, 1);

    return microstep;
}

/**
 * @brief:  Set Motor microstep (设置tmc2660电流缩放)
 * @retval: return scale 
 * @note:  scaleCurrent = scale / 32 * Current
 */
uint8_t BSP_TMC2660_CurrentScaleSet(enTCM2660Def t, uint8_t scale)
{
	uint32_t cmd = 0;

    if (scale > 31 || scale  < 0)
    {
        scale = 16;
    }

	cmd = REG_SGCSCONF | INIT_SGCSCONF | scale;

    tmc2660_SPI_CS(t, 0);
    uint32_t ret = tmc2660_SPI_Xfer(cmd);
    tmc2660_SPI_CS(t, 1);

    return scale;
}


  • BSP_TMC2660_MODE通过宏选择SPI模式还是STEP/DIR模式控制,通过设置REG_DRVCONF寄存器bit7来选择,但bit7为0时使用STEP/DIR模式为1时使用SPI模式

2.2.3 使用STEP/DIR方式驱动

STEP/DIR方式驱动很简单,给STEP引脚输入PWM信号即可,可以使用定时器输出PWM。
这里使用定时器比较输出翻转模式输出PWM进行控制。输出固定频率时候步进电机就匀速转动,频率越快步进电机转速就越快。

2.2.4 使用SPI驱动

查看手册可以知道DRVCTRL寄存器在SPI模式时用于控制步进电机。
在这里插入图片描述
在这里插入图片描述

  • 寄存器的bit17和bit8分别用于控制OA1-OA2、OB1-OB2的电流方向
  • bit16 - bit9用于控制通过OA1-OA2电流的大小。
  • bit7 - bit0 用于控制通过OB1-OB2电流的大小。

在这里插入图片描述

  • A ~ OA1
  • A ‾ \overline{A} A ~ OA2
  • B ~ OB1
  • B ‾ \overline{B} B ~ OB2

具体如何控制还需要了解步进电机控制原理:两相步进电机的控制及其实现
查看步进电机规格书里面也写了驱动时序 : 只要按照这个时序输出脉冲就可以控制。如果用STEP/DIR模式控制则由芯片把我们输出这种脉冲时序。
在这里插入图片描述

STEPAB A ‾ \overline{A} A B ‾ \overline{B} B
11100
20110
30011
41001
51100

* 第1节拍,OA 1 OB1 通电,也就是输出高电平;OA2、OB2输出低电平
对比这里双4拍可知步进电机的时序和这个是一样的。

使用SPI模式控制

/**
 * @brief:  SPI Mode To ctrl stepper motor
 * @retval:  
 * @note:  0
  */
void BSP_TMC2660_SPIMoveStep(enTCM2660Def t)
{
    static uint8_t index = 0;
    uint32_t beats[4] = {0x01f0f8, 0x03f0f8, 0x03f1f8, 0x01f1f8};
    // uint32_t beats[4] = {0x00f87c, 0x002f87c, 0x002f97c, 0x00f97c};
    uint32_t cmd;
    tmc2660Enable(t, 0);

    cmd = REG_DRVCTRL | beats[index];

    tmc2660_SPI_CS(t, 0);
    tmc2660_SPI_Xfer(cmd);
    tmc2660_SPI_CS(t, 1);

    index = (++index) % 4;
}
  • 第1节拍,向寄存器写入0x01f0f8,bit17和bit8是0,电流方向OA1 —> OA2、OB1 —>OB2,也就是X+Y+,对应规格书 时序 1 1 0 0
  • 第2节拍,向寄存器写入0x03f0f8,bit17为1,bit8为0,电流方向OA2 —> OA1、OB1 —>OB2,也就是X-Y+,对应规格书 时序 0 1 1 0
  • 第3节拍,向寄存器写入0x03f1f8,bit17为1,bit8为1,所以电流方向OA2 —> OA1、OB2 —>OB1,也就是X-Y-,对应规格书 时序 0 0 1 1,
  • 第4节拍,向寄存器写入0x01f1f8,bit17为0,bit8为1,所以电流方向OA1 —> OA2、OB2 —>OB1,也就是X+Y-,对应规格书 时序 1 0 0 1,

测试是可以运行的,说明SPI模式驱动步进电机完成。

问题

驱动很简单,然而按照上面驱动调试了好久电机都驱动不了。
问题就出在了电机连接线是6线,相比一般的4线驱动电机还多了ACOM线和BCOM线。
没有接电机的时候,示波器测试脉冲信号输出都是正常的,一旦接上这6线电机,再次测量脉冲信号就异常了,
在这里插入图片描述
正常波形应该是这样的:
在这里插入图片描述
更换了一个4线的电机,测试发现可以驱动,这证明驱动是没问题了。
对比两个电机就是多了ACOM和BCOM线,猜测可能是ACOM和BCOM影响的所以驱动不了,去掉ACOM和BCOM连接后,测试果然电机成功驱动。

推测原因:电机连接了ACOM和BCOM线,属于单极性步进电机?TMC2660芯片不支持驱动单极性步进电机?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C语言】数据结构-二叉树

主页&#xff1a;114514的代码大冒险 qq:2188956112&#xff08;欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ &#xff09; Gitee&#xff1a;庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com 引入 我们之前已经学过线性数据结构&#xff0c;今天我们将介绍非线性数据结构----树 树是一种非线性的…

面试官问我:说说你对Spring MVC的理解

文章目录什么是MVC模式MVC的原理图2.1 分析工作原理3.1 组件说明&#xff1a;3.1.1 组件&#xff1a;核心架构的具体流程步骤什么是MVC模式 MVC&#xff1a;MVC是一种设计模式 MVC的原理图 2.1 分析 M-Model 模型&#xff08;完成业务逻辑&#xff1a;有javaBean构成&#x…

C++11的异步操作让多线程开发变得简单

C11的异步操作简介一、std::future1.1、future的类型1.2、future的使用1.3、使用示例二、std::packaged_task三、std::promise总结简介 C提供如下的异步操作接口&#xff1a; std::future &#xff1a;异步指向某个任务&#xff0c;然后通过future特性去获取任务函数的返回结…

1. RNN神经网络初探

目录1. 神经网络与未来智能2. 回顾数据维度和神经网络3. 文本转变为词向量1. 神经网络与未来智能 2. 回顾数据维度和神经网络 循环神经网络&#xff0c;主要用来处理时序的数据&#xff0c;它对每个词的顺序是有要求的。 循环神经网络如何保存记忆功能&#xff1f; 当前样本只…

Window10开放某个端口

需求&#xff1a;由于防火墙原因&#xff0c;开放某个端口:如9999 在开始那里搜索防火墙-进入防火墙 第一步&#xff1a;核实是否启动了防火墙&#xff0c;之后进行 第二步&#xff1a;点击“高级设置”&#xff0c;→“入站规则”→“新建规则”→“端口”→ “下一步” …

【前端领域】3D旋转超美相册(HTML+CSS)

世界上总有一半人不理解另一半人的快乐。 ——《爱玛》 目录 一、前言 二、本期作品介绍 3D旋转相册 三、效果展示 四、详细介绍 五、编码实现 index.html style.css img 六、获取源码 公众号获取源码 获取源码&#xff1f;私信&#xff1f;关注&#xff1f;点赞&…

基于微信小程序的游戏账号交易小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

【C++初阶】十二、STL---反向迭代器的实现

目录 一、反向迭代器 二、反向迭代器的实现 一、反向迭代器 之前的模拟实现vector、list 的时候&#xff0c;这些都是实现了正向迭代器&#xff0c;反向迭代器都没有实现&#xff0c;这里就要实现反向迭代器 反向迭代器也是适配器&#xff08;配接器&#xff09;的一种&#…

在阿里干了2年的测试,总结出来的划水经验

测试新人 我的职业生涯开始和大多数测试人一样&#xff0c;开始接触都是纯功能界面测试。那时候在一家电商公司做测试&#xff0c;做了一段时间&#xff0c;熟悉产品的业务流程以及熟练测试工作流程规范之后&#xff0c;效率提高了&#xff0c;工作比较轻松&#xff0c;这样我…

代码随想录第55天(动态规划):● 309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费

一、最佳买卖股票时机含冷冻期 题目描述: 思路和想法&#xff1a; 这道题相较于之前的题目&#xff0c;注重对状态的分析&#xff0c;这里分为四个状态。 &#xff08;1&#xff09;状态一&#xff0c;买入状态 dp[i][0] 操作一&#xff1a;前一天就是持有状态&#xff08;状…

day39【代码随想录】动态规划之

文章目录前言一、不同路径&#xff08;力扣62&#xff09;二、不同路径||&#xff08;力扣63&#xff09;三、最小路径和&#xff08;力扣64&#xff09;前言 1、不同路径 2、不同路径|| 3、最小路径和 一、不同路径&#xff08;力扣62&#xff09; 一个机器人位于一个 m x n…

MyBatis-Plus分页插件和MyBatisX插件

MyBatis-Plus分页插件和MyBatisX插件六、插件1、分页插件a>添加配置类b>测试八、代码生成器1、引入依赖2、快速生成十、MyBatisX插件1、新建spring boot工程a>引入依赖b>配置application.ymlc>连接MySQL数据库d>MybatisX逆向生成2、MyBatisX快速生成CRUD申明…

学习open62541 --- [74] 软链接的妙用

一 原理 在同一台电脑里&#xff0c;可能会有多个工程同时用到open62541&#xff0c;比较简单的办法是每个工程都拷贝一份open62541源码&#xff0c;但是这样会造成空间浪费&#xff0c;而且open62541的源码包本身也不小。 对于Linux用户来说&#xff0c;可以使用软链接来解决…

【Python学习笔记】28.Python3 错误和异常

前言 作为 Python 初学者&#xff0c;在刚学习 Python 编程时&#xff0c;经常会看到一些报错信息&#xff0c;在前面我们没有提及&#xff0c;这章节我们会专门介绍。 Python3 错误和异常 Python 有两种错误很容易辨认&#xff1a;语法错误和异常。 Python assert&#xf…

德国奔驰、博世和保时捷的员工年薪有多少?

点击 欧盟IT那些事 关注我们公告&#xff1a;因企鹅审核规定&#xff0c;本公众号从《德国IT那些事》更名为《欧盟IT那些事》。从职场新人到总裁&#xff0c;一个个盘。位于德国斯图加特的梅赛德斯-奔驰集团及其子公司梅赛德斯-奔驰是世界最知名的汽车制造商之一。奔驰车代表着…

大数据之HBase高级

文章目录前言一、HBase的架构&#xff08;一&#xff09;Client&#xff08;二&#xff09;Master Server&#xff08;三&#xff09;Region Server二、HBase的工作原理&#xff08;一&#xff09;存储数据流程&#xff08;二&#xff09;读取数据流程&#xff08;三&#xff0…

《计算机组成与设计》01. 计算机抽象及相关技术

文章目录计算机体系结构中的 8 个伟大思想面向摩尔定律的设计使用抽象简化设计加速经常性事件通过并行提高性能通过流水线提高性能存储层次通过冗余提高可靠性性能性能的度量时钟周期数和时钟周期长度与CPU时间的公式指令性能公式经典的 CPU 性能公式CPI 计算公式程序执行时间计…

微前端基础

一、什么是微前端 微前端是一种软件架构&#xff0c;可以将前端应用拆解成一些更小的能够独立开发部署的微型应用&#xff0c;然后再将这些微应用进行组合使其成为整体应用的架构模式。微前端架构类似于组件架构&#xff0c;但不同的是&#xff0c;组件不能独立构建和发布&…

7 MMSegmentation 代码教学

本文是openmmlab AI实战营的第七次课程的笔记&#xff0c;以下是我比较关注的部分。本次课程的主要内容是 mmsegmentation的代码教学实战&#xff0c;我会稍微详细记载。环境安装云在线平台 &#xff1a;Featurize推荐代码运行环境&#xff1a;GPU RTX3060 ,CUDA 11.2安装pytor…

[SSD固态硬盘技术 0] SSD的结构和原理导论

版权声明&#xff1a; 本文禁止转载机械硬盘的存储系统由于内部结构,其IO访问性能无法进一步提高,CPU与存储器之间的性能差距逐渐扩大。以Nand Flash为存储介质的固态硬盘技术的发展&#xff0c;性能瓶颈得到缓解。1. 什么是SSD固态硬盘&#xff08;Solid State Drives&#xf…