Clion开发STM32之串口封装(HAL库)

news/2024/5/7 7:58:32/文章来源:https://blog.csdn.net/weixin_44742767/article/details/130444774

前提

  1. 在开发STM32过程中,芯片提供的串口引脚一般是不会发生变化的,所以为了方便移植,借助HAL提供的注册回调函数自定义,这边重新进行简要的封装
  2. 此工程开发是以Clion为开发的IDE,用keil只需将对应的文件进行移植即可.
  3. 文章末尾附带gitee工程地址

工程创建(以STM32F103C8T6为例)

  1. 参考Stm32开发环境从0搭建(Clion作为开发软件)
  2. 开启自定义注册串口硬件注册回调(方便后面工程移植,也可以使用HAL默认的硬件回调)
    在这里插入图片描述3. 打开工程并测试
    在这里插入图片描述

添加自定义的项目路径(方便后期移植)

  1. 创建目录框架
    在这里插入图片描述2. 编写CMakeLists文件t和CMakeLists模板文件(此步骤是将自定义目录框架包含到项目中)
    在这里插入图片描述在这里插入图片描述3. 创建同一的头文件去管理

在这里插入图片描述

统一串口宏定义

头文件 (bsp_serial_define.h)

#ifndef STM32_VET6_BSP_SERIAL_DEFINE_H
#define STM32_VET6_BSP_SERIAL_DEFINE_H#include "sys_driver_include.h"
// 串口只支持异步
/***********************************************************串口1相关宏定义*******************************************************/
#define USE_COM1_ENABLE (1)
#define USE_COM1_IRQ_ENABLE (0) // 串口1中断使能
#define USE_COM1_DMA_RX_ENABLE (0) // 串口1 DMA RX 使能
#define COM1_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM1_TX_PORT GPIOA
#define COM1_TX_PIN GPIO_PIN_9
#define COM1_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM1_RX_PORT GPIOA
#define COM1_RX_PIN GPIO_PIN_10
#define COM1_IRQ_Priority 5 // 抢占优先级
#define COM1_IRQ_SubPriority 0 // 响应优先级
#define COM1_DMA_RX_CHANNEL DMA1_Channel5
#define COM1_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM1_DMA_IRQ DMA1_Channel5_IRQn
#define COM1_IRQ_HANDLE DMA1_Channel5_IRQHandler
extern UART_HandleTypeDef com1_handle;
/***********************************************************串口2相关宏定义*******************************************************/
#define USE_COM2_ENABLE (0)
#define USE_COM2_IRQ_ENABLE (0) // 串口2中断使能
#define USE_COM2_DMA_RX_ENABLE (0) // 串口1 DMA RX 使能/**@details 引脚定义*/
#define COM2_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM2_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define COM2_TX_PIN GPIO_PIN_2
#define COM2_RX_PIN GPIO_PIN_3
#define COM2_TX_PORT GPIOA
#define COM2_RX_PORT GPIOA#define COM2_IRQ_Priority 5 // 抢占优先级
#define COM2_IRQ_SubPriority 0 // 响应优先级
#define COM2_DMA_RX_CHANNEL DMA1_Channel6
#define COM2_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM2_DMA_IRQ DMA1_Channel6_IRQn
#define COM2_IRQ_HANDLE DMA1_Channel6_IRQHandler
extern UART_HandleTypeDef com2_handle;
/***********************************************************串口3相关宏定义*******************************************************/
#define USE_COM3_ENABLE (0)
#define USE_COM3_IRQ_ENABLE (1) // 串口3中断使能
#define USE_COM3_DMA_RX_ENABLE (1) // 串口3 DMA RX 使能
#define COM3_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define COM3_TX_PORT GPIOD
#define COM3_TX_PIN GPIO_PIN_8
#define COM3_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define COM3_RX_PORT GPIOD
#define COM3_RX_PIN GPIO_PIN_9
#define COM3_IRQ_Priority 5 // 抢占优先级
#define COM3_IRQ_SubPriority 0 // 响应优先级
#define COM3_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()
#define COM3_DMA_RX_CHANNEL DMA1_Channel3
#define COM3_DMA_IRQ DMA1_Channel3_IRQn
#define COM3_IRQ_HANDLE DMA1_Channel3_IRQHandler
extern UART_HandleTypeDef com3_handle;
/***********************************************************串口4相关宏定义*******************************************************/
#define USE_COM4_ENABLE (0)
#define USE_COM4_IRQ_ENABLE (1) // 串口4中断使能
#define USE_COM4_DMA_RX_ENABLE (1) // 串口4 DMA RX 使能
#define COM4_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define COM4_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define COM4_TX_PORT GPIOC
#define COM4_RX_PORT GPIOC
#define COM4_TX_PIN GPIO_PIN_10
#define COM4_RX_PIN GPIO_PIN_11
#define COM4_IRQ_Priority 5 // 抢占优先级
#define COM4_IRQ_SubPriority 0 // 响应优先级
#define COM4_DMA_CLK_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define COM4_DMA_RX_CHANNEL DMA2_Channel3
#define COM4_DMA_IRQ DMA2_Channel3_IRQn
#define COM4_DMA_IRQ_HANDLE DMA2_Channel3_IRQHandler
extern UART_HandleTypeDef com4_handle;
#endif //STM32_VET6_BSP_SERIAL_DEFINE_H

