IAR for ARM仿真技术全教程

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:《IAR for ARM仿真教程》为工程师深入学习IAR开发环境在ARM架构上的仿真技术提供了详细的指导。教程覆盖了从工程创建、软件配置到实际仿真的全过程,包括新工程的建立、目标处理器的选择、项目属性配置、编译选项设置,以及使用EWARM调试器进行程序单步执行、变量观察和错误定位等。教程还包括了如何进行硬件不依赖的仿真,以及一系列教学视频,帮助开发者优化代码质量和执行效率,提高开发效率。

1. IAR for ARM开发环境介绍

1.1 IAR系统概览

IAR for ARM是针对ARM处理器设计的专业集成开发环境(IDE),它提供了高度优化的编译器和功能齐全的调试工具。该平台支持广泛的ARM处理器系列,并且集成了代码优化、系统性能分析和代码质量控制等强大功能。

1.2 开发环境特性

IAR for ARM提供了一个集成的开发环境,支持C和C++语言,是嵌入式系统开发者的首选工具。通过其友好的用户界面,开发人员能够轻松地进行源代码编辑、项目管理、程序编译、调试及分析。

1.3 系统要求和安装

在开始使用IAR for ARM之前,需要满足特定的系统要求,包括操作系统兼容性和最小硬件配置。安装过程中,用户需要遵循安装向导的指引,完成软件的安装和初始配置。安装后,建议进行系统检查,确保所有组件正常运行。

> **注意:** 系统要求和安装步骤对确保开发环境的稳定性和优化性能至关重要,初学者尤其需要仔细阅读官方文档和指南。

以上章节为IAR for ARM开发环境的介绍,接下来的章节将会详细介绍如何创建工程、配置项目属性、使用软件设置以及如何利用EWARM调试器进行程序调试。

2. 工程创建与目标处理器选择

2.1 工程的建立与管理

在IAR Embedded Workbench中,工程是项目开发的基本单元。创建和管理工程是每个嵌入式开发者的首要任务。本章节将详细介绍创建新工程的步骤和工程文件的基本结构。

2.1.1 创建新工程的步骤

  1. 打开IAR Embedded Workbench。
  2. 选择 "File" 菜单下的 "New",然后选择 "Project..."。
  3. 在弹出的对话框中选择一个模板,根据项目需求选择合适的模板。
  4. 为工程命名并选择一个存放路径。
  5. 选择目标设备或处理器系列。
  6. 根据需要配置项目选项,如内存设置等。
  7. 点击 "OK" 创建工程。

一旦完成以上步骤,一个新的工程就会在IAR中创建。接下来,我们可开始添加或创建源文件,包括C和汇编代码,为接下来的开发流程做好准备。

2.1.2 工程文件的基本结构

IAR工程文件通常包含以下几部分:

  • 工程文件(.ewp) :包含工程的配置信息,如工程设置、文件列表和目标设置。
  • 工程选项文件(.opt) :包含特定于目标选项的详细配置。
  • 源代码文件(.c, .cpp, .s) :包含项目的源代码。
  • 头文件(.h) :包含源代码文件中引用的声明。
  • 构建脚本(.bat, .sh) :如果使用自动化构建流程,则会用到这些脚本文件。
  • 其他资源文件 :如图像、文本文件等,视项目需求而定。

要管理这些文件,可以在工程树中查看和编辑它们。工程树以层次结构显示所有文件和文件夹,并且可以通过右键点击进行添加、删除或重命名等操作。

2.2 处理器选择与配置

在创建项目后,选择合适的处理器是至关重要的。这将决定我们的代码可以在哪些硬件上运行,以及需要考虑哪些特定的硬件功能和限制。

2.2.1 如何选择目标处理器

  1. 确定需求 :了解项目需求,包括性能要求、内存大小、外设需求等。
  2. 分析可用处理器 :查看支持的处理器列表,对比它们的特点。
  3. 考虑软件兼容性 :评估现有软件和库是否兼容目标处理器。
  4. 选择工具链 :根据处理器选择正确的编译器和链接器。
  5. 进行原型测试 :在决定前,尽可能在目标硬件上进行测试。

选择处理器时,务必考虑项目的长远发展,处理器性能应当有一定的余量以应对未来可能的升级和优化。

