当前位置: 首页 > news >正文

STM32之增量式编码器电机测速

STM32之增量式编码器电机测速

  • 编码器
    • 编码器种类
      • 按监测原理分类
        • 光电编码器
        • 霍尔编码器
      • 按输出信号分类
        • 增量式编码器
        • 绝对式编码器
    • 编码器参数
      • 分辨率
      • 精度
      • 最大响应频率
      • 信号输出形式
    • 编码器倍频
  • STM32的编码器模式
    • 编码器模式
    • 编码器的计数方向
      • 仅在TI1计数
        • 电机正转,向上计数。
        • 电机反转,向下计数。
      • 仅在TI2计数
      • 在TI1和TI2上均计数
        • 电机正转,向上计数。
        • 电机反转,向下计数。
    • 编码器计数实例
      • TI1FP1和TI1FP2极性不反相:Rising
      • TI1FP1和TI1FP2极性反相:Falling
  • 正交式(霍尔传感器测速码盘)编码器电机测速
    • 模块介绍
      • TB6612FNG电机驱动模块
        • 真值表
        • 电机控制
      • JGB37-520编码器电机
    • 接线
      • TB6612FNG模块与STM32板子接线
      • TB6612FNG模块与520电机接线
      • 520电机与STM32板子接线
    • STM32CubeMX相关配置
      • 配置SYS
      • 配置RCC
      • 配置GPIO
      • 配置USART1
      • 配置定时器2、3、4
      • 配置NVIC
      • 使用Micro库
    • 文件编写
      • 添加文件motor.c
      • 添加文件motor.h
      • 修改文件usart.c
      • 修改文件usart.h
      • 修改文件tim.c
      • main.c文件编写

编码器

编码器,是一种用来测量机械旋转或位移的传感器。它能够测量机械部件在旋转或直线运动时的位移位置或速度等信息,并将其转换成一系列电信号。
.

编码器种类

按监测原理分类

光电编码器

光电编码器,是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器,光电编码器是由光源、光码盘和光敏元件组成。
在这里插入图片描述

  • 光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,光栅盘与电动机同速旋转,经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号,通过计算每秒光电编码器输出脉冲的个数就能反映当前电动机的转速。
  • 为了判断旋转方向,码盘还可提供相位相差90°的两路脉冲信号。
    .

霍尔编码器

霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。在这里插入图片描述

  • 霍尔编码器是由霍尔码盘(磁环)和霍尔元件组成。

  • 霍尔码盘是在一定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号。
    .

按输出信号分类

增量式编码器

增量式编码器也称正交式编码器,是将设备运动时的位移信息变成连续的脉冲信号,脉冲个数表示位移量的大小。

特点:

  • 只有当设备运动时才会输出信号。

  • 一般会输出通道A和通道B 两组信号,并且有90° 的相位差(1/4个周期),同时采集这两组信号就可以计算设备的运动速度和方向。

  • 如下图,通道A和通道B的信号的周期相同,且相位相差1/4个周期,结合两相的信号值:

     当B相和A相先是都读到高电平(1 1),再B读到高电平,A读到低电平(1 0),则为顺时针转当B相和A相先是都读到低电平(0 0),再B读到高电平,A读到低电平(1 0),则为逆时针转
    
  • 除通道A、通道B 以外,还会设置一个额外的通道Z 信号,表示编码器特定的参考位置

  • 如下图,传感器转一圈后Z 轴信号才会输出一个脉冲,在Z轴输出时,可以通过将AB通道的计数清零,实现对码盘绝对位置的计算。

  • 增量式编码器只输出设备的位置变化和运动方向,不会输出设备的绝对位置。
    在这里插入图片描述
    .

绝对式编码器

绝对式编码器在总体结构上与增量式比较类似,都是由码盘、检测装置和放大整形电路构成,但是具体的码盘结构和输出信号含义不同。它是将设备运动时的位移信息通过二进制编码的方式(特殊的码盘)变成数字量直接输出。

