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

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级,之前做过PIC系列单片机的升级,现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。

因为国民技术系列单片机在很多大程度上都模仿了STM32,所以我想其升级方案极有可能差不多。于是在网上下载了STM32官方使用YMODEM协议实现的IAP,下载地址:STSW-STM32008 - STM32F10xxx in-application programming using the USART (AN2557) - STMicroelectronics,使用野火的STM32开发实测过是没有问题的,于是在它的基础上进行修改,移植到N32G031系列单片机中来,经过一番折腾还是搞定了,现在把相关内容分享下,另外资源可以在以下链接中下载,无需积分。

【免费】国民技术N32G031使用YMODEM协议实现IAP资源-CSDN文库

另外,关于YMODEM协议及secureCRT的使用可以参考以下链接:

stm32 Bootloader设计(YModem协议)-CSDN博客

关于secureCRT的破解方法请参考以下链接:

尝试SecureCRT_securecrt issue date-CSDN博客

主要介绍IAP程序的main.c文件,代码如下:

/*** @file main.c* @author Power* @version V1.0.1** @copyright Copyright (c) 2023, DS.*/
/*MIPS的全称是Million Instructions Per Second,每秒百万指令(西方或者国际上的计量体系中1M(兆)=100万=1000000);Mhz,是指单片机CPU的主频兆赫兹。单条指令执行时间:STM32F10X单片机在主频为72MHz下,C语言程序执行一条指令需要的时间可认为10ns~100ns。国民技术系列N32G031 MCU,以主频48MHz为例,这里估算的C语言执行一条指令的时间约为20ns-200ns
*/#include "main.h"
#include "common.h"
#include "ymodem.h"#define 	COMn                2
#define     RS485_GPIOx_CLK     RCC_APB2_PERIPH_GPIOF   //peripheral adress
#define     RS485_GPIO_PIN      GPIO_PIN_6              //pin address
#define     RS485_GPIOx         GPIOF                   //port address
#define     RS485_L()           GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_PIN)//RECEIVE_ mode
#define     RS485_H()           GPIO_SetBits(RS485_GPIOx, RS485_GPIO_PIN)//TRANSMIT modetypedef enum 
{COM1 = 0,COM2 = 1
} COM_TypeDef; /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern pFunction Jump_To_Application;
extern uint32_t JumpAddress;
uint16_t    led_cnt = 0;
volatile uint8_t Flag_1ms;      //1 milli-second timeout flag
uint8_t cTemp = 10;				//for RS485 mode switching delay/* Private function prototypes -----------------------------------------------*/
static void IAP_Init(void);
void RCC_Configuration(void);
void GPIO_Configuration(void);const uint16_t COM_TX_PIN[COMn] = {EVAL_COM1_TX_PIN, EVAL_COM2_TX_PIN};
const uint16_t COM_RX_PIN[COMn] = {EVAL_COM1_RX_PIN, EVAL_COM2_RX_PIN};
const uint32_t COM_TX_PORT_CLK[COMn] = {EVAL_COM1_TX_GPIO_CLK, EVAL_COM2_TX_GPIO_CLK}; 
const uint32_t COM_RX_PORT_CLK[COMn] = {EVAL_COM1_RX_GPIO_CLK, EVAL_COM2_RX_GPIO_CLK};
const uint32_t COM_USART_CLK[COMn] = {EVAL_COM1_CLK, EVAL_COM2_CLK};
GPIO_Module* COM_TX_PORT[COMn] = {EVAL_COM1_TX_GPIO_PORT, EVAL_COM2_TX_GPIO_PORT}; 
GPIO_Module* COM_RX_PORT[COMn] = {EVAL_COM1_RX_GPIO_PORT, EVAL_COM2_RX_GPIO_PORT};
USART_Module* COM_USART[COMn] = {EVAL_COM1, EVAL_COM2};/* Private functions ---------------------------------------------------------*/
/**
*@name: RS485_Configuration
*@description: RS485 GPIO initialization
*@params: none
*@return: none
*/
void RS485_Configuration(void)
{GPIO_InitType GPIO_InitStructure;RCC_EnableAPB2PeriphClk(RS485_GPIOx_CLK, ENABLE);/* -2- Configure GPIOx_PIN in output push-pull mode */GPIO_InitStruct(&GPIO_InitStructure);GPIO_InitStructure.Pin = RS485_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;GPIO_InitPeripheral(RS485_GPIOx, &GPIO_InitStructure);GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_PIN);
}/**
*@name: Process_1MS
*@description: 1 milli-second timeout process
*@params: none
*@return: none
*/
void Process_1MS(void)
{if (Flag_1ms == 0){return;}Flag_1ms = 0;if (led_cnt % 500 == 0) //LED toggle to see whether the timer works correctly.{GPIO_WriteBit(GPIOF, GPIO_PIN_7, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_PIN_7)));}led_cnt++;if (led_cnt >= 60000){led_cnt = 0;}
}/**
*@name: RS485_Mode_Switching
*@description: switch the RS485 work mode
*@params: mode: 1: receive, 0: transmit
*@return: none
*/
void RS485_Mode_Switching(uint8_t mode)
{cTemp = 10;if(mode){RS485_L();}else{RS485_H();}	while (cTemp-- != 0);
}/*** @brief  Main program.* @param  None* @retval None*/
int main(void)
{/* Flash unlock */FLASH_Unlock();/* Initialize Key Button mounted on N32G031-EVAL board *///N32_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);/* Test if Key push-button on N32G031 Board is pressed *///if (N32_EVAL_PBGetState(BUTTON_KEY)  == 0x00)    if (1){/* If Key is pressed *//* Execute the IAP driver in order to re-program the Flash */RCC_Configuration();GPIO_Configuration();RS485_Configuration();TIM3_Configuration();IAP_Init();        RS485_Mode_Switching(0);SerialPutString("\r\n===============================================================");SerialPutString("\r\n=              (C) COPYRIGHT 2023 DS Power Supply             =");SerialPutString("\r\n=                                                             =");SerialPutString("\r\n=     In-Application Programming  (Version 1.0.0)             =");SerialPutString("\r\n=                                                             =");SerialPutString("\r\n=                           By POWER          		      =");SerialPutString("\r\n===============================================================");SerialPutString("\r\n\r\n");Main_Menu();}/* Keep the user application running */else{/* Test if user code is programmed starting from address "ApplicationAddress" */if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000) == 0x20000000){/* Jump to user application */JumpAddress = *(__IO uint32_t*)(ApplicationAddress + 4);Jump_To_Application = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();}}while (1){}
}/*** @brief  Configures COM port.* @param  COM: Specifies the COM port to be configured.*   This parameter can be one of following parameters:    *     @arg COM1*     @arg COM2  * @param  USART_InitStruct: pointer to a USART_InitTypeDef structure that*   contains the configuration information for the specified USART peripheral.* @retval None*/
void IAP_COMInit(COM_TypeDef COM, USART_InitType* USART_InitStruct)
{GPIO_InitType GPIO_InitStructure;/* Enable GPIO clock */	RCC_EnableAPB2PeriphClk(COM_TX_PORT_CLK[COM] | RCC_APB2_PERIPH_AFIO, ENABLE);/* Enable UART clock */if (COM == COM1){RCC_EnableAPB2PeriphClk(COM_USART_CLK[COM], ENABLE); }else{RCC_EnableAPB1PeriphClk(COM_USART_CLK[COM], ENABLE);}GPIO_InitStruct(&GPIO_InitStructure);/* Configure USART Tx as alternate function push-pull */GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pin = COM_TX_PIN[COM];GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;//alternate functionGPIO_InitPeripheral(COM_TX_PORT[COM], &GPIO_InitStructure);    /* Configure USART Rx as input floating */  GPIO_InitStructure.Pin = GPIO_PIN_10;GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;//alternate functionGPIO_InitPeripheral(COM_RX_PORT[COM], &GPIO_InitStructure);/* USART configuration */USART_Init(COM_USART[COM], USART_InitStruct);/* Enable USART */USART_Enable(COM_USART[COM], ENABLE);
}/*** @brief  Initialize the IAP: Configure RCC, USART and GPIOs.* @param  None* @retval None*/
void IAP_Init(void)
{USART_InitType USART_InitStructure;/* USART resources configuration (Clock, GPIO pins and USART registers) ----*//* USART configured as follow:- BaudRate = 115200 baud- Word Length = 8 Bits- One Stop Bit- No parity- Hardware flow control disabled (RTS and CTS signals)- Receive and transmit enabled*/USART_InitStructure.BaudRate = 115200;USART_InitStructure.WordLength = USART_WL_8B;USART_InitStructure.StopBits = USART_STPB_1;USART_InitStructure.Parity = USART_PE_NO;USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;IAP_COMInit(COM1, &USART_InitStructure);
}/*** @brief  Configures the different system clocks.*/
static void RCC_Configuration(void)
{//PCLK1 = HCLK/4, set the prescaler of the APB1 clock and timer3 uses APB1 clockRCC_ConfigPclk1(RCC_HCLK_DIV4);//Enable GPIO clocksRCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOF, ENABLE);//TIM3 clock enableRCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
}/**
*@name: GPIO_Configuration
*@description: IO initialization
*@params: none
*@return: none
*/
static void GPIO_Configuration(void)
{GPIO_InitType GPIO_InitStructure;GPIO_InitStruct(&GPIO_InitStructure);//PF7: LEDGPIO_InitStructure.Pin       = GPIO_PIN_7;GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure);//set the default IO levelGPIO_SetBits(GPIOF, GPIO_PIN_7);
}#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*/
void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
{/* 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) *//* Infinite loop */while (1){}
}#endif/*
=============关于补码的简洁概括==============正数,本身就是补码。负数,就用它的正数,减一取反,即可得到补码。如,已知:+9 的二进制是:0000 1001。下面求-9 补码:先减一:0000 1001 - 1 = 0000 1000;再取反:1111 0111。所以有:-9 补码 = 1111 0111。这不就完了吗!简不简单? 意不意外?如果把一个值赋给一个有符号类型,如果补码的最高位是1,则是负数,还原成实际的负数值的步骤是:1、先按位取反2、再加1例如(int表示32位有符号):int a = -552305;(按正数552305的补码先减一再按位取反得到-552305二进制补码是:1111 1001 0010 1000 1111)(short表示16位无符号)short c = (short)a;由于short最大只有16位,因此高4位被忽略,剩下1001 0010 1000 1111又由于赋值给short,所以最高位表示符号位,这里是1表示负数,则将1001 0010 1000 1111除符号位外按位取反再加1得到1110 1101 0111 0001,最终的结果就是除符号位外的数据:110 1101 0111 0001=-28017
=============================================*//*** @}*//*** @}*/