2.2.2 处理器配置的参数解释

当选择了目标处理器后,通常需要配置一些参数,这些参数包括:

  • 时钟设置 :设定处理器和外设的时钟频率,这直接影响系统的运行速度和功耗。
  • 内存布局 :配置代码和数据在存储器中的布局,根据实际硬件进行调整。
  • 启动代码选择 :选择适合目标处理器的启动代码,以确保系统初始化正确。
  • 中断向量表 :配置中断向量表,以匹配目标硬件的中断处理需求。

处理器配置是项目成功的关键因素之一。配置得当能帮助我们充分利用硬件资源,从而提升程序性能和稳定性。

通过以上内容,我们能够理解在IAR for ARM开发环境中创建工程和选择目标处理器的基本方法。下一章我们将继续深入讨论项目属性与编译选项的配置,这两者是优化和定制项目行为的重要手段。

3. 项目属性与编译选项配置

项目属性设置

项目属性的基本设置方法

在IAR for ARM中,项目属性是控制编译、链接以及代码生成行为的关键部分。要设置项目属性,首先在项目工作区(Workspace)中找到对应项目,然后右键点击项目名称,选择“Options”(选项)进入项目属性界面。

1. General Settings(通用设置)
此选项卡下可以设置项目的输出类型,例如是生成可执行文件还是库文件,也可以指定输出文件的名称和路径。

2. C/C++ Compiler(C/C++编译器)
在此选项卡下配置编译器的具体行为,包括代码优化级别、预处理器定义、警告级别等。

3. Assembler(汇编器)
与编译器类似,汇编器的设置影响汇编代码的编译过程,通常不需要频繁调整。

4. Linker(链接器)
链接器选项卡用于配置最终的可执行文件如何通过链接过程生成。重要设置包括内存布局、库文件链接等。

5. Debugger(调试器)
调试器选项用于设置调试会话的行为,比如端口号、启动行为等。

6. Output Converter(输出转换器)
如果需要特定格式的输出文件,可以在此设置相应的转换器参数。

7. Advanced(高级设置)
包含更专业的设置,比如编译器优化选项、链接器脚本路径等,适用于需要精细控制的高级用户。

关键项目属性参数详解

每个选项卡中的参数对编译行为都有直接或间接的影响。下面是一些关键参数的解释:

  • Optimization Level(优化级别)
    此参数控制编译器的优化程度,对程序的执行速度和体积有直接影响。通常有无优化(Level 0)、大小优化(Level 1)、速度优化(Level 2)等选择。

  • Preprocessor Definitions(预处理器定义)
    用于定义宏指令,在代码中可以使用这些宏来进行条件编译或配置程序行为。

  • Include Paths(包含路径)
    指定编译器在寻找头文件时需要搜索的目录,对于大型项目管理依赖关系非常重要。

  • Library Configuration(库配置)
    此部分指定项目依赖哪些库文件,以及它们的搜索路径。

  • Linker Script(链接器脚本)
    链接器脚本定义了程序的内存布局,包括各个段(如代码段、数据段)的位置。

  • Debugger Settings(调试器设置)
    配置调试器在何种条件下启动,例如在程序崩溃时是否自动进入调试模式。

编译选项配置

编译器选项的配置

在“C/C++ Compiler”选项卡中,可以通过“Symbols”(符号)标签页添加或删除预处理器符号,这些符号在代码预处理时会被替换或判断。在“Optimization”(优化)标签页可以设置代码优化的级别和范围,以提高运行效率或减小代码体积。对于复杂的优化选项,推荐具有丰富经验的开发者谨慎选择,因为错误的优化设置可能会导致程序行为不可预测。

预处理器的使用和应用

预处理器是C/C++语言中非常强大的工具,它可以在代码编译之前处理代码,实现宏定义、条件编译、文件包含等操作。在IAR中配置预处理器的方法有:

1. 定义宏
通过在“Preprocessor Definitions”中添加宏定义,可以在源代码中使用 #ifdef , #ifndef , #define , #undef 等预处理指令。

2. 包含头文件
在“Include Paths”中设置头文件搜索路径,当代码中包含 #include 指令时,编译器会根据这些路径寻找头文件。