串口核心文件

头文件(bsp_serial.h)

#ifndef STM32_VET6_BSP_SERIAL_H
#define STM32_VET6_BSP_SERIAL_H#include "bsp_serial_define.h"
#include "bsp_serial_com1.h"void Com_Init_01(USART_TypeDef *uart, uint32_t baud);void Com_Init(UART_HandleTypeDef *comHandle, UART_InitTypeDef *config);void Com_RegisterCallback(UART_HandleTypeDef *comHandle);void Com_Dma_Init(DMA_HandleTypeDef *dmaHandle, DMA_InitTypeDef *config);void UART_MspInit(UART_HandleTypeDef *comHandle);void UART_MspDeInit(UART_HandleTypeDef *comHandle);void UART_RxEventCallback(UART_HandleTypeDef *com_handle, uint16_t Pos);#endif //STM32_VET6_BSP_SERIAL_H

源文件(bsp_serial.c)

#include "bsp_serial.h"static UART_InitTypeDef init_cnf = {.OverSampling = UART_OVERSAMPLING_16,.Mode = UART_MODE_TX_RX,.HwFlowCtl = UART_HWCONTROL_NONE,.Parity = UART_PARITY_NONE,.StopBits = UART_STOPBITS_1,.WordLength = UART_WORDLENGTH_8B,.BaudRate = 9600
};
static DMA_InitTypeDef default_dma_config = {.Direction = DMA_PERIPH_TO_MEMORY,.PeriphInc = DMA_PINC_DISABLE,.MemInc = DMA_MINC_ENABLE,.PeriphDataAlignment = DMA_PDATAALIGN_BYTE,.MemDataAlignment =DMA_MDATAALIGN_BYTE,.Mode = DMA_NORMAL,.Priority = DMA_PRIORITY_LOW
};/*** 通用串口初始化* @param uart  串口* @param baud*/
void Com_Init_01(USART_TypeDef *uart, uint32_t baud) {init_cnf.BaudRate = baud;if (uart == NULL) {}
#if USE_COM1_ENABLEelse if (uart == USART1) {Com_Init(&com1_handle, &init_cnf);}
#endif
#if USE_COM2_ENABLEelse if (uart == USART2) {Sw_Com_Init(&com2_handle, &init_cnf);}
#endif
#if USE_COM3_ENABLEelse if (uart == USART3) {Sw_Com_Init(&com3_handle, &init_cnf);}
#endif
#if USE_COM4_ENABLEelse if (uart == UART4) {Sw_Com_Init(&com4_handle, &init_cnf);}
#endif
}/*** @brief 通用串口初始化* @param comHandle* @param config*/
void Com_Init(UART_HandleTypeDef *comHandle, UART_InitTypeDef *config) {
#if USE_HAL_UART_REGISTER_CALLBACKScomHandle->MspDeInitCallback = UART_MspDeInit;comHandle->MspInitCallback = UART_MspInit;
#endifUART_InitTypeDef *ptr = NULL;if (config != NULL) {ptr = config;} else {ptr = &init_cnf;}memcpy(&comHandle->Init, ptr, sizeof(UART_InitTypeDef));if (HAL_UART_Init(comHandle) != HAL_OK) {common_error_handle(__FILE__, __LINE__);}
}/*** @brief 注册接收事件回调* @param comHandle*/
void Com_RegisterCallback(UART_HandleTypeDef *comHandle) {
#if USE_HAL_UART_REGISTER_CALLBACKSHAL_UART_RegisterRxEventCallback(comHandle, UART_RxEventCallback);
#endif
}void UART_MspInit(UART_HandleTypeDef *comHandle) {
#if USE_COM1_ENABLEif (comHandle->Instance == USART1) {Com1_MspInit();}
#endif
#if USE_COM2_ENABLEif (comHandle->Instance == USART2) {Com2_MspInit();}
#endif
#if USE_COM3_ENABLEif (comHandle->Instance == USART3) {Com3_MspInit();}
#endif
#if USE_COM4_ENABLEif (comHandle->Instance == UART4) {Com4_MspInit();}
#endif
}void UART_MspDeInit(UART_HandleTypeDef *comHandle) {
#if USE_COM1_ENABLEif (comHandle->Instance == USART1) {Com1_MspDeInit();}
#endif
#if USE_COM2_ENABLEif (comHandle->Instance == USART2) {Com2_MspDeInit();}
#endif
#if USE_COM3_ENABLEif (comHandle->Instance == USART3) {Com3_MspDeInit();}
#endif
#if USE_COM4_ENABLEif (comHandle->Instance == UART4) {Com4_MspDeInit();}
#endif
}/*** @brief 串口接收事件* @param com_handle* @param Pos*/
void UART_RxEventCallback(UART_HandleTypeDef *com_handle, uint16_t Pos) {if (com_handle == NULL) {common_error_handle(__FILE__, __LINE__);}
#if (USE_COM1_ENABLE == 1)else if (com_handle->Instance == USART1) {Com1_RxEvent(Pos);}
#endif
#if (USE_COM2_ENABLE == 1)else if (comHandle->Instance == USART2) {Com2_RxEvent(Pos);}
#endif
#if (USE_COM3_ENABLE == 1)else if (comHandle->Instance == USART3) {Com3_RxEvent(Pos);}
#endif
#if (USE_COM4_ENABLE == 1)else if (comHandle->Instance == UART4) {Com4_RxEvent(Pos);}
#endif
}/*** 错误回调* @param comHandle 串口句柄*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *comHandle) {switch (comHandle->ErrorCode) {case HAL_UART_ERROR_PE:__HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_PE);break;case HAL_UART_ERROR_NE:__HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_NE);break;case HAL_UART_ERROR_FE:__HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_FE);break;case HAL_UART_ERROR_ORE:__HAL_UART_CLEAR_FLAG(comHandle, UART_FLAG_ORE);break;}if (comHandle == NULL) {common_error_handle(__FILE__, __LINE__);}
#if (USE_COM1_ENABLE == 1)else if (comHandle->Instance == USART1) {Com1_ErrEvent();}
#endif
#if (USE_COM2_ENABLE == 1)else if (comHandle->Instance == USART2) {Com2_ErrEvent();}
#endif
#if (USE_COM3_ENABLE == 1)else if (comHandle->Instance == USART3) {Com3_ErrEvent();}
#endif
#if (USE_COM4_ENABLE == 1)else if (comHandle->Instance == UART4) {Com4_ErrEvent();}
#endif
}/*** @brief 统一DMA接口初始化* @param dmaHandle* @param config*/
void Com_Dma_Init(DMA_HandleTypeDef *dmaHandle, DMA_InitTypeDef *config) {DMA_InitTypeDef *ptr;if (config != NULL) {ptr = config;} else {ptr = &default_dma_config;}memcpy(&dmaHandle->Init, ptr, sizeof(DMA_InitTypeDef));
}

