Clion开发STM32——移植FreeModbus

STM32型号 :STM32H743VIT6
FreeModbus版本 :1.6
使用工具:stm32cubeMX,Clion
使用STM32作从机,模式:RTU

网上用keil的比较多,用Clion的比较少,如果你也用Clion,那么希望本文可以给你提供些许参考。

1 下载官网源码

官网地址:https://www.embedded-experts.at/en/freemodbus/about/
demo是移植例程,但是里面没有stm32的。
modbus是源码.
在这里插入图片描述
看一下modbus文件,我这里使用的模式是RTU模式,所以ascii和tcp文件夹就不需要了,如果你也只用RTU模式,那么只需要标红的文件夹。
在这里插入图片描述
在freemodbus-v1.6\demo\BARE\port这个文件夹中的文件全部需要,这些是接口文件。
在这里插入图片描述

把上面的文件放在一个文件夹里。

在自己的工程目录下新建FreeModbus(自己起名就好),并添加上面的文件,如下:在这里插入图片描述

在这里插入图片描述

2 修改CMakeLists_template

可以参考这篇文章Clion开发STM32——添加自己文件

增加头文件路径
在这里插入图片描述
增加编译文件
在这里插入图片描述
只关注蓝色框框起来的即可,其他文件可以忽略,那是我这个工程的其他文件。

3 cubeMX配置串口和定时器

3.1串口

在这里插入图片描述

3.2 定时器

在这里插入图片描述

3.3 NVIC

中断回调函数比较繁琐,所以我这里取消掉了,自己写中断内的内容。
在这里插入图片描述

4 修改接口 port

4.1 port.h

首先是port.h文件

#ifndef _PORT_H
#define _PORT_H#include <assert.h>
#include <inttypes.h>/* ----------------------- Platform includes --------------------------------*/
#include "stm32h7xx_hal.h"
#include "main.h"/* ----------------------- Defines ---------*/#define	INLINE                      inline
#define PR_BEGIN_EXTERN_C           extern "C" {
#define	PR_END_EXTERN_C             }#define ENTER_CRITICAL_SECTION( )   __set_PRIMASK(1)//禁止中断
#define EXIT_CRITICAL_SECTION( )    __set_PRIMASK(0)//允许中断typedef uint8_t BOOL;typedef unsigned char UCHAR;
typedef char CHAR;typedef uint16_t USHORT;
typedef int16_t SHORT;typedef uint32_t ULONG;
typedef int32_t LONG;#ifndef TRUE
#define TRUE            1
#endif#ifndef FALSE
#define FALSE           0
#endif#endif

包含平台,定义进出临界区
在这里插入图片描述

4.2 portserial.c

这个文件是留给用户写串口函数接口的。
使能串口中断(串口接收中断,串口发送中断)
这里串口发送中断,可以选择两种
1 发送寄存器空中断 UART_IT_TXE
2 发送完成中断 UART_IT_TC

两种都可以 ,只是UART_IT_TC不会主动触发中断,必须得发送完成,发送完成是只数据被写入到发送寄存器,然后串口会把数据送到移位寄存器,等到移位寄存器发送完成,才会置发送完成中断。所以后面发送函数里,得收到加一个发送函数来触发,才能进中断。

而UART_IT_TXE使能后就可以进入中断,因为发送寄存器本就空的。往发送寄存器里写数据之后,数据也会被送到移位寄存器。

我这里使用的事发生寄存器空中断UART_IT_TXE。