3. 控制调试和日志
预处理器常用于控制程序的调试输出或运行时日志记录,通过定义或取消定义特定宏,来包含或排除调试代码。

代码块示例:

#define DEBUG
#ifdef DEBUG
    #include <stdio.h>
    void debugPrint(const char* message) {
        printf("Debug Message: %s\n", message);
    }
#else
    void debugPrint(const char* message) {
        // Empty function to avoid linker errors
    }
#endif

// 在代码中使用debugPrint函数进行调试输出
debugPrint("This is a debug message");

在上述代码中,我们定义了一个 DEBUG 宏,并在需要调试的地方使用 debugPrint 函数。如果取消定义 DEBUG 宏(例如,在编译生产代码时),则相关的调试输出代码会被编译器忽略,从而不会影响最终程序的性能。

通过以上对项目属性与编译选项的详细配置,开发者能够精确控制IAR for ARM的编译和链接过程,确保生成的代码符合性能与资源使用的最佳平衡。

4. 软件设置详解

4.1 编译器选项详解

4.1.1 代码优化设置

代码优化是编译器将源代码转换成更高效机器码的过程。它包括但不限于减少代码大小、提升执行速度和减少资源消耗等策略。在IAR for ARM开发环境中,优化选项是通过 --opt 参数来配置的。IAR编译器提供了多种优化级别,如下:

  • Level 0(O0): 无优化,编译速度最快,便于调试。
  • Level 1(O1): 较少优化,平衡编译速度与性能。
  • Level 2(O2): 中等优化,适合常规应用。
  • Level 3(O3): 较多优化,可能增加代码大小,但显著提升性能。
  • Level 4(Os): 优化代码大小。

在配置代码优化时,开发者需要根据具体需求选择合适的级别。例如,当内存资源非常有限时,可能需要牺牲一些性能以减少代码大小。反之,对于对性能要求极高的应用场景,则可以启用更高一级的优化。

使用代码块来展示如何在命令行中设置代码优化级别:

iararm --opt O2 your_project.eww

在上述命令中, --opt O2 表示将优化级别设置为2。 your_project.eww 是编译工程文件。优化级别可以根据项目需求调整,例如设置为 --opt O0 来关闭优化。

4.1.2 编译器警告和错误处理

IAR编译器提供了丰富的警告和错误信息,帮助开发者检测和修正代码中可能存在的问题。有效的警告管理是确保代码质量的重要步骤。IAR提供了如下警告选项:

  • Error as Warning(E): 将错误信息报告为警告,而不是阻止编译继续。
  • Force All Warnings(W): 强制显示所有警告,即使某些警告默认被忽略。
  • Enable Specific Warning(+n): 启用特定编号的警告。
  • Disable Specific Warning(-n): 禁用特定编号的警告。

合理的使用这些选项,可以帮助开发者在开发阶段早期发现潜在问题。如下面的命令示例中,开发者希望启用所有警告:

iararm -W your_project.eww

在此命令中, -W 参数表示启用所有警告信息。通过这种方式,开发者可以更细致地审查代码,确保软件质量。

4.2 链接器设置

4.2.1 链接脚本的基本概念

链接器脚本用于指导链接器如何将多个编译后的目标文件链接成一个单一的可执行文件。它定义了内存布局,控制了符号的解析以及各模块的组织方式。在IAR for ARM中,链接器脚本使用 .icf 文件格式,它包含了一系列指令来描述链接过程。

一个基本的链接器脚本包含如下关键部分:

  • 内存区域定义: 描述内存布局,如RAM和ROM的起始地址与大小。
  • 段定义: 指定代码和数据如何映射到内存区域。
  • 符号重定位: 描述符号如何在最终的映像中被放置。

例如,下面的链接器脚本片段定义了一个内存区域和符号定位:

define symbol __ICFEDIT_region_relocating_start__ = 0x20000000;

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00010000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

4.2.2 链接器选项的配置与调试

链接器选项允许开发者调整链接过程的各个方面,如内存使用、符号解析等。正确的链接器配置可以减少最终可执行文件的大小,优化运行时性能。

下面的代码块展示了如何在IAR工程设置中配置链接器选项:

iararm --config your_project.icf your_project.eww