串口1

头文件(bsp_serial_com1.h)

#ifndef STM32_VET6_BSP_SERIAL_COM1_H
#define STM32_VET6_BSP_SERIAL_COM1_H#include "bsp_serial_define.h"#if USE_COM1_ENABLEvoid Com1_DMA_Init(uint32_t PreemptPriority, uint32_t SubPriority, DMA_InitTypeDef *config);void Com1_Init(UART_InitTypeDef *config);void Com1_MspInit(void);void Com1_MspDeInit(void);void Com1_DMA_Rx_MspInit(void);void Com1_DMA_Rx_MspDeInit(void);void Com1_RxEvent(uint16_t pos);void Com1_ErrEvent(void);#endif#endif //STM32_VET6_BSP_SERIAL_COM1_H

基础源文件(bsp_serial_com1.c)

#include "bsp_serial.h"UART_HandleTypeDef com1_handle = {.Instance=USART1};/*** @brief Com1初始化* @param config*/
void Com1_Init(UART_InitTypeDef *config) {Com_Init(&com1_handle, config);// 使用自定义的中断回调Com_RegisterCallback(&com1_handle);
}void Com1_MspInit(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};/* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();COM1_TX_GPIO_CLK_ENABLE();COM1_RX_GPIO_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = COM1_TX_PIN;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(COM1_TX_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = COM1_RX_PIN;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(COM1_RX_PORT, &GPIO_InitStruct);
#if USE_COM1_DMA_RX_ENABLECom1_DMA_Rx_MspInit();
#endif
}void Com1_MspDeInit(void) {/* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();HAL_GPIO_DeInit(COM1_TX_PORT, COM1_TX_PIN);HAL_GPIO_DeInit(COM1_RX_PORT, COM1_RX_PIN);
#if USE_COM1_DMA_RX_ENABLECom1_DMA_Rx_MspDeInit();
#endif
}void USART1_IRQHandler(void) {HAL_UART_IRQHandler(&com1_handle);
}

扩展串口接收dma(bsp_serial_dma_com1.c)

#include "bsp_serial.h"DMA_HandleTypeDef com1_dma_rx_handle={.Instance=COM1_DMA_RX_CHANNEL,
};void Com1_DMA_Init(uint32_t PreemptPriority, uint32_t SubPriority, DMA_InitTypeDef *config) {
/* DMA controller clock enable */COM1_DMA_CLK_ENABLE();/* DMA interrupt init */HAL_NVIC_SetPriority(COM1_DMA_IRQ, PreemptPriority, SubPriority);HAL_NVIC_EnableIRQ(COM1_DMA_IRQ);// com1初始化Com_Dma_Init(&com1_dma_rx_handle, config);
}void Com1_DMA_Rx_MspInit(void) {if (HAL_DMA_Init(&com1_dma_rx_handle) != HAL_OK) {common_error_handle(__FILE__, __LINE__);}__HAL_LINKDMA(&com1_handle, hdmarx, com1_dma_rx_handle);
#if USE_COM1_IRQ_ENABLEHAL_NVIC_SetPriority(USART1_IRQn, COM1_IRQ_Priority, COM1_IRQ_SubPriority);HAL_NVIC_EnableIRQ(USART1_IRQn);
#endif
}void Com1_DMA_Rx_MspDeInit(void) {/*  DMA DeInit */HAL_DMA_DeInit(&com1_dma_rx_handle);/*  interrupt Deinit */HAL_NVIC_DisableIRQ(COM1_DMA_IRQ);
}void COM1_IRQ_HANDLE(void) {/* USER CODE BEGIN DMA1_Channel5_IRQn 0 */HAL_DMA_IRQHandler(&com1_dma_rx_handle);
}/*** @brief 参考 @ref HAL_UARTEx_RxEventCallback* @param pos*/
__weak void Com1_RxEvent(uint16_t pos) {UNUSED(pos);
}
/*** @brief 错误事件*/
__weak void Com1_ErrEvent(void) {}

