嵌入式系统导论(钱晓捷 第2版) 课件 第1-5章 嵌入式系统设计基础-STM32的GPIO_第1页
嵌入式系统导论(钱晓捷 第2版) 课件 第1-5章 嵌入式系统设计基础-STM32的GPIO_第2页
嵌入式系统导论(钱晓捷 第2版) 课件 第1-5章 嵌入式系统设计基础-STM32的GPIO_第3页
嵌入式系统导论(钱晓捷 第2版) 课件 第1-5章 嵌入式系统设计基础-STM32的GPIO_第4页
嵌入式系统导论(钱晓捷 第2版) 课件 第1-5章 嵌入式系统设计基础-STM32的GPIO_第5页
已阅读5页,还剩228页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

嵌入式系统导论课程内容第01章嵌入式系统设计基础第02章

ARMCortex-M3处理器第03章

Thumb指令系统第04章

STM32微控制器第05章

STM32的GPIO第06章

CM3异常和STM32中断第07章

STM32的USART第08章

STM32的DMA接口第09章

STM32的定时器接口第10章

STM32的模拟接口嵌入式系统导论主讲教师:第1章嵌入式系统设计基础本章内容提要1.1嵌入式系统概述

1.什么是嵌入式系统

2.嵌入式系统的技术特点

3.嵌入式系统的组成1.2嵌入式系统的开发

1.嵌入式系统的开发模式

2.嵌入式系统开发需要的软硬件

3.软件开发流程嵌入式系统产品移动终端平板电脑、智能手机信息家电智能冰箱、洗衣机、智能空调、微波炉数字电视、数码相机与数码摄像机、游戏机汽车电子车载、车控智能仪器仪表通讯设备其他Embedded什么是嵌入式系统嵌入式计算机系统简称为嵌入式系统常见的定义以应用为中心、以计算机技术为基础,软件硬件可裁剪、以适用于应用系统对功能、可靠性、成本、体积、功耗等要求严格的专用计算机系统主要的特点与具体应用系统紧密结合,很强的专用性融合计算机技术、电子技术以及应用领域的技术根据应用需求对软硬件高效设计、量体载衣嵌入式系统的技术特点硬件的特点硬件电路高度集成、体积较小低成本、低功耗软件的特点实时性和可靠性软件剪裁和固化代码高效嵌入式系统的组成结构嵌入式系统一般由4个部分组成嵌入式处理器、外围硬件设备嵌入式操作系统(可选)、用户应用程序用户应用程序嵌入式操作系统嵌入式硬件平台嵌入式处理器外围硬件设备嵌入式处理器(EmbeddedProcessor)微控制器MCU

MicrocontrollerUnit(单片机SCM)

SingleChipMicrocomputer嵌入式微处理器MPU

MicroprocessorUnit数字信号处理器DSP

DigitalSignalProcessor片上系统SoC

SystemonChip外围硬件设备半导体厂商配套常用接口电路系统基本电路 时钟、复位、供电,以及存储器等基本接口电路 通用I/O端口、通信接口、定时器、A/D等

常用支持电路

CAN总线、USB接口、存储卡接口、以太网接口开发公司提供外围器件和软件系统控制具体行业的仪器设备嵌入式操作系统工作简单、任务单一的嵌入式系统可以不用操作系统,或运行简单的监控程序实时性强、任务多样的嵌入式系统需要实时操作系统(RTOS)uC/OS-II(现在已发展为uC/OS-III)VxWorks……功能强大、任务复杂的嵌入式系统使用多任务的操作系统嵌入式Linux(完善的网络支持)安卓Android(智能终端操作系统)WindowsCE……嵌入式系统的开发人员嵌入式硬件工程师硬件设计 器件选择、PCB板设计等,使用HDL语言硬件的软件接口

Bootloader程序等,使用C与汇编嵌入式软件程序员系统程序员 嵌入式OS移植、驱动程序移植等,使用C与汇编应用程序员

应用软件开发,使用C++、java等嵌入式系统的开发模式宿主机-目标机模式宿主机:通用微型机(PC机)目标机:待开发的嵌入式系统交叉开发宿主机建立完整的开发环境交叉编译产生目标机的可执行代码通过JTAG、串口、USB接口、网络等下载到目标机远程调试软件模拟(Simulator)在线硬件仿真(ICE:In-CircuitEmulator)宿主机-目标机开发模式嵌入式系统开发需要的软硬件开发工具套件Keil微控制器开发工具集(MDK-ARM)ARMDS-5(DevelopmentStudio5)IAR系统(ARMCortex-M的嵌入式工作平台)GNU编译器集合(GCC)目标板(开发板、评估板)调试适配器(仿真器)集成开发环境IDE下的软件开发步骤创建工程项目添加工程文件选用启动代码、头文件和外设驱动库函数创建源程序文件、编写程序配置工程选项交叉编译和连接程序下载(闪存编程)使用调试仿真器将目标代码下载到闪存(或SRAM)中运行运行和调试软件开发流程嵌入式系统导论主讲教师:第2章ARMCortex-M3处理器本章内容提要2.1ARM处理器2.2Cortex-M3处理器结构2.3Cortex-M3处理器的寄存器2.4Cortex-M3处理器的存储器组织参考资料:ARM开发者网站Cortex-M3设备一般用户指南

Cortex-M3DevicesGenericUserGuide为软件开发人员提供的用户指南提供程序员模型、核心外设的详细信息、指令集的通用信息Cortex-M3技术参考手册

Cortex-M3TechnicalReferenceManual