在命令中, --config 参数后跟链接器脚本文件( .icf 文件),用于指定工程的链接配置。 your_project.eww 是编译工程文件。开发者需要根据实际工程的需要,编辑或创建 .icf 文件,并在工程设置中引用它。

4.3 调试选项

4.3.1 调试信息的生成与使用

调试信息对于开发者来说至关重要,它包含了让调试器能够理解源代码和执行文件之间映射关系的所有必要数据。在IAR for ARM中,生成调试信息通常是在编译过程中通过特定的编译器开关来实现的。

调试信息生成的编译器开关为 --debug 。启用此选项后,编译器会生成额外的调试符号信息,并将其嵌入到最终的输出文件中。例如:

iararm --debug your_project.eww

此命令将为 your_project.eww 工程生成调试信息。

4.3.2 调试参数的优化与调整

在IAR for ARM中,调试参数的优化与调整是通过调试配置文件来完成的。调试配置文件通常具有 .dcd 扩展名,它允许开发者对调试会话进行细致的控制。通过调整这些参数,开发者可以优化性能,改善调试体验。

调试配置文件的一个简单示例:

define symbol __ICFEDIT_region_sniffer_start__ = 0x20000000;
define symbol __ICFEDIT_region_sniffer_end__ = 0x2000FFFF;

define symbol __ICFEDIT_region_board_name__ = "MyBoard";

define variable __ICFEDIT_size_cstack__ = 0x400;

define variable __ICFEDIT_size_pstack__ = 0x100;

define variable __ICFEDIT_verify_alignment__ = 1;

在此 .dcd 文件中,定义了堆栈大小、板卡名称和其他用于调试的重要信息。开发者可以针对特定硬件和需求,对这些参数进行调整,以获得最佳调试效果。

通过以上内容的介绍,我们可以看到IAR for ARM为软件开发提供了强大的工具链,以支持从编译到调试的每一个环节。理解这些选项的设置不仅有助于提高开发效率,还能对最终产品的质量起到决定性作用。

5. EWARM调试器的使用与功能

EWARM调试器是IAR Embedded Workbench for ARM的一个重要组成部分,它提供了一套强大的工具来帮助开发者在软件开发的早期阶段进行问题诊断和性能优化。本章节将详细介绍EWARM调试器的基本使用方法以及一些高级调试技巧。

5.1 调试器的基本使用

5.1.1 断点设置与分析

断点是调试过程中最常用的工具之一,它可以让程序执行在特定行或函数暂停。通过设置断点,开发者可以在程序运行到该点时暂停执行,这样就可以检查程序的状态,比如变量的值、程序的流程等。

在EWARM中设置断点非常简单,只需在代码编辑器中找到想要暂停的行,然后右键点击选择“Toggle Breakpoint”,或者直接点击编辑器左边的边缘空白区域。当程序运行到这里时,就会自动暂停。

// 示例代码段,将在main函数的第一行设置断点
void main(void) {
    // 断点设置在这里
    while(1) {
        // 程序的其它部分
    }
}

一旦程序执行到断点处,调试器会停止运行,并显示当前位置的源代码,以及变量和寄存器的状态。此时,开发者可以逐行执行程序(Step Over、Step Into),观察变量的变化。

5.1.2 变量和内存的监控

除了断点外,EWARM调试器还提供了变量和内存监控功能,允许开发者观察程序中变量的值以及内存的状态。这在程序中难以重现的错误中非常有用。

在监视窗口中,可以通过添加变量来监控其值。只需在监视窗口中输入变量名,即可查看其当前值,并在程序运行时自动更新。

// 示例:监控变量i的值
for (int i = 0; i < 10; i++) {
    // ...
}

要查看内存内容,可以使用内存查看窗口,在该窗口中,可以输入内存的起始地址,然后查看该地址及其邻近的内存单元的内容。

5.2 高级调试技术

5.2.1 堆栈跟踪和分析

堆栈跟踪允许开发者查看函数调用的历史记录,这对于理解程序是如何从当前点到达当前位置非常有用,特别是在调试递归函数和复杂的函数调用序列时。

在EWARM调试器中,堆栈窗口会显示当前函数调用堆栈。右键点击堆栈窗口中的任何函数调用,可以将其设置为程序执行的下一个断点,这称为“堆栈回溯”。