#include "port.h"/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"/* ----------------------- static functions ---------------------------------*/void prvvUARTTxReadyISR( void );//被UART发送空中断调用的函数,注意是空中断,通知modbus数据可以发送void prvvUARTRxISR( void );//被UART接收中断调用的函数,通知modbus有数据到来/* ----------------------- Start implementation -----------------------------*/
/*使能串口中断*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{/* If xRXEnable enable serial receive interrupts. If xTxENable enable* transmitter empty interrupts.*/if (xRxEnable) {/*设置485为接收模式*/__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);//使能接收中断} else {__HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);}if (xTxEnable) {/*设置485为发送模式*/__HAL_UART_ENABLE_IT(&huart2, UART_IT_TXE);//使能发送寄存器为空中断} else {__HAL_UART_DISABLE_IT(&huart2, UART_IT_TXE);}
}
/*初始化串口*/
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{/*MX_USART2_UART_Init*/return TRUE;
}
/*发送一个字节*/
BOOL
xMBPortSerialPutByte( CHAR ucByte )
{/* Put a byte in the UARTs transmit buffer. This function is called* by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been* called. */huart2.Instance->TDR = ucByte;//HAL_UART_Transmit(&huart2, (uint8_t*)&ucByte, 1, 0);return TRUE;
}
/*接收一个字节*/
BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{/* Return the byte in the UARTs receive buffer. This function is called* by the protocol stack after pxMBFrameCBByteReceived( ) has been called.*/*pucByte = (uint8_t)(huart2.Instance->RDR & (uint8_t)0x00FF);return TRUE;
}/* Create an interrupt handler for the transmit buffer empty interrupt* (or an equivalent) for your target processor. This function should then* call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that* a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character.*/void prvvUARTTxReadyISR( void )
{pxMBFrameCBTransmitterEmpty(  );
}/* Create an interrupt handler for the receive interrupt for your target* processor. This function should then call pxMBFrameCBByteReceived( ). The* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the* character.*/void prvvUARTRxISR( void )
{pxMBFrameCBByteReceived(  );
}

这两个函数需要取消static定义,这两个函数要在中断里被调用,而static就限制了它只能在本文件中使用,所以取消掉。(当然你把中断函数写在这个文件也可以,我个人习惯把中断都放在stm32h7xx_it.c文件中)
在这里插入图片描述

4.3 portimer.c

