STM32F4 IAP实现总结

2023-11-12

目录

IAP相关

        IAP概念:

        IAP与ICP/ISP的区别:

STM32F4的启动模式

FLASH相关

        STM32F4 FLASH简介

        STM32的内部闪存组织架构和其启动过程

        应用IAP时的FLASH分配

IAP工程在Keil中的设置

跳转函数iap_load_app()相关

升级APP相关

APP程序编写和跳转相关

Demo程序实现


功能实现:

正常上电或复位后运行用户Bootloader程序,检查变量存储区的标志位。如果标志位为APP_FLAG则跳转到APP程序运行;如果标志位为BOOT_FLAG,则运行用户Bootloader程序,等待接收文件并准备IAP升级后跳转到新的APP程序运行。

APP程序运行时,完成正常功能;当接收到上位机从串口发来升级的指令后,会在FLASH中的变量存储区写下升级的标志位BOOT_FLAG,并且通过软复位返回用户Bootloader程序。Bootloader程序会接收新的程序文件并放到FLASH的APP空间,完成升级后会写下跳转标志位APP_FLAG,同时运行新的APP程序。 

  • IAP相关

1.  IAP概念:

        IAP(In Application Programming)即在应用编程,也就是用户可以使用自己的程序对单片机 Flash的某一区域进行烧写。当产品发布后,可以很方便的使用预留的通信接口(串口、USB、网口、蓝牙等)来完成程序的升级,避免使用ICP/ISP方式烧写程序。实现IAP技术的核心是一段预先烧写在单片机内部的IAP程序。这段程序主要负责与外部的上位机软件进行握手同步,然后通过外设通信接口将来自上位机软件的程序数据接收后写入内部指定的Flash区域,然后再跳转执行新写入的APP程序,从而达到程序更新的目的。

        因此,实现IAP功能需要两套程序:

        ①  用户Bootloader程序。这部分程序一般存储在FLASH的起始位置,用来引导、升级App程序;

         ②App程序,即实现产品功能的程序。通过用户Bootloader来完成对App程序的更新升级,从而实现IAP功能。

2.  IAP与ICP/ISP的区别:

        ICP(In-Circuit Programming)技术是通过在线仿真器对单片机进行程序烧写;ISP(In-System Programming)技术则是通过单片机内置的Bootloader程序(区别于IAP中的用户Bootloader程序)引导的烧写技术。无论是ICP技术还是ISP技术,都需要有机械性的操作如连接下载线,设置跳线帽等。若产品的电路板已经封装在外壳中,或者安装在狭小空间等难以触及的地方,要通过ICP或ISP技术对程序进行更新非常困难。使用IAP则可以避免以上问题,而且若使用远距离或无线的数据传输方案,甚至可以实现远程编程和无线编程,这是ICP或ISP技术无法做到的。

  • STM32F4的启动模式

 图1  STM32F4启动模式

        如图1所示,当BOOT0设置为0时,启动模式为用户闪存存储器启动。此时主闪存存储器被映射到启动空间(0x00000000),但仍然能够在原有的地址(0x80000000)访问,即闪存存储器可以在0x00000000和0x80000000这两个地址区域访问。

        当BOOT0设置为1,BOOT1设置为0时,启动模式为从系统存储器启动。此时系统存储器被映射到启动空间(0x00000000),但仍然能够在他原有的地址(0x1FFFF000)访问。该模式用于串口下载。

        当BOOT0设置为1,BOOT1设置为1时,只能在0x20000000开始的地址区访问SRAM。

  • FLASH相关

        在开始编程之前,需要了解不同型号单片机的Flash容量和闪存模块组织,从而确定Flash分配。由于Flash在擦除时是以扇区(Sector)为单位进行,所以要在写程序之前确定好Flash的扇区分配,保证用户Bootloader程序、变量存储区和APP程序不能存在于一个扇区,防止更新程序或数据时误擦除其他数据,造成死机(踩坑点1)。

