嵌入式复习提纲
文章目录
- 嵌入式复习提纲
- 考试详情
- 第1章 嵌入式系统概述
- 1.1 什么是嵌入式系统
- 1.2 嵌入式处理器
- 性能指标*
- 分类*
- 1.3 嵌入式操作系统
- 特点*
- 常见的嵌入式实时操作系统*
- 第2章
- 2.1 ARM简介
- 2.1.1 精简指令集计算机(RISC)*
- 科普拓展(可忽略此段)
- 2.1.2 常用ARM处理器*
- 2.2 ARM7TDMI
- 2.2.1 后缀字母意义*(此段考简答)
- 2.2.2 三级流水线*
- 2.3 ARM功能框图
- 2.4 ARM处理器的状态*(必考,重点强调)
- 2.5 ARM处理器模式*(必考,可能简答)
- 2.6 ARM内部寄存器
- 2.6.1ARM状态下的五个重要寄存器*
- 2.7 CPSR-当前程序状态寄存器*
- 2.7.1CSPR寄存器的格式
- 2.8 异常优先级*
- 异常优先级*
- 第三章
- 第四章
- 4.1 LPC2000系列ARM简介
- 特性*(必考)
- 4.3系统启动代码介绍
- 4.3.1Bootloader*
- 4.4 系统控制模块
- 4.4.2时钟系统
- 4.4.3 晶体振荡器
- 4.4.4 复位
- 4.4.5 唤醒时钟
- 4.4.6 锁相环PLL
- 4.4.6.2.频率计算
- 4.4.6.3确定PLL设定过程
- 4.4.6.4PLL设置举例:*
- 4.4.6.5寄存器描述:
- 4.4.7 VPB分频器
- 4.4.7.1VPB设置示例:*
- 4.5 存储器
- 4.7 引脚连接模块
- 4.7.1 PINSEL寄存器
- 4.7.2PINSEL应用示例**
- 4.8 GPIO
- 4.8.2 GPIO寄存器
- 4.8.3 GPIO使用注意事项
- 4.8.4GPIO相关寄存器描述
- 4.8.5 GPIO应用示例(程序题)***
- 4.8.5.3按键控制蜂鸣器,(可能程序题)***
- 4.9 中断向量控制器
- 4.9.1 中断分类:
- 4.9.2 VIC寄存器描述
- 4.9.3 中断处理
- 4.11定时器0和定时器1
- 4.11.1定时器方框图
- 4.12SPI接口
- 4.12.2SPI总线配置
- 4.13 I^2^C接口
- 4.13.1 I^2^C总线上的位传输
- 4.14 UART
- 4.15 A/D转换器
- 4.16 看门狗(可能出简答)
- 看门狗示例程序
- 第五章
- 5.1最小系统
- 5.1.1框图
- 5.1.6完整的最小系统
- 六、最后附上考试可能考的程序题***
考试详情
- 时间:6月6日13:30-15:30
- 地点:1A205
题型 | 数量 | 范围 |
---|---|---|
选择题 | 10X2’ - | |
填空题 | 20X1’ | - |
判断题 | don’t know | - |
简答题 | 4X5’ | - |
程序题 | 12’+8’ | - |
第1章 嵌入式系统概述
-本章主要考小题
1.1 什么是嵌入式系统
- 概念:
嵌入式系统(Embedded system),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”,嵌入式系统是用来控制或者监视机器、装置、工厂等大规模设备的系统。- 从技术的角度定义:
以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 - 从系统的角度定义:
嵌入式系统是设计完成复杂功能的硬件和软件,并使其紧密耦合在一起的计算机系统。术语嵌入式反映了这些系统通常是更大系统中的一个完整的部分,称为嵌入的系统。嵌入的系统中可以共存多个嵌入式系统
- 从技术的角度定义:
-
与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务。由于嵌入式系统只针对一项特殊的任务,设计人员能够对它进行优化,减小尺寸降低成本。嵌入式系统通常进行大量生产,所以单个的成本节约,能够随着产量进行成百上千的放大
1.2 嵌入式处理器
性能指标*
-P4页
- 四个指标
- 尺寸
- 能耗
- 价格
- 性能
分为以下几类:
- 注重嵌入式处理器的尺寸、能耗和价格
应用于PDA等不注重计算的设备; - 注重嵌入式处理器的性能
应用于路由器等计算密集型的设备; - 注重嵌入式处理器的性能、尺寸、能耗和价格
应用于蜂窝电话等设备;
分类*
-P5页
-
嵌入式微处理器 EMPU——————(Embedded Microprocessor Unit)
嵌入式微处理器具有体积小、重量轻、成本低、可靠性高的优点,但是在电路板上必须包括ROM、RAM、总线接口、各种外设等器件,从而降低了系统的可靠性,技术保密性也较差。嵌入式微处理器及其存储器、总线、外设等安装在一块电路板上,称为单板计算机 -
微控制器(单片机) MCU—————(Microcontroller Unit)
嵌入式微控制器又称单片机,它是将整个计算机系统集成到一块芯片中。嵌入式微控制器一般以某一种微处理器内核为核心,芯片内部集成各种必要功能和外设。
和嵌入式微处理器相比,微控制器的最大特点是单片化,体积大大减小,从而使功耗和成本下降、可靠性提高。微控制器是目前嵌入式系统工业的主流。微控制器的片上外设资源一般比较丰富,适合于控制,因此称微控制器。 -
DSP处理器 DSP—————————(digital Signal Processor)
DSP处理器对系统结构和指令进行了特殊设计,使其适合于执行DSP算法,编译效率较高,指令执行速度也较高。在数字滤波、FFT、谱分析等方面DSP算法正在大量进入嵌入式领域,DSP应用正从在通用单片机中以普通指令实现DSP功能,过渡到采用嵌入式DSP处理器。 -
片上系统 SoC——————————(System on Chip)
在一个硅片上实现一个更为复杂的系统,这就是System On Chip(SOC)。用户只需定义出其整个应用系统,仿真通过后就可以将设计图交给半导体工厂制作样品。这样除个别无法集成的器件以外,整个嵌入式系统大部分均可集成到一块或几块芯片中去,应用系统电路板将变得很简洁,对于减小体积和功耗、提高可靠性非常有利。
SoC可以分为通用和专用两类。
注:了解各自的适用范围与区别
1.3 嵌入式操作系统
-
发展史概述
计算机系统由硬件和软件组成,在发展初期没有操作系统这个概念,用户使用监控程序来使用计算机。随着计算机技术的发展,计算机系统的硬件、软件资源也愈来愈丰富,监控程序已不能适应计算机应用的要求。于是在六十年代中期监控程序又进一步发展形成了操作系统(Operating System)。发展到现在,广泛使用的有三种操作系统即多道批处理操作系统、分时操作系统以及实时操作系统。 -
嵌入式操作系统采用实时操作系统
-
操作系统分类:
- 多道批处理操作系统:
适用于计算中心等较大的计算机 - 分时操作系统:
适用于多个用户共享系统资源 - 实时操作系统:
实时操作系统是一段在嵌入式系统启动后首先执行的背景程序,用户的应用程序是运行于RTOS之上的各个任务,RTOS根据各个任务的要求,进行资源(包括存储器、外设等)管理、消息管理、任务调度、异常处理等工作。
用于嵌入式设备和有实时性要求的系统中,分为两类:- 一般实时操作系统:
应用于实时处理系统的上位机和实时查询系统等实时性较弱的实时系统,并且提供了开发、调试、运用一致的环境。 - 嵌入式实时操作系统
应用于实时性要求高的实时控制系统,而且应用程序的开发过程是通过交叉开发来完成的,即开发环境与运行环境是不一致。嵌入式实时操作系统具有规模小(一般在几K~几十K 内)、可固化使用实时性强(在毫秒或微秒数量级上)的特点 。
- 一般实时操作系统:
- 多道批处理操作系统:
备注:
实时操作系统强调实时性、可靠性、灵活性
特点*
-P7页 ppt P20页
- 异步的事件响应
- 切换时间和中断延迟时间确定
- 优先级中断和调度
- 抢占式调度
- 内存锁定
- 连续文件
- 同步
常见的嵌入式实时操作系统*
-P11 ppt P35(目测选择题)
- μClinux
uClinux从Linux 2.0/2.4内核派生而来,沿袭了主流Linux的绝大部分特性。它是专门针对没有MMU的CPU,并且为嵌入式系统做了许多小型化的工作。适用于没有虚拟内存或内存管理单元(MMU)的处理器,例如ARM7TDMI。它通常用于具有很少内存或Flash的嵌入式系统。它保留了Linux的大部分优点:稳定、良好的移植性、优秀的网络功能、完备的对各种文件系统的支持、以及标准丰富的API等。 - Windows CE
Windows CE是微软开发的一个开放的、可升级的32位嵌入式操作系统,是基于掌上型电脑类的电子设备操作,它是精简的Windows 95。Windows CE的图形用户界面相当出色。Win CE具有模块化、结构化和基于Win32应用程序接口以及与处理器无关等特点。 - VxWorks
VxWorks操作系统是美国WIND RIVER(风河)公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地。它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中。 - μC/OS - Ⅱ
μC/OS-II是一个源码公开、可移植、可固化、可裁剪、占先式的实时多任务操作系统。其绝大部分源码是用ANSI C(由美国国家标准协会(ANSI)及国际标准化组织(ISO)推出的关于C语言的标准)写的,使其可以方便的移植并支持大多数类型的处理器。
注: 注意了解各自的优缺点,通读留个印象
第2章
-简答题X3,小题
2.1 ARM简介
- ARM:Advanced RISC Machines
- 它是一家微处理器行业的知名企业,该企业设计了大量高性能、廉价、耗能低的RISC (精简指令集)处理器。
- 公司的特点是只设计芯片,而不生产和向终端用户出售芯片。它将技术授权给世界上许多著名的半导体、软件和OEM厂商,通过转让设计方案让合作商生成各具特色的芯片,提供服务。
2.1.1 精简指令集计算机(RISC)*
-P16页,了解特性
- RISC结构特性
- 具有大量的通用存储器
- 独特的装载/保存(load-store)结构
- 简单的寻址模式
- 统一和固定长度的指令格式
- ARM体系其他特性(阅读、了解)
科普拓展(可忽略此段)
个人科普用,老师只要求了解这两个名词,并且大头考RISC,此段可以忽略
- 名词解释
CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构。它们的区别在于不同的CPU设计理念和方法。 - 区别
- 指令系统:
- RISC设计者把主要精力放在那些经常使用的指令上,尽量使它们具有简单高效的特色。对不常用的功能,常通过组合指令来完成。因此,在RISC机器上实现特殊功能时,效率可能较低。但可以利用流水技术和超标量技术加以改进和弥补。
- 而CISC计算机的指令系统比较丰富,有专用指令来完成特定的功能。因此,处理特殊任务效率较高。
- 存储器操作:
- RISC对存储器操作有限制,使控制简单化;
- 而CISC机器的存储器操作指令多,操作直接。
- 程序:
- RISC汇编语言程序一般需要较大的内存空间,实现特殊功能时程序复杂,不易设计;
- 而CISC汇编语言程序编程相对简单,科学计算及复杂操作的程序设计相对容易,效率较高。
- 中断:
- RISC机器在一条指令执行的适当地方可以响应中断;
- 而CISC机器是在一条指令执行结束后响应中断。
- CPU:
- RISC CPU包含有较少的单元电路,因而面积小、功耗低;
- 而CISC CPU包含有丰富的电路单元,因而功能强、面积大、功耗大。
- 设计周期:
- RISC微处理器结构简单,布局紧凑,设计周期短,且易于采用最新技术;
- CISC微处理器结构复杂,设计周期长。
- 用户使用:
- RISC微处理器结构简单,指令规整,性能容易把握,易学易用;
- CISC微处理器结构复杂,功能强大,实现特殊功能容易。
- 应用范围:
- 由于RISC指令系统的确定与特定的应用领域有关,故RISC机器更适合于专用机;
- 而CISC机器则更适合于通用机。
- 指令系统:
2.1.2 常用ARM处理器*
-P17,老师重点提到下面两个
-
Cortex-M3处理器
该处理器是首款基于ARMv7-M架构的处理器,采用了纯Thumb2指令的执行方式,具有极高的运算能力和中断响应能力。
Cortex-M3主要应用于汽车车身系统,工业控制系统和无线网络等对功耗和成本敏感的嵌入式应用领域- STM32采用该处理器
- 3级流水线
- 纯Thumb2指令执行方式
- 具有极高的运算能力和中断相应能力
- 主要应用于汽车车身系统,工业控制系统和无线网络
- 对功耗和成本敏感的嵌入式应用领域
-
ARM7(系列)
该系列包括ARM7TDMI、ARM7TDMI-S、带有高速缓存处理器宏单元的ARM720T和扩充了Jazelle的ARM7EJ-S。该系列处理器提供Thumb 16位压缩指令集和EmbededICE软件调试方式,适用于更大规模的SoC设计中。
ARM7系列广泛应用于多媒体和嵌入式设备,包括Internet设备、网络和调制解调器设备,以及移动电话、PDA等无线设备。- 3级流水线
- 冯·诺伊曼结构
- 包括ARM7TDMI、ARM7TDMI-S、带有高速缓存处理器宏单元的ARM720T和扩充了Jazelle的ARM7EJ-S
2.2 ARM7TDMI
- 简介:
ARM7TDMI是基于ARM体系结构V4版本的低端ARM核。 其弥补了ARM6很难在低于5V电压下稳定工作的不足,还增加了后缀所对应的功能:
2.2.1 后缀字母意义*(此段考简答)
ppt P17页
字母 | 全写 | 意义 |
---|---|---|
T | Thumb | 支持高密度16位的Thumb指令集 |
D | Debug | 支持片上调试 |
M | Multiplier | 支持64位乘法,内嵌硬件乘法器 |
I | 嵌入式ICE | 支持EmbededICE观察硬件;仿真功能模块,支持片上断点和调试点。 |
S | synthesizable | ARM7TDMI 的可综合(synthesizable)版本(软核),对应用工程师来说其编程模型与ARM7TDMI 一致 |
2.2.2 三级流水线*
书P20 ppt P20页,了解三个动作及作用、有点,可能考简答或填空
- 概念:
ARM处理器使用流水线来增加处理器指令流的速度,这样可使几个操作同时进行,并使处理和存储器系统连续操作,能提供0.9MIPS/MHz的指令执行速度。ARM7TDMI的流水线分3级,分别为:- 取指:从存储器取出一条指令
- 译码:对指令使用的寄存器经行译码
- 执行:
从寄存器组中读出寄存器
执行移位和ALU操作
寄存器写回到寄存器组
正常操作过程中,在执行一条指令的同时对下一条(第二条)指令进行译码,并将第三条指令从存储器中取出。
无论处理器处于何种状态,程序计数器R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或者正在“译码”的指令。
- 在ARM状态下,流水线上各指令的地址为:
- 在Thumb状态下,流水线上各指令的地址为:
- 例题pptP20页
0x4000 ADDPC,PC,#4 ;正在被执行的指令,将地址值PC+4写入PC
0x4004 …;正在被译码的指令
0x4008 …;正在被取指的指令,PC=0x4008
0x400C …;PC+4=0x400C
解:
- 程序计数器R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或“正在译码”的指令。
- 一般来说,人们习惯性约定将“正在执行”的指令作为参考点,则:
PC值=当前程序执行位置+8
注:ARM状态时,每条指令为4字节长。 - PC指向0x4000地址,取指ADD指令。
- PC指向0x4004地址,译码ADD指令。
- PC指向0x4008地址,执行ADD指令,所以指令执行的结果为: PC=PC+4=0x4008+4=0x400C。
其他参照ppt与书
2.3 ARM功能框图
-P23页 ppt P24页,可以忽略具体管脚名,主要记住周围的功能与接口,最可能的考法是对着图片填空
2.4 ARM处理器的状态*(必考,重点强调)
-P24页 ppt P28页
- 两套指令系统————为了让用户更好的控制代码量
- ARM状态(T=0)
- 32位(两套系统位长区别)
- ARM指令集
- 能执行完整功能
- 处理器执行字方式的ARM指令
- 处理器在系统上电时默认ARM状态
- Thumb状态(T=1)
- 16位
- Thumb指令集
- 能执行大部分功能
- 处理器执行半字方式的ARM指令
- ARM状态(T=0)
两个状态之间的切换并不影响处理器模式或寄存器内容。
注:不考状态切换相关知识,T是CPSR的一个控制位,注意结合下文看,CPSR也是必考点
2.5 ARM处理器模式*(必考,可能简答)
- 简介:
ARM体系结构支持7种处理器模式,分别为:用户模式、快中断模式、中断模式、管理模式、中止模式、未定义模式和系统模式。这样的好处是可以更好的支持操作系统并提高工作效率。ARM7TDMI完全支持这七种模式。
此处可结合异常优先级以及下面的ARM内部寄存图表理解记忆。
2.6 ARM内部寄存器
- 共有37个用户可访问的32位寄存器
-
31个通用32位寄存器
- 寄存器R0~R7为未分组的通用寄存器,它们在任何处理器模式都对应于相同的32位物理寄存器。
- 寄存器R8~R12有两个分组的物理寄存器。一个用于除FIQ模式之外的所有寄存器模式,另一个用于FIQ模式。
在发生FIQ中断后,处理器不必为保护寄存器而浪费时间,从而加速了FIQ的处理速度。
-
6个32位状态寄存器(目前均只使用了其中的12位)
寄存器R13、R14分别有6个分组的物理寄存器。1个用于用户和系统模式,其余5个分别用于5种异常模式。-
寄存器R13通常作为堆栈指针(SP),用于保存待使用的寄存器的内容。
-
寄存器R14称为链接寄存器(LR),在结构上有两个特殊功能:
- 当使用BL指令调用子程序时,返回地址将自动存入R14中;
- 当发生异常时,将R14对应的异常模式版本设置为异常返回地址(有些异常有一个小的固定偏移量)。
-
寄存器R15称为程序计数器(PC),它指向正在“取指”的指令。
-
-
-
2.6.1ARM状态下的五个重要寄存器*
- R13(堆栈指针SP)
- R14(链接寄存器LR)
- R15(程序计数器PC)
- CPSR(当前程序状态寄存器)
- SPSR(备份程序状态寄存器)
上下文有介绍
-P28页 ppt P34页
- R13拓展
由于处理器的每种运行模式均有自己独立的物理寄存器R13,在用户应用程序的初始化部分,一般都要初始化每种模式下的R13,使其指向该运行模式的栈空间。这样,当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈中恢复,采用这种方式可以保证异常发生后程序的正常执行。 - R14拓展:
异常的发生会导致程序正常运行的被打断,并将控制流转移到相应的异常处理(异常响应),有些异常(fiq、irq)事件处理后,系统还希望能回到当初异常发生时被打断的源程序断点处继续完成源程序的执行(异常返回),这就需要一种解决方案,用于记录源程序的断点位置,以便正确的异常返回。类似的还有子程序的调用和返回。在主程序中(通过子程序调用指令)调用子程序时,也需要记录下主程序中的调用点位置,以便将来的子程序的返回。
在ARM处理器中使用 R14实现对断点和调用点的记录,即使用R14用作返回连接寄存器(LR )。在硬件上和指令执行上,CPU 自动完成相应返回点的记录。在ARM 汇编语言程序设计时,R14和LR通用。
ARM处理器响应异常时,会自动完成将当前的PC保存到LR寄存器。
ARM处理器执行子程序调用指令(BL )时,会自动完成将当前的PC的值减去4的结果数据保存到LR寄存器。即将调用指令的下紧邻指令的地址保存到LR。
-R15
它指向正在“取指”的指令,由于ARM体系结构采用了多级流水线技术,对于ARM指令集而言,PC总是指向当前正在执行指令的下两条指令的地址,即PC的值为当前指令的地址值加8个字节程序状态寄存器。
注:记住每个寄存器是做什么的以及各个位的含义(CPSR)
2.7 CPSR-当前程序状态寄存器*
书 p36 ppt P43
-
简介
CPSR(当前程序状态寄存器)在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。
在异常中断退出时,可以用SPSR来恢复CPSR。由于用户模式和系统模式不是异常中断模式,所以他没有SPSR。当用户在用户模式或系统模式访问SPSR,将产生不可预知的后果。
ARM内核包含1个CPSR和5个仅供异常处理程序使用的SPSR。ARM的所有模式共享一个CPSR。CPSR反映当前处理器的状态,其包含:- 4位条件代码标志
- 4个条件代码标志(负标志N、零标志Z、进位标志C和溢出标志V );
- 8位控制位
- 2个中断禁止位(IRQ禁止与FIQ禁止);
- 5个对当前处理器模式进行编码的位(M[4:0]);
- 1个用于指示当前执行指令的位(ARM指令还是Thumb指令)。
- 保留位
- CPSR中的保留位被保留将来使用。当改变CPSR标志和控制位时,请确认没有改变这些保留位。
- 另外,请确保您的程序不依赖于包含特定值的保留位,因为将来的处理器可能会将这些位设置为1或者0。
- 4位条件代码标志
-
2.7.1CSPR寄存器的格式
助记:
字符 | 释义 | value |
---|---|---|
N | nagetive | 负或小于 |
Z | Zero | 零 |
C | Carry | 进位或借位拓展 |
V | oVerflow | 溢出标志 |
记住CPSR每个位的作用,老师强调过,可能简答或填空,可参照ppt P44页往后详细了解
2.8 异常优先级*
-P41页 ppt P49页 记住异常优先级
- 简介
只要正常的程序流被暂时中止,处理器就进入异常模式。例如在用户模式下执行程序时,当外设向处理器内核发出中断请求导致内核从用户模式切换到异常中断模式。
如果同时发生两个或更多异常,那么将按照固定的顺序来处理异常。 -
异常优先级*
当多个异常同时发生时,一个固定的优先级决定系统处理它们的顺序。
- 用户希望发生的中断:
FIQ、IRQ、软中断 - 用户不希望发生的中断:
复位、
数据中止、预取指中止、未定义指令中止
第三章
不考
第四章
-4.3-4.6 了解即可
-4.7-4.16 重点
4.1 LPC2000系列ARM简介
- 简介
conversion toolLPC2000系列微控制器基于ARM7TDMI-S CPU内核。支持ARM和Thumb指令集,芯片内集成丰富外设,而且具有非常低的功率消耗。使该系列微控制器特别适用于工业控制、医疗系统、访问控制和POS机等场合。
特性*(必考)
P88页看一看
P89页的特性:
- 片内Boot装载程序实现在系统编程(ISP)和在应用中编程(IAP)
- 4/8(64/144脚封装)10位A/D转换器,转换时间低至2.44ms
- 多个串行接口,包括2个UART、高速I2Cj接口(400kb/s)和2个SPI接口
- 通过片内PLL可实现最大为60MHz的CPU操作频率*
- 晶振频率范围为1-30Hz,若使用PLL或ISP功能,则为10-25MHz*
- 46个(64脚封装)或112个(144脚封装)通用I/O口(可承受5V电压)
- 2个低功耗模式:空闲和掉电
- 双电源:
- CPU操作电压范围1.65~1.95V(1.8V,±8.3%)
- I/O操作电压范围为3.0~3.6v(3.3V,±10%)
4.3系统启动代码介绍
-P112页,老师由此引入一个Bootloader的概念、记住你认为有用的
4.3.1Bootloader*
- 定义:
在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
Bootloader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装在到内存中然后跳转到操作系统所在的空间,启动操作系统运行。
-
操作模式
- 1.自启动模式:在这种模式下,bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。
- 2.交互模式:在这种模式下,目标机上的bootloader将通过串口或网络等通行手段从开发主机(Host)上下载内核映像等到RAM中。可以被bootloader写到目标机上的固态存储媒质中,或者直接进入系统的引导。
-
启动过程,分为两个阶段
- 第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。
- 基本的硬件设备初始化(屏蔽所有的中断、关闭处理器内部指令/数据Cache等)。
- 为第二阶段准备RAM空间。
- 复制Bootloader的第二阶段代码到RAM。
- 设置堆栈。
- 跳转到第二阶段的C程序入口点。
- 第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。
- 初始化本阶段要使用到的硬件设备。
- 检测系统内存映射。
- 将内核映像和根文件系统映像从Flash读到RAM。
- 为内核设置启动参数。
- 调用内核。
- 第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。
4.4 系统控制模块
-P113页,熟悉这些概念有助于更好的理解PLL与VPB
- 一个ARM芯片中通常有很多功能部件,有一些部件是全局性的,它们状态的改变可能引起整个系统运行状态的改变,这些部件我们统一称之为系统控制模块。
在系统控制模块中,有些部件需要在进行寄存器配置后才能正常工作,如存储器映射控制、锁相环、功率控制、VPB分频器。
4.4.2时钟系统
-
(简单了解,有助于后面PLL与VPB的理解)
-
时钟是计算机系统的脉搏,处理器核在一拍接一拍的时钟驱动下完成指令执行、状态变换等动作。
-
外设部件在时钟的驱动下进行着各种工作,比如串口数据的收发、A/D转换、定时器计数等。
-
时钟系统结构
-
LPC2000系列微控制器的时钟系统包括四个部分:晶体振荡器、唤醒定时器、锁相环(PLL)和VPB分频器。
图解:- ① 为系统提供基本的时钟信号(Fosc) 。
- ② 在复位或处理器从掉电模式被唤醒时,为输入的时钟信号做计数延时,使芯片内部部件有时间进行初始化。
- ③ 把Fosc信号提高到一个符合用户需要的频率(Fcclk) 其中Fcclk用于CPU内核。
- ④ 用于把Fcclk信号降低到一个合适的Fpclk值(也可以不降低),该信号用于外设部件 。
4.4.3 晶体振荡器
可分为两种模式:
- 从属模式(使用外部时钟源产生时钟)
- 通过X1引脚从外部输入
- 输入频率范围:1~50MHz
- 幅度范围:200mV~1.8V
- 振荡模式(使用外接晶体和片内振荡电路产生时钟)
- 振荡频率范围:1~30MHz
- 注意:如果使用了ISP下载功能或者连接PLL提高频率,则输入的时钟频率范围必须在10~25(MHz)之间。
4.4.4 复位
-
概念
- 复位指将计算机系统中的硬件逻辑归位到一个初始的状态,比如让寄存器恢复默认值、让处理器从第一条指令开始执行程序等。
- LPC2000系列芯片有两个复位源:
- 外部复位 : 把nRESET引脚拉为低电平,并保持一个最小时间,引发复位
- 看门狗复位:通过设置看门狗相关寄存器,当看门狗定时器溢出后,引发复位
4.4.5 唤醒时钟
: 唤醒定时器能够确保振荡器和芯片内部硬件电路在处理器开始执行指令之前有足够的时间初始化 。
当给芯片加电或某个事件使芯片退出掉电模式后,振荡器就开始工作,但是需要一段时间来产生足够振幅的信号驱动时钟逻辑。振荡的波形大致如下:
4.4.6 锁相环PLL
-需要熟悉PLL频率计算
- 作用
LPC2000系列芯片内部均具有PLL电路,振荡器产生的时钟Fosc通过PLL升频,可以获得更高的系统时钟(Fcclk)。示意图如下:
- PLL内部框图
- 频率计算中需要用到的符号说明
符号 | 说明 | 助记 |
---|---|---|
Fosc | 晶体振荡器的输出频率 | OS clk |
Fcco | PLL电流控制振荡器的输出频率 | current-controlled-output |
Fcclk | PLL最终的输出频率 | cpu-clk |
M | PLLCFG寄存器中MSEL位的倍增器值 | Multiplication |
P | PLLCFG寄存器中PSEL位的分频器值 |
4.4.6.2.频率计算
或者忽略书本和ppt上那么多无谓的换算,直接用我们日常的习惯写出输入输出的关系
- Fcclk=Fcco/(2xP)=Fosc x M
- Fcclk:输出
- Fosc:输入
- 这个方程的反映了PLL的工作原理(闭环反馈控制电路):
- 首先我们从电流控制振荡器(cco)开始
- 电流控制振荡器(cco)输出的高频频率(Fcco)经历了2P分频(Fcco /2P)之后输出,但此时的输出不一定是最终的CPU频率(Fcclk)
- 系统通过一个闭环反馈控制电路判断这个输出是否是输入频率(Fosc)的M倍:
- 这个输出再次经过M分频(Fcco /2PM),
- 之后相位频率检测器根据两者(Fosc与Fcco/2PM)频率相位的差异输出自适应电流改变cco的输出频率,
- 重复以上过程,直至Fosc=Fcco/2PM,至此达到反馈控制的目的
- Fosc的范围位10~25MHz
- Fcclk的范围为10MHz-Fmax
- Fcco的范围为156~320MHz
4.4.6.3确定PLL设定过程
- ①选择处理器的时钟频率(Fcclk)
- ②选择振荡器频率,Fcclk一定要是Fosc的整数倍数
- ③计算M值(倍频值)以配置MSEL位,M=Fcclk/Fosc,M的取值范围为1~32。实际写入M位的值位M-1。(适应计算机从0开始计数)
- ④选择P值(分频值)以配置PSEL位,使Fcco在定义的范围内(P不减一的原因很简单,0不能当分母)
- Fcclk=Fcco/2*P
- => P=Fcco/( Fcclk2)*
- Fcco为156~320 MHz
4.4.6.4PLL设置举例:*
-
要求:
- 系统要求Fosc=10MHz,Fcclk=60MHz。 解:
-
根据这些要求:
①确定Fcclk=60MHz;
②选择Fosc=10MHz;
③计算M= Fcclk/Fosc=60MHz/10MHz=6。M-1=5,所以写入PLLCFG[4:0]=00101;
④计算P=Fcco/( Fcclk*2),其中 Fcco为156~320 MHz。当Fcco=156MHz时,P=156MHz/(2x60MHz)=1.3当Fcco=320MHz时, P=2.67
P取整数2,所以写入PLLCFG[6:5]=01。
这里参照课本P134,PPT P87页,P88页有程序和流程图
4.4.6.5寄存器描述:
ppt P81
-
PLLCON
- PLLE:PLL使能,该位为1时将激活PLL并允许其锁定到指定的频率;
- PLLC:PLL连接,当PLLE为1,并且在PLL锁定后,该位为1,将把PLL作为时钟源连接到CPU,否则直接使用振荡器时钟。
-
PLLCFG
配置寄存器,下图错了,等我有空改,或者我忘了
- PSEL[1:0]:PLL分频器值,在PLL频率计算中其值为P。
- MSEL[4:0]:PLL倍频器值,在PLL频率计算中其值为(M-1)
-
PLLSTATE
- PLOCK:反映PLL的锁定状态。为0时,PLL未锁定;为1时,PLL锁定到指定频率。
- MSEL[4:0]、PSEL[1:0]、PLLE、PLLC:读出反映这几个参数的设置值,写入无效;
-
PLLFEED
- PLLFEED[7:0]:PLL馈送序列必须写入该寄存器才能使PLL配置和控制寄存器的更改生效。
馈送序列分两步进行,如下所示:- step1. 将值0xAA写入PLLFEED
- step2. 将值0x55写入PLLFEED
- PLLFEED[7:0]:PLL馈送序列必须写入该寄存器才能使PLL配置和控制寄存器的更改生效。
4.4.7 VPB分频器
-P137页,了解VPB分频设置,工作频率的设置
-
概念:
VPB总线是芯片的内部总线,上面挂接着绝大部分的外设,而这些外设的工作速度相对于ARM内核来说都要慢一些,VPB分频器决定了处理器时钟(cclk)与外设器件所使用的时钟(pclk)之间的关系。 -
用途:
- 将处理器时钟(cclk)分频,以便外设在合适的速度下工作。
- 降低系统功耗。
-
VPB寄存器
VPBDIV[1:0]:设置分频值,可以设定3个值;
4.4.7.1VPB设置示例:*
根据外设时钟与内核时钟的关系,设置对应的VPB值:
void VPBSet(uint32 Fcclk, uint32 Fpclk)
{
uint8 i;
if((Fpclk / (Fcclk / 4)) == 1) //是系统时钟1/4
{
VPBDIV = 0; //写入00
}
else
if((Fpclk / (Fcclk / 4)) == 2) //是系统时钟1/2
{
VPBDIV = 2; //写入10
}
else
if((Fpclk / (Fcclk / 4)) == 4) //和系统时钟相等
{
VPBDIV = 1 //写入01
}
}
4.5 存储器
不考
4.7 引脚连接模块
4.7.1 PINSEL寄存器
此节主要看懂PINSEL寄存器的作用
-
概述:
LPC2000系列微控制器的大部分管脚都具有多种功能,即管脚复用,但是同一引脚在同一时刻只能使用其中一个功能,通过配置相关寄存器控制多路开关来连接引脚与片内外设。- 例:
P0.0选择保留功能,配置对应位为11
- 例:
-
寄存器描述
LPC2000系列微控制器具有三个32位宽度PINSEL寄存器:
其中PINSEL0和PINSEL1控制端口0,PINSEL2根据芯片的不同控制的端口数量也不同 。
其中PINSEL0共32位,控制P0.0~15这16个端口,2位控制一个端口。
4.7.2PINSEL应用示例**
-
要求
-
将P0.8、P0.9设置为TxD1、RxD1
通过查阅PINSE0寄存器设置表,得到P0.9和P0.8的控制位为PINSEL0[19:16],当该域设置为[0101] (0x05)时选择 RxD1和 TxD1。
PINSEL0 = 0x05 << 16;
- 代码解析
- 0x05代表 [0101],题中要求设置TxD功能,由上图可知00代表GPIO功能,01代表TxD功能;
0101则代表P0.8和P0.9都选择了TxD功能 - <<为左移运算,左移16位到达P0.9和P0.8的控制位(查表可得),然后再写入0101的控制指令。达到了控制指定位数、指定端口的目的。
- 0x05代表 [0101],题中要求设置TxD功能,由上图可知00代表GPIO功能,01代表TxD功能;
- 拓展
硬件编程中常用到 “<<”左移操作来达到控制固定位数数值的目的
一些硬件编程中会将这个操作直接定义为一个宏定义(不了解的话简单理解为快捷方式):
意义:将1左移x位,这样可以非常方便且清晰的控制寄存器的每个位#define BV(x) (1 << (x))
比如以上操作可以在宏定义之后被写为:PINSEL0|=BV(16);//设置P0.8,第16位为1, 0 1 0‘1’ PINSEL0|=BV(18);//设置P0.9,第18为为1, 0‘1’0 1 ```
- 代码解析
- 代码完善:
不同于以上赋值方式,在实际操作中为了不影响别的管脚连接设置,通常选择下面的设置方法。
为什么用以上赋值方式,按之前的方法直接写等于不是更简单?PINSEL0 = (PINSEL0 & 0xFFF0FFFF) | (0x05 << 16);
为解释清楚这个问题,我们先从代码 0xFFF0FFFF的 意思说起- 0xFFF0FFFF
PINSEL0总共32位,控制从P0.0到P0.15共16个引脚,两个二进制位也就是(00)控制一个引脚:-
P0.0到P0.15共16个引脚,2个引脚一组,共8组
于是有8个F -
F是十六进制,换成二进制就是0000四个二进制位
于是就是8x4=32位 -
一个F(0000)对应两个引脚,那么一个引脚对应两个二进制位(00)
每个引脚取值范围(00-01-10-11)共四个状态 -
结合题意,P0.8和P0.9应该是第5组,对应其中第五个F,
按从右到左的顺序,右面两个00代表P0.8的控制位,左边两个00代表P0.9的控制位
这里第五个F为0的意思是一次性设置P0.8和P0.9两个管脚,并保持其他管脚的设置不变
-
- PINSEL0 & 0xFFF0FFFF
- &是按位与操作,任何位和1进行与操作结果还是他原来的状态,不会改变
- 将第五个F位写0则是将P0.8和P0.9的状态置位,方便下面进行或“|" 运算经行状态位写入
- (PINSEL0 & 0xFFF0FFFF) | (0x05 << 16);
- |是或运算,0与其他数进行或运算,结果都会被其他数代替,
- 所以通过或运算将之前用0置位而空缺的P0.8和P0.9的控制位填充,达到设置的目的,却不影响其他原先已经设定好的控制位
- 0xFFF0FFFF
-
总结
-
嵌入式中位运算
只修改要修改的位,不要影响到其它位。
直接等于(=)的操作赋值的同时也改变了其它位的状态,在基础实验功能单一,感觉不出来,如果在协议桟中就有严重问题了
用上述写法一眼就知道操作的位,易懂,
-
拓展理解:
PIDIR|=0x01; //写1不改变其他位 PISEL&=~0x01: //写0不改变其他位
-
PIDIR |=0x01与 PIDIR=0x01;
-
P1DIR|=0x01
是复合值语句,等价于P1DIR=P1DR|0x01,这是个按位或运算,然后再赋值- 0与任何数做或运算都是不改变其值,所以在这个语句中只有将最低位置位了,其余位没有变化。
- 所以这个运算的好处是,只改变最低位的值,而不影响其他位;
-
P1DIR=0x01,就是简单的额一条值语句,
- 意思就是说最低位是1,其他位都是0
- 假如P1DIR之前是别的值,那么这条语句的结果就是将0x01赋值给了P1DIR
-
区别就是:
- P1DIR |=0x01只有最低位置位了而没有影响其他位
- P1DIR=0x01直接赋值,可能会改变之前P1DIR其他位已经设定好的值。
-
-
PlSEL&=~0x01 :
写0而不影响其他位,同上,如果我们想写入0而不影响其他位可以利用&=~的复合运算- ~0x01
是取反运算,如代码将0x01取反就是0x1111 1110,除了第一位为0,其他位都是1。- 这里有些人可能会误以为取反是0x10,其实原来的0x01写全了应该是0x0000 0001
- &=~0x01
这里已经为了方便理解写为 PlSEL=PlSEL&0x1111 1110- 我们已经知道,任何数和1进行与&运算不会该百年原来的数值
- 但是任何数与0进行与&运算都会变成0
- 上面的组合操作达到了对第一位写0而不影响其他位的操作
- ~0x01
-
ppt P43页应用示例
4.8 GPIO
4.8.2 GPIO寄存器
-P179页,这节主要了解几个重要寄存器的配置
4.8.3 GPIO使用注意事项
- 概念:
LPC2114/2124微控制器具有两个端口——P0和P1,可以作为GPIO使用的引脚数为46个。
LPC2210/2212/2214微控制器还包含另外两个端口——P2和P3,这个两个端口与外部存储器总线复用,当它们全部作为GPIO使用时,GPIO引脚数多达112个。
4.8.4GPIO相关寄存器描述
-
IOxPIN
- 该寄存器反映了当前引脚的状态。IOxPIN中的x对应于某一个端口,如P1口对应于IO1PIN。所以芯片存在多少个端口,就有多少个IOxPIN分别与之对应。
- 注意:无论引脚被设置为输入还是输出模式,都不影响引脚状态的读出。
-
IOxDIR
- 当引脚设置为GPIO输出模式时,可使用该寄存器控制引脚的方向。
- 向某位写入1使对应引脚作为输出功能
- 写入0时作为输入功能。
作为输入功能时,引脚处于高阻态。
Tips:(老师上课强调过)
-
两个寄存器设置区别(P182页)
- IOxSET
- 输出置位,当引脚设置为GPIO输出模式时,可使用该寄存器从引脚输出高电平。
- 向某位写入1使对应引脚输出高电平
- 写入0无效。
从该寄存器读回的数据为GPIO输出寄存器的值。该值不反映外部环境对引脚的影响。
- IOxCLR
- 输出清零,当引脚设置为GPIO输出模式时,可使用该寄存器从引脚输出低电平。
- 向某位写入1使对应引脚输出低电平
- 写入0无效。
注意:读取该寄存器无效,不能读回输出寄存器的值。
- IOxSET
-
P183页,主要了解为啥要接上拉电阻:
- LPC2000系列大部分I/O引脚为推挽方式输出
- 但是带有IIC总线功能的I/O引脚为开漏输出(P0.2/3和P0.11/14)
- 使用开漏输出的引脚做GPIO,并用于高电平输出或者引脚状态输出时,需要接上拉电阻才能使用。
4.8.5 GPIO应用示例(程序题)***
-P186页,大概率会根据这些内容出一道8分程序题
-
使用GPIO注意点:
- 引脚设置为输出方式时,输出状态由IOxSET和IOxCLR中最后操作的寄存器决定;
- 大部分GPIO输出为推挽方式(个别引脚为开漏输出),正常拉出/灌入电流均为4mA(短时间极限值40mA);
- 复位后默认所有GPIO为输入模式。
-
示例1:设置P0.0输出高电平
... PINSEL0 &= 0xFFFFFFFC; //设置管脚连接模块,设置 P0.0为GPIO功能(=00) IO0DIR | = 0x00000001; //设置P0.0管脚输入输出模式,此处设置为输出(=1) IO0SET = 0x00000001; //设置P0.0管脚的状态,此处为高电平(IO0SET=1) ...
代码解释:
- PINSEL0 &= 0xFFFFFFFC
- PINSEL0
每段的代码的第一步都应该是设置管脚的连接模式,是设置其为外设模式,还是GPIO模式
从上一节中我们了解到PINSEL可以由四个状态,其中GPIO的状态控制位为:00 - &=
同上一节中提过的|=,&=也是一个组合运算,A&=B是A=A&B的简写
同上文的解释,1与任何位与都不会改变那个位原来的状态
但是0与任何位与都会被置为 0
所以&=经常用于置0的操作中
相反 |=经常用于写1的操作中 - 0xFFFFFFFC
我们知道PINSEL0中每两个管脚为1组,共8组,一组为四位0000,
所以P0.0的控制位自然是第一组的右边两个00
需要设置为GPIO这两位应该置为”00”
为了不影响其他位,所以在置0的时候,其他位皆为1;
则最后四个二进制位是1100,也就是十六进制的C,而其他二进制位都为1,也就全F
所以最后写入的命令就是0xFFFFFFFC
- PINSEL0
- PINSEL0 &= 0xFFFFFFFC
-
tips
一般&=经常用于置0的操作中
相反 |=经常用于写1的操作中 -
示例2 读取P0.0状态
... uint32 PinStat; PINSEL0 &= 0xFFFFFFFC; //设置管脚连接模块,设置 P0.0为GPIO功能(=00) IO0DIR &= 0xFFFFFFFE; //设置P0.0管脚输入输出模式,此处设置为输入(=0) PinStat = IO0PIN & 0x01; //从IO0PIN读取引脚状态 ...
代码解释:
- IO0DIR &= 0xFFFFFFFE;
- 关于&=的上个例子中有解释
- 在GPIO控制寄存器组中,不同于PINSEL两位二进制控制一个引脚(因为GPIO有四个状态),
GPIO控制寄存器组的每一位控制一个管脚(只有0/1两种状态)
P0.0的控制位为32位中的第一位
这里设置P0.0为输入模式,也就是第一位为设置为0
则为了不改变其他位的状态其他位都为1
=>最后一个二进制位为0,其他三位为1,4个二进制为一组,构成1110,对应十六进制的“E”
其他位都为F
最后:控制字段则为:0xFFFFFFFE;
- IO0DIR &= 0xFFFFFFFE;
4.8.5.3按键控制蜂鸣器,(可能程序题)***
电路图:
程序:
/******************************************************************************
*功能:读取I/O引脚值,并输出控制蜂鸣器
* 使用I/O口输入方式对P0.14经行扫描
******************************************************************************/
#include <LPC21xx.H>
#include <cohfig.h>
#define BEEPCON 0x00000080; /*P0.7引脚,控制蜂鸣器,输出低电平蜂鸣*/
#define P0_14 0x00004000; /*P0.14引脚,获取按键状态*/
/*******************************************************************************
**函数名: main()
**描述: 读取P0.14口的值,并通过P0.7控制蜂鸣器
********************************************************************************/
int main(void) {
int p014State; //自定义一个变量用来获取按键状态
PINSEL0 = 0x00000000; /*设置引脚为GPIO */
IO0DIR = BEEPCON; /*将P0.7设置为输出,其他都为输入 */
IO0SET = BEEPCON; /*使P0.7输出高电平,也就是让他先保持安静 */
p014State = IO0PIN&P0_14; /*获取按键状态 */
while (1) {
/*读取按键状态*/
if(p014State == 1){ //如果按键没按下,P0.14为高电平
IO0SET = BEEPCON; //输出高电平,让他安静
}
else{
IO0CLR = BEEPCON; //输出低电平,让他叫
}
}
}
- 代码解析:
P0.7为输出,P0.14为输入
GPIO寄存器组中一位控制一个引脚(不同于PINSEL寄存器,上文有解释)
P0.7是第8个引脚,所以对应32位中的第8位,32位分为8组,一组4位,第8位在第二组的最后一个即是(1000)对应十六进制的8所以为0x0000 0080
同理P0.14是第十五位控制,对应第四组(0100),对应的十六进制为4,所以为0x0000 4000
嵌入式开发的基本模式如下:
在这里的无限循环中,程序进入一个循环等待判断阶段:#include <xxxx.h> //包含库 #define xxxx xxxx //预定义 /******************************************************************************* **函数名: main() **描述: 主程序流程 ********************************************************************************/ main(){ PINSELx; //设置管脚模式,如GPIO IOxDIR; //设置输入输出 IOxSET; //设置初始电平 //以上都为初始化 //下面进入一个无限循环,负责执行操作或者等待中断发生 //可能刚接触的人很难理解这个无限循环,明明在c语言中要避免死循环啊?? //没有这个无限循环,程序执行一次就会结束,从而失去了实时性的意义 while(1){ ···//事件在循环中被执行或者在中断处理函数中被执行 } }
当满足if中的条件,也就是按键的状态改变变为低的时候,才会通过IO0CLR寄存器第8位写1,让P0.7输出低电平,从而让蜂鸣器鸣叫。
不符合条件则让他熄灭。
4.9 中断向量控制器
- 概念:
ARM7TDMI内核具有两个中断输入,分别为IRQ中断和FIQ中断。向量中断控制器(VIC)负责管理芯片的中断源,最多可以管理32个中断输入请求。
4.9.1 中断分类:
-P189页,ppt P61页
-
FIQ中断:具有最高优先级;
-
IRQ中断:
- 向量IRQ中断:具有中等优先级;
- 非向量IRQ中断:具有最低优先级;
4.9.2 VIC寄存器描述
-了解中断的基本流程,以及了解相关寄存器功能
-P199页,了解流程图,
- VIC使用基本流程:
- 判断中断类型FIQ还是RIQ
- 若为FIQ,进行相关初始化
- 若为IRQ,判断是向量IRQ还是非向量IRQ
- 清除中断标志
- 使能中断
- 编写中断服务程序
4.9.3 中断处理
-记住两个入口地址
- ARM对中断的响应过程
- 将寄存器LR设置为返回地址(R14,链接寄存器)
- 保存当前程序状态寄存器(CPSR):
将前一模式的CPSR保存到SPSR寄存器中 - 关中断,防止同类型中断嵌套
- 将PC值设置为该异常中断的入口地址:
- IRQ中断时,PC=0x0000 0018
- FIQ中断时,PC=0x0000 001C
- FIQ中断硬件处理流程
- IRQ中断相应流程
- 图示中断发生过程
- 从异常中断处理函数中返回
- 恢复CPSR程序状态寄存器:
将异常状态寄存器SPSR中的值拷贝给CPSR - 恢复用户程序
这两个操作是通过用户软件实现的。
- 恢复CPSR程序状态寄存器:
4.11定时器0和定时器1
4.11.1定时器方框图
-P224页 ppt P24页,图4.98定时器方框图,熟悉流程
- 定时器的工作流程如下:
- 定时器内部的预分频器对定时器时钟电源进行分频。
- 分频后,输出的时钟才是定时器内部的计数器时钟源
- 计数值与匹配器中的值不断地比较,当两个值相等时,发生匹配事件,然后执行相应的操作——产生中断、MAT引脚输出指定信号等
- 当捕获引脚出现有效边沿时,定时器会将当前的计数器值保存到捕获寄存器中,同时也可以产生中断
本节主要了解定时器的配置,通过配置定时器,实现小灯定时亮灭(非delay函数)
4.12SPI接口
ppt P62页
4.12.2SPI总线配置
-书本P239页,总线配置,几根?,什么时候上拉。对应ppt P67页
-
概念
SPI总线系统是一种同步串行外设接口,允许MCU与各种外设以串行的方式进行通信、数据交换。
一般使用4条线:- SCK:串行时钟线
- MISO:主机输入/从机输出数据线
- MOSI:主机输出/从机输入数据线
- SSEL:从机选择线(低电平有效)
-
SPI工作模式:
主机模式:上拉 -
图4.110 SPI总线的配置
如图所示,一个SPI主线可以接多个主机和从机,但是在同一时刻只允许有一个主机操作总线。在数据传输的过程中,总线上只能有一个主机和一个从机通信。在一次传输中,主机总是向从机发送一个 字节数据(MOSI),而从机也总是向主机发送一个字节数据(MISO)。SPI总线时钟总是由主机产生的。
-
使用SPI接口的注意要点
- 作主机时,SSEL引脚必须接上拉电阻,不能作为IO口使用;
- 作主机时,在发送一字节数据的同时接收一字节数
- SPI时钟分频值必须大于或等于8;
- 数据寄存器与内部移位寄存器之间没有缓冲区,写SPDR会使数据直接进入移位寄存器。因此数据只能在上一次数据发送完成后写入SPDR寄存器。
4.13 I2C接口
-书P250页,ppt P95页,了解概念和常识性知识,比如几根总线,总线方式——别吐槽,老师原话
-
概念:
I2C总线是Philips推出的串行传输总线,它以2根连线实现了完善的双向数据传输,可以极方便地构成多机系统和外围器件扩展系统。
I2C总线的两根线(串行数据SDA,串行时钟SCL)连接到总线上的任何一个器件,每个器件都应有一个唯一的地址,而且都可以作为一个发送器或接收器,此外,器件在执行数据传输的时候也可以被看作主机从机。- 发送器:本次传送中发送数据(不包括地址和命令)到总线的器件;
- 接收器:本次传送中从总线接收数据(不包括地址和命令)的器件;
- 主 机:初始化发送、产生时钟信号和终止发送的器件,它可以是发送器或接收器。主机通常是微控制器。
- 从 机:被主机寻址的器件,它可以是发送器或接收器。
-
典型结构:
在图中,CPUA可以作为该总线上的唯一主机,其他部件都是从机。另一种方式是CPUA和CPUB都作为总线上的主机。
当两个以上的CPU同时发动传输时,只能有一个控制器件能真正控制总线成为主机,并使报文不被破坏,这个过程叫仲裁。与此同时,能同步多个控制器件所产生的时钟信号
SDA和SCL都是双向线路。连接到总线的器件的输出极必须使漏极开路或者集电极开路,都通过一个电流源或上拉电阻连接到正的电源电压,这样才能实现”线与“的功能。当总线空闲时,这两条线路都是高电平。
在标准模式下,总线数据的速度为0~100kbit/s,在高速模式下,可达0-400kbit/s。
总线速率越高,上拉电阻越小。。100kbit/s总线速率,上拉电阻通常使用5.1kΩ。
4.13.1 I2C总线上的位传输
I2C总线上每传输一个数据位必须产生一个时钟脉冲
- 数据的有效性
SDA总线上的数据必须在时钟线SCL的高电平期间保持稳定,数据线SDA的电平状态只有在SCL线的时钟信号为低电平时才能改变。 - 起始信号和结束信号
唯一违反上述有效性的是起始信号(S)和结束信号(P)这两个信号一般由主机产生- 起始信号:
在时钟线SCL为高电平时,数据线SDA由高向低切换 - 停止信号:
在时钟线SCL为高电平时,数据线SDA由低向高切换
- 起始信号:
4.14 UART
-P278页,ppt P3页
- 使用串口经行数据传输时的接线
- TxD接RxD,RxD接TxD
- GDN接法
- LPC2000系列微控制器具有两个功能强大的UART,其特性如下:
16字节接收FIFO和16字节发送FIFO;
寄存器位置符合16C550工业标准;
接收FIFO触发点可设置为1、4、8或14字节;
内置波特率发生器;
UART1含有标准调制解调器接口信号 。 - 应用举例 :
4.15 A/D转换器
-P304页,ppt P45页
-
特性
LPC2114/2124具有一个AD转换器,LPC2200系列具有两个AD转换器,它们具有如下特性:- 10位逐次逼近式模式转换器;
- 测量范围:0~3.3V;
- 10位转换事件>=2.44us;
- 可设置AD转换触发方式;
- 具有掉电模式。
-
描述
A/D转换器的基本时钟由VPB时钟提供。可编程分频器可将时钟调整至逐步逼近转换所需的4.5MHz(最大)。如要要得到10位精度的结果,需要11个A/D转换时钟。
A/D转换器的参考电压来自V3A和VSSA引脚。
-
ADC转换时钟分频值计算:
- FADCLK:
FADCLK是将VPB时钟(PCLK)进行分频之后得到的
FADCLK必须小于或等于4.5MHz。 - CLKDIV:
一个功能位,代表时钟分频值
通常将CLKDIV编程为允许的最小值,以获得4.5MHz或稍低于4.5MHz的时钟。 - 公式:
CLKDIV = ( PCLK / FADCLK)-1
- FADCLK:
-
ADC使用方法
使用ADC模块时,先要将测量通道引脚设置为AINx功能,然后通过ADCR寄存器设置ADC的工作模式、ADC转换通道、转换时钟(CLKDIV时钟分频值),并启动ADC转换。可以通过查询或中断的方式等待ADC转换完毕,转换数据保存在ADDR寄存器中。
A/D没有独立的参考电压引脚,A/D的参考电压与供电电压连接在一起即3.3V。假定从ADDR寄存器中读到的10位A/D转换结果为VALUE,则对应的实际电压是:
4.16 看门狗(可能出简答)
-P311页,熟悉看门狗定时器的功能
- 看门狗功能
看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分,它实际上是一个计数器,一般给看门狗一个数字,程序开始运行后看门狗开始倒计数。如果程序运行正常,过一段时间CPU应发出指令让看门狗复位,重新开始倒计数。如果看门狗减到0就认为程序没有正常工作,强制整个系统复位。
个人理解:- 狗在家里看家,你不及时回来喂它就会乱叫。
看门狗定时器就是一条狗,看的是程序的正常运行。
看门狗定时器从一个定值向下递减(狗肚子里的狗粮慢慢消化); - 如果程序运行(你及时回家了),看门狗定时器的计数器没有递减为0(狗还没饿疯),CPU发出指令让定时器复位到初始值(你把狗喂饱),看门狗定时器就不会强制整个系统复位(狗就不会乱叫);
- 相反,程序没有正常运行(你没有及时回家,那你肯定出事了,至于好事坏事那就不管了,不过程序出事铁是坏事),没有执行让看门狗复位到初始计数值操作(你没回来喂狗),那么看门狗定时器就会强制复位(狗肚子空了,饿疯了,会乱吠)。
- 狗在家里看家,你不及时回来喂它就会乱叫。
- 使用看门狗的注意要点
- WDT定时器为递减计数,向下溢出时产生中断和(或)复位;
- 使能看门狗后,必需要要执行一次正确的喂狗操作才能启动看门狗;
- 看门狗没有独立的振荡器,其使用PCLK作为时钟。所以CPU不能进入掉电模式,否则看门狗将停止工作;
- 看门狗溢出时间 = N×tpclk×4
- 流程
- 在WDTC寄存器中设置看门狗定时器的固定装载值
- 在WDMOD寄存器中设置模式并使能看门狗
- 通过WDFEED寄存器顺序写入0xaa和0x55,第一次喂狗启动定时器
- 定时喂狗防止复位或中断
看门狗示例程序
void WDT_Init(unit 32 time)
{
WDTC=time; //设置看门狗的溢出时间
WDMOD=0x03; //看门狗定时器定时溢出后,中断且复位
WDFEED=0xaa; //执行喂狗序列启动看门狗
WDFEED=0x55;
}
//看门狗喂狗程序
void FeedDog()
{
IRQDisable();//禁止总断
WDFEED=0xaa;//喂狗序列
WDFEED=0x55;
IRQEnable();//使能中断
}
//看门狗演示程序
#define KEY (1<<20) //按键为P0.20
#define BEEP (1<<7) //蜂鸣器控制引脚
int main()
{
unit32 dly;
PINSEL0=0x00;
PINSEL1=0x00;
IO0DIR=BEEP;
IO0CLR=BEEP; //复位后,蜂鸣器鸣叫一声
for(dly=0;dly<5000;dly++);
IO0SET=BEEP;
WDT_Init(0x1000 0000) //初始化看门狗定时器,溢出产生复位
while(1)
{
while((IO0PIN&KEY)==0); //按下按键,停止喂狗
for(dly=0;dly<100;dly++);
FeedDog();
}
return 0;
}
第五章
5.1最小系统
- 概念
一个嵌入式处理器自己是不能独立工作的,必须给它供电、加上时钟信号、提供复位信号,如果芯片没有片内程序存储器,则还要加上存储器系统,然后嵌入式处理器芯片才可能工作。这些提供嵌入式处理器运行所必须的条件的电路与嵌入式处理器共同构成了这个嵌入式处理器的最小系统。而大多数基于ARM7处理器核的微控制器都有调试接口,这部分在芯片实际工作时不是必需的,但因为这部分在开发时很重要,所以也把这部分也归入最小系统中。
5.1.1框图
–P353页,图5.1最小系统原理框图
5.1.6完整的最小系统
-P360页,大概了解,程序题中要求画出原理图,不需要所有引脚,但是关键引脚需要记住。
六、最后附上考试可能考的程序题***
前两个是老师给的例程,里面加上了注释
-
要求:
- 控制小灯定时亮灭,且在窗口输出提示字样
- 原理图:
- 代码:
#include <LPC21xx.H> #define CR 0x0D //换行 char ledDown[]={"The LED is down!\n"}; //定义字符串 char ledUp[]={"The LED is up!\n"}; int putchar (int ch) {/* UART输出一个字符 */ if (ch == '\n') { while (!(U1LSR & 0x20)); U1THR = CR; //输出换行符 } while (!(U1LSR & 0x20)); return (U1THR = ch); } void delay (void) { /* 延时函数 */ unsigned volatile long i,j; for(i=0;i<60000;i++) for(j=0;j<5;j++) ; } void serialPuts(char *p){/* UART输出字符串 */ while (*p != '\0'){ putchar(*p++); } } int main (void) { /*初始化 UART*/ PINSEL0 = 0x00050000;/* 设置P0.8和P0.9为Txd模式(UART1[RxD1&TxD1] 打开UART)*/ PLLCFG=0; //PLL配置寄存器 //PLLCON = 1;//enable PLL PLLCON=3; //使能并连接PLL //VPBDIV=0; //写入00,是系统时钟的1/4 VPBDIV=1; //写入01,根据前面可知与系统时间相等 PLLFEED=0XAA;//在有效的馈送之后 激活 PLL PLLFEED=0X55; U1LCR = 0x83;/* 8bit data 无奇偶校验,1 bit 停止位,DLAB=1 */ //U1DLM=0 //因为默认为0,所以此段可以省略 U1DLL = 97;/* 当 VPB 15MHz 波特率 9600 */ U1LCR = 0x03;/* DLAB = 0 */ /*结束初始化 UART*/ IO0DIR = 0x000001;/*设置 P0.0 为输出 */ while (1) { IO0CLR = 0x000001;//P0.0口输出低电平,点亮LED serialPuts(ledUp);//串口输出点亮字符串 delay(); IO0SET = 0x000001;//P0.0口输出高电平,熄灭LED serialPuts(ledDown);//串口输出熄灭字符串 delay(); } }
- 执行效果
小灯周期性闪烁,串口输出对应状态字符串。 - 拓展
- PLL 初始化过程:
-
写PLLCFG 和PLLCON:启动PLL,但是不连接PLL 到系统内核。 PLLCON = 0x01、 PLLCFG=0x04
-
保存中断寄存器,关中断
-
连续写PLLFEED(必须连续,不能被中断) PLLFEED = 0xAA PLLFEED = 0x55
-
查询PLLSTAT 一直到PLOCK=1
While((PLLSTAT & 0x40) == 0) { Wait; //等待,一直到PLOCK=1 } -
写PLLCFG 和PLLCON:
启动PLL,连接PLL 到系统内核。 PLLCON = 0x03、 PLLCFG=0x04 -
连续写PLLFEED(必须连续,不能被中断) PLLFEED = 0xAA PLLFEED = 0x55
-
查询PLLSTAT,等待PLOCK=1,PLLE=1,PLLC=1,MSEL4:1 和PSEL1:0(PLLSTAT 的位6-5) 看是否完全符合,如果符合执行下一步,不符合报错。
-
恢复原来的中断寄存器状态
- 波特率发生器
UART0和UART1各含有一个内置的波特率发生器,除数所存是波特率发生器的一部分,它保存了用于产生波特率时钟的VPB时钟(PCLK)分频值,波特率时钟是波特率的16倍。
UnDLL与UnDLM寄存器一起构成一个16位的除数,UnDLL包含除数的低8位,UnDLM包含高8位。
也就是
U0DLM=(Fpclk/(16xbaud))/256
U0DLL=(Fpclk/(16xbaud))%256
值0x0000被看成0x0001因为不允许除数为0
97的由来:- baud=Fpclk/(16x(UnDLM:UnDLL))
- =>除数=Fpclk/(16xbaud)
①Fpclk=15M=15x106
②baudx16=9600x16
除数=Fpclk/(16xbaud)=97
因为不超过256,
所以U0DLM=0,U0DLL=97,U0DLM默认为0,代码中省略
除数锁存访问位(DLAB)必须为1,寄存器才能正确访问。
所以配置顺序应该是:U1LCR = 0x83;/* 8bit data 无奇偶校验,1 bit 停止位,DLAB=1 */ U1DLM=0 //因为默认为0,所以此段可以省略 U1DLL = 97;/* 当 VPB 15MHz 波特率 9600 */ U1LCR = 0x03;/* DLAB = 0 */
然后才是设置DLM与DLL
最后使DLAB=0
-
要求
- 定时器应用举例:定时器0控制小灯闪烁
- 程序:
#include <LPC21xx.H> #define LED 0x000001 typedef unsigned int uint32; typedef unsigned char uint8; uint8 timer0Times = 0; //中断服务程序 __irq void timer0_ISR (void) //定时器触发IRQ中断处理函数 { //中断处理 uint32 i; timer0Times++; //计数累加,产生一次中断加1 if(timer0Times == 10){ //产生10次中断执行以下操作 i=IO0SET; //读取当前LED控制值 if((i&LED)==0){ //IOPIN是否为0 IO0SET=LED; //若为0,熄灭LED }else{ IO0CLR=LED; //反之点亮 } timer0Times = 0; //计数归零 } T0IR = 1; //定时器0的中断标志清零 VICVectAddr = 0; //向量地址寄存器,中断结束后该寄存器恢复为0 , //通知中断处理结束 } //定时器0初始化 void timer0Init (void) { T0MR0 = 119999; //设置匹配值 T0MCR = 3; //匹配后复位TC,并产生中断 T0TCR = 1; //启动定时器0,T0TCR计数控制寄存器 VICVectAddr0 = (unsigned long)timer0_ISR; //设置定时器0的中断服务程序地址 VICVectCntl0 = 0x20 | 4; //定时器0分配给向量IRQ通道0,优先级最高 VICIntEnable = 0x00000010; //定时器0中断使能 } int main(void) { PINSEL0 = 0; //设置所有引脚为GPIO模式 IO0DIR = LED; //设置P0.0输出 IO0SET = LED; //输出高电平,默认熄灭 timer0Init(); //初始化定时器0 while (1) { } }
- 执行结果:
LED灯周期亮灭
拓展
- 向量地址寄存器(VICVectAddr):
该寄存器存放的是IRQ中断服务程序的地址,当发生一个IRQ中断后,CPU读取该寄存器的值并跳转到对应的地址处,执行中断程序。
在中断结束时通常把该寄存器的值恢复为0,等待下次中断产生时把IRQ中断服务程序的地址复制过来。 - VIC的基本使用方法
- 确定中断类型,FIR还是IRQ
- 根据FIR或者IRQ进行相关初始化
- 清楚响应的中断标志,并使能响应中断
- 便携中断服务程序
- _irq
在ADS下,IRQ中断服务程序必须要用_irq关键字声明,这样编译器才能自动生成处理器模式切换代码和现场保护、恢复代码。
**最后为了复习方便,把上面的蜂鸣器程序也贴到这里**
-
要求
- 按键控制蜂鸣器
-
电路图:
-
程序:
/****************************************************************************** *功能:读取I/O引脚值,并输出控制蜂鸣器 * 使用I/O口输入方式对P0.14经行扫描 ******************************************************************************/ #include <LPC21xx.H> #include <cohfig.h> #define BEEPCON 0x00000080; /*P0.7引脚,控制蜂鸣器,输出低电平蜂鸣*/ #define P0_14 0x00004000; /*P0.14引脚,获取按键状态*/ /******************************************************************************* **函数名: main() **描述: 读取P0.14口的值,并通过P0.7控制蜂鸣器 ********************************************************************************/ int main(void) { PINSEL0 = 0x00000000; /*设置引脚为GPIO */ IO0DIR = BEEPCON; /*将P0.7设置为输出,其他都为输入 */ IO0SET = BEEPCON; /*使P0.7输出高电平,也就是让他先保持安静 */ while (1) { /*读取按键状态*/ if((IO0PIN&P0_14) == 1){ //如果按键没按下,P0.14为高电平 IO0SET = BEEPCON; //输出高电平,让他安静 } else{ IO0CLR = BEEPCON; //输出低电平,让他叫 } for(i=0;i<1000;i++) } return 0; }
-
代码解析:
P0.7为输出,P0.14为输入
GPIO寄存器组中一位控制一个引脚(不同于PINSEL寄存器,上文有解释)
P0.7是第8个引脚,所以对应32位中的第8位,32位分为8组,一组4位,第8位在第二组的最后一个即是(1000)对应十六进制的8所以为0x0000 0080
同理P0.14是第十五位控制,对应第四组(0100),对应的十六进制为4,所以为0x0000 4000
嵌入式开发的基本模式如下:#include <xxxx.h> //包含库 #define xxxx xxxx //预定义 /******************************************************************************* **函数名: main() **描述: 主程序流程 ********************************************************************************/ main(){ PINSELx; //设置管脚模式,如GPIO IOxDIR; //设置输入输出 IOxSET; //设置初始电平 //以上都为初始化 //下面进入一个无限循环,负责执行操作或者等待中断发生 //可能刚接触的人很难理解这个无限循环,明明在c语言中要避免死循环啊?? //没有这个无限循环,程序执行一次就会结束,从而失去了实时性的意义 while(1){ ···//事件在循环中被执行或者在中断处理函数中被执行 } }
在这里的无限循环中,程序进入一个循环等待判断阶段:
当满足if中的条件,也就是按键的状态改变变为低的时候,才会通过IO0CLR寄存器第8位写1,让P0.7输出低电平,从而让蜂鸣器鸣叫。
不符合条件则让他熄灭。
更多推荐
嵌入式复习提纲
发布评论