/* ----------------------- Platform includes --------------------------------*/
#include "port.h"/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"/* ----------------------- static functions ---------------------------------*/void prvvTIMERExpiredISR( void );//被定时器溢出中断调用的函数,通知modbus3.5个字符等待时间到/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{TIM_MasterConfigTypeDef sMasterConfig = {0};htim7.Instance = TIM7;htim7.Init.Prescaler = 11999;htim7.Init.CounterMode = TIM_COUNTERMODE_UP;htim7.Init.Period = usTim1Timerout50us - 1;htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_Base_Init(&htim7) != HAL_OK){return FALSE;}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK){return FALSE;}return TRUE;
}/*使能定时器*/
inline void
vMBPortTimersEnable(  )
{__HAL_TIM_CLEAR_IT(&htim7,TIM_IT_UPDATE);__HAL_TIM_SET_COUNTER(&htim7,0);HAL_TIM_Base_Start_IT(&htim7);/* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
}/*禁止定时器*/
inline void
vMBPortTimersDisable(  )
{HAL_TIM_Base_Stop_IT(&htim7);__HAL_TIM_SET_COUNTER(&htim7,0);__HAL_TIM_CLEAR_IT(&htim7,TIM_IT_UPDATE);/* Disable any pending timers. */
}/* Create an ISR which is called whenever the timer has expired. This function* must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that* the timer has expired.*/void prvvTIMERExpiredISR( void )
{( void )pxMBPortCBTimerExpired(  );
}

这个函数同样取消static,它被定时器溢出中断调用
在这里插入图片描述
关于定时器参数为什么要这么设置,可以看一下FreeModbus学习——eMBInit初始化

4.4 添加port.c文件

这个文件中存放的都是功能码处理函数调用的回调函数,当然你也可以放在别的文件,比如main.c里都可以。

这个文件中的函数怎么调用的,可以看一下FreeModbus学习——读输入寄存器eMBFuncReadInputRegister

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"/* ----------------------- Defines ------------------------------------------*/
//输入寄存器
#define REG_INPUT_START  3000
#define REG_INPUT_NREGS  4//保持寄存器
#define REG_HOLD_START   4000
#define REG_HOLD_NREGS   10//线圈
#define REG_COILS_START  0
#define REG_COILS_NREGS  4//开关寄存器
#define REG_DISCRETE_START 1000
#define REG_DISCRETE_NREGS 4
/* ----------------------- Static variables ---------------------------------*/
static USHORT   usRegInputStart = REG_INPUT_START;
static USHORT   usRegInputBuf[REG_INPUT_NREGS] = {0x01, 0x02, 0x03, 0x04};static USHORT   usRegHoldStart = REG_HOLD_START;
static USHORT   usRegHoldBuf[REG_HOLD_NREGS];static USHORT   usRegCoilsStart = REG_COILS_START;
static uint8_t  usRegCoilsBuf[REG_COILS_NREGS];static USHORT   usRegDiscreteStart = REG_DISCRETE_START;
static uint8_t  usRegDiscreteBuf[REG_DISCRETE_NREGS];
/****************************************************************************
* 名	  称:eMBRegInputCB
* 功    能:读取输入寄存器,对应功能码是 04 eMBFuncReadInputRegister
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
*						usAddress: 寄存器地址
*						usNRegs: 要读取的寄存器个数
* 出口参数:
* 注	  意:上位机发来的 帧格式是: SlaveAddr(1 Byte)+FuncCode(1 Byte)
*								+StartAddrHiByte(1 Byte)+StartAddrLoByte(1 Byte)
*								+LenAddrHiByte(1 Byte)+LenAddrLoByte(1 Byte)+
*								+CRCAddrHiByte(1 Byte)+CRCAddrLoByte(1 Byte)
*							3 区
****************************************************************************/
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{eMBErrorCode    eStatus = MB_ENOERR;int             iRegIndex;//寄存器数组索引usAddress = usAddress - 1;//传进来的地址+1了,这里要减1//判断地址是否在输入寄存器范围内if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ){iRegIndex = ( int )( usAddress - usRegInputStart );//地址 - 开始地址  =  索引while( usNRegs > 0 ){*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );//寄存器值高位*pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );//寄存器值低位iRegIndex++;usNRegs--;}}else{eStatus = MB_ENOREG;}return eStatus;
}
/****************************************************************************
* 名	  称:eMBRegHoldingCB
* 功    能:对应功能码有:06 写保持寄存器 eMBFuncWriteHoldingRegister
*													16 写多个保持寄存器 eMBFuncWriteMultipleHoldingRegister
*													03 读保持寄存器 eMBFuncReadHoldingRegister
*													23 读写多个保持寄存器 eMBFuncReadWriteMultipleHoldingRegister
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
*						usAddress: 寄存器地址
*						usNRegs: 要读写的寄存器个数
*						eMode: 功能码
* 出口参数:
* 注	  意:4 区
****************************************************************************/
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{eMBErrorCode    eStatus = MB_ENOERR;int             iRegIndex;usAddress = usAddress - 1;if((usAddress >= REG_HOLD_START) && ((usAddress+usNRegs) <= (REG_HOLD_START + REG_HOLD_NREGS))){iRegIndex = (int)(usAddress - usRegHoldStart);switch(eMode){case MB_REG_READ://读寄存器while(usNRegs > 0){*pucRegBuffer++ = (uint8_t)(usRegHoldBuf[iRegIndex] >> 8);*pucRegBuffer++ = (uint8_t)(usRegHoldBuf[iRegIndex] & 0xFF);iRegIndex++;usNRegs--;}break;case MB_REG_WRITE://写寄存器while(usNRegs > 0){usRegHoldBuf[iRegIndex] = *pucRegBuffer++ << 8;usRegHoldBuf[iRegIndex] |= *pucRegBuffer++;iRegIndex++;usNRegs--;}}}else//错误{eStatus = MB_ENOREG;}return eStatus;
}/****************************************************************************
* 名	  称:eMBRegCoilsCB
* 功    能:对应功能码有:01 读线圈 eMBFuncReadCoils
*													05 写线圈 eMBFuncWriteCoil
*													15 写多个线圈 eMBFuncWriteMultipleCoils
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
*						usAddress: 线圈地址
*						usNCoils: 要读写的线圈个数
*						eMode: 功能码
* 出口参数:
* 注	  意:如继电器
*						0 区
****************************************************************************/
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{eMBErrorCode    eStatus = MB_ENOERR;USHORT          iRegIndex;USHORT usCoilGroups = ((usNCoils - 1) / 8 + 1);UCHAR  ucStatus     = 0;UCHAR  ucBits       = 0;UCHAR  ucDisp       = 0;usAddress = usAddress - 1;if((usAddress >= REG_COILS_START) &&	((usAddress + usNCoils) <= (REG_COILS_START + REG_COILS_NREGS))){iRegIndex = (int)(usAddress - usRegCoilsStart);switch(eMode){case MB_REG_READ://读线圈while(usCoilGroups--){ucDisp = 0;ucBits = 8;while((usNCoils--) != 0 && (ucBits--) != 0){ucStatus |= (usRegCoilsBuf[iRegIndex++] << (ucDisp++));}*pucRegBuffer++ = ucStatus;}break;case MB_REG_WRITE://写线圈while(usCoilGroups--){ucStatus = *pucRegBuffer++;ucBits   = 8;while((usNCoils--) != 0 && (ucBits--) != 0){usRegCoilsBuf[iRegIndex++] = ucStatus & 0X01;ucStatus >>= 1;}}}}else//错误{eStatus = MB_ENOREG;}return eStatus;
}
/****************************************************************************
* 名	  称:eMBRegDiscreteCB 
* 功    能:读取离散寄存器,对应功能码有:02 读离散寄存器 eMBFuncReadDiscreteInputs
* 入口参数:pucRegBuffer: 数据缓存区,用于响应主机   
*						usAddress: 寄存器地址
*						usNDiscrete: 要读取的寄存器个数
* 出口参数:
* 注	  意:1 区
****************************************************************************/
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{eMBErrorCode    eStatus = MB_ENOERR;USHORT          iRegIndex;USHORT usDiscreteGroups = ((usNDiscrete - 1) / 8 + 1);UCHAR  ucStatus     = 0;UCHAR  ucBits       = 0;UCHAR  ucDisp       = 0;usAddress = usAddress - 1;if((usAddress >= REG_DISCRETE_START) &&	((usAddress + usNDiscrete) <= (REG_DISCRETE_START + REG_DISCRETE_NREGS))){iRegIndex = (int)(usAddress - usRegDiscreteStart);while(usDiscreteGroups--){ucDisp = 0;ucBits = 8;while((usNDiscrete--) != 0 && (ucBits--) != 0){if(usRegDiscreteBuf[iRegIndex]){ucStatus |= (1 << ucDisp);}ucDisp++;}*pucRegBuffer++ = ucStatus;}}else//错误{eStatus = MB_ENOREG;}return eStatus;
}

4.5 写中断服务函数

void USART2_IRQHandler(void)
{/* USER CODE BEGIN USART2_IRQn 0 */if((__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) != RESET)&& (__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE)!= RESET)) {__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_RXNE);prvvUARTRxISR();return;}if ((__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_TXE)!= RESET)&& (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE)!= RESET)){__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_TXE);prvvUARTTxReadyISR();return;}}void TIM7_IRQHandler(void)
{/* USER CODE BEGIN TIM7_IRQn 0 */if(__HAL_TIM_GET_FLAG(&htim7, TIM_FLAG_UPDATE) != RESET&& __HAL_TIM_GET_IT_SOURCE(&htim7, TIM_IT_UPDATE) !=RESET) {__HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE);prvvTIMERExpiredISR();}}