1. STM32F4 FLASH简介

        STM32F411xC/E 产品的闪存模块组织如图2所示:

 图2  STM32F4闪存模块组织

        STM32F4的闪存模块由主存储器(Main memory)、系统存储器(System memory)、OPT区域和选项字节(Option bytes)等4部分组成。

        主存储器(Main memory)部分用来存放代码和数据常数(如const类型的数据), 共有8个扇区。扇区0~3容量为16KB,扇区4容量为64KB,扇区5~7容量为128K,不同容量的STM32F411拥有的扇区数不同。此次使用的芯片是STM32F411CE,Flash大小为512KB,共有7个扇区,从图2可以看出主存储器的起始地址是 0x08000000。BOOT0GND时,从0x08000000开始运行代码。

        系统存储器(System memory)主要用来存放STM32F4的内置Bootloader代码。此代码在出厂时固化在STM32F4芯片内部,用来给主存储器下载代码。当 BOOT0接3.3V,BOOT1 接GND时,从该存储器启动(即进入串口下载模式)。

        OTP区域,即一次性可编程区域,共528字节,被分成两个部分。前512字节(32字节为1块,共16块),可以用来存储一些用户数据(一次性的,写完一次永远不可以擦除),后面16字节用于锁定对应块。

        选项字节(Option bytes)用于配置读保护、 BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。

        闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构。

        在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。

2. STM32的内部闪存组织架构和其启动过程

        STM32的内部闪存地址起始于0x08000000,一般情况下,程序文件就从此地址开始写入。STM32内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是0x8000004。当中断来临,STM32的内部硬件机制会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。

图3  STM32正常运行流程图 

STM32常规的程序运行流程如图3所示:

  • STM32复位后,会从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序,如图3中标号所示。
  • 复位中断服务程序执行的最终结果是跳转至C程序的main函数,如图3中标号所示。而main函数应该是一个死循环,是一个永不返回的函数。
  • main函数执行的过程中,发生了一个中断请求,此时STM32的硬件机制会将PC指针强制指回中断向量表处,如图3中标号所示。
  • 根据中断源进入相应的中断服务程序,如图3中标号所示。
  • 中断服务程序执行完毕后,程序再度返回至main函数中执行,如图3中标号所示。

 

 图4  加入IAP之后程序运行流程图

        在STM32微控制器上实现IAP方案,除了常规的串口等通讯接口接收数据以及闪存数据写入等常规操作外,还需注意STM32的启动过程和中断响应方式。

加入IAP程序后,程序运行流程图如图4所示:

  • STM32复位后,从地址为0x8000004处取出复位中断向量的地址,并跳转执行复位中断服务程序,随后跳转至IAP程序的main函数,如图4中标号所示。这个过程和图1相应部分是一致的。
  • 执行完IAP过程后(STM32内部多出了新写入的程序,图4中以灰色底纹方格表示,地址始于0x8000004+N+M)跳转至新写入程序的复位中断向量表,如图4中标号所示。取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数,其过程如图4的标号所示。新程序的main函数应该也具有永不返回的特性。同时应该注意在STM32的内部存储空间在不同的位置上出现了2个中断向量表。
  • 在新程序main函数执行的过程中,一个中断请求来临,PC指针仍会回转至地址为0x8000004中断向量表处,而不是新程序的中断向量表,这是由STM32的硬件机制决定的,如图4中标号所示。
  • 根据中断源跳转至对应的中断服务,如图4中标号所示。注意此时是跳转至了新程序的中断服务程序中。
  • 中断服务执行完毕后,返回main函数。如图4中标号所示。

总结:

通过以上两个过程的分析, IAP 程序必须满足两个要求:

  • 新程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始;
  • 必须将新程序的中断向量表做相应的移动,移动的偏移量为 x。

 3. 应用IAP时的FLASH分配

        此次设计程序时将Flash分为3部分:

  • 0x08000000 ~ 0x08010000-1: 64K(Sector0~Sector3),用于存放用户Bootloader程序;
  • 0x08010000 ~ 0x08020000-1: 64K(Sector4),作为变量存储区,用来存放程序运行标志位等;
  • 0x08020000 ~ 0x08080000-1:384K(Secror5~Secror7),用于存放APP程序。
  • IAP工程在Keil中的设置

  1. 设置Flash分区:

        因为用户Bootloader程序和APP程序都是单独的工程,所以要分别在Keil中设置IROM1的大小(踩坑点2):

        ① 用户Bootloader工程

        Options for Target -> Target -> IROM1 设置0x08000000~0x0800FFFF的64K空间作为用户Bootloader程序存储区:

 图5  用户Bootloader工程起始地址设置

        ② APP工程

        Options for Target -> Target -> IROM1 设置0x08020000~0x0807FFFF的384K空间作为APP程序存储区:

 图6  APP工程起始地址设置

        2. 设置中断向量表偏移量:

        在系统启动的时候,会首先调用SystemInit函数初始化时钟系统,同时SystemInit还完成了中断向量表的设置。STM32通过VTOR寄存器存放中断向量表的起始地址,对于Flash APP,需要设置中断向量表的偏移量为0x20000,设置方法为在Flash APP的main函数最开头处添加一行代码实现中断向量表的起始地址的重映射(踩坑点3): 