5.2.2 性能分析和瓶颈定位

性能分析是指通过使用EWARM提供的分析工具来确定程序中运行缓慢或者资源消耗较多的部分。这可以帮助开发者优化程序,提升性能。

EWARM的性能分析器可以用来收集数据,显示函数调用的次数、花费的时间等。这可以通过在项目属性中启用性能分析器,然后执行程序并获取报告来完成。

分析报告通常会列出每个函数的调用次数和所花费的时间,这使得开发者可以快速找到可能的性能瓶颈。

在使用EWARM调试器的过程中,理解和掌握这些基本和高级调试技术对于成功诊断和解决问题是至关重要的。通过实践和深入应用,开发者可以大大提高开发效率和软件质量。

6. 硬件不依赖的仿真

6.1 仿真环境的搭建

6.1.1 虚拟硬件的配置

在硬件不依赖的仿真过程中,虚拟硬件的配置是至关重要的一步。虚拟硬件不仅提供了一个软件层面模拟真实硬件运行环境的平台,而且为开发人员提供了一个风险较低的开发和测试环境。在IAR Embedded Workbench for ARM (EWARM)环境中,虚拟硬件的配置通常涉及到以下几个关键步骤:

  1. 选择合适的仿真器 :首先需要选择一个合适的仿真器来模拟目标硬件。EWARM支持多种仿真器,如J-Link、ULINK等。在创建工程时,应根据目标芯片选择对应的仿真器,并确保仿真器驱动程序已正确安装。

  2. 设置仿真器参数 :在工程配置中,需要指定仿真器的连接参数,包括端口、速度、以及目标芯片的特定配置等。这些参数直接影响到仿真器与虚拟硬件通信的准确性和效率。

  3. 配置芯片和外设 :在虚拟硬件中,需要根据实际目标硬件配置相应的芯片型号以及外设模型。这一步骤确保了在仿真过程中可以测试到外设功能,并且验证代码对硬件的适配性。

  4. 加载启动文件和库文件 :EWARM提供了一系列的启动文件和库文件,这些文件包含了芯片的初始化代码和外设驱动的框架,对于确保仿真环境正常运行是必需的。正确加载这些文件可以确保程序能够在仿真环境中正确地初始化硬件资源。

6.1.2 仿真环境的测试和验证

一旦虚拟硬件配置完成,接下来就是对仿真环境进行测试和验证。这一步骤的目的是确保仿真环境已经按照预期搭建完成,并且可以被可靠地用于后续的开发和调试。测试和验证通常包括以下内容:

  1. 运行引导程序 :引导程序是程序运行的第一步,它负责设置系统并加载应用程序。仿真时,运行引导程序并检查是否能顺利进入程序的主循环,是验证仿真环境的第一步。

  2. 测试基础功能 :在仿真环境初始化之后,需要测试基本的输入输出功能,例如LED闪烁、按键读取等。这可以帮助开发者验证硬件抽象层(HAL)是否正确配置。

  3. 外设功能测试 :每一种外设都有其特定的功能和操作模式。开发者需要对每一种外设进行测试,例如ADC读取、定时器计时等,确保外设能按预期工作。

  4. 代码覆盖率分析 :在仿真测试的同时,可以开启代码覆盖率分析工具,它能够帮助开发者了解代码执行的完整性,从而指导后续的测试工作。

  5. 性能和资源使用分析 :虽然仿真环境与真实环境有所不同,但是它仍然可以用来分析程序的性能和资源占用情况,如内存和CPU的使用率。

6.2 仿真与实际硬件的差异

6.2.1 仿真中的潜在问题

在硬件不依赖的仿真环境中,虽然我们可以模拟大部分硬件行为,但仍存在一些潜在问题。这些问题主要与仿真环境和实际硬件之间的差异有关,具体包括:

  1. 时序问题 :仿真环境通常无法完全精确地模拟真实硬件中的所有时序,尤其是对于高速或者对时序要求严格的应用。

  2. 外设特性 :由于外设的模拟是基于软件层面实现的,因此它可能无法完全准确地反映真实硬件的物理特性,例如电流或电压的波动、温度影响等。

  3. 中断响应 :在仿真环境中,中断响应时间和优先级可能和真实硬件有所不同,这可能会导致一些依赖精确中断控制的行为出现问题。