特点:

  • 其码盘利用若干透光和不透光的线槽组成一套二进制编码,这些二进制码与编码器转轴的每一个不同角度是唯一对应的。

  • 绝对式编码器的码盘上有很多圈线槽,被称为码道,每一条(圈)码道内部线槽数量和长度都不同。它们共同组成一套二进制编码,一条(圈)码道对应二进制数的其中一个位(通常是码盘最外侧的码道表示最低位,最内侧的码道表示最高位)。

  • 码道的数量决定了二进制编码的位数,一个绝对式编码器有N 条码道,则它输出二进制数的总个数是2的N次方个。

  • 读取这些二进制码就能知道设备的绝对位置,所以称之为绝对式编码器。 编码方式一般采用自然二进制、格雷码或者BCD 码等。

     自然二进制的码盘易于理解,但当码盘的制造工艺有误差时,在两组信号的临界区域,所有码道的值可能不会同时变化,或因为所有传感器检测存在微小的时间差,导致读到错误的值。比如从000跨越到111,理论上应该读到111,但如果从内到外的3条码道没有完全对齐,可能会读到如001或其它异常值。格雷码的(相邻的两个2进制数只有1个位不同)码盘可以避免二进制码盘的数据读取异常,因为格雷码码盘的相邻两个信号组只会有1位的变化,就算制造工艺有误差导致信号读取有偏差,最多也只会产生1个偏差(相邻信号的偏差)
    

在这里插入图片描述
.

编码器参数

分辨率

分辨率是指编码器能够分辨的最小单位。

  • 对于增量式编码器,其分辨率表示为编码器转轴旋转一圈所产生的脉冲数,即脉冲数/转(Pulse Per Revolution或PPR)。码盘上透光线槽的数目其实就等于分辨率,也叫多少线。
  • 对于绝对式编码器,内部码盘所用的位数就是它的分辨率,单位是位(bit),具体还分单圈分辨率和多圈分辨率。
    .

精度

精度是指编码器每个读数与转轴实际位置间的最大误差,通常用角度、角分或角秒来表示。

  • 精度由码盘刻线加工精度、转轴同心度、材料的温度特性、电路的响应时间等各方面因素共同决定。
  • 例如有些绝对式编码器参数表里会写±20′′,这个就表示编码器输出的读数与转轴实际位置之间存在正负20 角秒的误差。
    .

最大响应频率

最大响应频率是指编码器每秒输出的脉冲数,单位是Hz。

  • 计算公式:最大响应频率 = 分辨率 * 轴转速 / 60
    .

信号输出形式

  • 对于增量式编码器,每个通道的信号独立输出,输出电路形式通常有集电极开路输出、推挽输出、差分输出等。
  • 对于绝对式编码器,由于是直接输出几十位的二进制数,为了确保传输速率和信号质量,一般采用串行输出或总线型输出,例如同步串行接口(SSI)、RS485、CANopen或EtherCAT 等,也有一部分是并行输出,输出电路形式与增量式编码器相同。
    .

编码器倍频

增量式编码器输出的脉冲波形一般为占空比50% 的方波,通道A 和B 相位差为90°。

  • 如果只使用通道A(或通道B)计数,并且只捕获通道A(或通道B)的上升沿或下降沿,即为1倍频(没有倍频)。
  • 如果只使用通道A(或通道B)计数,并且捕获了通道A(或通道B)的上升沿和下降沿,则编码器转一圈的计数值翻倍,实现2倍频。
  • 如果既使用通道A计数,又使用通道B计数,而且都捕获了上升沿和下降沿,则实现了4倍频。
    在这里插入图片描述
    如果某个增量式编码器的分辨率为11PPR,能分辨的最小角度为0.6°,那么经过4倍频后它的分辨率能提高到44PPR,能分辨的最小角度为0.15°,即编码器进行倍频能提高其精度。
    .

STM32的编码器模式

在STM32中,高级定时器TIM1、TIM8和通用定时器TIM2、TIM3、TIM4、TIM5都提供编码器接口模式,不过该模式是适用于增量式编码器的。
.

编码器模式

  • 模式1:计数器仅在TI1的边沿处计数。(2倍频)
  • 模式2:计数器仅在TI2的边沿处计数。(2倍频)
  • 模式3:计数器既在TI1的边沿处计数,又在TI1的边沿处计数。(4倍频)
    .

编码器的计数方向

编码器模式下,计数器的计数方向(递增计数还是递减计数)会根据增量编码器的速度和方向自动进行修改,因此,其计数值始终表示编码器的位置。计数方向对应于所连传感器的旋转方向。在这里插入图片描述
STM32 的编码器接口在计数的时候,并不是单纯采集某一通道信号的上升沿或下降沿,而是需要综合另一个通道信号的电平。
.

TI1 <–> 通道A
.
TI2 <–> 通道B

仅在TI1计数

电机正转,向上计数。

假定电机正转时,编码器的通道A的信号比通道B提前1/4个周期(也即相位提前90度),在通道A的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向,所以,在正转的情况下:

  • 通道A上升沿,通道B为低电平,向上计数,代表电机正转。
  • 通道A下降沿,通道B为高电平,向上计数,代表电机正转。
    在这里插入图片描述
    .

电机反转,向下计数。