SCB->VTOR = FLASH_BASE | 0x20000;	//FLASH_BASE为0x80000000

 图7  设置中断向量表偏移

        3.生成.bin文件:

        IAP更新需要用到.bin文件,而MDK默认生成的是.hex文件。可通过MDK自带的格式转换工具“fromelf.exe”来实现“.axf”文件到“.bin”文件的转换。该工具在MDK的安装目录\ARM\ARMCC\bin文件夹。“fromelf.exe”转换工具的语法格式为: fromelf [options] input_file。

        ① 打开Flash APP工程文件Options for Target ->USER选项卡,在After Build/Rebuild菜单下勾选Run #1,User Command栏中填写如下内容,注意修改生成的.bin文件名与.axf文件名相同:图8  编译后生成.bin文件

         ② 打开Linker选项卡,勾选“Use Memory Layout from Target Dialog”

 图9  STM32的默认链接文件配置

         编译成功后,会在相应文件夹下看到生成.bin文件。得到.bin文件之后,只需要将该文件传送给单片机,即可执行 IAP 升级。

 图10  编译后生成.bin文件

         4.  APP 程序的生成步骤总结:

                ①  设置APP程序的起始地址和存储空间大小

                ②  设置中断向量表偏移量,即重新设置 SCB->VTOR 的值

                ③  设置编译后运行fromelf.exe,生成.bin文件,用于IAP更新

        经过以上3个步骤,就可以得到一个格式为.bin的APP程序,通过用户Bootloader程序即可实现更新。

  • 跳转函数iap_load_app()相关