5 调用协议栈

依次调用
eMBInit( MB_RTU, 1, 3, 9600, MB_PAR_NONE );
eMBEnable();

然后把eMBPoll();放在循环里
在这里插入图片描述

6 测试

以读输入寄存器为例
功能码04

使用软件Modbus Poll
在这里插入图片描述
软件配置:
在这里插入图片描述
效果:
在这里插入图片描述
OK !
移植结束。
想深入了解FreeModbus源码,可以看我写的其笔记FreeModbus,写的不好,对源码理解上以及写的时候,难免有瑕疵纰漏,如有错误还请大佬指出。您原谅着瞧,原谅着看。

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

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

相关文章

【LLM】-07-提示工程-聊天机器人

目录 1、给定身份 1.1、基础代码 1.2、聊天机器人 2、构建上下文 3、订餐机器人 3.1、窗口可视化 3.2、构建机器人 3.3、创建JSON摘要 利用会话形式&#xff0c;与具有个性化特性&#xff08;或专门为特定任务或行为设计&#xff09;的聊天机器人进行深度对话。 在 Ch…

鸿蒙仓颉语言【cryptocj 库】(介绍与SHA、MD5、HMAC摘要算法)

cryptocj 库 介绍 cryptocj 是一个安全的密码库&#xff0c;包括常用的密码算法、常用的密钥生成和签名验证。 该库是对 C 语言的 openSSL 封装的仓颉加密算法 1 提供SHA、MD5、HMAC摘要算法。 前置条件&#xff1a;NA 场景&#xff1a; OHOS&#xff0c; Linux&#xff…