假定电机反转时,编码器的通道A的信号比通道B滞后1/4个周期(也即相位滞后90度),在通道A的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向,所以,在反转的情况下:

  • 通道A下降沿,通道B为低电平,向下计数,代表电机反转。
  • 通道A上升沿,通道B为高电平,向下计数,代表电机反转。
    在这里插入图片描述
    .

仅在TI2计数

同理与仅在TI1计数,不多赘述。
.

在TI1和TI2上均计数

电机正转,向上计数。

假定电机正转时,编码器的通道A的信号比通道B提前1/4个周期(也即相位提前90度),在通道A和通道B的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向,所以在正转的情况下:

  • 通道A上升沿,通道B为低电平,向上计数,代表电机正转。
  • 通道B上升沿,通道A为高电平,向上计数,代表电机正转。
  • 通道A下降沿,通道B为高电平,向上计数,代表电机正转。
  • 通道B下降沿,通道A为高电平,向上计数,代表电机正转。
    在这里插入图片描述
    .

电机反转,向下计数。

假定电机反转时,编码器的通道A的信号比通道B滞后1/4个周期(也即相位滞后90度),在通道A和通道B的上升沿与下降沿均计数,因为计数的方向代表的电机转动的方向,所以在反转的情况下:

  • 通道A上升沿,通道B为高电平,向下计数,代表电机反转。
  • 通道A下降沿,通道B为高电平,向下计数,代表电机反转。
  • 通道B上升沿,通道A为低电平,向下计数,代表电机反转。
  • 通道B下降沿,通道A为高电平,向下计数,代表电机反转。在这里插入图片描述

编码器计数实例

TI1FP1和TI1FP2极性不反相:Rising

  • 电机正转时,编码器的通道A(TI1)的信号超前通道B(TI2),计数器向上计数。
  • 电机反转时,编码器的通道A(TI1)的信号滞后通道B(TI2),计数器向下计数。在这里插入图片描述
    .

TI1FP1和TI1FP2极性反相:Falling

极性反相可以改变计数器计数方向。

  • 电机正转时,编码器的通道A(TI1)的信号超前通道B(TI2),计数器向下计数。
  • 电机反转时,编码器的通道A(TI1)的信号滞后通道B(TI2),计数器向上计数。在这里插入图片描述

正交式(霍尔传感器测速码盘)编码器电机测速

使用TB6612FNG电机驱动模块来驱动电机,控制电机的正转、反转、制动、停止等功能,利用STM32的定时器作为编码器模式来获取电机在单位时间内产生的脉冲数来达到电机测速的目的。
.

模块介绍

TB6612FNG电机驱动模块

在这里插入图片描述
TB6612FNG是双驱动,也就是可以驱动两个电机,VM外接12V左右电源,GND连接一个即可。
.

真值表

输入输出
IN1IN2PWMSTBYO1O2电机状态
HighLowHighHighHighLow正转
LowHighHighHighLowHigh反转
HighHighxHighLowLow刹车
LowHighLowHighLowLow
HighLowLowHighLowLow
LowLowHighHighOFF自由刹车
xxxLowOFF待机
  • x:可以是High,也可以是Low。
  • 刹车:电机停止时,通过提供电源来将电机锁定在当前位置。这样可以防止电机继续旋转,也可以提供一定的力矩来抵消负载。
  • 自由刹车:将电机锁定在当前位置,不允许电机旋转,但也不提供额外的电源以保持电机的当前位置。
  • 待机:该模块不工作。
    .

电机控制

  • 如果PWM引脚给予一个高电平,那么通过IN1和IN2引脚就能控制电机的四个状态(电机旋转时为全速状态)。
  • 如果PWM引脚给予PWM波(有效电平为高电平,实测80kHz好用),那么可以通过PWM波的占空比大小来控制电机旋转时的速度,同样通过IN1和IN2引脚就能控制电机的四个状态。
    .

JGB37-520编码器电机

在这里插入图片描述
JGB37-520编码器电机(AB相增量式霍尔编码器)是一款直流减速电机,使用的是一款霍尔传感器测速码盘,配有 11 线强磁码盘(即编码器线数为11ppr),减速比为1:30(即减速前转速为330rpm)。在电机旋转一圈单相输出11个脉冲,在四倍频情况下电机旋转一圈输出11 * 30 * 4 = 1320个计数。
.

接线

TB6612FNG模块与STM32板子接线

  • PB3 <-> STBY
  • PB4 <-> AIN1
  • PB5 <-> AIN2
  • PA6(定时器3通道1输出PWM波) <-> PWMA
  • 12V左右外接电源 <-> VM
  • 单片机5V或3.3V <-> VCC
  • GND <-> GND(连接一个即可)
    .