示例

  1. 开启串口中断和DMA接收中断
    在这里插入图片描述
/* 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 <stdbool.h>
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include "bsp_serial.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* 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 */
static uint8_t buffer[256];
// 接收数据标志位
static volatile bool rec_data_flag = false;
// 接收数据长度
static volatile uint16_t rec_len = 0;/*** @brief 错误事件*/
void Com1_ErrEvent(void) {rec_len = 0;rec_data_flag = false;// 重新开启DMA接收HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);
}void Com1_RxEvent(uint16_t pos) {rec_len = pos;rec_data_flag = true;}static uint16_t com_rec(void *retBuf) {if (rec_data_flag) {rec_data_flag = false;memcpy(retBuf, buffer, rec_len);HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);return rec_len;}return 0;
}
/* 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 */
#if 0/* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */
#endifCom1_DMA_Init(5, 0, NULL);Com_Init_01(USART1, 9600);// 开启串口屏接收数据HAL_UARTEx_ReceiveToIdle_DMA(&com1_handle, buffer, 256);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint8_t read_buf[256];while (1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */uint16_t data_len = com_rec(read_buf);if (data_len > 0) {// todo 解析数据 read_buf}}/* 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 */

项目gitee

https://gitee.com/scl_arm/serial_proj.git

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java——Java面向对象