经纬恒润与奇瑞汽车签订新能源项目重点供应商合作协议,共同开启合作新篇章

近日&#xff0c;2024年国家级芜湖经开区汽车零部件生态大会成功举行&#xff0c;经纬恒润受邀出席&#xff0c;与行业各伙伴齐聚经开区&#xff0c;同绘发展蓝图&#xff0c;助力经开区汽车产业高质量发展。会上&#xff0c;经纬恒润与奇瑞汽车签署合作协议&#xff0c;成为奇…

Superset二次开发之筛选器native Filters 水平布局

引言 Apache Superset作为一个功能强大的开源数据探索和可视化平台&#xff0c;提供了丰富的配置选项来定制化用户体验。其中&#xff0c;HORIZONTAL_FILTER_BAR 是一个重要的配置项&#xff0c;专注于优化和改进Superset中的筛选器条布局与交互。 什么是HORIZONTAL_FILTER_B…

免费【2024】springboot stone音乐播放器的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

【数据库】数据库设计规范文件(Word)

方便业务功能实现、业务功能扩展&#xff1b;方便设计开发、增强系统的稳定性和可维护性&#xff1b;保证数据完整性和准确性&#xff1b;提高数据存储效率&#xff0c;在满足业务需求的前提下&#xff0c;使时间开销和空间开销达到优化平衡。资料获取&#xff1a;本文本个人名…

江科大/江协科技 STM32学习笔记P9-11

文章目录 OLED1、OLED硬件main.c EXTI外部中断1、中断系统2、中断执行流程图3、STM32中断4、中断地址的作用5、EXTI6、EXTI基本结构7、AFIO复用IO口8、EXTI框图或门和与门 9、旋转编码器介绍10、硬件电路 OLED 1、OLED硬件 SCL和SDA是I2C的通信引脚&#xff0c;需要接在单片机…

机器学习的运作原理和算法分类,让机器学习更加通俗易懂

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

微信扫码登陆验证在Go系统开发时的应用与实践

微信扫码登录实现 登录流程 总体来说&#xff0c;就是三步&#xff1a; 点击微信登录&#xff0c;跳转到微信页面微信扫码登录&#xff0c;确认登陆微信跳转回来 这里&#xff0c;我们就得&#xff0c;明确两个问题&#xff1a; 跳到微信界面&#xff0c;跳过去的 URL 是什…