TB6612FNG模块与520电机接线

  • M+(M1) <-> AO1
  • M-(M2) <-> AO2
    .

520电机与STM32板子接线

  • PA0(定时器2通道1,编码器模式) <-> A相
  • PA1(定时器2通道2,编码器模式) <-> B相
  • 单片机5V或3.3V <-> VCC
  • GND <-> GND
    .

STM32CubeMX相关配置

配置SYS

在这里插入图片描述
.

配置RCC

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

配置GPIO

  • PB3引脚配置成输出高电平模式。
  • PB4引脚配置成输出高电平模式。
  • PB5引脚配置成输出高电平模式。
    在这里插入图片描述
    .

配置USART1

在这里插入图片描述
.

配置定时器2、3、4

  • 配置定时器2为编码器模式。
  • 配置定时器3通道1输出PWM波(80kHZ好用)。
  • 配置定时器4定时1s产生溢出中断。
    .

配置定时器2为编码器模式。在这里插入图片描述在这里插入图片描述
.
.
配置定时器3通道1输出PWM波(80kHZ好用)。
在这里插入图片描述
在这里插入图片描述
.
.
配置定时器4定时1s产生溢出中断。在这里插入图片描述
.

配置NVIC

打开定时器4中断和USART1中断。
在这里插入图片描述
.

使用Micro库

只要映射了printf用来发送数据去串口都要使用这个库。
在这里插入图片描述

.

文件编写

添加文件motor.c

#include "gpio.h"
#include "motor.h"#define STBY_pin GPIO_PIN_3#define AIN1_pin GPIO_PIN_4
#define AIN2_pin GPIO_PIN_5#define STBY(x)  do{ x ?  HAL_GPIO_WritePin(GPIOB, STBY_pin, GPIO_PIN_SET)  :  HAL_GPIO_WritePin(GPIOB, STBY_pin, GPIO_PIN_RESET); }while(0)#define AIN1(x)  do{ x ?  HAL_GPIO_WritePin(GPIOB, AIN1_pin, GPIO_PIN_SET)  :  HAL_GPIO_WritePin(GPIOB, AIN1_pin, GPIO_PIN_RESET); }while(0)
#define AIN2(x)  do{ x ?  HAL_GPIO_WritePin(GPIOB, AIN2_pin, GPIO_PIN_SET)  :  HAL_GPIO_WritePin(GPIOB, AIN2_pin, GPIO_PIN_RESET); }while(0)void motor_left_forward()
{STBY(1);AIN1(1);AIN2(0);
}void motor_left_back()
{	STBY(1);AIN1(0);AIN2(1);
}void motor_left_stop()
{STBY(1);AIN1(0);AIN2(0);
}

.

添加文件motor.h

void motor_left_forward(void);void motor_left_back(void);void motor_left_stop(void);

.