//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(uint32_t appxaddr)
{ 
	if(((*(__IO uint32_t*)appxaddr) & 0x2FFE0000) == 0x20000000)	//检查栈顶地址是否合法.在0x2000 0000 - 0x 2000 2000之间
	{ 	
		jump2app=(iapfun)*(__IO uint32_t*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(__IO uint32_t*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.
	}
}		 	 

        该函数位于iap.c文件中,用于实现用户Bootloader程序到APP程序的互相跳转。

1.  if(((*(__IO uint32_t*)appxaddr) & 0x2FFE0000) == 0x20000000)

        判断栈顶地址值是否在0x20000000 ~ 0x20002000之间。在iap.h文件中定义了应用程序的起始地址为0x08020000,那么*(__IO uint32_t*)appxaddr即取0x08020000开始到0x08020003的4个字节的值。因为APP应用程序的“中断向量表”放置在0x08020000开始的位置,而中断向量表里第一个放的就是栈顶地址,参考图4。

        该语句即通过判断栈顶地址值是否正确(是否在0x20000000 ~ 0x20002000之间,因为栈顶地址就是整个地址空间中SRAM所在的位置) 来判断应用程序是否已经下载了,因为应用程序的启动文件刚开始就去初始化栈空间,如果栈顶值正确,说明已经下载应用程序并且已执行启动文件的初始化。

2.  jump2app=(iapfun)*(__IO uint32_t*)(appxaddr+4);

        appxaddr+4即0x08020004 ,该地址存放的是图4中第二个“中断向量表”的第二项“Reset_Handler”。

  • 升级APP相关

        升级即新程序替换旧程序的过程。因此升级的实质就是擦除原有数据所在的Flash扇区,再将新数据写入的过程。STM32F4的Flash在编程时,必须要求其写入地址的Flash扇区 是被擦除了的(扇区内的值必须是 0XFFFFFFFF),否则无法写入。对STM32F4的Flash编程步骤如下:

  1. 检查 FLASH_SR 中的 BSY 位,确保当前未执行任何 FLASH 操作
  2. FLASH_CR 寄存器中的 PG 位置 1,激活 FLASH 编程
  3. 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作:
    • 并行位数为 x8 时按字节写入(PSIZE=00
    • 并行位数为 x16 时按半字写入(PSIZE=01
    • 并行位数为 x32 时按字写入(PSIZE=02
    • 并行位数为 x64 时按双字写入(PSIZE=03
  4. 等待 BSY 位清零,完成一次编程。

按以上四步操作,就可以完成一次Flash编程。不过有几点要注意:

  1. 编程前,要确保要写如地址的Flash已经擦除
  2. 要先解锁(否则不能操作 FLASH_CR)
  3. 编程操作对OPT 区域也有效,方法相同

将新程序写入Flash指定区域函数具体在stmflah.c 和stmflash.h中实现。

  • APP程序编写和跳转相关

        1.  APP应用程序的主要功能包含两个方面:

                ①  除升级功能外的所有应用功能

                ②   跳转至用户Bootloader程序准备升级

        2.  跳转至用户Bootloader的两种方式:

                ①  使用跳转函数iap_load_app();

                ②  软重启Reboot

     Demo中使用软重启完成从APP程序到用户Bootloader的跳转。      

  • Demo程序实现

1.  使用STM32F411CEU6芯片,上电后运行APP程序,串口显示Start to Execute APP Program...,LED(PB4)以10Hz频率闪烁

2.  通过串口调试助手发送abc到串口6,程序跳转至用户Bootloader,等待接收文件更新,此时LED频率变为2Hz。注意串口参数设置,勾选“发送新行”:

 若发送的数据不是abc,则提示“Error Message! Please Check the Command and Try Again!”

3.  在串口调试助手中点击打开文件,选择需要更新的APP的bin格式文件,点击发送。此时串口调试助手会显示接收到的文件大小并判断接收到的文件格式是否正确,若发送的文件格式正确,则完成更新后重新开始执行APP程序

 若发送的文件不正确,则提示“Illegal Flash Applications! Please Check Your File and Try Again!”,此时可重新发送正确文件。

 Demo源码:利用STM32F411实现IAP测试程序https://download.csdn.net/download/Tiffany982/76638993

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F4 IAP实现总结 的相关文章

  • 线程安全的向量和字符串容器?

    我之前发过一个问题 在嵌入式 Linux 平台上使用 std string 时出现段错误 https stackoverflow com questions 2412667 seg fault when using stdstring on
  • arm64 汇编:LDP 与 LD4 执行时间

    假设我想用连续内存位置的值加载四个连续的 aarch64 向量寄存器 一种方法是 ldp q0 q1 x0 ldp q2 q3 x0 32 根据ARM优化指南 https static docs arm com uan0016 a cort
  • ARM 的启动过程是怎样的?

    我们知道 对于X86架构 按下电源按钮后 机器开始执行0xFFFFFFF0处的代码 然后开始执行BIOS中的代码以进行硬件初始化 BIOS 执行后 它使用引导加载程序将操作系统映像加载到内存中 最后 操作系统代码开始运行 对于ARM架构 使
  • 嵌入式 C++ (ARM9) 单元测试

    我来自 Java 和 JUnit 的世界 我演示了 Hudson 以及我使用 JUnit 取得的所有成果 我想在嵌入式设备上对 C 代码执行相同的操作 但找不到从哪里开始 该项目使用 iccarm exe IAR 编译器 进行编译 现在使用
  • 将结构体偏移属性赋予汇编器

    如何将 C 结构体的偏移量发送到汇编代码 例如 在我的 C 代码中 typedef struct unsigned int a unsigned int b CMyStruct 我向 ASM 函数发送一个 CMyStruct 结构的指针 假
  • 使用 ARM NEON 内在函数添加 alpha 和排列

    我正在开发一个 iOS 应用程序 需要相当快地将图像从 RGB gt BGRA 转换 如果可能的话 我想使用 NEON 内在函数 有没有比简单分配组件更快的方法 void neonPermuteRGBtoBGRA unsigned char
  • 如何使用 gcc 编译代码和 ARM Cortex A8 目标进行调用图分析?

    我对这个已经咬牙切齿了 我需要在 ARM 板上进行分析并需要查看调用图 我尝试使用 OProfile Kernel perf 和 Google 性能工具 一切正常 但不输出任何调用图信息 这使我得出结论 我没有正确编译代码 我在编译 C 代
  • GCC ARM 汇编预处理器宏

    我正在尝试使用汇编 ARM 宏进行定点乘法 define MULT a b asm volatile SMULL r2 r3 0 1 n t ADD r2 r2 0x8000 n t ADC r3 r3 0 n t MOV 0 r2 ASR
  • ARM 中只有两个操作数的 ADD 或 SUB

    我正在学习ARM汇编语言 我读过 ADD 应该有 3 个操作数 然而 我见过很多案例 现实中只有两种 例如 STR R1 SP 0x20 var 1C LDR R1 a lua 0x1DE4E6 MOVS R0 R4 haystack AD
  • 源和目标具有不同的 EABI 版本

    我正在尝试使用 ARM 工具链编译 so 文件 但是我不断收到这个错误 错误 源对象的 EABI 版本为 0 但目标对象的 EABI 版本为 5 我无法更改工具链中的任何内容 因为我必须使用给定的工具链 我以前从未见过这个错误 我使用了这个
  • 可以使用Visual Studio 2012构建ARM桌面程序吗?

    我正在使用 Visual Studio 2012 beta 我的桌面 win32 程序在 ARM 架构中编译得很好 升级到 Visual Studio 2012 RC 后 编译器无法工作并出现以下错误 不支持为 ARM 平台编译桌面应用程序
  • M1 MacBook Pro 上的 Android Studio 无法使用 ABI armeabi-v7a 模拟系统映像

    我的 M1 Macbook Pro 上的 Android Studio 可以很好地模拟 ABI arm64 v8a 的所有系统映像 API 24 29 30 31 但是 它无法使用 ABI armeabi v7a 运行所有映像 例如 API
  • Beaglebone Black 的 U-boot 无法构建 - 目标 CPU 不支持 THUMB 指令

    我正在尝试按照 Chris Simmonds 的 掌握嵌入式 Linux 编程 中的说明为 Beagle Bone Black 构建 u boot 我已经构建了交叉工具链 现在正在尝试使用该工具链构建 Das U boot 但由于不支持 T
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • 为什么 GCC 交叉编译不构建“crti.o”?

    在尝试为arm构建gcc 4 x x交叉编译器时 我陷入了缺失的困境crti o文件在 BUILD DIR gcc子目录 An strace在顶层Makefile表明编译后的xgcc正在调用交联器ld with crti o 作为一个论点
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • iPhone 3GS 上的 ARM 与 Thumb 性能比较,非浮点代码

    我想知道是否有人有关于 iPhone 3GS 上 ARM 与 Thumb 代码性能的硬性数据 特别是对于非浮点 VFP 或 NEON 代码 我知道 Thumb 模式下的浮点性能问题 更大的 ARM 指令的额外代码大小是否会在某个时刻成为性能
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加
  • 英特尔的最后分支记录功能是英特尔处理器独有的吗?

    最后分支记录是指存储与最近执行的分支相关的源地址和目标地址的寄存器对 MSR 的集合 它们受英特尔酷睿 2 英特尔至强和英特尔凌动处理器系列的支持 http css csail mit edu 6 858 2012 readings ia3
  • 需要一些建议来开始在 ARM(使用 Linux)平台上编程

    我 也许 很快就会在托管 Linux 发行版的 ARM 平台上工作 我不知道哪个发行版 我知道该项目涉及视频流 但我无法告诉你更多信息 其实我只收到通知 还没见到任何人 我从来没有在这样的平台上工作过 所以我的想法是在项目开始之前进行测试

随机推荐

  • Java 抽象类能不能实例化

    短回答就是 不能 这里有 2 个概念 什么是抽象类和什么是实例化 实例化 实例化简单来说就是为 Java 中使用的对象分配存储空间 抽象类 从代码上来说 抽象类就是一个用 abstract 关键字来修饰的类 这个类除了不能被实例化以外 其他
  • 若依使用模块窗口时把子页面内容传递给父页面

    在若依开发中 经常需要将子页面的表格中勾选内容传回父页面 本文将具体说明实现方式 1 父页面中存在一个按钮 点击即打开子页面 一个模态窗口 会阻塞父页面的行为 2 在父页面中 需要完成打开子页面和回调给父页面的方法 而且此方法可在若依样例中
  • 【程序人生】从土木专员到网易测试工程师,薪资翻3倍,他经历了什么?

    转行对于很多人来说 是一件艰难而又纠结的事情 或许缺乏勇气 或许缺乏魄力 或许内心深处不愿打破平衡 可对于我来说 转行是一件不可不为的事情 因为那意味着新的方向 新的希望 我是学工程管理的 一个工程类的专业 毕业之后的职业轨迹 土木工程专员
  • 【VSCode】1、VSCode 如何连接服务器

    文章目录 一 安装 remote ssh 插件 二 直接连接 三 配置 SSH 公匙 免密登录 一 安装 remote ssh 插件 点击插件搜索框 搜 remote ssh 点击安装 安装完成后就会出现下面的图标 二 直接连接 点击加号
  • r语言中出现unused argument怎么办

    如果在使用 R 语言时出现 unused argument 的错误提示 通常是因为在调用函数时传入了多余的参数 为了解决这个问题 你需要检查你的代码 确保你只传入了函数所需的参数 例如 如果你调用的函数只有两个参数 但你却传入了三个参数 那
  • 蓝桥杯打卡Day7

    文章目录 阶乘的末尾0 整除问题 一 阶乘的末尾0IO链接 本题思路 由于本题需要求阶乘的末尾0 由于我们知道2 5 10可以得到一个0 那么我们就可以找出2的数和5的数 但是由于是阶乘 所以5的数量肯定是小于2的数量 因此我们只需要知道5
  • Python中configparser读取配置

    Python中的configparser模块可以帮助开发者轻松地读取和写入配置文件 配置文件通常用于存储应用程序的设置 例如数据库连接信息 API密钥等等 在本篇博客中 我们将介绍如何使用configparser模块来读取和写入配置文件 读
  • leetcode No1833 雪糕的最大数量

    题目 题解 贪心 排序 贪心 顾名思义就是贪到最多的 本题要求一定数额的钱 要获得最多数量的雪糕 那以我们平常人的思维去买 就是 先买最便宜的 然后再买次便宜的 因此我们可以先将数组排序 排序后从头开始遍历 一直算到前i个雪糕价钱之和大于c
  • 高效素数判断

    素数是指在大于1的自然数中 除了1和它本身以外不再有其他因数的自然数 那么 对于任意数N 判断其是否是素数 就需要从 2 N 一一枚举整除判断 若都不能整除 则N为素数 public static boolean isprime int n
  • 魔改并封装 YoloV5 Version7 的 detect.py 成 API接口以供 python 程序使用

    文章目录 Introduction Section 1 起因 Section 2 魔改的思路 Section 3 代码 Part 1 参数部分 Part 2 识别 API Part 3 完整的 DetectAPI py Part 4 修改
  • 免费商品信息查询接口(条形码)

    最近公司有一个需求 扫描商品条形码显示商品信息 原以为国内应该会免费提供接口 理想总是美好的 现实都是残酷的 在阿里云 京东等API开放平台找了一番 基本都是按次调用收费 公司的需求每位用户一天可能多次调用接口 这样一算 成本太高 既然没有
  • thrift介绍及应用(二)—简单应用

    原文 http blog csdn net guxch article details 12162131 六 一个最简单的实例 Thrift文件 demo thirft 来自官网 如下 plain view plain copy struc
  • 力扣160链表相交(c++版)

    力扣160链表相交 c 力扣题目链接 思路 如果两个链表相交 又都不存在环 那么不难想象这两个链表共同构成了一个Y型 相交部分全部都相同 两链表交点处指针相等 声明指针A指向链表A的头结点 指针B指向链表B的头结点 我们求出两个链表的长度
  • 【基础】创建react脚手架

    React day01 Hello world 一 升级node 1 进入官网 https nodejs org en 2 重新下载最新版本 3 重新安装 一直选择next 既会被覆盖 4 输入 node v 查看最新版本 注 window
  • vue项目中用 cdn 优化

    在我们写项目中 优化问题是不容忽视的 尤其是首屏优化更是重中之重 这里介绍两种方法优化方法 cdn和异步加载 异步请看 http blog csdn net gang456789 article details 78224751 1 cdn
  • Fiddler 八个实用技巧

    目录 前言 1 双击Session时 使响应页始终显示到 json tab页 使请求页始终显示到 webform tab页 2 显示每个Session 的请求IP地址 3 修改响应Header中的Content Type 4 右键sessi
  • 2023AE软件、Adobe After Effects安装下载教程

    2023AE软件是一款由Adobe公司开发的视频编辑软件 也被称为Adobe After Effects 它在广告 电影 电视和网络视频等领域广泛应用 用于制作动态图形 特效 合成和其他视觉效果 该软件支持多种视频和音频文件格式 具有丰富的
  • mybatis增删改查

    MyBatis 是一款优秀的持久层框架 它支持定制化 SQL 存储过程以及高级映射 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集 MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息 将接口和
  • C语言第五章第3节用do...while语句实现循环学习导案

    课 题 5 3 用do while语句实现循环 课时安排 2课时 课 型 新授 学 习目标 掌握do while循环语句的一般形式 掌握do while循环语句的执行过程 掌握do while语句和while语句的区别 重点 do whil
  • STM32F4 IAP实现总结

    目录 IAP相关 IAP概念 IAP与ICP ISP的区别 STM32F4的启动模式 FLASH相关 STM32F4 FLASH简介 STM32的内部闪存组织架构和其启动过程 应用IAP时的FLASH分配 IAP工程在Keil中的设置 跳转