其实也很简单,主要就是串口和RS485相关外设的初始化,串口这里没有使用中断的方法。

外设初始化完成后就会进入主菜单,根据用户输入的值进行不同的操作,剩下就是YMODEM协议的理解。后面有空准备自己做一个上位机来实现YMODEM协议,因为自己有逻辑分析仪,可以抓取到实际传输的数据。

我刚开始调试的时候一直出现在secureCRT中输入菜单编号后单片机没有反应的情况,仔细检测了代码发现和STM32的也差不多,没有什么问题。于是使能串口的接收中断,我测试在secureCRT中选择菜单后串口收到的是什么,后来查看确实有问题,无论secureCRT中输入什么内容,打印出来的都是两个字节,有时候是0xFD 0xFF,有时又是0xF9 0xFF的,感觉莫名其妙的。后来想起来之前使用N32G031串口发送有时少一字节的问题,特别是在RS485通信中最容易出现,再查看本项目的下面这个函数:

/*** @brief  Print a character on the HyperTerminal* @param  c: The character to be printed* @retval None*/
void SerialPutChar(uint8_t c)
{USART_SendData(EVAL_COM1, c);while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXDE) == RESET);   //while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXDE) == RESET)//{//}
}

我忽然想起来了,还有一个非常重要的语句没有调用,那就是:

 while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXC) == RESET);