该系列博文会告诉你如何从入门到进阶&#xff0c;一步步地学习Java基础知识&#xff0c;并上手进行实战&#xff0c;接着了解每个Java知识点背后的实现原理&#xff0c;更完整地了解整个Java技术体系&#xff0c;形成自己的知识框架。 概述&#xff1a; Java是面向对象的程序…

XR技术在手术中的应用调研

虚拟现实、增强现实、混合现实等概念和技术是最近几年发展起来的&#xff0c;相信你对去年大火的元宇宙深有感触&#xff0c;元宇宙属于虚拟现实的技术范畴&#xff0c;头号玩家电影也让虚拟现实走进大众的视野中。早在2015年&#xff0c;笔者参加一次展会时就有接触&#xff0…

py_rabbitmq

安装 服务端 https://www.jianshu.com/p/2fb6d5ac17b9 客户端 pip install pika文档 https://rabbitmq.com/tutorials/tutorial-one-python.html 简单示例 生产者 import pika import rabbitmq_study.settings as settingscredentials pika.PlainCredentials(settings…

手记系列之四 ----- 关于使用MySql的一些经验

前言 本篇文章主要介绍的关于本人在使用MySql记录笔记的一些使用方法和经验&#xff0c;温馨提示&#xff0c;本文有点长&#xff0c;约1.5w字&#xff0c;几十张图片&#xff0c;建议收藏查看。 一、MySql安装 下载地址:https://dev.mysql.com/downloads/ 在安装MySql之前&a…

闪电加密和隐藏加密文件夹忘记密码怎么办?

闪电加密和隐藏加密是文件夹加密超级大师的两种文件夹加密类型&#xff0c;它们都拥有超快的加密算法&#xff0c;可以瞬间加密超大文件夹。那么这两种文件夹加密类型忘记密码该怎么办呢&#xff1f;下面我们一起来了解一下吧。 闪电加密和隐藏加密文件夹找回密码 首先&#x…

【计算机图形学】课堂习题汇总

在直线的光栅化算法中&#xff0c;如果不考虑最大位移方向则可能得到怎样的直线&#xff1f; A&#xff1a;斜率为1的线 B&#xff1a;总是垂直的 C&#xff1a;离散的点&#xff0c;无法构成直线 D&#xff1a;总是水平的 在直线的改进的Bresenham算法中&#xff0c;每当误…

【五一创作】使用Scala二次开发Spark3.3.0实现对MySQL的upsert操作

使用Scala二次开发Spark实现对MySQL的upsert操作 背景 在我们的数仓升级项目中&#xff0c;遇到了这样的场景&#xff1a;古人开发的任务是使用DataStage运算后&#xff0c;按照主键【或者多个字段拼接的唯一键】来做insert then update&#xff0c;顾名思义&#xff0c;也就…

【C++】vector OJ练习

文章目录 1. 只出现一次的数字思路讲解AC代码 2. 杨辉三角思路讲解AC代码 3. 只出现一次的数字 III思路讲解AC代码 4. 只出现一次的数字 II思路讲解AC代码 5. 删除有序数组中的重复项思路讲解AC代码 6. 数组中出现次数超过一半的数字思路讲解AC代码 这篇文章我们来做几道vector…