6.2.2 硬件与仿真间的同步

为了缩小仿真与硬件之间的差异,并确保测试的准确性,开发者需要采取一些同步措施:

  1. 更新仿真模型 :随着硬件的发展,仿真模型也需要更新,以包含最新硬件的特性。

  2. 交叉验证 :在仿真测试阶段结束后,需要在实际硬件上进行交叉验证,确保程序在实际硬件上的表现和在仿真环境中的表现一致。

  3. 测试关键性能指标 :在硬件上运行时,应特别关注那些在仿真环境中可能无法充分测试的关键性能指标,如实时性能、功耗和温度等。

  4. 使用硬件抽象层 :通过使用硬件抽象层(HAL),可以提高代码在仿真环境和实际硬件之间迁移的灵活性和兼容性。

通过本章节的介绍,我们已经了解了IAR EWARM环境下仿真环境的搭建和测试验证的详细过程,以及仿真与实际硬件之间的差异和同步措施。这为开发人员提供了一个全面了解硬件不依赖仿真环境的途径,从而更加高效地进行嵌入式系统的开发和调试工作。

7. 教学视频内容概述

7.1 视频教程概览

7.1.1 视频课程结构

视频课程旨在为读者提供从基础到高级的全面指导,覆盖IAR for ARM开发环境的主要特性和功能。课程分为基础、进阶和专家三个层次,每个层次都包含一系列的视频模块,以确保内容的连贯性和完整性。

7.1.2 各章节内容简要介绍

  • 第一章 :介绍IAR for ARM开发环境的基本信息,包括软件的安装和界面布局,帮助新用户快速上手。
  • 第二章 :深入讲解如何创建工程,以及如何选择和配置目标处理器,为项目打下坚实的基础。
  • 第三章 :着重介绍项目属性和编译选项的配置方法,这对于生成高效的代码至关重要。
  • 第四章 :详细解析软件的各个设置,包括编译器、链接器和调试器,以帮助开发者更好地理解其背后的原理和应用。
  • 第五章 :指导如何使用EWARM调试器进行代码调试,包括断点设置、变量监控等高级技巧。
  • 第六章 :探讨硬件不依赖的仿真技术,如何搭建仿真环境,以及如何处理仿真与实际硬件间的差异。

7.2 学习资源与参考

7.2.1 推荐学习资料和链接

为帮助读者拓展学习资源,本课程提供了一系列的推荐链接,包括官方文档、开发社区、论坛讨论以及相关的技术博客和视频教程。

7.2.2 常见问题与解决方案集合

针对在学习过程中可能遇到的常见问题,本课程特别提供了问题集合和相应的解决方案,方便读者查阅和自我解决问题。常见问题覆盖了从安装配置到项目调试的各个方面。

代码示例和应用

为了加深理解,每个章节的视频内容都会包含至少一个实际的代码示例或者应用实例,以便于读者将理论与实践相结合,快速掌握知识点。

以下是一个视频教学中可能涉及的代码示例,用于演示如何创建一个简单的ARM项目并进行编译:

#include <stdio.h>

void main(void)
{
    printf("Hello, ARM World!\n");
}

通过上述代码示例,观众可以跟随视频指导一步步地创建项目,编译并运行代码,最终在目标硬件上看到"Hello, ARM World!"的输出结果。

在进行代码编写和调试的过程中,对于高级用户来说,理解编译器的优化设置和调试器的高级功能是提升开发效率的关键。因此,视频教程会引导观众深入了解这些内容,并实际操作,以达到最佳的学习效果。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:《IAR for ARM仿真教程》为工程师深入学习IAR开发环境在ARM架构上的仿真技术提供了详细的指导。教程覆盖了从工程创建、软件配置到实际仿真的全过程,包括新工程的建立、目标处理器的选择、项目属性配置、编译选项设置,以及使用EWARM调试器进行程序单步执行、变量观察和错误定位等。教程还包括了如何进行硬件不依赖的仿真,以及一系列教学视频,帮助开发者优化代码质量和执行效率,提高开发效率。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值