修改文件usart.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file    usart.c* @brief   This file provides code for the configuration*          of the USART instances.******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 */#include <stdio.h>
#include <string.h>#define USART_REC_LEN 200// 串口接收缓存(1字节)
uint8_t buf = 0;uint8_t UART1_RX_Buffer[USART_REC_LEN]; // 接收缓冲,串口接收的数据存放地点// 串口接收状态,16位
uint16_t UART1_RX_STA = 0;
// bit15: 如果是1表示接收完成
// bit14: 如果是1表示接收到回车(0x0d)
// bit13~bit0: 接收到的有效字节数目/* USER CODE END 0 */UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* 开启串口1的接收中断 */HAL_UART_Receive_IT(&huart1, &buf, 1); /* 每接收一个串口数据调用一次串口接收完成回调函数 */printf("usart1 is ok\r\n");/* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* 重写stdio.h文件中的prinft()里的fputc()函数 */
int fputc(int my_data, FILE *p)
{unsigned char temp = my_data;// 改写后,使用printf()函数会将数据通过串口一发送出去HAL_UART_Transmit(&huart1, &temp, 1, 0xffff); // 0xfffff为最大超时时间return my_data;
}/* 串口接收完成回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 判断中断是哪个串口触发的if (huart->Instance == USART1){// 判断接收是否完成,即判断UART1_RX_STA的bit15是否为1if (!(UART1_RX_STA & 0x8000)){ // 如果没接收完成就进入接收流程// 判断是否接收到回车0x0dif (UART1_RX_STA & 0x4000){// 判断是否接收到换行0x0aif (buf == 0x0a){// 如果回车和换行都接收到了,则表示接收完成,即把bit15拉高UART1_RX_STA |= 0x8000;}else{ // 如果接收到回车0x0d没有接收到换行0x0a// 则认为接收错误,重新开始接收UART1_RX_STA = 0;}}else{ // 如果没有接收到回车0x0d// 则判断收到的这个字符是否是回车0x0dif (buf == 0x0d){// 如果这个字符是回车,则将将bit14拉高,表示接收到回车UART1_RX_STA |= 0x4000;}else{ // 如果不是回车// 则将这个字符存放到缓存数组中UART1_RX_Buffer[UART1_RX_STA & 0x3ffff] = buf;UART1_RX_STA++;// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收if (UART1_RX_STA > USART_REC_LEN - 1){UART1_RX_STA = 0;}}}}// 如果接收完成则重新开启串口1的接收中断HAL_UART_Receive_IT(&huart1, &buf, 1);}
}/* 对串口接收数据的处理 */
void usart1_receive_data_handle()
{/* 判断判断串口是否接收完成 */if (UART1_RX_STA & 0x8000){printf("接收完成\r\n");// 串口接收完数据后,对串口数据进行处理if (!strcmp((const char *)UART1_RX_Buffer, "haozige")){printf("浩子哥\r\n");}// 接收到其他数据,进行报错else{printf("%s\r\n", "输入错误,请重新输入");}// 换行,重新开始下一次接收memset(UART1_RX_Buffer, 0, USART_REC_LEN);UART1_RX_STA = 0;}
}/* USER CODE END 1 */

.

修改文件usart.h

.

/* USER CODE BEGIN Header */
/********************************************************************************* @file    usart.h* @brief   This file contains all the function prototypes for*          the usart.c file******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"/* USER CODE BEGIN Includes *//* USER CODE END Includes */extern UART_HandleTypeDef huart1;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_USART1_UART_Init(void);/* USER CODE BEGIN Prototypes */void usart1_receive_data_handle(void);/* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __USART_H__ */

修改文件tim.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file    tim.c* @brief   This file provides code for the configuration*          of the TIM instances.******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;/* TIM2 init function */
void MX_TIM2_Init(void)
{/* USER CODE BEGIN TIM2_Init 0 *///编码器/* USER CODE END TIM2_Init 0 */TIM_Encoder_InitTypeDef sConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM2_Init 1 *//* USER CODE END TIM2_Init 1 */htim2.Instance = TIM2;htim2.Init.Prescaler = 0;htim2.Init.CounterMode = TIM_COUNTERMODE_UP;htim2.Init.Period = 65535;htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;sConfig.EncoderMode = TIM_ENCODERMODE_TI12;sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC1Prescaler = TIM_ICPSC_DIV1;sConfig.IC1Filter = 6;sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;sConfig.IC2Prescaler = TIM_ICPSC_DIV1;sConfig.IC2Filter = 6;if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM2_Init 2 */__HAL_TIM_SetCounter(&htim2,0);	 //设置定时器2的计数值为0__HAL_TIM_ENABLE(&htim2);  //使能定时器2HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);  //开启TIM2的编码器模式/* USER CODE END TIM2_Init 2 */}
/* TIM3 init function */
void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *///输出PWM/* USER CODE END TIM3_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance = TIM3;htim3.Init.Prescaler = 8;htim3.Init.CounterMode = TIM_COUNTERMODE_UP;htim3.Init.Period = 99;htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim3) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(&htim3) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 0;sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 */HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);  开启定时器3的通道1的PWM/* USER CODE END TIM3_Init 2 */HAL_TIM_MspPostInit(&htim3);}
/* TIM4 init function */
void MX_TIM4_Init(void)
{/* USER CODE BEGIN TIM4_Init 0 *///定时1s/* USER CODE END TIM4_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM4_Init 1 *//* USER CODE END TIM4_Init 1 */htim4.Instance = TIM4;htim4.Init.Prescaler = 7199;htim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.Period = 9999;htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim4) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM4_Init 2 */HAL_TIM_Base_Start_IT(&htim4);  //启动定时器4,并使能中断/* USER CODE END TIM4_Init 2 */}void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_encoderHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspInit 0 *//* USER CODE END TIM2_MspInit 0 *//* TIM2 clock enable */__HAL_RCC_TIM2_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM2 GPIO ConfigurationPA0-WKUP     ------> TIM2_CH1PA1     ------> TIM2_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN TIM2_MspInit 1 *//* USER CODE END TIM2_MspInit 1 */}
}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspInit 0 *//* USER CODE END TIM3_MspInit 0 *//* TIM3 clock enable */__HAL_RCC_TIM3_CLK_ENABLE();/* USER CODE BEGIN TIM3_MspInit 1 *//* USER CODE END TIM3_MspInit 1 */}else if(tim_baseHandle->Instance==TIM4){/* USER CODE BEGIN TIM4_MspInit 0 *//* USER CODE END TIM4_MspInit 0 *//* TIM4 clock enable */__HAL_RCC_TIM4_CLK_ENABLE();/* TIM4 interrupt Init */HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM4_IRQn);/* USER CODE BEGIN TIM4_MspInit 1 *//* USER CODE END TIM4_MspInit 1 */}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(timHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspPostInit 0 *//* USER CODE END TIM3_MspPostInit 0 */__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM3 GPIO ConfigurationPA6     ------> TIM3_CH1*/GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN TIM3_MspPostInit 1 *//* USER CODE END TIM3_MspPostInit 1 */}}void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
{if(tim_encoderHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspDeInit 0 *//* USER CODE END TIM2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM2_CLK_DISABLE();/**TIM2 GPIO ConfigurationPA0-WKUP     ------> TIM2_CH1PA1     ------> TIM2_CH2*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);/* USER CODE BEGIN TIM2_MspDeInit 1 *//* USER CODE END TIM2_MspDeInit 1 */}
}void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspDeInit 0 *//* USER CODE END TIM3_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM3_CLK_DISABLE();/* USER CODE BEGIN TIM3_MspDeInit 1 *//* USER CODE END TIM3_MspDeInit 1 */}else if(tim_baseHandle->Instance==TIM4){/* USER CODE BEGIN TIM4_MspDeInit 0 *//* USER CODE END TIM4_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM4_CLK_DISABLE();/* TIM4 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM4_IRQn);/* USER CODE BEGIN TIM4_MspDeInit 1 *//* USER CODE END TIM4_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* USER CODE END 1 */

.

main.c文件编写

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "motor.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 *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */short encoder; //定义编码值
short pulse;	  //定义电机实际脉冲值
float speed;/* 获取定时器2计数值 */
short get_left_encoder(void)  //使用计数值  
{short encoder_cnt;encoder_cnt = (short)__HAL_TIM_GetCounter(&htim2);		//获取定时器2的脉冲值__HAL_TIM_SetCounter(&htim2,0);	  //将定时器2计数值清0return encoder_cnt;	
}/* 定时器中断的回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{// 如果是定时器4产生的中断(1s产生一次中断)if (htim4.Instance == TIM4){encoder = get_left_encoder();pulse = encoder / 4;  //4倍频speed = (float)encoder / 1320;printf("encoder: %d\r\n",encoder);printf("pulse: %d\r\n",pulse);printf("speed: %0.2f c/s\r\n",speed);}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* 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_TIM2_Init();MX_TIM3_Init();MX_TIM4_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, 22);  //修改PWM占空比motor_left_back();//motor_left_forward();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */usart1_receive_data_handle();}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** 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.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != 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 */__disable_irq();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,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

相关文章:

STM32之增量式编码器电机测速

STM32之增量式编码器电机测速 编码器编码器种类按监测原理分类光电编码器霍尔编码器 按输出信号分类增量式编码器绝对式编码器 编码器参数分辨率精度最大响应频率信号输出形式 编码器倍频 STM32的编码器模式编码器模式编码器的计数方向仅在TI1计数电机正转&#xff0c;向上计数…...

一图看懂 xlsxwriter 模块:用于创建 Excel .xlsx 文件, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 xlsxwriter 模块&#xff1a;用于创建 Excel .xlsx 文件, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【xlsxwriter】统计常量模块1 xlsxwrit…...

【社区图书馆】NVMe协议的命令

声明 主页:元存储的博客_CSDN博客 依公开知识及经验整理,如有误请留言。 个人辛苦整理,付费内容,禁止转载。 内容摘要 前言 命令由host提交到内存中的SQ队列中,更新TDBxSQ后,NVMe控制器通过DMA的方式将SQ中的命令(怎么取,如何取,取多少,因设计而异)取到控制器缓冲区…...

Nginx网站服务

Nginx概述 Nginx 是开源、高性能、高可靠、低资源消耗的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热更新。对HTTP并发…...

第八篇 Spring 集成JdbcTemplate

《Spring》篇章整体栏目 ————————————————————————————— 【第一章】spring 概念与体系结构 【第二章】spring IoC 的工作原理 【第三章】spring IOC与Bean环境搭建与应用 【第四章】spring bean定义 【第五章】Spring 集合注入、作用域 【第六章】…...

双塔模型:微软DSSM模型浅析

1.背景 DSSM是Deep Structured Semantic Model (深层结构语义模型) 的缩写&#xff0c;即我们通常说的基于深度网络的语义模型&#xff0c;其核心思想是将query和doc映射到到共同维度的语义空间中&#xff0c;通过最大化query和doc语义向量之间的余弦相似度&#xff0c;从而训…...

DAY 44 Apache网页优化

Apache网页优化 概述 在企业中&#xff0c;部署Apache后只采用默认的配置参数&#xff0c;会引发网站很多问题&#xff0c;换言之默认配置是针对以前较低的服务器配置的&#xff0c;以前的配置已经不适用当今互联网时代 为了适应企业需求&#xff0c;就需要考虑如何提升Apach…...

移动端手机网页适配iPad与折叠屏设备

采用的网页适配方案&#xff1a;移动端页面px布局适配方案&#xff08;viewport&#xff09; 产生此问题的原因 由于手机与平板等设备宽高比差异导致页面展示不全或者功能按钮展示在视口之外点击不到。 简单来说就是我们的页面都是瘦长(即高大于宽)的&#xff0c;而折叠屏等设…...

深入剖析 Qt QMap:原理、应用与技巧

目录标题 引言&#xff1a;QMap 的重要性与基本概念QMap 简介&#xff1a;基本使用方法&#xff08;QMap Basics: Concepts and Usage&#xff09;QMap 迭代器&#xff1a;遍历与操作键值对&#xff08;QMap Iterators: Traversing and Manipulating Key-Value Pairs&#xff0…...

SpringBoot使用Hbase

SpringBoot使用Hbase 文章目录 SpringBoot使用Hbase一&#xff0c;引入依赖二&#xff0c;配置文件添加自己的属性三&#xff0c;配置类注入HBASE配置四&#xff0c;配置Hbase连接池五&#xff0c;配置操作服务类 一&#xff0c;引入依赖 <dependency><groupId>org…...

SQL优化总结

SQL优化总结 1. MySQL层优化五个原则2. SQL优化策略2.1 避免不走索引的场景 3. SELECT语句其他优化3.1 避免出现select *3.2 避免出现不确定结果的函数3.3 多表关联查询时&#xff0c;小表在前&#xff0c;大表在后。3.4 使用表的别名3.5 调整Where字句中的连接顺序 附录 1. My…...

【python学习】基础篇-字典的基本操作 获取当前日期时间

1.字典的定义与创建 定义字典时&#xff0c;每个元素都包含两个部分“键”和“值”&#xff0c;在“键”和“值”之间使用冒号(:)分隔&#xff0c;相邻两个元素使用逗号分隔&#xff0c;所有元素放在一个大括号“{}”中。语法格式如下: dictionary (‘key1’:‘value1’, &quo…...

Python FreeCAD.Vector方法代码示例

Python FreeCAD.Vector方法代码示例 本文整理汇总了Python中FreeCAD.Vector方法的典型用法代码示例。如果您正苦于以下问题&#xff1a;Python FreeCAD.Vector方法的具体用法&#xff1f;Python FreeCAD.Vector怎么用&#xff1f;Python FreeCAD.Vector使用的例子&#xff1f;那…...

HDFS 梳理

HDFS客户端 客户端作用 管理文件目录文件系统操作读写 客户端生成 配置项 配置 客户端状态 缓冲相关参数&#xff0c;读写缓冲 失败切换操作 推测执行?? NN引用 NNProxy 客户端关闭 关闭IO流 修改状态 关闭RPC连接 是否有多个RPC连接&#xff1f; HDFS读 打开文件构…...

ChatGPT团队中,3个清华学霸,1个北大学霸,共9位华人

众所周知&#xff0c;美国硅谷其实有着众多的华人&#xff0c;哪怕是芯片领域&#xff0c;华为也有着一席之地&#xff0c;比如AMD 的 CEO 苏姿丰、Nvidia 的 CEO 黄仁勋 都是华人。 还有更多的美国著名的科技企业中&#xff0c;都有着华人的身影&#xff0c;这些华人&#xff…...

通过工具生成指定 类型 大小 文件

今天给大家介绍一个神器 首先 大家在开发过程中或许经常需要涉及到文件上传类的功能 需要测试文件过大 空文件等等清空 不同大小的文件 而这种文件大小是比较不好控制的 但大家可以下载我的资源 文件生成工具(可生成指定大小 类型文件) 下载下来里面就有一个 fileGeneration…...

超外差收音机的制作-电子线路课程设计-实验课

超外差收音机的制作 一、原理部分&#xff1a; 超外差收音机&#xff1a;超外差式收音机是将接收到的不同频率的高频信号全部变成一个固定的中频信号进行放大&#xff0c;因而电路对各种电台信号的放大量基本是相同的&#xff0c;这样可以使中放电路具有优良的频率特性。 超…...

TensorFlow 深度学习实战指南:1~5 全

原文&#xff1a;Hands-on Deep Learning with TensorFlow 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;只关心如…...

【数据结构】队列的实现

白日去如箭&#xff0c;达者惜今阳。 --朱敦儒目录 &#x1f681;前言&#xff1a;​ &#x1f3dd;️一.队列的概念及结构 &#x1f33b;二.队列各种功能的实现 &#x1f34d;1.队列的初始化 &#x1f3dd;️2.队列…...

【数据库】— 无损连接、Chase算法、保持函数依赖

【数据库】— 无损连接、Chase算法 Chase算法Chase算法举例一种简便方法&#xff1a;分解为两个模式时无损连接和函数依赖的一个简单例子 Chase算法 形式化定义&#xff1a; 构造一个 k k k行 n n n列的表格&#xff0c;每行对应一个模式 R i ( 1 ≤ i ≤ k ) Ri (1≤i ≤ k)…...

用英语翻译中文-汉字英文翻译

中文转英语翻译 作为一款高效、准确的中文转英语翻译软件&#xff0c;我们的产品可以帮助全球用户更好地沟通和合作&#xff0c;实现跨文化交流。 在全球化的今天&#xff0c;中英文翻译已经成为商务、学术、娱乐等各个领域不可或缺的一部分。我们的中文转英语翻译软件是为了…...

瑞吉外卖项目——缓存优化

用户数量多&#xff0c;系统访问量大 频繁访问数据库&#xff0c;系统性能下降&#xff0c;用户体验差 环境搭建 maven坐标 在项目的pom.xml文件中导入spring data redis的maven坐标: <dependency><groupId>org.springframework.boot</groupId><arti…...

从头创建一个新的浏览器,这合理吗?

从头构建一个新浏览器&#xff1f;这如果是不是个天大的“伪需求”&#xff0c;便是一场开发者的噩梦&#xff01; 要知道&#xff0c;如果没有上百亿的资金和数百名研发工程师的投入&#xff0c;从头开始构建一个新的浏览器引擎&#xff0c;几乎是不可能的。然而SerenityOS系统…...

TypeScript泛型类型和接口

本节课我们来开始了解 TypeScript 中泛型类型的概念和接口使用。 一&#xff0e;泛型类型 1. 前面&#xff0c;我们通过泛型变量的形式来存储调用方的类型从而进行检查&#xff1b; 2. 而泛型也可以作为类型的方式存在&#xff0c;理解这一点&#xff0c;先了解下函数的…...

docker命令

1.运行 docker-compose up 2.查看命令 docker images 3.删掉docker镜像: docker rmi -f [id] docker卸载 1.杀死docker有关的容器&#xff1a; docker kill $(docker ps -a -q) 2.删除所有docker容器&#xff1a;docker rm $(docker ps -a -q) 3.删除所有docker镜像&…...

2023 年 3 月 NFT 月度报告

作者&#xff1a;Danielfootprint.network 数据来源&#xff1a;NFT Monthly Report 三月份的 NFT 市场上出现了两个有趣的趋势。一方面&#xff0c;Polygon 链尽管在二月份有所突破&#xff0c;达到了 NFT 总交易量的 4.2%&#xff0c;但于三月再次跌至 1% 以下&#xff0c;…...

【http】 get方法和Post方法区别;http和https

get方法和Post方法 get方法&#xff1a;通过url传参&#xff0c;回显输入的私密信息&#xff0c;不够私密 Post方法&#xff1a;通过正文传参&#xff0c;不会回显&#xff0c;一般私密性有保证。 一般如果上传的图片&#xff0c;音频比较大&#xff0c;推荐Post方法&#x…...

第三章 法的渊源与法的分类

目录 第一节 法的渊源的分类 一、法的渊源释义二、法的渊源种类 第二节 正式法源 一、正式法源的含义二、当代中国的正式法源三、正式法源的一般效力原则 第三节 非正式法源 一、当代中国的非正式法源 第四节 法的分类 一、法的一般分类二、法的特殊分类 第一节 法的渊源的…...

在Ubuntu18.04或者20.04下搭建edk2运行环境

#更新完之后依次执行下面两条命令 1.apt-get update 2.apt-get upgrade 如果执行之后出现源不能更新的问题,到/etc/apt/sources.list.d 下删除对应的ppa源重新更新即可解决 git clone https://github.com/tianocore/edk2.git cd edk2 git submodule update --init 如果git cl…...

多线程编程常用函数用法

一、多线程编程常用函数用法 1、pthread_create 头文件 #include<pthread.h>函数声明 int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*&#xff08;*start_rtn)(void*),void *restrict arg)函数功能 pthread_create是UNIX环境…...