Cortex-M3处理器产品的技术规格书(TRM)包括诸如指令时序、部分接口信息等参考资料:STM32网站编号PM0056的Cortex-M3编程手册STM32F10xxxCortex-M3programmingmanual为使用STM32的开发人员提供Cortex-M3基本知识提供编程模型、指令集和核心外设的编程知识/content/st_com/zh.html/ARM(AdvancedRISCMachines)ARM公司著名的处理器设计公司,成立于1990年总部位于英国剑桥ARM处理器ARM公司专注于设计、并不制作和销售处理器芯片授权转让设计许可、合作公司开发生产芯片ARM技术体积小、功耗少、成本低、性能高等优势基于精简指令集计算机RISC思想2.1ARM处理器ARM处理器体系结构8个版本的ARM体系结构(Architecture)版本v4开始被广泛应用,目前主要使用v7、v8结构授权厂商生产多种ARM处理器系列(family)基于不同版本的结构版本号与处理器系列(数字)并不一致例如,ARM7、ARM9、ARM11等ARMv7、v8结构使用Cortex作为ARM处理器商标面向不同应用领域划分成3种系列·Cortex-A·Cortex-R·Cortex-M2021年,ARM宣布ARMv9体系结构ARMCortex处理器Cortex-A(Application)基于ARMv7-A(ARMv8-A)体系结构用于高性能开放应用程序平台,支持操作系统Cortex-R(Real-time)基于ARMv7-R(ARMv8-R)体系结构用于实时性要求的高端嵌入式系统Cortex-M(Microcontroller)基于ARMv7-M(ARMv8-M)和ARMv6-M体系结构用于运行实时控制系统的小规模应用程序Cortex-M系列处理器广泛应用于现代微控制器产品、以及片上系统SoC和专用标准产品ASSPCortex-M3是ARM公司的第一个Cortex系列处理器Cortex-M3和Cortex-M4基于ARMv7-M体系结构Cortex-M0、Cortex-M0+和Cortex-M1

基于ARMv6-M体系结构,指令集更小Cortex-M0和Cortex-M0+针对低成本微控制器产品Cortex-M1专为FPGA应用设计用于替代传统的ARM7(甚至ARM9)处理器2.2Cortex-M3处理器结构高性能、低功耗、32位RISC处理器基于ARMv7-M结构,只执行Thumb-2指令3段指令流水线(取指-译码-执行)可嵌套向量中断控制器NVIC4GB地址空间,统一的存储器地址分配哈佛(存储)结构允许指令和数据同时访问一系列内部调试部件,支持多种调试接口(可选)存储器保护单元MPU……复杂指令集和精简指令集复杂指令集计算机CISC(CISC:ComplexInstructionSetComputer)指令丰富、程序设计方便、程序短小、执行性能高处理器硬件复杂,不易使用先进的流水线技术,导致其执行速度和性能难以进一步提高精简指令集计算机RISC(RISC:ReducedInstructionSetComputer)指令系统很简单,只有少数简单、常用的指令处理器硬件简单,比较方便地实现优化RISC技术的主要特点指令条数较少寻址方式简单面向寄存器操作指令格式规整单周期执行先进的流水线技术编译器优化……Load-Store结构Load:从主存读取数据Store:把数据写入主存Load-Store结构:只有Load和Store指令存取主存数据,其他运算指令的操作数均在寄存器中冯·诺依曼存储结构和哈佛存储结构指令存储器数据存储器哈弗结构处理器总线总线存储器指令数据冯·诺依曼结构处理器总线冯·诺依曼存储结构系统只有一个存储空间指令和数据共存于此占用不同的存储区域哈佛存储结构系统有两个存储空间一个用于存储指令一个用于存储数据Cortex-M3功能模块Cortex-M3的两个操作状态工作状态(ThumbState)Cortex-M3启动后 执行程序代码(Thumb指令)的工作状态调试状态(DebugState)通过调试程序的停止请求或者处理器调试事件 才能进入的调试状态停止执行指令,只应用于调试操作Thumb状态和Debug状态Cortex-M3的两级特权层次在工作状态时,处理器具有两级特权层次特权级(PrivilegedLevel)可以访问所有处理器资源,执行所有指令可执行异常处理程序和应用程序用户级(非特权级,UnprivilegedLevel)不能访问部分受限的存储区域和进行部分操作只能执行应用程序特权级用户级异常程序异常模式非法应用程序线程模式线程模式Cortex-M3的两种操作模式在工作状态时,处理器还具有两种操作模式异常模式(例程模式,HandlerMode)只能在特权级下,执行异常处理程序线程模式(ThreadMode)特权级和用户级下,执行应用程序复位后,处理器默认进入工作状态的特权级下的线程模式执行应用程序特权级用户级异常程序异常模式非法应用程序线程模式线程模式两级特权层次和两种操作模式2.3Cortex-M3的寄存器通用寄存器应用程序主要使用的寄存器16个,32位,名称:R0–R15R13是(堆)栈指针寄存器SP(StackPointer)R14是连接寄存器LR(LinkRegister)R15是程序计数器PC(ProgramCounter)专用寄存器程序状态寄存器PSR(ProgramStatusRegister)中断/异常屏蔽寄存器控制寄存器CONTROLCortex-M3的通用寄存器Cortex-M3的专用寄存器2.4Cortex-M3的存储器组织32位地址,支持4GB线性地址空间0x00000000–0xFFFFFFFF哈佛(存储)结构,共用存储器地址空间代码区数据区外设区处理器系统外设区等Cortex-M3的地址空间分配位带区(BitBandRegion)数据位的常规操作外设控制常要针对字中某个位(Bit)操作以字节编址的存储器地址空间中,需要3步骤1.(从外设)读取包含该位的字节数据2.设置该位为0或1、同时屏蔽其他位(不改)3.将包含该位的字节数据写入(外设)

LDRr0,=0x20000300

LDRr1,[r0] ;读取数据

ORRr1,r1,#0x4

;D2位设置为1

STRr1,[r0] ;写回结果数据位的位段操作数据位若采用位编址(每位具有一个地址)就可以直接针对这个地址读写代码会更加紧凑、执行效率更高

LDRr0,=0x22006008MOVr1,#1 ;D2位设置为1

STRr1,[r0] ;写入结果0x20000300

0x22006008

位带区地址别名映射位带区的地址映射0x20000000~0x200FFFFF

0x22000000~0x23FFFFFF

别名地址(32MB)数据区(1MB)0x40000000~0x400FFFFF

0x42000000~0x43FFFFFF

别名地址(32MB)外设区(1MB)别名地址

=位带基址

+字节偏移量×32+位号×4地址映射示例字地址0x20000300中位号2的位位段基址=0x22000000字节偏移量=0x20000300-0x20000000=0x300别名地址

=0x22000000+0x300×32+2×4