服装店铺装修有哪些窍门?做好这3点,顾客主动上门

现在街边有各种各样的服装店&#xff0c;有的服装店客流不断&#xff0c;有的服装店却很冷清&#xff0c;导致这种现象的原因有很多&#xff0c;比较重要的一点就是你的服装店铺装修没做好。 你的服装店铺装修足够吸引人吗&#xff1f; 什么样的服装店铺装修才能吸引顾客&#…

【VM服务管家】VM4.0平台SDK_2.5 全局工具类

目录 2.5.1 全局相机&#xff1a;全局相机设置参数的方法2.5.2 全局相机&#xff1a;获取全局相机列表的方法2.5.3 全局通信&#xff1a;通信管理中设备开启状态管理2.5.4 全局通信&#xff1a;接收和发送数据的方法2.5.5 全局变量获取和设置全局变量的方法 2.5.1 全局相机&…

最新发布!面向开发者的 ChatGPT Prompt Engineering 免费教程,吴恩达与OpenAI合作打造!...

就在几小时之前&#xff0c;吴恩达在Twitter上宣布了与OpenAI合作的最新免费教程&#xff1a;《ChatGPT Prompt Engineering for Developers》 我们可以通过下面的链接&#xff0c;直达官网网站&#xff1a; https://www.deeplearning.ai/short-courses/chatgpt-prompt-enginee…

JavaScript用map实现Hashmap

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;数据结构与算法 &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 正如我们已经看到的&#xff0c;Map 对象是一个键值对。最初&#xff0c;M…

[ICLR 2023] Token Merging: Your ViT But Faster

Contents IntroductionToken MergingExperimentsImage ExperimentsDesign choicesModel SweepComparison to Other WorksVisualizations Video ExperimentsAudio Experiments References Introduction 作者提出了一种 token 合并方法 Token Merging (ToMe)&#xff0c;能够在不…

( 字符串) 647. 回文子串 ——【Leetcode每日一题】

❓647. 回文子串 难度&#xff1a;中等 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使…

( 栈和队列) 20. 有效的括号 ——【Leetcode每日一题】

❓20. 有效的括号 难度&#xff1a;简单 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;]的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合…

*2.5 迭代法的收敛阶与加速收敛方法

学习目标&#xff1a; 了解迭代法的基本概念和原理。学习者需要理解迭代法的基本概念和原理&#xff0c;包括迭代过程、迭代格式、收敛性等基本概念。 熟练掌握迭代法的收敛阶和收敛速度。学习者需要了解迭代法的收敛阶和收敛速度&#xff0c;掌握如何计算迭代法的收敛阶和收敛…

【校招VIP】IT职位校招简历千万不要用两栏的模板,另外,告诉你个陷阱:越个性机会越少

前两天在简历指导的直播里&#xff0c;发现了不应该出现的一种简历格式问题。 有的同学喜欢用那种竖栏两栏的简历模板。 我们建议研发岗的校招&#xff0c;简历不要这么去写。 因为两栏的话&#xff0c;实际上有一个很大的问题。 因为简历上需要写项目经历&#xff0c;需要写…

LeetCode:142. 环形链表 II

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 题解目录 一、&#x1f331;[142. 环形链表 II](https://leetcode.cn/problems/linked-l…

2.6 浮点运算方法和浮点运算器

学习目标&#xff1a; 以下是一些具体的学习目标&#xff1a; 理解浮点数的基本概念和表示方法&#xff0c;包括符号位、指数和尾数。学习浮点数的运算规则和舍入规则&#xff0c;包括加、减、乘、除、开方等。了解浮点数的常见问题和误差&#xff0c;例如舍入误差、溢出、下…

软件维护(Software maintenance)的流程

软件维护(Software maintenance)是一个软件工程名词&#xff0c;是指在软件产品发布后&#xff0c;因修正错误、提升性能或其他属性而进行的软件修改。 软件维护主要根据需求变化或硬件环境的变化对应用程序进行部分或全部的修改&#xff0c;修改时应充分利用源程序。修改后要填…