异常处理和swagger使用

全局异常处理类 定义全局异常处理类&#xff0c;会将错误全部提交到这个异常处理类中进行处理&#xff0c;这个类会将处理的统一结果响应给前端&#xff0c;如果不添加异常处理类&#xff0c;异常不会按照统一的响应格式进行&#xff0c;前端无法识别&#xff0c;当然也可以在…

vue-快速入门

Vue 前端体系、前后端分离 1、概述 1.1、简介 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;可以高效地开发用户界面。…

浏览器的最大并发数(http1.1)

HTTP/1.1&#xff1a;每个资源请求通常需要单独的TCP连接&#xff0c;尽管支持Keep-Alive机制&#xff0c;允许在同一个TCP连接上连续发送多个请求。但通常浏览器限制并发TCP连接数&#xff08;例如&#xff0c;每个域名最多6个并发连接&#xff09;。 HTTP/2&#xff1a;引入…

HarmonyOS三方库的使用

系统组件难以提供比较优秀的界面&#xff0c;需要第三方库来实现一些比较好看的界面效果 三方库的获取&#xff1a; 开源社区支持OpenHarmony-TPC 和 Openharmony三方库中心仓 先目前已经拥有各种各样的三方库&#xff0c;包括UI 图片 动画 网络 数据存储 工具类 多媒体 安全等…

leetcode 2236.判断根节点是否等于字节点

1.题目要求: 给你一个 二叉树 的根结点 root&#xff0c;该二叉树由恰好 3 个结点组成&#xff1a;根结点、左子结点和右子结点。如果根结点值等于两个子结点值之和&#xff0c;返回 true &#xff0c;否则返回 false 。2.思路: 直接数组前序遍历&#xff0c;然后判断后面两个…

unity美术资源优化(资源冗余,主界面图集过多)

图片资源冗余&#xff1a; UPR unity的性能优化工具检查资源 1.检查纹理读/写标记 开启纹理资源的读/写标志会导致双倍的内存占用 检查Inspector -> Advanced -> Read/Write Enabled选项 2.检查纹理资源alpha通道 如果纹理的alpha通道全部为0&#xff0c;或者全部为2…

UEFI DebugLib 介绍

1.我们调试中常用Debug 打印信息&#xff0c;这些会输出到BIOS串口日志中 EFI_STATUSEFIAPIHelloWorld2(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){EFI_STATUS Status;StatusEFI_SUCCESS;gST->ConOut->OutputString(gST->ConOut,L&q…

【vluhub】zabbix漏洞

介绍&#xff1a; zabbix是对服务器资源状态例如、内存空间、CPU、程序运行状态进行检测、设置预警值、短信设置等功能等一款开源工具。配置不当存在未授权,SQL注入漏洞 弱口令 nameadmin&passwordzabbix nameguest&password POST /index.php HTTP/1.1 Host: 192.1…

Flex布局中元素主轴上平均分布 多余的向左对齐

content&#xff1a;父元素 content-item: 子元素 主轴上子元素平均分布 .content {display: flex;flex-wrap: wrap;justify-content: space-between;.service-item {display: flex;flex-direction: column;justify-content: center;align-items: center;width: 80px;height:…

【C++】19.红黑树模拟实现 set 和 map

我们想要实现STL中的set和map&#xff0c;那么第一步就需要看一下库函数是如何实现的&#xff1a; 通过查看源代码我们发现两个容器都包含了stl_tree.h&#xff0c;因此我们猜测此头文件实现的是红黑树。 但是set和map很显然不是使用同一棵树实现的&#xff0c;那么STL库是怎么…

vue3 Axios封装使用

先安装axios&#xff1a; npm install axios 第一步&#xff1a;项目src下创建一个名为request的文件夹&#xff08;看一下示例图&#xff09;&#xff1a; 然后在request下创建两个api.ts和index.ts的文件 api.ts里的内容&#xff1a;&#xff08;url写你自己的接口&#xff…