=0x22006008位号乘以4(二进制左移2位)的原因保证每个别名地址是4字节地址对齐其他3个地址不用字节偏移量乘以32(二进制左移5位)的原因一个字节8位共占用32个地址位带区和别名区关系对齐与不对齐地址访问支持不对齐地址边界的数据传输,使编译器 更自由的在存储器中安排程序数据更加节省存储空间地址边界对齐地址边界不对齐字节存储顺序多字节数据默认采用小端方式存放也支持大端方式的存储系统每个字Word是32位指令字长有16位(Thumb指令)

还有32位(Thumb-2指令)访问代码区必须对齐偶地址(PC最低位是0)大部分指令要求对齐地址访问部分指令可以支持非对齐地址访问1203340256017800地址嵌入式系统导论主讲教师:第3章Thumb指令系统本章内容提要3.1ARM指令集和Thumb指令集3.2统一汇编语言UAL3.3数据寻址3.4常用指令3.5STM32启动代码3.6开发工具MDK3.132位ARM指令和16位Thumb指令传统的ARM处理器具有两种指令执行状态32位ARM状态:所有32位指令,以获得高性能16位Thumb状态:仅16位指令,以提高代码密度很多应用程序混合使用ARM和Thumb代码ARM和Thumb指令的转换需要进行状态切换带来执行时间和代码数量的额外开销增加软件编译的复杂度没有经验的开发人员很难进行软件优化32、16位指令是指令字长是32、16位Thumb-2技术Cortex-M系列处理器的指令系统被称为Thumb包括16位Thumb指令和新的32位Thumb指令Cortex-M3/M4使用Thumb-2技术允许混合16和32位Thumb指令,无需状态切换简化软件开发,提高代码密度、效率和性能不支持32位ARM指令导致Cortex-M3无法向后兼容传统的ARM处理器不过Cortex-M3完全支持原来16位Thumb指令大多数程序使用C语言开发,转换比较简单Thumb指令系统ARM指令集的发展动态编译器支持VFPv3NEONThumb-2(可选)Thumb-2(标配)TrustZoneSIMDVFPv2Jazelle仅Thumb-2ARMv5ARMv6ARMv7A&RARMv7M3.2统一汇编语言UALUAL(Unifiedassemblylanguage)ARM和Thumb指令的通用汇编语言语法过去的语法被称为:pre-UAL最新的ARM软件开发工具已经支持UALPre-UAL目前仍被大多数开发工具接受KeilMDK-ARM中,指示符THUMB ;使用UAL语法的Thumb指令CODE16 ;使用pre-UAL语法的Thumb指令ARM汇编程序的语句格式symbolmnemonicoperand1,operand2,... ;Comments标识符助记符操作数1,操作数2,... ;注释标识符symbol必须起始于第一列(顶格)所有指令不能顶格书写标号等标识符大小写敏感指令、寄存器可全大写、全小写,不要大小写混用汇编语言的程序结构代码区:定义指令代码序列汇编后被保存在代码(CODE)存储器数据区:声明使用的数据,还可以提供初始值或常量汇编后在数据(DATA)存储器预留空间(初值)系统堆栈:在存储器中保留空间、设置栈指针SP区域指示符AREA定义存储区段(section):代码区或数据区区段名可以使用两个垂线字符括起类型:code(代码)、data(数据)属性主要是一些选项:readonly:只读(CODE区段的默认属性)readwrite:可读可写(DATA区段的默认属性)align=n:地址对齐2n分配,n=0~31noinit:说明DATA区段没有初始值或初始值为0AREA区段名{,类型}{,属性}... ;区段内容,指令或数据定义过程指示符PROC/ENDP(FUNCTION/ENDFUNC)定义过程结构(函数、子程序)可选{reglist1}是过程要保护的寄存器列表过程名 PROC[{reglist1}] ;开始

... ;过程体(指令序列)

ENDP ;结束AREAmysect,CODE,readonly,align=2MyFunctPROC ... ENDP起始执行指示符 ENTRY ... ;第一条执行的指令 ... END ;汇编语言程序结束汇编结束指示符地址对齐指示符 ALIGN{expr}不带参数设置当前位置是下一个字(4个字节)边界带参数expr对齐expr字节边界expr是2幂次方的值,例如2、4、8、……由于ARM处理器大多数情况下都要求对齐地址边界操作,所以经常需要使用ALIGN指令以保证数据和代码对齐了适合的地址边界预留存储器空间指示符SPACE伪指令预留内容是0的存储空间SPACE可以使用“%”替代FILL伪指令预留内容是value值的存储空间label是可选的标号expr是分配存储器空间的大小(字节为单位)value在存储空间预留的值,无表示是0valuesize是value的字节数(1、2或4), 无表示是1{label}SPACEexpr{label}FILLexpr{,value{,valuesize}}数据定义指示符DC(DefineConstant),在存储单元定义固定初值数据区域分配的静态数据,类似共享变量DCB/DCW/DCD/DCQ依次以1/2/4/8字节分配空间赋初值expr(可以是多个数值)DCB的初值expr还可以是括起的字符串没有U选项,则要求相应地址对齐U选项不要求地址对齐,但有风险、慎用{label}DCBexpr{,expr}{label}DCW{U}expr{,expr}{label}DCD{U}expr{,expr}{label}DCQ{U}expr{,expr}常量表达十六进制数像C语言一样使用0x前缀字符用单引号,字符串用双引号字符和字符串中都可以是C语言标准的转义符布尔常量 逻辑真→{TRUE},逻辑假→{FALSE}符号常量声明使用等价EQU指示符

STACK_TOPEQU0x00000400指令中,常量要使用“#”作为前导字母

MOVR0,#0x12 ;R0=0x12立即数寻址

MOVR0,#0x12 ;R0=0x12在16位Thumb指令中,立即数只能是8位数据32位指令MOVW的立即数超过8位、不超过16位32位指令编码无法直接表达32位立即数:

MOVR5,#0X1FF400 ;=>AssemblyERRORUAL语法支持MOV32伪指令: MOV32{cond}Rd,expr ;一般格式 MOV32R5,#0X1FF400 ;示例MOV32伪指令实质是使用MOV和MOVT指令组合32位数据的赋值:使用伪指令LDR

LDRRi,=val ;一般格式

LDRR5,=0X1FF400 ;示例实际上,这里没有立即数,而是类似:

LDRR5,[PC,#18] ;从[PC+18]获得数据数据保存在被汇编程序事先创建的存储区域(假设是当前PC的偏移位置18处)该伪指令也用于获得指针(变量地址) MOVRi,#val ;实际生成的MOV指令

LDRRi,[PC,#n] ;或者生成的LDR指令3.3数据寻址立即数寻址:从指令的机器代码中获得数据数据本身直接编码在指令的机器代码中,指令执行时可以立即从机器代码中获得立即数多以常量形式表达,用井号“#”作为前导寄存器寻址:从处理器的寄存器中访问数据存储器寻址:从主存储器中访问数据寄存器寻址通用寄存器13个:R0~R12R13(SP)和R14(LR)多数情况下也可以使用但由于他们的特定含义和作用,要小心使用R15(PC),大多数指令不能使用它因为它将改变程序流程、非常危险改变流程,应该使用跳转指令(B、BL、BX等)寄存器移位寻址ARM和Thumb-2指令的特有寻址方法对第3个寄存器操作数实现移位操作移位(shift)操作有5种LSL(LogicalShiftLeft),逻辑左移LSR(LogicalShiftRight),逻辑右移ASR(ArithmeticShiftRight),算术右移ROR(RotateRight),循环右移RRX(RotateRighteXtended),循环右移扩展即带进位标志的右移 ANDR0,R1,R2,LSL#3 ;R0←R1&(R2<<3)寄存器移位寻址的MOV指令只有移位、没有其他操作的MOV指令寄存器在UAL语法中,直接使用移位关键字为助记符寄存器移位寻址的MOV指令UAL语法MOVRd,Rn,LSLshiftMOVRd,Rn,LSRshiftMOVRd,Rn,ASRshiftMOVRd,Rn,RORshiftMOVRd,Rn,RRXLSLRd,Rn,shiftLSRRd,Rn,shiftASRRd,Rn,shiftRORRd,Rn,shiftRRXRd,Rn访问(存取)存储器操作数RISC处理器采用Load-Store结构存储器操作指令只有两种读取存储器操作数LoadtoRegister

LDRRi,{expr}存储存储器操作数StorefromRegister

STRRi,{expr}操作数expr有多种形式(寻址方式)存储器操作数的寄存器间接寻址

LDRRi,[Rj] ;Ri=[Rj]expr是“[Rj]”形式存储器地址保存在某个通用寄存器中ARM不支持直接寻址Indirectaddressing存储器操作数的寄存器偏移寻址LDRRi,[Rj,#offset] ;①Ri=[Rj+offset]LDRRi,[Rj,Rk] ;②Ri=[Rj+Rk]LDRRi,[Rj,Rkshift#n] ;③Ri=[Rj+(Rkshift#n)]存储器地址由通用寄存器内容加上一个位移量(Displacement)、也称偏移量(Offset)组成位移量可以来自①立即数(通常在4KB范围内)②寄存器③寄存器移位(LSL、LSR、ASR、ROR、RRX)Indirectaddressingwithdisplacement存储器操作数的寄存器后偏移寻址

LDRRi,[Rj],#offset ;Ri=[Rj],Rj=Rj+offset

LDRRi,[Rj],Rk ;Ri=[Rj],Rj=Rj+Rk

LDRRi,[Rj],Rkshift#n ;Ri=[Rj],Rj=Rj+(Rkshift#n)这种寻址方式的指令具有两个功能:先用[Rj]间接寻址访问存储器内容赋值Ri之后将Rj加上位移量更新Rj的地址Indirectaddressingwithpost-displacement存储器操作数的寄存器前偏移寻址

LDRRi,[Rj,#offset]! ;Rj=Rj+offset,Ri=[Rj]

LDRRi,[Rj,Rk]! ;Rj=Rj+Rk,Ri=[Rj]

LDRRi,[Rj,Rkshift#n]! ;Rj=Rj+(Rkshift#n),Ri=[Rj]这种寻址方式的指令具有两个功能:先将Rj加上位移量更新Rj的地址然后用[Rj]间接寻址访问存储器内容赋值RiIndirectaddressingwithpre-displacement3.4Cortex-M3的指令系统存储器访问指令,批量32位数据传输指令通用数据处理加减运算、逻辑运算以及硬件除法等指令乘法指令饱和运算指令位操作指令跳转、条件分支和功能调用指令系统控制、操作系统支持等指令ARM处理器的指令格式花括号“{}”表示可选opcode指令操作码:使用助记符表示Rd目的寄存器存储器读(除批量读)指令,是读入数据的寄存器存储器写(除批量存)指令,该寄存器内容写入存储器Rn(第1个源操作数)寄存器{,operand2}第2个源操作数非存储器访问指令支持寄存器移位寻址存储器访问指令支持间接、偏移和前偏移、后偏移寻址opcode{S}{cond}Rd,Rn{,operand2}S后缀:更新APSR没有S后缀:不影响APSR中的标志有S后缀:更新APSR内容opcode{S}{cond}Rd,Rn{,operand2}313029282726:252415:108:0NZCVQICI/ITTICI/IT异常号APSREPSRIPSRPSR或xPSR应用程序状态寄存器APSRN(Negative)负数标志有符号整数的结果是负数设置N标志为1结果是正数或0设置N标志为0Z(Zero)零标志执行结果是0(两数比较相等)设置为1,否则为0C(Carry)进位标志对无符号相加,无符号溢出(进位)设置为1对无符号相减,结果没有借位设置为1,借位为0V(Overflow)溢出标志对有符号整数加减,当有符号溢出时设置为1ApplicationProgramStatusRegister{cond}后缀:条件执行没有cond后缀:总是执行有cond后缀:条件成立,执行条件不成立,不执行opcode{S}{cond}Rd,Rn{,operand2}这样,大多数指令都成了条件执行指令条件cond后缀标志含义EQZ=1Equal,相等NEZ=0NotEqual,不相等MIN=1Minus,负数PLN=0Plus,正数VSV=1oVerflowSet,溢出VCV=0oVerflowClear,未溢出CSHSC=1CarrySet,进位HigherorSame,高于或等于CCLOC=0ClearCarry,无进位Lower,低于条件cond(续)后缀标志含义HIC=1ANDZ=0unsignedHigher,无符号高于LSC=0ORZ=1unsignedLowerorSame,无符号低于或等于GEN=VsignedGreaterthanorEqual,有符号大于或等于LTN≠VsignedLessThan,有符号小于GTZ=0ANDN=VsignedGreaterThan,有符号大于LEZ=1ORN≠VsignedLessthanorEqual,有符号小于或等于处理器内的传送指令寄存器之间传送、传送立即数到寄存器

MOV{S}{cond}Rd,Operand2 ;寄存器传送

MOV{cond}Rd,#imm16 ;立即数传送

MVN{S}{cond}Rd,Operand2 ;源操作数取反后传送给目的寄存器(取反)专用寄存器与通用寄存器之间传送

MRS{cond}Rd,spec_reg ;专用寄存器读取

MSR{cond}spec_reg,Rn ;专用寄存器写入存储器访问指令存储器读写

LDR{cond}Rd,Rn,Operand2 ;存储器读

STR{cond}Rd,Rn,Operand2 ;存储器写存储器批量读写

LDM{cond}Rn{!},reglist ;存储器批量读

STM{cond}Rn{!},reglist ;存储器批量写堆栈操作指令

PUSH{cond}reglist

POP{cond}reglist生成相对PC的地址

ADR{cond}Rd,label ;Rd=label的地址label是标号汇编程序也支持label加减一个数字或者[PC,#number]形式加减运算、逻辑运算指令ADD(加法)、ADC(带进位加法)SUB(减法)、SBC(带进位减法)RSB(反转减法,ReverseSubtract)

oprand2–Rn→RdAND(逻辑与)、ORR(逻辑或)、EOR(逻辑异或)BIC(逻辑与非,operand2求反后与Rn相逻辑与)ORN(逻辑或非,operand2求反后与Rn相逻辑或)op{S}{cond}{Rd,}Rn,Operand2

;Rnopoprand2→Rdop{cond}{Rd,}Rn,#imm12;仅ADD和SUB比较测试指令 CMP{cond}Rn,Operand2 ;Rn-oprand2,类似SUBS、但不保存结果

CMN{cond}Rn,Operand2;Rn+oprand2,类似ADDS、但不保存结果

TST{cond}Rn,Operand2;Rn与oprand2,类似ANDS、但不保存结果

TEQ{cond}Rn,Operand2 ;Rn异或oprand2,类似EORS、但不保存结果移位指令 op{S}{cond}Rd,Rm,Rs op{S}{cond}Rd,Rm,#n RRX{S}{cond}Rd,Rm操作码op指逻辑左移LSL、逻辑右移LSR算术右移ASR、循环右移RORRs指保存移位位数的寄存器,只用最低字节n是移位位数乘除法指令

MUL{S}{cond}{Rd,}Rn,Rm ;乘法:Rd=(Rn×Rm)低32位

MLA{cond}Rd,Rn,Rm,Ra ;乘加:Rd=(Rn×Rm)低32位+Ra

MLS{cond}Rd,Rn,Rm,Ra ;乘减:Rd=Ra–(Rn×Rm)低32位

SDIV{cond}{Rd,}Rn,Rm ;有符号数除法:Rd=Rn÷Rm

UDIV{cond}{Rd,}Rn,Rm ;无符号数除法:Rd=Rn÷Rm长乘法指令 UMULL{cond}RdLo,RdHi,Rn,Rm;无符号数64位长乘法:(RdHi,RdLo)=Rn×Rm

SMULL{cond}RdLo,RdHi,Rn,Rm;有符号数64位长乘法:(RdHi,RdLo)=Rn×Rm

UMLAL{cond}RdLo,RdHi,Rn,Rm;无符号数64位长乘加:

(RdHi,RdLo)=(RdHi,RdLo)+Rn×Rm SMLAL{cond}RdLo,RdHi,Rn,Rm;有符号数64位长乘加:

(RdHi,RdLo)=(RdHi,RdLo)+Rn×Rm跳转调用指令

B{cond}label ;跳转到label

BL{cond}label ;跳转并连接到label ;调用label子程序(下条指令地址存入R14)

BX{cond}Rm ;跳转到Rm指定的地址

;子程序返回一般用“BXLR“指令

BLX{cond}Rm ;调用Rm指定地址的子程序 (下条指令地址存入R14)分支指令

CBZRn,label ;Rn等于0跳转到Label

CBNZRn,label ;Rn不等于0跳转到Label

IT{x{y{z}}}cond ;分支(If-Then)条件指令

;cond说明IT块中第1条指令执行的条件

;x、y和z依次说明IT块中第2、3和4条指令执行的条件开关T或E:

;如果是T(Then)表示条件成立执行

;否则是E(Else)表示条件不成立执行。其他指令

NOP{cond} ;空操作指令

BKPT#imm ;断点(Breakpoint)指令

;引起处理器进入调试状态

SVC{cond}#imm ;引起管理员调用SVC ;(SupervisorCall)异常

WFI{cond} ;等待中断WaitForInterrupt ;暂停执行直到非屏蔽中断产生并响应、

;被PRIMASK屏蔽的中断被挂起(pending)、

;或者有调试(DebugEntry)请求3.5STM32启动代码(StartupCode)用来初始化硬件电路为高级语言编写的应用程序做好运行前准备通常采用汇编语言编写是处理器上电复位时的程序运行入口点启动代码与使用的处理器和硬件设备有关过程大致相同,主要是:堆和栈的定义及初始化异常(中断)向量表的建立提供默认异常(中断)处理程序调用函数配置时钟系统最终转向main函数开始执行应用程序Cortex-M3启动方式通过boot引脚设置,有3种启动方式方式1:SRAM区中断向量表定位于SRAM区起始地址和PC指针是0x20000000方式2:Flash区中断向量表定位于Flash区起始地址和PC指针是0x80000000方式3:Bootloader区中断向量表定位于内置Bootloader区起始地址必须存放栈顶指针第2个地址必须存放复位入口地址STM32启动代码文件在STM32库V3.5.0中,启动代码的文件名是startup_stm32f10x_??.s“??”表示不同类型STM32微控制器例如,“xl”,指超高密度容量的微控制器芯片启动代码基本一样,分成4个片段:(1)定义堆和栈的大小(2)定义中断向量表(3)默认的中断处理程序(4)用户初始化堆和栈分析startup_stm32f10x_hd.sSTM32启动代码1:定义堆和栈的大小Stack_SizeEQU0x00000400 ;栈大小为0x400

AREASTACK,NOINIT,READWRITE,ALIGN=3 ;定义栈STACK,未初始化、可读可写、8字节对齐Stack_MemSPACEStack_Size ;为栈分配空间__initial_sp ;栈地址标号Heap_SizeEQU0x00000200 ;堆大小为0x200

AREAHEAP,NOINIT,READWRITE,ALIGN=3__heap_base ;堆基地址标号Heap_MemSPACEHeap_Size ;为堆分配空间__heap_limit ;堆容量地址标号

PRESERVE8 ;指定当前堆栈8字节对齐

THUMB ;使用32位Thumb指令、支持UAL汇编语言STM32启动代码2:定义中断向量表

AREARESET,DATA,READONLY ;定义复位(RESET)区、数据段,只读

EXPORT__Vectors

;中断向量地址(程序地址)

EXPORT__Vectors_End

EXPORT__Vectors_Size

;EXPORT定义全局标号,表示可在其他文件中使用__Vectors DCD__initial_sp ;地址0x00保存堆栈指针

DCDReset_Handler ;地址0x04保存复位地址

DCDNMI_Handler ;地址0x08保存非屏蔽地址

…… ;略(所有中断向量地址)STM32启动代码3:默认中断处理程序

AREA|.text|,CODE,READONLY

;代码段、只读Reset_HandlerPROC ;复位处理程序

EXPORTReset_Handler[WEAK] ;[WEAK]选项:若其他文件也定义该标号(函数) ;连接时使用其他文件的地址;否则以此处地址连接

IMPORT__main IMPORTSystemInit ;IMPORT表示标号在其他文件中定义

STM32启动代码3:默认中断处理程序(续1) LDRR0,=SystemInit ;把SystemInit的地址给RO

BLXR0 ;调用SystemInit,初始化STM32的时钟系统

LDRR0,=__main ;把__main的地址给RO

BXR0 ;跳转到__main标号

ENDP注1:SystemInit定义在system_stm32f10x.c中注2:__main指向C/C++初始化子程序(初始化堆和栈等),最后跳转到C语言程序的main函数STM32启动代码3:默认中断处理程序(续2) ;默认异常(中断)处理程序(无限循环、可被修改)NMI_HandlerPROC ;NMI处理程序

EXPORTNMI_Handler[WEAK] B. ;“.”代表当前指令地址 ;“B

.”类似C语言的while(1)语句,无限循环

ENDP …… ;略

ALIGN ;按照要求进行对齐注3:V3.5.0前启动代码没有调用SystemInit,需要用户在应用程序主函数main中首先调用STM32启动代码4:用户初始化堆和栈

IF:DEF:__MICROLIB ;如果定义了__MICROLIB则为真,否则为假

EXPORT__initial_sp ;为真,让外部文件使用定义的堆和栈地址

EXPORT__heap_base EXPORT__heap_limitMicroLib是为基于ARM嵌入式应用编写的一个高度优化的C语言库,提供了更紧凑的代码大小、可应用于无操作系统支持的情况,不支持文件I/O和宽字符、有些函数速度略慢MicroLib的选择(目标选项)STM32启动代码4:用户初始化堆和栈(续)

ELSE

;为假,使用默认的C语言运行库

IMPORT__use_two_region_memory EXPORT__user_initial_stackheap__user_initial_stackheap LDRR0,=Heap_Mem ;堆起始地址

LDRR1,=(Stack_Mem+Stack_Size) ;栈大小

LDRR2,=(Heap_Mem+Heap_Size) ;堆大小

LDRR3,=Stack_Mem ;栈顶指针

BXLR ALIGN ENDIF END3.6开发工具MDK-ARM流行的Cortex-M处理器商业开发平台包括各种组件:μVision集成开发环境(IDE)ARM编译工具(C/C++编译器、汇编器、连接器等)调试器和模拟器RTX实时操作系统核心超过1000个微控制器的参考启动代码Flash编程算法程序示例KeilMicrocontrollerDevelopmentKitforARM基于MDK的一般开发流程μVision集成界面MDK安装目录MDK-ARM5安装的Keil目录UV4子目录(μVision5的文件)ARM子目录(主要文件)ARMCC\bin是主要的程序文件armcc.exe:C/C++编译程序armasm.exe:汇编程序armlink.exe:连接程序fromelf.exe:下载生成程序BIN是动态链接库DLLHlp保存各种帮助文件Pack驱动程序包(库)的目录软件包程序目录Pack目录(驱动程序文件)ARM是ARM公司的基本驱动程序Keil保存有ST公司的驱动程序 含启动代码文件、外设驱动程序的头文件和源程序文件等……创建应用程序1.新建项目:Project–NewμVisionProject选择或新建一个目录,输入项目文件名选择目标微控制器(ST公司的STM32F103ZE)根据项目需求,选择相应的驱动程序修改目标名、组名,或增加新组创建应用程序2.新建源程序文件:File–New编辑源程序代码、保存文件加入项目(AddExistingFilestoGroup)intmain(){}创建应用程序3.构建应用程序:Project–BuildTarget编译、汇编和连接4.调试应用程序:

Debug–Start/StopDebugSession目标选项的调试配置:OptionforTarget使用模拟器UseSimulator启动时载入应用程序

LoadAplicationatStartup运行至主函数Runtomain()目标选项的调试配置【例3-1】简化STM32微控制器启动代码-1Stack_Size EQU0x00000400

AREASTACK,NOINIT,READWRITE,ALIGN=3

SPACEStack_Size__initial_sp

THUMB

AREARESET,DATA,READONLY

DCD__initial_sp;设置栈指针

DCDReset_Handler;设置复位程序入口

AREA|.text|,CODE,READONLY【例3-1】简化STM32微控制器启动代码-2Reset_HandlerPROC

movr0,#10

;R0=10

addr1,r0,r0

;R1=R0+R0

addr1,r1,r1,lsl#2 ;R1=R1+R1×4=R0×10=100

mulr2,r0,r0

;R3=R0×R0=100

B.

;无限循环

ENDP

END不要选择“运行至主函数Runtomain()”单步调试:Step单步通过:StepOver【例3-2】独立的汇编语言程序-1 THUMB ;使用THUMB指令和UAL语法 AREARESET,DATA,READONLY ;数据区、只读 DCD0x20000460 ;设置栈指针 DCDstart ;设置起始执行位置 AREA|.text|,CODE,READONLY ;代码区、只读 ENTRY ;程序开始执行点start movr1,#num ;传送求和个数给R1 ldrr2,=array ;获取数组地址给R2 movr0,#0 ;使用R0进行累加求和,初始为0【例3-2】独立的汇编语言程序-2again ldrr3,[r2],#4 ;取数组元素值给R3,然后R2增量4 addr0,r0,r3 ;求和 subsr1,r1,#1 ;个数减1 bneagain ;个数大于0,继续求和 ldrr4,=sum strr0,[r4] ;保存求和R0到结果变量sum b. ;无限循环【例3-2】独立的汇编语言程序-3 AREA|.rodata|,DATA,READONLY,ALIGN=3 ;数据区、只读array dcd3,-17,26,-13,101 ;数组num equ(.-array)/4 ;求得数组元素个数 AREA|.data|,DATA,READWRITE,ALIGN=3 ;数据区、可读写sum dcd0 ;保存求和结果 END“运行(Run)”命令执行“停止(Stop)”命令结束【例3-2】MDK模拟运行结果嵌入式系统导论主讲教师:第4章STM32微控制器本章内容提要4.1STM32微控制器结构4.2STM32微控制器开发4.3复位与时钟控制(RCC)4.1STM32微控制器结构基于Cortex-M3/M4设计微控制器产品的公司意法半导体(STMicroelectronics)爱特梅尔(Atmel)三星(Samsung)……微控制器包含许多不同的模块处理器核心存储器时钟电路、系统总线外设(硬件单元):I/O接口、通信接口、定时器、ADC和DAC,……基于Cortex-M3的微控制器STM32微控制器应用类别STM32系列产品主要特点(核心,时钟频率等)高性能STM32F2系列STM32F4系列STM32F7系列STM32H7系列Cortex-M3、120MHz,基础产品线Cortex-M4+FPU、180MHz,基础或先进产品线Cortex-M7+FPU、216MHz,极高性能双核Cortex-M7+M4FPU、480MHz,极高性能主流STM32F0系列STM32G0系列STM32F1系列STM32F3系列STM32G4系列Cortex-M0、48MHz,入门级,适用于成本敏感的应用Cortex-M0+、64MHz,新一代入门级、首个8引脚STM32Cortex-M3、72MHz,基础产品线Cortex-M4+FPU、72MHz,具有16位ADC等Cortex-M4+FPU、170MHz,具有数学加速器等超低功耗STM32L0系列STM32L1系列STM32L4系列STM32L4+系列STM32L5系列STM32U5系列Cortex-M0+、32MHz,低功耗模式+RAM+RTCCortex-M3、32MHz,低功耗模式+RAM+RTCCortex-M4+FPU、80MHz,低功耗模式+RAM+RTCCortex-M4+FPU、80MHz,低功耗模式+RAM+RTCCortex-M33+FPU、110MHz,低功耗模式+RAM+RTCCortex-M33+FPU、160MHz,低功耗模式+RAM+RTCSTM32微控制器STM32F0系列:入门级MCU、基于CM0STM32F1系列:主流MCU、基于CM3STM32F2系列:高性能MCU、基于CM3STM32F3系列:具有DSP和FPU的MCU、基于CM4STM32F4系列:具有DSP和FPU的高性能MCU、基于CM4STM32L0系列:低功耗MCU、基于Cortex-M0+STM32L1系列:低功耗MCU、基于Cortex-M3……CM:Cortex-M,CM3:Cortex-M3,CM4:Cortex-M4STM32F10x系列微控制器STM32F10xSTM32F1系列微控制器STM32F10024MHz,具有马达控制器和HDMICEC功能STM32F10136MHz,多达1MBFlash存储器STM32F10248MHz,支持USB接口STM32F10372MHz,多达1MBFlash存储器支持马达控制、USB和CAN接口STM32F105/10772MHz,支持以太网、CAN和USB2.0OTG接口STM32F10xSTM32F103系统结构哈佛存储结构独立的指令总线(I-bus),连接Flash总线矩阵(BusMatrix)提供多种数据通道数据总线(D-bus)系统总线(System)DMA和SRAM通过AHB-APB桥连接2个先进外设总线APBAPB2可全速工作于72MHz,但APB1限制在36MHz外设连接在APB上STM32F103系统结构STM32F103的主要外设通过APB连接外设和I/O接口,共同具有的外设:通用和复用功能I/O(GPIO和AFIO)通用定时器(TIMx)实时时钟(RTC)(Cortex处理器自带系统时间片时钟SysTick)看门狗(WatchDog)通用同步异步接收发送器(USART)串行外设接口(SPI)I2C接口(I2C)模拟数字转换器ADC(以及温度传感器)更高性能的STM32微控制器还支持更多外设STM32F10x存储器结构4GB线性地址空间,全部统一编排地址4GB空间分成8个512MB(0.5GB)区域代码区(Code),起始于0x00000000Flash组成,程序代码起始于0x08000000SRAM区,起始于0x20000000型号不同、容量不同:16KB、48KB、64KB等

外设区,起始于0x40000000外设的寄存器访问地址外部区,起始于0x600000001GB用于外部RAM,1GB用于外设系统外设区,起始于0xE0000000STM32地址空间4.2STM32微控制器开发基于目标机-宿主机的交叉编译系统在集成开发环境(MDK)的支持下进行通常采用高级语言(C/C++语言)编写Cortex微控制器软件接口标准CMSIS为基于Cortex-M处理器的系统定义了标准软件接口是Cortex-M处理器与供应商无关的硬件抽象层可实现与处理器和外设间的一致且简单的软件接口从而简化软件的重用,便于初学者使用、降低成本目前,CMSIS包含以下组件CMSIS-Core:处理器与外围寄存器间的接口CMSIS-RTOS:实时操作系统的标准化编程接口CMSIS-DSP:60多种DSP函数库CMSIS-SVD:系统视图描述的XML文件CortexMicrocontrollerSoftwareInterfaceStandard基于CMSIS-Core的开发结构https:///cmsisCMSIS-Core的标准化工作标准化处理器外设定义标准化访问处理器特性的访问函数(有些文献称之为应用程序接口API)标准化访问特殊指令的函数标准化系统异常处理程序的函数名标准化系统初始化的函数(系统初始化使用“SystemInit()”函数)……CortexMicrocontrollerSoftwareInterfaceStandardCMSIS-Core使用很多针对Cortex-M的软件产品都兼容CMSISCMSIS文件被集成在设备驱动程序库中有些文件是ARM提供、对所有微控制器厂商通用有些文件与厂商设备相关的MDKV5开发平台,用户应用程序需要:startup_<device>.s(startup_stm32f10x_hd.s) 设备的启动代码,包括复位处理程序和异常向量system_<device>.c(system_stm32f10x.c)

设备的基本配置文件,包括时钟和总线设置<device>.h(stm32f10x.h) 用户代码需要的包含文件,用于访问设备嵌入式应用程序的开发方式针对外设寄存器直接编程需要详细掌握各个寄存器、费时耗力但能够深入理解原理,通常代码简洁高效适合C51等比较简单的8位单片机(微控制器)基于厂商提供的驱动程序库进行开发简单快捷、兼容性好、便于移植,但代码略多32位STM32微控制器结构比较复杂直接从寄存器入手会很困难建议初学者从驱动程序库入手逐渐深入到寄存器编程STM32驱动程序库(标准外设固件库)ST公司为使用STM32提供的函数接口开发人员通过调用库函数配置STM32寄存器STM32库是以函数源代码形式提供的函数接口库函数是直接对寄存器编程非常好的实例通过阅读学习这些官方库函数不仅能够深入理解STM32工作原理同时也是进一步熟练掌握C语言的极佳机会直接对寄存器编程,也可利用其头文件STM32F10xStandardPeripheralsFirmwareLibrarySTM32库-基本代码文件stm32f10x.hSTM32寄存器地址、结构体类型定义的底层头文件使用STM32库的应用程序都要引用(包含)该文件system_stm32f10x.c(system_stm32f10x.h)定义核心时钟变量、设置系统时钟和总线时钟等的源程序文件startup_stm32f10x_??.s启动文件,“??”表示不同类型STM32微控制器MDKV5通过“运行环境管理”添加到项目中STM32-外设驱动程序文件StdPeriph_Driver\src子目录驱动程序的源文件stm32f10x_ppp.cStdPeriph_Driver\inc子目录驱动程序的头文件stm32f10x_ppp.hMDKV5通过“运行环境管理”添加到项目中STM32标准外设名称-1缩写ppp

外设名称adcbkpcanceccrcdacdbgmcudmaextiflashfsmcA/D转换器备份寄存器CAN控制器局域网消费电子控制CRC计算单元D/A转换器MCU调试模块DMA控制器外部中断/事件控制器闪存灵活的静态存储器控制器STM32标准外设名称-2缩写ppp

外设名称gpioi2ciwdgpwrrccrtcsdiospitimusartwwdg通用I/O端口I2C总线接口独立看门狗电源控制复位和时钟控制器实时时钟SD存储卡接口SPI串行外设接口定时器通用同步异步收发器窗口看门狗C语言的数据类型ARM处理器C数据类型C99标准位数Bytecharint8_tuint8_t8Halfwordshortint16_tuint16_t16Wordint,longint32_tuint32_t32Doublewordlonglongint64_tuint64_t64intN_t有符号整数,uintN_t无符号整数C语言的位操作

a&=~(1<<6);//位与实现复位

//将整型变量a的D6位清零、其他位不变

a|=(1<<6);//位或实现置位

//将整型变量a的D6位置位、其他位不变

a^=(1<<6);//位异或实现求反

//将整型变量a的D6位取反、其他位不变运算符含义示例(假设为char类型)&位与0x69&0x55→0x41|位或0x69|0x55→0x7D~位非~0x69→0x96^位异或0x69^0x55→0x3CI/O接口和外设的访问外设单独编排地址主存空间I/O空间FFFFF0FFFF主存部分I/O部分存储器空间00000FFFFF外设与存储器统一编址外设寄存器的访问I/O接口寄存器通过存储器地址访问C语言使用指针访问这些外设寄存器“volatile”类型修饰符必不可少volatile说明的变量表示是随时可能发生变化的每次操作需要直接访问地址单元获取最新的数据编译器不能进行编译优化外设寄存器的访问都需要进行如此限定

/*定义*/#defineGPIOA_CRL(*((volatileunsignedlong*)(0x40010800)))

/*使用*/GPIOA_CRL=0;外设寄存器的结构类型外设具有多个寄存器可以定义成为结构类型每个寄存器是结构成员定义结构体变量(指针)通过结构成员访问寄存器/*定义*/typedef

struct{__IOuint32_tCRL;__IOuint32_tCRH;__IOuint32_tIDR;__IOuint32_tODR;__IOuint32_tBSRR;__IOuint32_tBRR;__IOuint32_tLCKR;}GPIO_TypeDef;/*使用*/

GPIO_TypeDef

GPIOx;

GPIOx.CRL=0;

GPIO_TypeDef*GPIOx;

GPIOx->CRL=0;#define__IOvolatile外设基地址的定义定义外设基地址后,外设 被定义为指向这个基地址的结构类型指针#definePERIPH_BASE((uint32_t)0x40000000)...#defineAPB2PERIPH_BASE(PERIPH_BASE+0x10000)...#defineGPIOA_BASE(APB2PERIPH_BASE+0x0800)#defineGPIOA((GPIO_TypeDef*)GPIOA_BASE)该方法应用于微控制器驱动程序库中4.3复位和时钟控制(RCC)为了让STM32微控制器工作,需要提供电源电源上电复位后,接着就需要提供工作时钟为了降低功耗,需要对时钟进行灵活控制所以,STM32设计的时钟系统非常复杂所有振荡器、PLL、总线配置等属于

复位和时钟控制(RCC)(ResetandClockControl)电源控制(PWR)系统复位后,微控制器默认处于运行模式需要节省能耗时,进入低功耗模式睡眠模式(Sleep

Mode):CPU时钟关闭,所有外设(包括Cortex-M3核心外设)保持运行停止模式(Stop

Mode):基于CPU时钟关闭的睡眠模式、再关闭外设时钟备用模式(Standby

Mode):基于睡眠模式,再停止1.8V主电源,微控制器处于最低功耗状态 (备用模式也

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论