解释如下:

/*==========关于串口直接发送正常,而485出现少发1字节的问题==============

            我看我的代码发现我的检测标志位是USART_FLAG_TXDE(发送寄存器空)。

            以前一直用这个写也没啥问题,但是现在出现了丢失字节,我就怀疑可能是寄存器空,

            但是数据还没有完全发出(注意:当你用USART_FLAG_TXDE标志位去认为已经发完,并去控制RTS引脚的时候,485芯片会从发送转接收,

            导致如果有字节没有发完就不发了)。

            因此,我们只需要再加一个标志位检测就好。========================================================================

USART_FLAG_TXC表示数据发送完成,只有当它置1才表示最后一个数据发送结束了。加了这个标志位检测后RS485的收发就正常工作了。

另外,关于用户应用程序的中断向量表偏移的问题,除了在MDK中设置ROM的偏移值外,还要设置中断向量表。N32G031系列没有像STM32系列那样有类似SCB->VTOR的成员设置中断向量表的偏移,IAP接收完bin文件后用户程序总是不执行。我在网上搜索,终于找到了一篇文章专门介绍这个的:

【精选】国民技术N32G030F6S7使用ymodem协议更新固件_n32g452 ymodem远程升级-CSDN博客

感谢这位博主,要不然我不知道还要折腾多久。这个芯片厂家应该要把资料准备得齐全一些,尤其是这种关键的内容。

下面是在secureCRT中主菜单和发送完成bin后的界面:

相关文章:

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级,之前做过PIC系列单片机的升级,现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。 因为国民技术系列单片机在很多大程度上都模仿了STM32,所以我想其升级方案极有可能差不多。于是在…...

Pycharm中添加Python库指南

一、介绍 Pycharm是一款为Python开发者提供的集成开发环境(IDE),支持执行、调试Python代码,并提供了许多有用的工具和功能,其中之一就是在Pycharm中添加Python库。 添加Python库有许多好处,比如能够增加开…...

Oracle OCP / MySQL OCP认证容易通过吗

诸多学员在首次考OCP时,不清楚要如何选择。在本文中,我会为大家进行讲解! 选择OCP认证时需要考虑的几大项目: 授课老师师资经验 课程大纲 试听课程 考试通过率 业界口碑 服务质量 郭一军老师的OCP培训在业界培训的学员中已…...

flutter web 中嵌入一个html

介绍 flutter web 支持使用 HtmlElementView嵌入html import dart:html; import dart:ui as ui; import package:flutter/cupertino.dart;class WebWidget extends StatelessWidget {const WebWidget({super.key});overrideWidget build(BuildContext context) {DivElement fr…...

使用Spark SQL读取阿里云OSS的数据

读OSS数据 创建一个table,并关联OSS目录路径 CREATE TABLE my_table USING parquet OPTIONS (path oss://my_bucket/my_data_dir/dt20230904, -- 关联OSS路径header true, -- 如果Parquet文件包含列名的头部信息,则设置为true,否则设置为f…...

【0235】修改私有内存(private memory)中的MyBEEntry时,st_changecount值前后变化

上一篇: 【0234】PgBackendStatus 记录当前postgres进程的活动状态 1. pg_stat_activity中xxx实时信息如何实现? 客户端(eg:psql)在连接上postmaster之后,postmaster守护进程会fork()一个后端进场(backend process),之后此客户端的所有操作、交互均有此对应的Backen…...

Linux学习命令之source

在Linux中,source命令用于在当前shell环境中执行指定脚本文件中的命令。它通常用于重新加载修改过的shell配置文件,例如.bashrc或.profile,以使更改生效,而不需要退出当前的shell会话。 使用方法为: source 文件路径…...

2342. 数位和相等数对的最大和

我的解法&#xff1a; 对数组进行排序&#xff0c;最大数一定最先进入哈希表进行加和 class Solution { public:int maximumSum(vector<int>& nums) {unordered_map<int, vector<int>> h;int ans -1;sort(nums.begin(), nums.end());for (int i nums.…...

FISCO BCOS 3.0【01】搭建第一个区块链网络

官方技术文档&#xff1a;https://fisco-bcos-doc.readthedocs.io/zh-cn/latest/index.html 我们在官方技术文档的基础上&#xff0c;进行&#xff0c;对文档中一些不清楚的地方进行修正 搭建Air版本FISCO BCOS联盟链 本节以搭建单群组FISCO BCOS链为例操作&#xff0c;使用开…...

UE4动作游戏实例RPG Action解析四:装备系统

导语: 以加血道具为例,详细分析拆解ActionRPG的装备系统,包含装备系统需求和数据结构设计,以及实现 一、装备系统需求: 装备槽: 已获取装备和未获取装备: 当已经装备一个道具时,再次捡到道具,会把道具放在装备库,不会放在装备槽中, 当没有装备道具时,会拾取道具…...

AIGC之Stable Diffusion

AIGC是什么? AIGC:Artificial Intelligence Generated Content,生成式人工智能。通俗一点来讲,对AI下达指令任务,通过处理人的自然语言,自动生成图片、视频、音频等等。 Stable Diffusion 官网:https://stablediffusionweb.com/ 介绍:stablediffusionweb.com is an eas…...

PHP接收并处理请求中携带的xml格式的信息

企业微信以xml的形式给服务器发送通知。具体参考&#xff1a;企业微信文档——事件格式 dump(file_get_contents("php://input"));/***string(530) "<xml><ToUserName><![CDATA[ww55ca070cb9b7eb22]]></ToUserName><FromUserName>…...

信息安全相关标准

GB/T 25070-2019 信息安全技术 网络安全等级保护安全设计技术要求 在线预览|GB/T 25070-2019 (gb688.cn) 每一级安全保护环境分为安全计算环境&#xff0c;安全区域边界&#xff0c;安全通信网络。 一级通用安全计算环境 二级通用安全 计算环境 三级 通用安全计算环境 第四级…...

Python入门学习篇(一)——注释变量输入输出

1 注释 1.1 作用 a 方便他人和自己阅读代码 b 告诉编译器这部分内容是不用执行的。1.2 单行注释 # 注释内容1.3 多行注释(引号) 1.3.1 三对双引号 """ 注释内容 """1.3.2 三对单引号 注释内容 1.4 pycharm快捷键使用 ctrl/ 多行注释(以# …...

基于单片机智能液位水位监测控制系统设计

**单片机设计介绍&#xff0c; 基于单片机智能液位水位监测控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能液位水位监测控制系统可以用来检测和控制液位的高低&#xff0c;并可以用于水泵的控制和自…...

iOS 添加震动效果

1. AudioServicesPlaySystemSound 较早的系统版本&#xff0c;我们会使用AudioTool.framework。 #import <AudioToolbox/AudioToolbox.h>一般震动 AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);普通短震&#xff08;类似3D Touch的 Peek 反馈 &#xff09; …...

合并word中参考文献-(Endnote生成)

合并word中的 两部分的参考文献引用 Merge Citations in the Word document Original&#xff1a; A is a big character [78-80] and B is another one [81-85] Modified&#xff1a; A and B are big characters [78-85] Solutions&#xff1a; Remove the space betwee…...

linux(centos7)常用命令 开启关闭防火墙

查看防火墙状态 centos7 systemctl status firewalld.service 运行上述命令后&#xff0c;如果看到有绿色字样标注的“active&#xff08;running&#xff09;”&#xff0c;说明防火墙是开启状态。 开启防火墙 centos7 systemctl start firewalld.service 关闭防火墙 c…...

数据结构与算法面试题——C++

自己在秋招过程中遇到的数据结构与算法方面的面试题 数据结构 vector vector是⼀种序列式容器&#xff0c;与array唯⼀差别就是对于空间运⽤的灵活性 array占⽤的是静态空间&#xff0c;⼀旦配置了就不可以改变⼤⼩&#xff0c;如果遇到空间不⾜的情况还要⾃⾏创建更⼤的空间…...

数字音频工作站FL Studio21.1中文版本如何下载?

在现在这个数字音乐时代&#xff0c;各种音乐中都或多或少有些电子音乐的影子&#xff0c;或是合成器音色、或是通过数字效果器制作出的变幻莫测的变化效果。而小马丁、Brooks、Eliminate等众多电子音乐巨头便是使用FL Studio来制作音乐的。今天小编就以FL Studio五年的资深用户…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 原创笔记&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;《数据结构第4章 数组和广义表》…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...