当前位置:首页 >> 信息与通信 >>

PICKit3 中文使用手册


PICkit? 3 Debug Express PIC18F45K20——MPLAB? C 课程

? 2009 Microchip Technology Inc.

DS41370C_CN

请注意以下有关 Microchip 器件代码保护功能的要点: ? ? ? Microchip 的产品均达到 Microchip

数据手册中所述的技术指标。 Microchip 确信:在正常使用的情况下, Microchip 系列产品是当今市场上同类产品中最安全的产品之一。 目前,仍存在着恶意、甚至是非法破坏代码保护功能的行为。就我们所知,所有这些行为都不是以 Microchip 数据手册中规定的 操作规范来使用 Microchip 产品的。这样做的人极可能侵犯了知识产权。 Microchip 愿与那些注重代码完整性的客户合作。 Microchip 或任何其他半导体厂商均无法保证其代码的安全性。代码保护并不意味着我们保证产品是 “牢不可破”的。

? ?

代码保护功能处于持续发展中。 Microchip 承诺将不断改进产品的代码保护功能。任何试图破坏 Microchip 代码保护功能的行为均可视 为违反了 《数字器件千年版权法案 (Digital Millennium Copyright Act)》。如果这种行为导致他人在未经授权的情况下,能访问您的 软件或其他受版权保护的成果,您有权依据该法案提起诉讼,从而制止这种行为。

提供本文档的中文版本仅为了便于理解。请勿忽视文档中包含 的英文部分,因为其中提供了有关 Microchip 产品性能和使用 情况的有用信息。 Microchip Technology Inc. 及其分公司和相 关公司、各级主管与员工及事务代理机构对译文中可能存在的 任何差错不承担任何责任。建议参考 Microchip Technology Inc. 的英文原版文档。 本出版物中所述的器件应用信息及其他类似内容仅为您提供便 利,它们可能由更新之信息所替代。确保应用符合技术规范, 是您自身应负的责任。Microchip 对这些信息不作任何明示或 暗示、书面或口头、法定或其他形式的声明或担保,包括但不 限于针对其使用情况、质量、性能、适销性或特定用途的适用 性的声明或担保。 Microchip 对因这些信息及使用这些信息而 引起的后果不承担任何责任。如果将 Microchip 器件用于生命 维持和 / 或生命安全应用,一切风险由买方自负。买方同意在 由此引发任何一切伤害、索赔、诉讼或费用时,会维护和保障 Microchip 免于承担法律责任,并加以赔偿。在 Microchip 知识 产权保护下,不得暗中或以其他方式转让任何许可证。

商标 Microchip 的名称和徽标组合、 Microchip 徽标、 dsPIC、 KEELOQ、 KEELOQ 徽标、 MPLAB、 PIC、 PICmicro、 PICSTART、 rfPIC 和 UNI/O 均为 Microchip Technology Inc. 在美国和其他国家或地区的注册商标。 FilterLab、 Hampshire、 HI-TECH C、 Linear Active Thermistor、MXDEV、MXLAB、SEEVAL 和 The Embedded Control Solutions Company 均为 Microchip Technology Inc. 在美国的注册商标。 Analog-for-the-Digital Age、 Application Maestro、 CodeGuard、 dsPICDEM、 dsPICDEM.net、 dsPICworks、 dsSPEAK、 ECAN、 ECONOMONITOR、 FanSense、 HI-TIDE、 In-Circuit Serial Programming、 ICSP、 Mindi、 MiWi、MPASM、MPLAB Certified 徽标、MPLIB、MPLINK、 mTouch、 Octopus、 Omniscient Code Generation、 PICC、 PICC-18、 PICDEM、 PICDEM.net、 PICkit、 PICtail、 PIC32 徽标、 REAL ICE、 rfLAB、 Select Mode、 Total Endurance、 TSHARC、 UniWinDriver、 WiperLock 和 ZENA 均为 Microchip Technology Inc. 在美国和其他国家或地区的商标。 SQTP 是 Microchip Technology Inc. 在美国的服务标记。 在此提及的所有其他商标均为各持有公司所有。 ? 2009, Microchip Technology Inc. 版权所有。

Microchip 位于美国亚利桑那州 Chandler 和 Tempe 与位于俄勒冈州 Gresham 的全球总部、设计和晶圆生产厂及位于美国加利福尼亚州和 印度的设计中心均通过了 ISO/TS-16949:2002 认证。公司在 PIC? MCU 与 dsPIC? DSC、KEELOQ? 跳码器件、串行 EEPROM、单片机外 设、非易失性存储器和模拟产品方面的质量体系流程均符合 ISO/TS16949:2002。此外, Microchip 在开发系统的设计和生产方面的质量体 系也已通过了 ISO 9001:2000 认证。

DS41370C_CN 第ii 页

? 2009 Microchip Technology Inc.

PICkit? 3 DEBUG EXPRESS 目录
第 1 章 简介
1.1 课前准备 ......................................................................................................... 7

第 2 章 PIC18FXXXX 单片机架构概述
2.1 存储器构成 ...................................................................................................... 9 2.2 程序存储器 ...................................................................................................... 9
2.2.1 数据存储器 .................................................................................................10 2.2.2 特殊功能寄存器 ..........................................................................................10 2.2.3 返回地址堆栈 .............................................................................................10

第 3 章 PICkit? 3 Debug Express 课程
3.1 第 1 课:Hello LED ....................................................................................... 11
3.1.1 在 MPLAB? IDE 中创建第 1 课的项目 .......................................................11 3.1.1.1 Step One: Select a device (第 1 步:选择器件) .....................11 3.1.1.2 Step Two: Select a language toolsuite (第 2 步:选择 语言工具包) ..............................................................................12 3.1.1.3 Step Three: Create a new project (第 3 步:创建新项目) ......13 3.1.1.4 Step Four: Add existing files to your project (第 4 步: 向项目添加现有文件) ...............................................................13 3.1.1.5 Summary (摘要) .....................................................................14 3.1.2 探究第 1 课的源代码 ..................................................................................16 3.1.3 编译和编程第 1 课的代码 ...........................................................................18

3.2 第 2 课: 使 LED 闪烁 ................................................................................... 21
3.2.1 在 MPLAB IDE 中打开第 2 课的项目和工作区 ...........................................21 3.2.2 在源代码中定义配置位设置 ........................................................................21 3.2.3 探究第 2 课的源代码 ..................................................................................23 3.2.4 编译和编程第 2 课的代码 ...........................................................................24

3.3 第 3 课: 轮流点亮 LED ................................................................................. 25
3.3.1 分配文件寄存器存储单元 ...........................................................................25 3.3.2 分配程序存储器 ..........................................................................................26 3.3.3 探究第 3 课的源代码 ..................................................................................27 3.3.4 编译和编程第 3 课的代码 ...........................................................................28

3.4 第 4 课: 开关输入 ......................................................................................... 29
3.4.1 文件和 #define 伪指令 ................................................................................29 3.4.2 开关去抖 ....................................................................................................30 3.4.3 探究第 4 课的源代码 ..................................................................................30 3.4.3.1 变量 ............................................................................................31 3.4.3.2 开关输入 ....................................................................................31 3.4.3.3 轮流点亮 LED .............................................................................32 3.4.4 编译和编程第 4 课的代码 ...........................................................................32 3.5.1 PIC18F45K20 Timer0 模块 ........................................................................33 3.5.2 探究第 5 课的源代码 ..................................................................................35 3.5.3 编译和编程第 5 课的代码 ...........................................................................36 3.5.4 分配 Timer0 预分频器 ................................................................................36

3.5 第 5 课: 使用 Timer0 .................................................................................... 33

? 2009 Microchip Technology Inc.

DS41370C_CN 第iii 页

PICkit? 3 Debug Express
3.6 第 6 课:使用 PICkit Debug Express ........................................................... 37
3.6.1 PICkit 3 Debug Express 保留的资源 ..........................................................37 3.6.1.1 常规资源 .....................................................................................37 3.6.1.2 程序存储器和数据存储器资源 ....................................................37 3.6.2 在 MPLAB IDE 中选择 PICkit 3 作为调试器 ...............................................38 3.6.3 基本调试操作 .............................................................................................38 3.6.3.1 Halt (暂停) ..............................................................................38 3.6.3.2 单步运行 .....................................................................................39 3.6.3.3 Run (运行) ..............................................................................39 3.6.3.4 Reset (复位) ...........................................................................39 3.6.4 使用断点 .....................................................................................................40 3.6.5 观察变量和特殊功能寄存器 ........................................................................43 3.7.1 PIC18F45K20 ADC 基础知识 ....................................................................45 3.7.2 ADC 配置和工作 ........................................................................................45 3.7.3 探究第 7 课的源代码 ..................................................................................48 3.7.4 使用 PICkit 3 Debug Express 编译和运行第 7 课的代码 ............................48 3.8.1 PIC18FXXXX 中断架构 ..............................................................................49 3.8.2 探究第 8 课的源代码 ..................................................................................50 3.8.3 使用 PICkit 3 Debug Express 编译和运行第 8 课的代码 ............................53

3.7 第 7 课:模数转换器 (ADC) ...................................................................... 45

3.8 第 8 课:中断 ............................................................................................... 49

3.9 第 9 课:内部振荡器 ..................................................................................... 54
3.9.1 内部振荡器模块 ..........................................................................................54 3.9.2 配置内部振荡器 ..........................................................................................55 3.9.3 探究第 9 课的源代码 ..................................................................................57 3.9.4 使用 PICkit 3 Debug Express 编译和运行第 9 课的代码 ............................57 3.10.1 从 EEPROM 读一个数据字节 ...................................................................58 3.10.2 向 EEPROM 写数据字节 ..........................................................................59 3.10.3 探究第 10 课的源代码 ..............................................................................60 3.10.4 使用 PICkit 3 Debug Express 编译和运行第 10 课的代码 ........................60 3.11.1 擦除和写闪存程序存储器 .........................................................................63 3.11.2 通过配置位保护程序存储器 ......................................................................65 3.11.3 使用 PICkit 3 Debug Express 探究第 11 课的源代码 ...............................66

3.10 第 10 课: 使用内部 EEPROM .................................................................... 58

3.11 第 11 课: 程序存储器工作 ......................................................................... 61

3.12 第 12 课: 使用 CPP 模块的 PWM 功能 ...................................................... 68
3.12.1 PWM 概述 ................................................................................................68 3.12.2 使用 CPP 模块 .........................................................................................68 3.12.3 探究第 12 课的源代码 ..............................................................................71 3.12.4 使用 PICkit 3 Debug Express 编译和运行第 12 课的代码 ........................72

附录 A 原理图 ................................................................................................................ 73

DS41370C_CN 第 iv 页

? 2009 Microchip Technology Inc.

PICkit? 3 DEBUG EXPRESS 前言
客户须知
所有文档均会过时,本文档也不例外。 Microchip 的工具和文档将不断演变以满足客户的需求,因此 实际使用中有些对话框和 / 或工具说明可能与本文档所述之内容有所不同。 请访问我们的网站 (www.microchip.com)获取最新文档。 文档均标记有 “DS”编号。 此编号位于每页底部的页码之前。 DS 编号的命名约定为 “DSXXXXXA” , 其中 “XXXXX”为文档编号, “A”为文档版本。 欲了解开发工具的最新信息,请参阅 MPLAB? IDE 在线帮助。 在 Help (帮助)菜单中选择 Topics (主题) ,打开现有在线帮助文件列表。

简介
本章包含使用 PICkitTM 3 Debug Express 前需要了解的一般信息。 本章讨论的内容包 括: ? ? ? ? ? ? ? ? 文档编排 本指南使用的约定 保修登记 推荐读物 Microchip 网站 开发系统客户变更通知服务 客户支持 文档版本历史

文档编排
本文档说明了如何使用 PICkitTM 3 Debug Express 作为开发工具在目标板上仿真和调 试固件。 本手册内容编排如下: ? 第 1 章 “简介”——创建了 12 节 PICkit 3 Debug Express 课程并描述了开始这些 课程之前必需的准备工作。 ? 第 2 章 “PIC18FXXXX 单片机架构概述” ——概述了 PIC18FXXXX 单片机架构。 ? 第 3 章 “PICkit? 3 Debug Express 课程”——详细描述了这 12 节 PICkit 3 Debug Express 课程。 ? 附录 A“原理图”——给出了带有 PIC18F45K20 的 PICkit 3 Debug Express 44 引脚演示板的原理图。

? 2009 Microchip Technology Inc.

DS41370C_CN 第1 页

PICkit? 3 Debug Express
本指南使用的约定
本手册采用下列文档约定: 文档约定
说明 Arial 字体: 斜体字符 涵义 示例 MPLAB? IDE User’s Guide ... 仅有的编译器 ... Output 窗口 Settings 对话框 选择 Enable Programmer “Save project before build” File>Save 单击 OK 单击 Power 选项卡 4‘b0010, 2‘hF1

参考书目 需强调的文字 首字母大写 窗口 对话框 菜单选项 引用 窗口或对话框中的字段名 带右尖括号前有下划线的斜体 菜单路径 文字 粗体字 对话框按钮 选项卡 N‘Rnnnn verilog 格式的数字,其中 N 是总位数, R 是基数, n 是其 中一位。 尖括号 < > 括起的文字 键盘上的按键 Courier New 字体: 常规 Courier New 源代码示例 文件名 文件路径 关键字 命令行选项 位值 常数 斜体 Courier New 可变参数 方括号 [ ] 花括号和竖线:{ | } 省略号 ... 可选参数 选择互斥参数; “或”选择 代替重复文字 表示由用户提供的代码

按 <Enter> 和 <F1> #define START autoexec.bat c:\mcc18\h _asm, _endasm, static -Opa+, -Opa0, 1 0xFF,’A’ file.o,其中 file 可以是任 一有效文件名 mcc18 [options] file [options] errorlevel {0|1} var_name [, var_name...] void main (void) { ... }

DS41370C_CN 第 2 页

? 2009 Microchip Technology Inc.

前言
保修登记
请填写随附的保修登记卡 (Warranty Registration Card)并尽快寄出。 寄出保修登记 卡的客户将可收到新产品更新信息。 临时发布的软件在 Microchip 网站上提供。

推荐读物
本用户指南说明了如何使用 PICkitTM 3 Debug Express。 下面列出了其他有用的文档。 以下 Microchip 文档均已提供,并建议读者作为补充参考材料。 PICkitTM 3 Debug Express 的自述文件 如需了解使用 PICkitTM 3 Debug Express 的最新信息,请阅读 MPLAB IDE 安装目录的 Readmes 子目录下的 “Readme for PICkitTM 3 Debug Express.txt”文件 (ASCII 文本文件) 该自述文件包含了本用户指南中可能未包括的更新信息和已知问 。 题。 自述文件 如需关于使用其他工具的最新信息,请阅读 MPLAB IDE 安装目录的 Readmes 子目录 下的相应工具的自述文件。 这些自述文件包含了本用户指南中可能未包括的更新信息 和已知问题。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 3 页

PICkit? 3 Debug Express
MICROCHIP 网站
Microchip 网站 (www.microchip.com)为客户提供在线支持。客户可通过该网站方便 地获取文件和信息。 只要使用常用的因特网浏览器即可访问,网站提供以下信息: ? 产品支持——数据手册和勘误表、应用笔记和示例程序、设计资源、用户指南以 及硬件支持文档、最新的软件版本和存档软件 ? 一般技术支持——常见问题解答 (FAQ) 、技术支持请求、在线讨论组以及 Microchip 顾问计划成员列表 ? Microchip 业务——产品选型和定购指南、最新 Microchip 新闻稿、研讨会与活动 安排表、 Microchip 销售办事处、代理商以及工厂代表列表

开发系统客户变更通知服务
Microchip 的客户通知服务有助于客户了解 Microchip 产品的最新信息。 注册客户可在 他们感兴趣的某个产品系列或开发工具发生变更、更新、发布新版本或勘误表时,收 到电子邮件通知。 欲注册,请登录 Microchip 网站 www.microchip.com,点击 “变更通知客户” (Customer Change Notification)服务并按照注 册说明完成注册。 开发系统产品的分类如下: ? 编译器——Microchip C 编译器及其他语言工具的最新信息, 包括 MPLAB C18 和 MPLAB C30 C 编译器; MPASM? 和 MPLAB ASM30 汇编器; MPLINK? 和 MPLAB LINK30 目标链接器;以及 MPLIB? 和 MPLAB LIB30 目标库管理器。 ? 仿真器——Microchip 在线仿真器的最新信息,包括 MPLAB ICE 2000 和 MPLAB ICE 4000。 ? 在线调试器——Microchip 在线调试器 MPLAB ICD 2 的最新信息。 ? MPLAB? IDE——关于开发系统工具的 Windows? 集成开发环境 Microchip MPLAB IDE 的最新信息。主要针对 MPLAB IDE、 MPLAB SIM 软件模拟器、 MPLAB IDE 项目管理器以及一般的编辑和调试功能。 ? 编程器——Microchip 编程器的最新信息,包括 MPLAB PM3 和 PRO MATE? II 器 件编程器以及 PICSTART? Plus 和 PICkit? 1 开发编程器。

DS41370C_CN 第 4 页

? 2009 Microchip Technology Inc.

前言
客户支持
Microchip 产品的用户可以通过以下渠道获得帮助: ? ? ? ? 代理商或代表 当地销售办事处 应用工程师 (FAE) 技术支持

客户应联系其代理商、代表或应用工程师 (FAE)寻求支持。当地销售办事处也可为 客户提供帮助。本文档后附有销售办事处的联系方式。 也可通过 http://support.microchip.com 网站获取技术支持。

文档版本历史
版本 A (2009 年 1 月)
? 本文档的初始版本。

版本 B (2009 年 1 月)
? 修改了文档标题,并将整个文档中涉及的编译器从 C18 改为 C 编译器。

版本 C (2009 年 4 月)
? 修改了附录 A:原理图。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 5 页

PICkit? 3 Debug Express
注:

DS41370C_CN 第 6 页

? 2009 Microchip Technology Inc.

PICkit? 3 DEBUG EXPRESS 第 1 章 简介
下面一系列课程涵盖了开发 Microchip PIC18 系列单片机应用的基础知识。在这一系列 课程中,介绍了如何配合使用 MPLAB? IDE、用于 PIC18 的 MPLAB? C 编译器以及 PICkit? 3开发编程器/调试器, 包括从简单的点亮LED到创建中断服务程序等基本单片 机操作。 所有课程都可以在可免费获得的 Microchip MPLAB 集成开发环境中通过可免费获得的 MPLAB C18 学生版编译器完成。 可从提供的光盘中安装课程文件。 请注意这些课程不是为了教授 C 编程语言本身,所以在学习这些课程之前必须首先熟 悉 C 语言。 PICkit 3 Debug Express 课程 - 第 1 课: Hello LED (点亮 LED) - 第 2 课: 使 LED 闪烁 - 第 3 课: 轮流点亮 LED (按顺序点亮) - 第 4 课: 开关输入 - 第 5 课: 使用 Timer0 - 第 6 课: 使用 PICkit3 Debug Express - 第 7 课: 模数转换器 (ADC) - 第 8 课: 中断 - 第 9 课: 内部振荡器 - 第 10 课: 使用内部 EEPROM - 第 11 课: 程序存储器操作 - 第 12 课: 使用 CPP 模块的 PWM 功能 附录 A “原理图” :带有 PIC18F45K20 的 PICkit 3 Debug Express 44 引脚演示板的 原理图。

1.1

课前准备
在开始学习这些课程之前,请确保您的 PC 上已安装了以下文件和软件: 1. MPLAB IDE v8.20 或更新版本。 2. 用于 PIC18 的 MPLAB C 编译器 v3.13 或更新版本。可以使用学生版。 安装 MPLAB C 编译器时请确保选择了以下选项,如图 1-1 所示。 Add header file path to MCC_INCLUDE environment variable(添加头文件路径 到 MCC_INCLUDE 环境变量) Update MPLAB IDE to use this MPLAB C18 (更新 MPLAB IDE 以使用此 MPLAB C18) Place Link to documentation for this compiler in MPLAB IDE Help Topics(设置 链接指向 MPLAB IDE Help Topics (MPLAB IDE 帮助主题)中关于此编译器的文档) 3. PICkit 3 Debug Express 课程文件。

? 2009 Microchip Technology Inc.

DS41370C_CN 第7 页

PICkit? 3 Debug Express
图 1-1: MPLAB C 编译器安装配置选项

DS41370C_CN 第 8 页

? 2009 Microchip Technology Inc.

PICkit? 3 DEBUG EXPRESS 第 2 章 PIC18FXXXX 单片机架构概述
本章提供了 PIC18FXXXX 单片机架构的简要概述。

2.1

存储器构成
PIC18FXXXX 单片机是哈佛架构微处理器,也就是说程序存储器和数据存储器位于独 立的空间中。这使程序总线和数据总线成为独立的专用总线,所以两种类型存储器不 必使用同一条总线,加快了执行速度。 返回地址堆栈也具有自己专用的存储区。

2.2

程序存储器
使用 21 位的程序计数器 (Program Counter, PC)来寻址程序存储空间,因此可允 许 2 Mb 的程序存储空间。通常, PIC18FXXXX 单片机拥有 4 KB 至 128 KB 范围的片 上程序存储器。有些器件还允许扩展外部存储器。 复位时, PC 设置为 0,取出第一条指令。中断向量位于地址为 0x000008 和 0x000018 的存储单元中,因此通常会在地址为 0 的存储单元中放置一条 GOTO 指令以 使程序跳过中断向量。 大多数指令是 16 位的,但有些是双字 32 位指令。无法执行奇数字节的指令。 以下是 PIC18C 架构和 MPLAB C 编译器功能与程序存储器有关的一些重要特性: MPLAB C 编译器实现 请参见 《MPLAB? C18 C 编译器用户指南》 (DS51288J_CN)了解更多关于这些特 性的信息。 ? 通常通过段属性 code 将指令存储到程序存储器中。 ? 可通过段属性 romdata 和 rom 关键字将数据存储到程序存储器中。 ? 可对 MPLAB C 编译器进行配置,为两种存储模型 (小存储模型和大存储模型) 生成代码。在使用小存储模型时,指向程序存储器的指针使用 16 位。大存储模型 使用 24 位指针。 PIC18 架构 在某些 PIC18XXXX 器件中,可对整个或部分程序存储器进行代码保护。代码会被正 确执行但是无法读出或复制。 可使用表读指令读程序存储器, 使用表写指令通过一段特殊的代码序列写程序存储器。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 9 页

PICkit? 3 Debug Express
2.2.1 数据存储器
在 PIC18XXXX 系列器件中,数据存储器称为 “文件寄存器”存储器。 它由一个最大 4096 字节的 8 位 RAM 组成。上电时,数据存储器中的值是随机的。 数据由 256 字节 的存储区为单位构成,需要使用存储区选择寄存器 (Bank Select Register, BSR) (寄存器地址的高 4 位)选择某个存储区。但可以直接访问 Bank 0 和 Bank 15 中的特 殊存储区,而无需考虑分区问题。 这些特殊数据存储区称为快速操作 RAM。大部分特 殊功能寄存器位于快速操作 RAM 的高地址区中。 使用 MPLAB C 编译器时,分区通常是透明的,但可使用 #pragma varlocate 伪指 令来告知编译器变量的存储位置,从而产生更高效的代码。 未初始化数据存储器变量、数组和结构通常通过段属性 udata 存储到存储器中。可在 MPLAB C 编译器中定义初始化数据,以确保在编译器执行初始化操作时变量的值正 确。这意味着启动时,存储在程序存储器中的值会被传送到数据存储器中。根据应用 程序所需的初始化存储空间量,使用初始化数据 (不是仅在运行时设置数据值)可能 会对程序存储器的高效使用产生不良影响。 由于文件寄存器是 8 位的,所以在使用变 量时应考虑将其定义为最合适的数据类型。 例如,如果不希望变量值超过 255,那么 将其定义为 char 类型 (而不是 int 类型)会缩减代码大小,加快代码执行速度。

2.2.2

特殊功能寄存器

特殊功能寄存器 (Special Function Register, SFR)包括 CPU 内核寄存器 (例如堆 栈指针、 STATUS 寄存器和程序计数器) ,以及针对单片机外设 (包括输入和输出引 脚、定时器、 USART 以及用于读写器件 EEDATA 区的寄存器等)模块的寄存器。 MPLAB C 编译器可以按名称访问这些寄存器,还可以像读写应用程序中定义的变量那 样读写这些寄存器。 但是,由于一些特殊功能寄存器具有不同于变量的特性,所以应 该谨慎使用。例如,一些特殊功能寄存器只有某些位可用,一些是只读寄存器,而有 一些寄存器在被访问时可能会影响其他寄存器或器件的操作。这些寄存器映射到数据 存储器的 Bank 15 中的地址单元。

2.2.3

返回地址堆栈

CALL 和 RETURN 指令将程序计数器的值压入和弹出返回地址堆栈。返回堆栈是独立的 存储区,允许 31 层子程序嵌套。 CALL/RETURN堆栈与MPLAB C编译器维护的软件堆栈不同。软件堆栈用于自动参数和 局部变量,并按照链接描述文件中的定义将它们分配到文件寄存器存储区中。

DS41370C_CN 第 10 页

? 2009 Microchip Technology Inc.

PICkit? 3 DEBUG EXPRESS 第 3 章 PICkit? 3 Debug Express 课程
将 PICkit? 3 编程器 / 调试器连接到 PC USB 端口,并通过标有 ICSP? 的连接头 P1 连接演示板和 PICkit。

3.1

第 1 课:HELLO LED
第一课说明如何在 MPLAB? IDE 中创建 MPLAB C 编译器项目以及使用 PIC18F45K20 点亮演示板上的 LED。 重要概念 - 使用 MPLAB IDE Project Wizard (项目向导)为单片机新建一个项目。 - 使用 TRISx 特殊功能寄存器 (SFR)将单片机端口 I/O 引脚方向设置为输入 或输出。 - 使用 LATx SFR 设置单片机端口输出引脚为高电平或低电平状态。

3.1.1

在 MPLAB? IDE 中创建第 1 课的项目

首先通过桌面上的快捷图标打开 MPLAB IDE: 要使用 MPLAB IDE Project Wizard 创建项目,请选择菜单 Project > Project Wizard… (项目 > 项目向导 ...) 将显示 Project Wizard “Welcome!” 。 (欢迎 !)对话框。 单击 Next (下一步)继续。 3.1.1.1 STEP ONE: SELECT A DEVICE (第 1 步:选择器件)

在 Project Wizard 对话框中,从下拉框中选择 PIC18F45K20 作为目标器件 (如图 3-1 所示) ,并单击 Next 继续。

? 2009 Microchip Technology Inc.

DS41370C_CN 第11 页

PICkit? 3 Debug Express
图 3-1:
向导第 1 步:选择 PIC18F45K20 器件

3.1.1.2

STEP TWO: SELECT A LANGUAGE TOOLSUITE (第 2 步:选择语言工 具包)

此 PIC18F 单片机项目将使用 C 语言编写,所以请从 “Active Toolsuite:” (有效工具 包:)下拉框中选择 “Microchip C18 Toolsuite” (Microchip C18 工具包) ,如图 3-2 所示。 单击 Next 继续。 图 3-2:
向导第 2 步:选择工具包

DS41370C_CN 第 12 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.1.1.3 STEP THREE: CREATE A NEW PROJECT (第 3 步:创建新项目) 在现有目录中创建第 1 课的项目文件。 浏览到目录文件夹 C:\Lessons\PICkit 3 Debug Express Lessons\01 Hello LED,将项目命名为“Lesson 1 LED” Save (保存)该项目并单击 Next 继续,如下 。 面的图 3-3 所示。 图 3-3:
向导第 3 步:创建新项目

3.1.1.4

STEP FOUR: ADD EXISTING FILES TO YOUR PROJECT (第 4 步:向 项目添加现有文件)

此对话框允许向项目添加任何现有的源文件或其他文件。 注意还可以在创建项目后将 新文件添加到项目中。在左边窗格中,从第 3 步的项目目录中选择 01 Hello LED.c 文件并单击 Add (添加) 该文件现在显示在对话框窗口的右窗格中,如图 3-4 所 。 示。 单击 Next 继续。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 13 页

PICkit? 3 Debug Express
图 3-4: 向导第 4 步:添加现有文件

3.1.1.5

SUMMARY (摘要)

在向导的最后一个对话框窗口中,检查项目参数并单击 Finish (完成) 要在 。 MPLAB IDE 中查看项目窗口,请选择菜单 View>Project (查看 > 项目) 。 项目窗口 (见图 3-5)在标题栏中显示工作区文件名 (Lesson 1 LED.mcw) ,在文 件树视图顶部显示项目文件 (Lesson 1 LED.mcp) 工作区文件跟踪打开的文件和 。 窗口、窗口在 MPLAB IDE 工作区中的位置、选择的编程器或调试器工具及其配置方 式,以及关于如何设置 MPLAB IDE 环境的其他信息。项目文件跟踪编译项目所需的所 有文件,包括源文件、头文件、库文件、链接描述文件和其他文件。 如图 3-5 所示,Lesson 1 LED 项目目前只包含一个源文件 01 Hello LED.c,该文件 是在 Project Wizard 中添加的。

DS41370C_CN 第 14 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-5: 项目窗口

为了完成项目设置,我们将向项目添加链接描述文件和单片机头文件。 链接描述文件 是编译项目时必不可少的文件。它是链接器的命令文件,定义了描述目标单片机上可 用存储器的选项。此单片机有四个示例链接文件:
18f45k20.lkr 18f45k20_e.lkr 18f45k20i.lkr 18f45k20i_e.lkr 基本链接描述文件,用于以非扩展处理器模式编译存储器映像。 (将在稍后的课程中提供更多关于扩展模式的信息。 ) 链接描述文件,用于以扩展模式进行编译。 调试时使用的链接描述文件。这些链接描述文件可以防止应用代码 使用为调试器保留的一小部分存储区。 链接描述文件,用于以扩展模式进行调试。

通过选择菜单 Project > Add files to project…(项目 > 添加文件到项目 ...)来添加链接描述 文件。在 “Files of type” (文件类型)下拉框中选择 “Linker Scripts (*.lkr)” (链接描 述文件 (*.lkr) ,如图 3-6 所示。 浏览到链接描述文件目录 C:\MCC18\lkr 并打开 ) 18f45k20i.lkr 文件 (因为将在后面课程中用到调试器) 。 也可通过在项目窗口中右键单击文件来添加文件。 右键单击 “Header Files” (头文 件)文件夹并从弹出菜单中选择 Add Files… (添加文件 ...) 浏览到 MPLAB C 头文 。 件目录 C:\MCC18\h 并打开 p18f45k20.h 头文件。项目窗口现在应如图 3-7 所示。 需要注意的是,在文件所在的目录下选择的文件将添加到项目中,所以修改它会修改 原始文件。 如果不希望修改原始文件,请打开该文件并使用 File > Save As… (文件 > 另存为 ...) ,将在当前项目目录中保存一个新副本,然后将这个新文件添加到项目。 最 后一步是使用 File > Save Workspace (文件 > 保存工作区)保存项目及其工作环境。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 15 页

PICkit? 3 Debug Express
图 3-6: ADD FILES TO PROJECT

图 3-7:

新项目文件

选择 Project > Save Project (项目 > 保存项目)以保存新项目配置。

3.1.2

探究第 1 课的源代码

双击 01 Hello LED.c 源文件名以在 MPLAB IDE 编辑器窗口中打开此课程源代码文 件。

DS41370C_CN 第 16 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-8:
/** C O N F I

第 1 课 “HELLO LED”的源代码
G U R A T I O N B I T S ******************************/

#pragma config FOSC = INTIO67 #pragma config WDTEN = OFF, LVP = OFF /** I N C L U D E #include "p18f45K20.h" /** void { D E main C L A R A S **************************************************/

T

I

O

N

S

*******************************************/

(void)

TRISD = 0b01111111;// LATDbits.LATD7 = 1;// while (1) ; }

PORTD bit 7 to output (0); bits 6:0 are Set LAT register bit 7 to turn on LED

inputs

(1)

此代码被编译、烧写到 PIC18F45K20 单片机中并执行后,将通过驱动 I/O 引脚 RD7 为高电平来点亮与该引脚相连的 LED。我们来讨论一下用来实现此操作的代码要素:
#pragma config Pragma 是对特定编译器有意义的伪指令。在 MPLAB C 中与 属性结合使用来向编译器传送与实现相关的信息。在这里它 与定义 PIC18FXXXX 配置位状态的 config 伪指令结合使 用。将在第 2 课中详细讨论。 包含了 p18f45k20.h 文件,因为这个特定于器件的头文件 包含了用于访问单片机特殊功能寄存器 (SFR)的变量的定 义。在此头文件中还定义了一些有用的宏,例如 Nop() 和 ClrWdt()。 此变量用于访问同名 SFR,在包含的单片机头文件 p18f45k20.h 中定义。 TRIS (三态)寄存器用于设置相关 I/O 端口的引脚 (这里指引脚 RD0 至 RD7)的方向。TRISD 位值为 0 会将引脚设置为输出,值为 1 将引脚设置为输入。 二进制值 0b01111111 会将 RD7 设置为输出,将 RD6-RD0 设置为输入。 LATDbits 结构也是在 p18f45k20.h 中定义的,允许访问 LATD SFR 中的各个位。 (还提供了用于访问 TRISD 位的 TRISDbits 结构, 定义了用于访问整个字节宽寄存器的 LATD 变量。 LATD (锁存)寄存器用于设置 RD7-RD0 引脚的输 ) 出状态。位值 1 会将输出引脚置为高电平状态。这些位对在 TRIS 寄存器中定义为输入的引脚没有影响。设置 LATDbits.LATD7 = 1 会在 RD7 引脚上输出高电平, 从而点 亮演示板上的 LED 7。 本例中的代码在嵌入式单片机上运行,所以在代码执行完毕 后不会返回到操作系统。因此可使用无限 C while 循环保持 单片机运行,并防止它退出 main() 程序和尝试执行未定义 的存储单元。

#include

TRISD

LATDbits.LATD7

while(1)

? 2009 Microchip Technology Inc.

DS41370C_CN 第 17 页

PICkit? 3 Debug Express
3.1.3 编译和编程第 1 课的代码
通过在 MPLAB IDE 中选择 Project > Build All (项目 > 编译全部)来将此课程的代码 编译为可执行存储器映像。存储器映像保存在项目目录中的 .hex 文件中。 编译的结果将显示在 MPLAB IDE 工作区中 Output (输出)窗口的 Build (编译)选 项卡下。显示了对 MCC18 编译器和链接器的调用以及可能产生的任何错误。 如果编 译成功, Output 窗口将显示 BUILD SUCCEEDED (编译成功) ,如图 3-9 所示。 图 3-9: MPLAB IDE OUTPUT 窗口中的编译结果

注:

如果产生了找不到头文件 p18f45k20.h 的错误,这通常表示安装 MPLAB C 编译器期间没有选中 Add header file path to MCC_INCLUDE environment variable (添加头文件路径到 MCC_INCLUDE 环境变量)选项。 建议在选 中此选项的情况下重新安装 MPLAB C 编译器。

要将代码烧写到 PIC18F45K20 单片机中,需使用 PICkit 3 编程器 / 调试器。 在 MPLAB IDE 中通过选择菜单 Programmer > Select Programmer > PICkit 3 (编程器 > 选择编程器 > PICkit 3)来选择 PICkit 3 作为编程器。 这将在 Output 窗口中为 PICkit 3 编程器新建一个选项卡,用于显示来自编程器的消息。 PICkit 3 将被初始化并应该报告在演示板上找到了 PIC18F45K20 单片机,如图 3-10A 所 示。 PICkit 3 必须配置为对演示板供电,如果未这样做, PICkit 3 将检测不到目标器件 (通 过图 3-10A 中的错误消息显示) 。使用 Programmer > Settings... (编程器 > 设置 ...) 显示图 3-10B 中所示的窗口。浏览到 Power (电源)选项卡并使用滑动条设置输出电 压为 3.25V,选中标有 “Power target circuit from PICkit 3” (通过 PICkit 3 为目标电 路供电)的框并单击 OK (确定)按钮。 使能了为目标电路供电后,将显示 PIC18F45K20 的器件 ID (图 3-10A 中的最后一行) 。

DS41370C_CN 第 18 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-10A: OUTPUT 窗口中的 PICkit 3 编程器

图 3-10B:

PICkit 3 编程器电源

通过选择菜单 Programmer > Program (编程器 > 编程)将编译后的代码烧写到 PIC? 单片机中。 Output 窗口中将显示编程操作的结果,如图 3-11 所示。 恭喜! 您已经创建、编译、编程并执行了第一个 Microchip PIC18F 项目!

? 2009 Microchip Technology Inc.

DS41370C_CN 第 19 页

PICkit? 3 Debug Express
图 3-11: OUTPUT 窗口中的 PICkit 3 编程结果

注:

如果编程期间发生错误,可在 MPLAB IDE 中查询 PICkit 3 帮助文件。 选择 Help > Topics… (帮助 > 主题 ...) ,然后在 “Programmers” (编程器) 标题下选择 “PICkit 3 Programmer” (PICkit 3 编程器)并单击 OK。 在 Contents (内容)选项卡上选择 “Troubleshooting” (故障诊断)部分以 获取所需信息。

DS41370C_CN 第 20 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.2 第 2 课:使 LED 闪烁
本课程讨论 PIC18FXXXX 单片机的配置位以及如何在 MPLAB C 源文件中设置它们。 还将展示如何使用库函数以及如何使用延时使演示板上的 LED 闪烁。 重要概念 - 通过在 MPLAB IDE 中选择 File > Open Workspace… (文件 > 打开工作区 ...)来打开现有的项目工作区。 - 配置位是用来设置 PIC 单片机工作模式和使能或禁止单片机功能的特殊用途 熔丝位。 - MPLAB C 编译器中提供了许多具有预定义和已编译函数的库。 《MPLAB C18 C 编译器函数库》文档 (DS51297F_CN)提供了关于所有包含的库的 详细信息。 - 可使用软件循环创建延时来为事件定时。

3.2.1

在 MPLAB IDE 中打开第 2 课的项目和工作区

本课程以及余下课程都具有一个已定义的项目和工作区。 要打开第 2 课的工作区,请 在 MPLAB IDE 中选择菜单 File > Open Workspace…。 浏览到目录 C:\Lessons\PICkit 3 Debug Express Lessons\02 Blink LED 并打开 02 Blink LED.mcw 文件。 在打开新工作区之前, MPLAB IDE 会提示您保存当前工作区。 通常比较好的做法是单 击 Yes (是) 然后将打开第 2 课的新工作区和项目。 。

3.2.2

在源代码中定义配置位设置

配置位是 PIC18FXXXX 单片机中的熔丝位,与应用程序代码一起编程以设置或 “配 置”不同单片机工作模式和使能或禁止某些单片机功能。 例如,在 PIC18F45K20 中, 配置位可选择如下功能:要使用的振荡器选项、处理器以传统模式还是扩展模式运行、 是否使用欠压复位电路以及具体的跳变电压、使能或禁止看门狗定时器以及要使用的 选项、是否使能闪存代码保护功能以及许多其他选项。 请注意,某些功能,例如看门狗定时器,可以配置为在执行应用程序代码时通过特殊 功能寄存器由软件使能或禁止它们。关于 PIC18F45K20 配置位的详细说明及相关信 息,请参见数据手册中第 23.0 节 “CPU 的特殊功能”下的第 23.1 节 “配置位” 。 在第 2 课的源代码中,在 02 Blink LED.c 文件开头定义了所有配置位,如图 3-12 所示。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 21 页

PICkit? 3 Debug Express
图 3-12:
/** C O N F I

第 2 课 “使 LED 闪烁”的配置位定义
G U R = AT I O N B I FCMEN = T S ******************************/ IESO = OFF // // // // // // // // // // // CONFIG1H CONFIG2L CONFIG2H CONFIG3H CONFIG4L CONFIG5L CONFIG5H CONFIG6L CONFIG6H CONFIG7L CONFIG7H

#pragma #pragma #pragma #pragma #pragma #pragma #pragma #pragma #pragma #pragma #pragma

config config config config config config config config config config config

FOSC

INTIO67,

OFF,

PWRT = WDTEN MCLRE STVREN CP0 = CPB = WRT0 = WRTB = EBTR0 = EBTRB =

OFF, BOREN = SBORDIS, BORV = 30 = OFF, WDTPS = 32768 = OFF,LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC = ON, LVP = OFF, XINST = OFF OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF OFF, CPD = OFF OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF OFF, WRTC = OFF, WRTD = OFF OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF OFF

可使用 #pragma config 伪指令为每个配置字定义配置位。根据特定单片机所支持的 功能不同,各个 PIC18FXXXX 单片机中用于引用每个位或位域设置 (即 OSC = INTIO67) 的MPLAB C属性也可能不同。在MPLAB IDE帮助中可以找到某个特定单片 机可用的所有属性。 我们来查找 PIC18F45K20 的属性: 1. 选择 MPLAB IDE 菜单 Help > Topics… 在 “MPLAB Help Topics” (MPLAB 帮助主题)对话框中找到 “Language Tools” (语言工具)类别,选择 “PIC18 Config Settings” (PIC18 配置设置)主题。 2. “PIC18 Config Settings”主题如图 3-13 所示。 单击 OK。 3. 帮助窗口打开后,选择 Contents 选项卡并展开 “Configuration Settings” (配 置设置)部分。 4. 选择 PIC18F45K20 单片机以显示可与 #pragma config 伪指令结合使用的所 有配置位设置属性,如图 3-14 所示。 图 3-13: MPLAB HELP TOPICS  图 3-14: PIC18F45K20 配置

DS41370C_CN 第 22 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
以下配置位设置对于本课程的项目非常重要,且不使用默认值:
FOSC = INTIO67 这会将 PIC18F45K20 设置为使用内部振荡器工作,无需晶振或外 部振荡器。默认频率是 1 MHz。会在第 9 课中详细说明该振荡器。 它还将 OSC1 和 OSC2 引脚设置为用作 RA6 和 RA7 I/O 端口引脚 (因为不需要使用 OSC 引脚功能) 。 这会关闭看门狗定时器,因为本课程中不使用它。使能看门狗定时 器时,必须在代码中定期将其清零,否则它会使单片机复位。 这会关闭低电压编程功能,并释放 PGM 引脚以用作 RB5 I/O 端口 引脚。 (PICkit 3 编程器不使用 LVP 模式。 )

WDTEN = OFF

LVP = OFF

尽管所有其他位都保留为默认设置,但还是强烈建议在源代码中定义所有位,就像在 第 2 课的源代码中所做的那样。这可以确保编译器编译生成的 .hex 文件中的程序存储 器映像包含所有用于目标应用的配置设置。但 DEBUG 位除外,它是由 MPLAB IDE 环境根据目标单片机是否运行在调试模式下来定义的。

3.2.3

探究第 2 课的源代码

在 MPLAB IDE 编辑器窗口中打开第 2 课的源代码文件 02 Blink LED.c (如果未打 开的话) 。 图 3-15: 第 2 课 “使 LED 闪烁”的源代码
S **************************************************/

/** I N C L U D E #include "p18f45k20.h" #include "delays.h" /** D E C L A R A

T

I

O

N

S

*******************************************/

void {

main

(void)

TRISD while {

= (1)

0b01111111;//

PORTD

bit

7

to

output

(0)

;

bits

6:0

are

inputs

(1)

LATDbits.LATD7

=

~LATDbits.LATD7; Delay 50 x

//

toggle =

LATD cycles; 200ms @ 1MHz

Delay1KTCYx(50);// } }

1000

50,000

此源代码中有两个新行值得注意。 第一行是新的头文件: #include "delays.h" 这是 MCC18 “delays”库的头文件,它提供了用于创建一定数量的处理器周期的程序 延时的函数。 MPLAB C 编译器配备了许多有用的库,包括标准 C 函数库 stdio 和 stdlib 以及 ctype 、 delays、math 和 string 函数库。还有使用硬件外设功能所需 的库,如 adc、 i2c、 pwm、 spi、 usart 和 timers,以及对外设进行软件仿真所 需的库,如 sw_i2c、 sw_uart 和 sw_spi。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 23 页

PICkit? 3 Debug Express
在 MCC18 头文件目录 C:\MCC18\h 中可以找到这些库的头文件。在 C:\MCC18\src 中可以找到大部分库的源代码,而库本身位于 C:\MCC18\lib 中。 更多关于包含的库 函数的详细信息,请参见 《MPLAB? C18 C 编译器函数库》 (DS51297F_CN)文档。 另一需特别注意的新行是对 delays 库中一个函数的调用: Delay1KTCYx(50); 此函数使用软件创建延时,即 1000 (1k)指令周期 (TCY)乘以参数值。 此例中的 参数是 50, 所以此函数将延时 50 x 1,000 = 50,000 个指令周期。 PIC18FXXXX 单片机 上的指令速率等于 1/4 振荡器时钟周期;也就是说,执行一条指令占用 4 个时钟周期。 此例的时钟是 1 MHz 的内部振荡器,因此指令速率为 250 kHz,或 TCY = 4 us 每指 令。总延时为 50,000 x 4us = 200 ms,这非常缓慢,用人的肉眼足以看见 LED 点亮和 熄灭。 第 2 课的程序在一个无限 while 循环中运行此延时,这会将 RD7 I/O 引脚设置为在每 个 RD7 输出电平变化之间使用 200 ms 的延时对其当前值进行补偿 (结果就是在高低 电平之间来回切换) 这会使演示板上的 LED 7 闪烁。 。

3.2.4

编译和编程第 2 课的代码

请选择 MPLAB IDE 菜单、编译第 2 课的项目并使用 PICkit 3 编程器将代码烧写到演示 板 PIC18F45K20,就像在第 1 课中所做的那样。 演示板 LED 7 将连续闪烁,点亮 200 ms,然后熄灭 200 ms。

DS41370C_CN 第 24 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.3 第 3 课:轮流点亮 LED
本课程以前两节课程为基础,介绍了如何定义全局变量和代码段,并将轮流点亮功能 添加到 LED 显示中。 它将首先点亮 LED 0、然后依次是 LED 1、 LED 2,一直到 LED 7,然后再点亮 LED 0。 在本节以及随后的课程中,请在课程开始时在 MPLAB IDE 中打开相应的课程工作区。 重要概念 - 伪指令 #pragma udata 和 #pragma idata 用于在文件寄存器中为静态变 量分配存储单元。 - 伪指令 #pragma code 用于指示要编译到 PIC18FXXXX 程序存储器的指令 段。 - 伪指令 #pragma romdata 用于将常量 (只读)数据存储到程序存储器中。 它与关键字 rom 结合使用。 - 将常量数据存储到程序存储器中是为了避免用尽文件寄存器 RAM。

3.3.1

分配文件寄存器存储单元

在第 3 课的源代码文件 03 Rotate LED.c 中声明了全局变量 LED_Number,如图 3-16 所示。 图 3-16: 第 3 课中的全局变量声明

/** V A R I A B L E S *************************************************/ #pragma udata // declare statically allocated uninitialized variables unsigned char LED_Number; // 8-bit variable

在声明变量 LED_Number 之前使用伪指令 #pragma udata 是为了指示编译器接下来 的声明是应存储在 PIC18FXXXX 文件寄存器中的数据变量。 这一点与 PC 编译器不 同,因为 PIC18FXXXX 采用哈佛架构 (如本文档的第 2.1 节所述) ,而在 PC 编译器 中指令和变量共用同一存储空间。 以下两条伪指令可在定义变量时与 #pragma 结合使用:
udata idata 未初始化数据。该伪指令随后的数据以未初始化状态存储在文件寄存器空间中。 已初始化数据。该伪指令随后的数据存储在文件寄存器空间中。初始化值存储 在程序存储器中,然后在程序执行开始之前由启动初始化代码传送到文件寄存 器。

也可以为数据声明提供段名。段名可与链接描述文件的 SECTION 条目结合使用以将 其放到存储器的特定位置。 更多关于段与链接描述文件结合使用的信息,请参见 《MPLAB? C18 C 编译器用户指南》 (DS51288J_CN)的第 2.9 节。即使没有链接描 述文件段,也可使用 #pragma udata 伪指令指定在文件寄存器中存储数据的起始地 址。 例如,要将 LED_Number 存放到文件寄存器 Bank 3 的起始处,请按如下方式声 明 udata 段:
#pragma udata mysection = 0x300 unsigned char LED_Number; // 8-bit variable unsigned int AnotherVariable;

在 udata 或 idata 段中声明的其他变量将放到其随后的地址。 例如,上面的 16 位整 数 AnotherVariable 将占用地址 0x301 和 0x302。 注意函数的局部变量将放到软件堆栈中。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 25 页

PICkit? 3 Debug Express
如需 MPLAB C 支持的数据类型列表及其大小和限制,请参见 《MPLAB? C18 C 编译 器用户指南》 (DS51288J_CN)的第 2.1 节。

3.3.2

分配程序存储器

程序存储器常用于存储程序指令和常量数据。 第 3 课的源代码包括这两者的示例,如 图 3-17 所示。 图 3-17: 第 3 课中的常量数据和程序代码

/** D E C L A R A T I O N S *******************************************/ // declare constant data in program memory starting at address 0x180 #pragma romdata Lesson3_Table = 0x180 const rom unsigned char LED_LookupTable[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; #pragma void { code// declare executable instructions

main

(void)

以下两条基本伪指令用于定义程序存储器段:
code romdata 程序存储器指令。 将所有后续指令编译到目标 PIC18FXXXX 的程序 存储空间。 存储在程序存储器的数据。 用于与 rom 关键字结合使用,将后续常 量数据编译到程序存储空间。

在本课程中,我们使用常量数组 LED_LookupTable 将一个代表 LED 0-7 的数字转换 为一个用于置 1 相应 PORTD 引脚以点亮相应 LED 的位模式。 此常量数组是在 romdata 段中声明的,并使用了 rom 关键字以便存放到程序存储器中。由于程序不会 需要更改这些数组值,这就省去了用于存储真正变量的文件寄存器空间。 请注意,也可使用段名和绝对地址来声明 romdata 段:
#pragma romdata Lesson3_Table = 0x180

这些可选属性会强制编译器将 8 字节字符数组存放到程序存储器地址 0x0180 处。如果 未指定地址,链接器不可能总是将 code 或 romdata 段存放在确定的地址处。 请选择 MPLAB IDE 菜单 Project > Build All 以编译第 3 课的代码,然后选择 View > Program Memory 以显示程序存储器的编译后内容。 用于执行本课程程序代码的指令 包含在地址 0x0000 和 0x0146 处。 请注意,已将数组值编译到程序存储器中从指定地 址 0x180 开始到地址 0x186 结束的地址范围内,如图 3-18 所示。

DS41370C_CN 第 26 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-18: 程序存储器 “LED_LOOKUPTABLE”数组值

然后使用伪指令 #pragma 代码指定随后的段 (以 main () 声明开头)是将存放到程 序存储器中的可执行指令。 由于未指定可选段名和地址,此代码指令将被链接器存放 到第一个可用地址处。 与数据伪指令一样,段名也可以与链接描述文件中的 SECTION 条目集合使用,为段分配一段程序存储器空间。

3.3.3

探究第 3 课的源代码

在编辑器窗口中打开本课程的源代码文件 03 Rotate LED.c (如果未打开的话) 。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 27 页

PICkit? 3 Debug Express
图 3-19: 第 3 课 “轮流点亮 LED”的源代码
/** V A R I A B L E S *************************************************/ #pragma udata // declare statically allocated uninitialized variables unsigned char LED_Number; // 8-bit variable /** D E C L A R A T I O N S *******************************************/ // declare constant data in program memory starting at address 0x180 #pragma romdata Lesson3_Table = 0x180 const rom unsigned char LED_LookupTable[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; #pragma code// declare executable instructions

void main (void) { LED_Number = 0;// TRISD while { = (1)

initialize PORTD bits 7:0 are all outputs (0)

0b00000000;//

// use lookup table to output one LED on based on LED_Number value LATD = LED_LookupTable[LED_Number]; LED_Number++;// rotate 8) go display by 1

if (LED_Number == LED_Number = 0;// Delay1KTCYx(50);// } }

back 50

to x

LED 1000

0. = 50,000 cycles; 200ms @ 1MHz

Delay

以下是轮流点亮 LED 程序的基本流程:
初始化变量和 I/O 端口 用于保存我们当前想要点亮的 LED 号的全局变量 LED_Number 已置为 0,表示 将点亮第一个 LED。 TRISD 寄存器位也置为全 0,以使所有 8 个端口 D 引脚 RD0-RD7 都为输出。 使用 while(1) 语句无限循环: 设置 I/O 端口以点亮 LED。 要点亮的 LED 号 LED_Number 用作数组 LED_LookupTable 的下 标,数组返回一个与要点亮的 LED 对应的位置 1 的值。该值被写入 LATD 寄存器以点亮此 LED。 轮流 LED 号 LED 号递增到下一个 LED。if 语句用于检查是否已递增到最后一 个 LED。如果是,将复位到第一个 LED,其编号为 0。 延时 200ms (循环结束) 就像在第 2 课中一样, “delays”库函数用于创建延时。

3.3.4

编译和编程第 3 课的代码

在 MPLAB IDE 中,编译第 3 课的项目并使用 PICkit 3 编程器将代码烧写到演示板。 演示板 LED 从 LED 0 到 LED 7 依次点亮然后返回到 LED 0。

DS41370C_CN 第 28 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.4 第 4 课:开关输入
在本课程中使用演示板开关,在每次按下该开关时轮流点亮 LED。 重要概念 - 伪指令 #define 用于为 SFR 寄存器和位提供更有意义的名称。 - 如果共用模拟输入通道的 I/O 引脚用作数字输入,则必须使用 SFR ADCON1 将其配置为数字引脚,否则它们将始终读为 0。 - PORTx SFR 用于读输入端口引脚上的逻辑状态。 - 用软件进行机械开关去抖处理,这样可避免使用可能需要的外部元件。

3.4.1

文件和 #define 伪指令

本课程添加了一个头文件到名为 04 Switch Input.h 的项目,如图 3-20 所示。 图 3-20:
头文件

如果读者熟悉 C 语言头文件,就会注意到在 04 Switch Input.h 头文件中使用了 #define 伪指令为开关 I/O 引脚变量和一个常量值提供了更有意义的名称。
#define #define Switch_Pin DetectsInARow PORTBbits.RB0 5

与其他 C 编译器中 #define 的用法一样, MPLAB C 在编译时使用文本 “PORTBbits.RB0”替换所有的 “Switch_Pin”文本实例。记住,为了使编译器知道 #define 定义, 必须在 C 文件中包含头文件, 就像在 04 Switch Input.c 中所做的 那样:
#include "04 Switch Input.h" // header file

? 2009 Microchip Technology Inc.

DS41370C_CN 第 29 页

PICkit? 3 Debug Express
3.4.2 开关去抖
在嵌入式处理器应用中会经常遇到机械开关,而且机械开关便宜、简单、可靠。 但是, 这种开关通常也会产生非常大的电噪声。 这种噪声称为开关抖动,即开关触点之间的 连接会连上和断开多次,甚至可能是上百次,然后才稳定到最终的开关状态。 这会导 致那些速度较快的器件将一次开关按键检测为多次不同的开关按键,尤其是在使用边 沿敏感型输入时。 如果 “前进” TV 频道,将不会跳到下一个频道,而是选择向前跳过 两个或三个频道。 消除开关抖动的传统方案包括使用阻容电路滤除快速开关抖动跳变或使用可重新设置 的逻辑移位寄存器。 这些方法尽管有效,但会额外增加成本,增大电路板面积。 用软 件消除开关抖动可解决这些问题。 消除开关抖动的简单方法是在信号稳定之前对开关进行采样。 采样时间到底多长才合 适,这需要对开关特征进行一些研究,但是通常来说, 5 ms 已经足够了。 本课程的代码演示了每 1 ms 对开关输入采样一次,如果 5 次连续采样到同一值,就可 以确定已按下开关。 请注意, 44 引脚演示板上的开关抖动次数并不多,但却是消除所 有系统开关抖动的一个很好的做法。 图 3-21: 开关去抖程序流程图

3.4.3

探究第 4 课的源代码

在编辑器窗口中打开本课程的源代码文件 04 Switch Input.c (如果未打开的 话) 。

DS41370C_CN 第 30 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-22: 第 4 课 “开关输入”源代码
/** V A R I A B L E S *************************************************/ #pragma udata // declare statically allocated uinitialized variables unsigned char LED_Display; // 8-bit variable /** D E C L #pragma code// void { main A R A declare T I O N executable S *******************************************/ instructions

(void) char = Switch_Count 1; = 0; // // // // // // initialize PORTD bits 7:0 are all outputs (0)

unsigned

LED_Display TRISD =

0b00000000;

INTCON2bits.RBPU = 0; WPUBbits.WPUB0 = 1; ANSELH = 0x00; TRISBbits.TRISB0 = 1; while (1) { LATD = LED_Display; LED_Display <<= 1; if (LED_Display == 0) LED_Display = 1; while (Switch_Pin !=

enable PORTB internal pullups enable pull up on RB0 AN8-12 are digital inputs (AN12 on RB0) PORTB bit 0 (connected to switch) is input

(1)

// // //

output rotate rotated

LED_Display display by bit out,

value 1 so set

to

PORTD

LEDs

bit

0

1);//

wait

for

switch

to

be

released

Switch_Count = 5; do { // monitor switch input for 5 lows in a row to debounce if (Switch_Pin == 0) { // pressed state detected Switch_Count++; } else { Switch_Count = 0; } Delay10TCYx(25); // delay 250 cycles or 1ms. } while (Switch_Count < DetectsInARow);

3.4.3.1

变量

此程序声明了 2 个变量:全局变量 LED_Display 和局部变量 Switch_Count。 全局 变量将存放到第 3 课中讨论的文件寄存器空间中的专用地址。局部变量存放到软件堆 栈中,在进入函数时创建,退出函数时释放 (从堆栈中除去) 。 3.4.3.2 开关输入

演示板开关与 I/O 引脚 RB0 相连,该引脚通常在内部上拉到 VDD。 按下开关时,它将 RB0 拉至地 (低电平状态) 。 PORTx 特殊功能寄存器用于读输入引脚的状态。 因此,读 PORTBbits.RB0 会读到 RB0 引脚上的信号值。 不要忘记在头文件中, PORTBbits.RB0 被定义为 Switch_Pin,即代码用来读引脚值的位:
#define Switch_Pin PORTBbits.RB0

? 2009 Microchip Technology Inc.

DS41370C_CN 第 31 页

PICkit? 3 Debug Express
在 PIC18F45K20 中, RB0 与模拟输入 AN12 共用同一引脚。这种引脚必须配置为数 字或模拟输入。 这非常重要,因为 RB0 将被用作数字输入引脚以读取寄存器 PORTB 中的开关状态。 如果 RB0 配置为模拟输入,它将始终读为 0,而不是开关的实际状 态。在 SFR ANSEL 和 ANSELH 中将引脚配置为模拟或数字引脚。 图 3-23: ANSELH:模拟寄存器 1

清零 ANSELH 以将所有引脚设置为数字功能:ANSELH = 0x00; 现在我们可将 RB0 用作数字输入,所以相应的 TRISB 位应置 1 以将其配置为输入: TRISBbits.TRISB0 = 1; 3.4.3.3 轮流点亮 LED

此程序使用一个比第 3 课 (使用查找表实现演示目的)更为简单的方法来轮流点亮 LED。 04 Switch Input.c 在 LED_Display 变量中使用了一个置 1 位,将其写入 LATD 并在每次更新显示时移动一位。 最终该位将移出 LED_Display 的最高有效位, 当代码检查到此情况发生时,将 LED_Display 再次置为 1。 关于 I/O 端口引脚的更多信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN)的 。 第 10 节 “I/O 端口”

3.4.4

编译和编程第 4 课的代码

编译第 4 课的项目并使用 PICkit 3 编程器将代码烧写到演示板。 按下 Demo Board Switch (演示板开关)按钮以轮流点亮 LED。 每次按下按钮时都 会将 LED 编号前进到下一个 LED。

DS41370C_CN 第 32 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.5 第 5 课:使用 TIMER0
轮流点亮演示板上 LED 时,不使用程序循环提供延时,而是使用 Timer0 提供延时。 演示板开关可反转轮流方向。 重要概念 - Timer0 是单片机中实现的、用于计数时钟周期或外部事件的硬件计数器。 - 使用定时器代替处理器延时循环可将处理器从对周期进行计数中释放出来, 去执行一些其他有用的工作。 - 定时器 “预分频器”设置使定时器递增 1 所需的时钟周期数或事件数,允许 它比相同频率的时钟运行得更快或更慢。

3.5.1

PIC18F45K20 Timer0 模块

Timer0 模块是 PIC18FXXXX 单片机的定时器 / 计数器外设,可用于计数 T0CKI 引脚 上的振荡器时钟周期或外部事件。可将其配置为 8 位或 16 位定时器,其计数范围分别 为 0 至 255 或 0 至 65535。当计数器从最大值计满返回到零时,某个位标志置 1。 Timer0 模块还包括一个可选预分频器,该预分频器可配置为在定时器时钟源到达定时 器 / 计数器之前先对其分频。 例如,如果分频比为 1:1,那么定时器每个指令时钟周期 递增一次。 (记住,指令时钟周期 TCY 为振荡器时钟 FOSC/4。 如果分频比为 1:8, ) 那么定时器每 8 个时钟周期递增一次。 每次写定时器时,预分频器清零。 图 3-24: 16 位 TIMER0 简化框图

Timer0 配置为 16 位定时器时,读写定时器值必须谨慎。 定时器的低字节可作为 SFR TMR0L 直接读写。 但是,不能直接访问高字节,而是通过 SFR TMR0H 进行缓冲。 读 TMR0L 时使用定时器高字节值更新 TMR0H。 写 TMR0L 也会将 TMR0H 的内容写入 Timer0 高字节。 这使得用户可以一次读或写整个 16 位定时器。 因此,读定时器时应始终先读 TMR0L 再读 TMR0H。 写定时器时应始终先写 TMR0H 再写 TMR0L。 T0CON SFR 控制 Timer0 操作,如图 3-24 所示。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 33 页

PICkit? 3 Debug Express
图 3-25: T0CON:TIMER0 控制寄存器

要使用 Timer0 代替软件延时 Delay1KTCYx(50),应对其进行设置以便约每 200 至 300 ms 溢出。让我们回顾下产生这种效果的 T0CON 位的设置: T08BIT = 0 Timer0 配置为 16 位定时器 / 计数器来说明 TMR0H 的缓冲行为。 T0CS = 0 Timer0 以内部指令时钟运行。 Fosc = 1MHz 时,内部时钟为 250 kHz。 T0SE = 0 如果 Timer0 使用 T0CKI 引脚上的信号作为时钟源,那么此位将决定 Timer0 是在 T0CKI 引脚信号的下降沿还是上升沿递增。由于我们采用的是内部时钟,故此位 为 “无关位” 。这表示操作不会受此位的任何设置的影响。 PSA = 1 定时器将在计满 65536 个计数时溢出。在指令时钟速率为 250 kHz 时,每  65536 x (1 / 250,000) = 262 ms 就发生一次定时器溢出。这是我们希望范围内的时 间,所以不必将预分频器分配给 Timer0。它直接以指令时钟运行。

DS41370C_CN 第 34 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
T0PS2:T0PS0 = 000 由于未分配预分频器,故这些位为 “无关位” 。 最后: TMR0ON = 0 此位可启动和关闭定时器。 在此将其设置为 0,因为定时器将完成设置后启动。 要对 Timer0 配置这些设置,请将二进制值 0b0000100 写入 T0CON。 PIC18F45K20 还有 3 个其他可配置定时器: Timer1、 Timer2 和 Timer3。 更多关于所 有 4 个定时器模块的信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN)中 第 11 至 14 节。

3.5.2

探究第 5 课的源代码

在编辑器窗口中打开本课程源代码文件 05 Timer.c 和头文件 05 Timer.h(如果还 未打开的话) 。 请注意在 05 Timer.h 中定义了两个定制枚举型变量类型:
typedef enum { LEFT2RIGHT, RIGHT2LEFT} LEDDirections; typedef enum {FALSE, TRUE} BOOL;

这允许我们使用这些类型声明变量并在 main() 中初始化它们:
LEDDirections Direction = LEFT2RIGHT; BOOL SwitchPressed = FALSE;

Direction 变量跟踪 LED 轮流点亮的方向,SwitchPressed 记住开关是否已按下, 这是因为开关按下时只应更改 LED 轮流方向一次。 while(1) 循环之前的以下代码按照之前讨论的那样设置 Timer0 模块。
// Init Timer INTCONbits.TMR0IF // T0CON = = 0; // // // // = 1; // line line line line line 1 2 3 4 5 T0CON = 0b00001000; 0b00000001; TMR0H = 0; TMR0L = 0; T0CONbits.TMR0ON

(ignore commented line for now)

为便于说明,注释中标明了行号,我们来讨论设置定时器时每行的功能。 Line 1 将 INTCON SFR 中的 TMR0IF 标志清零。 每当定时器溢出 (计满返回) 时该标志 位置 1,所以程序将查询该位以了解 LED 轮流延时何时结束。 但是,该标志不能由硬 件复位,必须用软件复位,所以程序在启动定时器之前必须确保它已清零。 Line 2 将设置装入 T0CON 以按照本课程之前讨论的那样配置定时器。 Line 3清零TMR0H缓冲区。记住TMR0H只缓冲定时器的高字节。直到写入TMR0L后0 值才真正写入定时器高字节。 Line 4 清零 TMR0L, 并导致将 TMR0H 写入定时器的高字节。因此, 整个 16 位定时器装 入了十六进制值 0x0000。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 35 页

PICkit? 3 Debug Express
Line 5 将 T0CON 寄存器的 TMR0ON (bit 7) 位置 1 以启动定时器使其开始递增。使用 某个 SFR 联合来访问某个位 (像 T0CONbits.TMR0ON)会更改此位,而不会影响其 他位。 注: 请注意在有些情况下,使用 SFR 联合来访问某个位也可能影响其他位。 此 指令执行期间实际发生的操作是读寄存器、修改位和重写整个寄存器。 此 操作称为读 - 修改 - 写。 如果读到的某个位的值与上次所设置的值不同,那 么此操作可能影响了寄存器中的其他位。 仔细检查 SFR 位的定义。 对于 T0CON,所有位都是可读写的,都只能由软件置 1 ;硬件不会影响任何位 的设置。

在 while(1) 循环中,更新 LED_Display 全局变量以基于 Direction 变量值循环 为 1 的位,然后更新 LATD。 然后 do{…}while() 循环在其等待定时器溢出和 TMR0IF 标志位置 1 时查询开关以 确定是否按下开关。 这是一个通过使用定时器使单片机在等待延时时不浪费处理时间 来计数指令循环期间的周期数、而是执行其他工作的简单示例。 按下开关时,反转 Direction 变量值。 在完成 do{…}while() 循环中的 if – else if 逻辑流后,可以看到按下开关时,方向只反转一次,直到释放开关并再次按 下为止。 最后,在 Timer0 溢出并且 TMR0IF 标志置 1 后,退出 do{…}while() 循环。 然后 TMR0IF 用软件程序清零,以便检测到下一次定时器溢出。

3.5.3

编译和编程第 5 课的代码

编译和编程第 5 课的项目。 LED 将轮流点亮,按下 Demo Board 按钮会反转轮流方 向。

3.5.4

分配 Timer0 预分频器

现在我们返回到 Timer0 设置语句中注释掉的代码行。请注释掉 T0CON 赋值语句而取 消注释另一条语句的注释, Timer0 设置代码应为:
INTCONbits.TMR0IF = 0; //T0CON = 0b00001000; T0CON = 0b00000001; TMR0H = 0; TMR0L = 0; T0CONbits.TMR0ON = 1;

看看会有什么改变: PSA = 0 预分频器现在分配给 Timer0, T0PSx 的值将设置预分频器的时钟分频比。 T0PS2:T0PS0 = 001 该值将预分频值设置为 1:4,表示 Timer0 现在将每 4 个指令周期递增一次而不是 每个指令周期递增一次。它现在占用的时间是计满到 65536 所需时间的 4 倍—— 刚超过 1 秒钟! 使用更改后的源代码再次编译和编程第 5 课的项目。 LED 轮流点亮的速率变慢了,确 切地说比以前慢了 4 倍。

DS41370C_CN 第 36 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.6 第 6 课:使用 PICkit 3 DEBUG EXPRESS
本课程讨论将 PICkit 3 用作在线调试器 (In-Circuit-Debugger, ICD) 它使用与第 5 。 课中相同的 MPLAB IDE 工作区和项目。请将 T0CON 分配设置回 “no prescale” (无 预分频)语句 (如果在上一课中修改了的话) 。 重要概念 - PICkit 3 之类的在线调试器使用一些片内资源使能调试功能。这些保留的文 件寄存器和程序存储单元在 MPLAB IDE 视图中被标记为 “R” ,用户应用程 序无法使用它们。 - 调试功能也保留了一个一层深的硬件返回地址堆栈和两个 I/O 引脚。 - 调试功能允许程序运行、暂停、单步逐语句运行以及在程序语句上设置断 点。 - 可用断点数取决于使用的 PIC 单片机。

注:

本课程使用 “第 5 课:使用 Timer0”的项目和源代码。

3.6.1

PICkit 3 Debug Express 保留的资源

PICkit 3 Debug Express 使用一些片内资源使能调试功能。用户应用程序代码无法使用 这些资源。 3.6.1.1 常规资源

? 为调试功能保留的 MCLR 引脚;调试时此引脚不能用作数字 I/O。 ? PGD 和 PGC 端口引脚为编程和在线调试功能保留。 因此,调试期间无法使用这 两个引脚上复用的其他功能。 ? 一个一层深的堆栈供调试器使用,用户代码无法使用此堆栈。 3.6.1.2 程序存储器和数据存储器资源

PICkit? 3 Debug Express 在调试期间使用目标器件中的程序存储器和文件寄存器地址 单元。 用户代码无法使用这些地址单元。 在 MPLAB IDE 中,寄存器显示中标记了 “R”的寄存器表示保留寄存器,如图 3-26 所示。 图 3-26: PIC18F45K20 中保留的 ICD 文件寄存器地址单元

? 2009 Microchip Technology Inc.

DS41370C_CN 第 37 页

PICkit? 3 Debug Express
如本文档的第 3.1.1 节所述,调试时必须使用 ICD “i”链接描述文件。 本 课程的项目已使用了正确的链接描述文件 18f45k20 i.lkr。

注:

3.6.2

在 MPLAB IDE 中选择 PICkit 3 作为调试器

PICkit 3 无法同时用作编程器和调试器,所以如果 PICkit 3 当前被选为编程器,选择它 作为调试器将导致禁止它作为编程器。 要在 MPLAB IDE 中使能 PICkit 3 作为调试器,请选择 Debugger > Select Tool > PICkit 3 (调试器 > 选择工具 > PICkit 3) Output 窗口将显示到目标单片机的连接, 。 如图 3-10A 所示。 开始调试 ? 在 MPLAD IDE 工具栏中,将项目配置从 “Rlease” (发布)更改为 “Debug” (调试) 。 ? 编译项目: Project > Build All ? 编程目标单片机: Debugger > Program (调试器 > 编程) ? 选择 Debugger > Run (调试器 > 运行)开始执行程序。 第 5 课的代码现在运行在调试模式下。 因为目标单片机将在调试模式下如正常情况下 一样工作,所以 LED 将轮流点亮,也可以按下按钮反转轮流方向。

3.6.3
3.6.3.1

基本调试操作
HALT (暂停)

演示板上的 PIC18F45K20 现在正在运行此课程的程序代码。 可随时选择 Debugger > Halt <F5> (调试器 > 暂停 <F5>)来暂停 (停止)代码执行。 MPLAB IDE 编辑器窗 口左边空白处的绿色箭头指示要执行的下一条语句。 代码有可能停止在与图 3-27 中所 示位置不同的其他地方。 图 3-27: 绿色箭头指向要执行的下一条语句

DS41370C_CN 第 38 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.6.3.2 单步运行 单步运行允许代码一次执行一条语句。 提供了三个单步运行选项: Step Into (单步执行) 这将一次单步运行一条语句,直到到达函数调用。 当对函数调用选择了 Step Into 时,调试器将跳入被调用函数的第一条语句。 快捷键是 <F7>。 图 3-28: STEP INTO

Step Over (单步跳过) 这将导致一次单步运行一条语句。当语句包含函数调用时,将执行整个函数,调 试器将跳到函数调用后的下一条语句。不会单步执行函数。 快捷键是 <F8>。 图 3-29: STEP OVER

Step Out (单步跳出) 这将完成当前函数的执行并跳到函数调用后的下一条语句。 可通过使用 Debugger > Step Over (调试器 > 单步跳过)的快捷键 <F8> 单步运行此 课程的代码。 3.6.3.3 RUN (运行)

Debugger > Run <F9> (调试器 > 运行 <F9>)将开始执行代码直到用户暂停它或遇到 断点。 3.6.3.4 RESET (复位)

Debugger > Reset > Processor Reset(调试器 > 复位 > 处理器复位)将执行目标单片 机的完全复位,所以将再次从程序代码开始处开始执行。此功能仅在目标器件暂停时 使用。 暂停演示板上的 PIC18F45K20 (如果它当前正在运行的话)并选择 Debugger > Reset > Processor Reset <F6>。这将在 MPLAB IDE 中打开一个名为 c018i.c 的新 文件。 这是启动代码,是 MPLAB C 库的一部分。 此库代码初始化 C 软件堆栈,分配 合适的数据值给任何已初始化数据变量并跳转到应用程序函数 main() 的开头。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 39 页

PICkit? 3 Debug Express
图 3-30: C018 库启动代码

3.6.4

使用断点

调试代码时可在程序语句上添加断点。 运行程序时,调试器遇到断点语句会暂停目标 单片机运行。 在 MPLAB IDE 05 Timer.c 源代码中,将编辑器光标置于第 111 行 “SwitchPressed = TRUE;”上,并右键单击以打开上下文菜单。 选择 Set Breakpoint (设置断点) ,如图 3-31 所示。在编辑器空白处将出现一个标有字母 “B”的红色八角形,表示已在此行设置了一个断点。

DS41370C_CN 第 40 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-31: 在第 111 行设置断点

图 3-32:

断点设置

按下 Demo Board Switch 按钮时将执行设置了断点的语句。选择 Debugger > Run 开 始执行程序。由于尚未执行设置了断点的语句,所以代码执行时演示板上的 LED 将轮 流点亮。 按下 Demo Board Switch 按钮。 程序在断点语句处暂停,如图 3-33 所示。现在可使 用 <F8> 单步运行代码。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 41 页

PICkit? 3 Debug Express
图 3-33:
断点暂停

程序中一次性可设置的断点数取决于被调试的 PIC18FXXXX 器件。 选择菜单 Debugger > Breakpoints… (调试器 > 断点 ...)将打开一个对话框以显示当前设置的 断点。 Silicon Debug Resource Toolbar (芯片调试资源工具栏)提供了所选器件的可 用断点总数 ( “HW BP” )和已使用断点数 ( “Used” 。 PIC18F45K20 一次最多可 ) 设置 3 个断点,且当前还可设置 2 个断点,这是因为已经在 05 Timer.c 的第 111 行 上设置了一个断点。 图 3-34:
BREAKPOINTS 对话框

DS41370C_CN 第 42 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
注: 有效断点数影响 Step Into 和 Step Over 功能的使用。使用这些功能时,在 要跳入的下一条语句上设置断点。 如果所有断点当前都已使用,没有可用 断点,那么 MPLAB IDE 无法在下一条 C 语句上设置断点。 它必须单步执 行每一条汇编指令,直到到达下一条语句为止。 如果使用了 Step Over,它 可能需要一些时间来单步跳过已编译函数中的所有汇编函数。 可通过释放 断点来解决这个问题。

3.6.5

观察变量和特殊功能寄存器

可通过打开 View > File Registers (视图 > 文件寄存器)来查看文件寄存器中的所有 值,通过打开 View > Special Function Registers (视图 > 特殊功能寄存器)来查看特 殊功能寄存器中的值。 但是,不建议保持这两个窗口为打开状态。 这是因为在运行、 暂停和每个单步运行操作时必须从目标器件读取整个文件存储器和所有 SFR。 通过 ICD 总线读所有这些数据需占用大量的时间。实际所花的时间取决于目标 PIC18FXXXX 所具有的存储器大小以及目标振荡器的速度。 由于目标振荡器速度直接 影响 ICD 总线速度,所以振荡器越慢,所花时间就越长。 如果已打开这两个窗口中的任一窗口,请现在关闭它们。 观察变量和 SFR 的最好方法是使用 Watch (观察)窗口。 此方法只更新所关注的变量 和寄存器。 要打开 Watch 窗口,请选择 View > Watch (视图 > 观察) 。 图 3-35:
WATCH 窗口

请从左上角的下拉框中选择某个 SFR 并单击 Add SFR (添加 SFR)按钮来将其添加 到 Watch 窗口。依此方法添加用于读取开关状态的 PORTB 和程序用来设置 LED 的 LATD。 使用右上角的下拉框选择某个符号并单击 Add Symbol (添加符号)按钮来添加用户 变量。 现在添加 LED_Display、 SwitchPressed 和 Direction 变量。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 43 页

PICkit? 3 Debug Express
图 3-36:
观察变量

注:

Watch 窗口、 File Register 窗口和 Special Function Register 窗口中的 “值”字段可能在首次打开时不会立即有效。 单步运行代码一次以更新值。

对于每个观察变量, Watch 窗口显示文件寄存器地址、符号名 (变量名)和当前值。 可在某个值上右键单击并从弹出菜单中选择 Properties (属性)来更改该值的显示格 式。 请注意,两个枚举型变量 SwitchPressed 和 Direction 将显示枚举值,而非助记 符。 Watch 窗口还可用于编辑变量值。 选择并单击 LATD 值,输入十六进制值 AA。 按下 enter 键以设置此值。查看演示板;请注意现在间隔点亮了 LED。 这是因为我们刚才通 过 Watch 窗口直接向 LATD 寄存器写入了值 0xAA,其二进制表示为 0b10101010! 选择 PORTB 符号,右键单击并选择 Properties。在属性对话框中,转到 “Format:” (格式:)下拉框并选择 “Binary” (二进制) 单击 OK 以关闭对话框。 PORTB 值 。 现在以二进制格式显示,左边为 bit 7。 使用 <F8> 单步运行代码一次。 请注意 PORTB bit 0 (即与演示板开关连接的引脚 RB0)的值。该位的值现在应置 1 (1) 按下 Demo Board 按钮时,再次使用 <F8> 。 单步运行代码一次。请注意由于按下了开关, PORTB bit 0 现在为低电平! 请花些时间演示课程代码、单步运行它并观察变量和演示板 LED。 也可以按下按钮并 单步执行开关检测语句。设置不同的断点以使用它们进行实验。 将 TMR0L 和 TMR0H SFR 添加到 Watch 窗口,并观察单步运行代码时它们的计数情 况。请注意,它们并不是每步递增一次,这是因为每条 C 语句可能被编译成多条汇编 指令, Timer0 每条汇编 (机器)指令递增一次。

DS41370C_CN 第 44 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.7 第 7 课:模数转换器 (ADC)
第 7 课以前一课为基础,使用片上 ADC 读演示板上电位器的电压。所得的结果用于改 变 LED 轮流点亮延时以便电位器能够控制 LED 轮流点亮的速度。 重要概念 - 模数转换器用于将模拟电压转换为表示电压的数字。 - ANSEL、 ANSELH、 ADCON0、 ADCON1 和 ADCON2 SRF 用于配置和控 制片上 ADC。 - 可向定时器寄存器写入一个值,该值将导致定时器在应用程序所需的特定时 间间隔溢出。

3.7.1

PIC18F45K20 ADC 基础知识

简单的说, ADC 采用输入电压与参考电压的比值并将其表示为数字。 此数与 ADC 分 辨率的位数有关。 例如,如果 PIC18F45K20 ADC 的分辨率为 10 位,那么这意味着提 供了从 0 到 1023 的 1024 个数字来表示电压比。 数学表示为: ADC 值 = (VIN/VREF) * 1023 如果 VIN = 2.5V 且 VREF = 5.0V,那么 ADC 值为 (2.5/5)*1023 = 511。这就是说,由于 VIN 是 VREF 的一半,所以 ADC 值是 1023 的一半。 在求解 VIN 的等式中,如果已知参考电压,可将 ADC 值转换回电压值: VIN = (ADC 值 /1023) * VREF PIC18F45K20 ADC 可以以器件 VDD 电压或外部参考电压作为参考电压。 本课程中的 ADC 以 PICkit 3 提供的 PIC18F45K20 入门工具包演示板 VDD 为参考电压。为此器件 提供的电压通常为 3.3V 左右。 此 ADC 可转换 PIC18F45K20 上的 13 个通道中任一通道的电压。这些编号为 AN0 至 AN12 的模拟输入通道与单片机数字引脚复用,所以必须配置为模拟输入以供 ADC 使 用。 由下列 5 个特殊功能寄存器配置和控制 ADC: ANSEL、 ANSELH、 ADCON0、 ADCON1 和 ADCON2。 将在下一节中详细讨论这些寄存器。

3.7.2

ADC 配置和工作

查看附录中 44 引脚演示板的电路原理图可知,电位器 (RP1)输出与 PIC18F45K20 的 RA0/AN0 引脚相连。 此引脚上 ADC 电压转换所需的基本步骤是: 1. 2. 3. 4. 5. 在 ANSEL 中配置 RA0/AN0 引脚为模拟输入。 在 ADCON1 中设置 ADC 参考电压。 在 ADCON2 中设置结果对齐方式、 ADC 时钟源和采集时间。 在 ADCON0 中选择通道并开启 ADC。 在 ADCON0 中启动转换操作。

#1:要将某个引脚用作模拟输入,则同一引脚上复用的其他外设功能不得使用此引 脚。引脚 TRIS 位必须设置为 1 (输入) ,与 RA0 关联的 ANSEL 位应设置为 1 (模 拟输入) 但是,我们仍然希望 RB0/AN12 配置为开关的数字输入。 因此,我们在 。 ANSELH 中将与 AN12 相应的位设置为 0。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 45 页

PICkit? 3 Debug Express
#2:ADCON1 中的 VCFGx 位可选择 ADC 参考电压为 AN2 和 AN3 引脚上的电压、 VDD 和 VSS 或其他电压组合。由于演示板没有连接参考电压到 AN2 和 AN3,所以 ADC 以 VDD 和 VSS 为参考。这意味着 ADC 结果 “0”与 0V 或 VSS 相对应。 结果 “1023”与约 3.3V 或 VDD 相对应。 包括 #1 中的值在内,本课程的 ADCON1 设置为 ADCON1 = 0; 图 3-37: ADCON2:A/D 控制寄存器 2

#3:ADC 时钟应设置得尽可能短但仍应大于最小周期 “TAD” (数据手册参数 130) 。编写本文档时 PIC18F45K20 的最小 TAD 时间为 1.4 us。 如果振荡器的 FOSC 为 1 MHz,那么选择位 ADCS = FOSC/2 会提供一个 500 kHz 的 ADC 时钟。一个时钟 周期为 1/500kHz = 2us,大于最小 TAD 时间 1.4us。 因此 ADCSx = 000。

DS41370C_CN 第 46 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
ACTQx 位用于确定采集时间,还应考虑 ADC 的内部采集时间 Tacq (数据手册参数 132)和与 ADC 引脚连接的应用电路的稳定时间。数据手册中的内部采集时间 Tacq 在工作温度范围内为 1.4us。 应用电路是由电位器和电容 C3 组成的 RC 网络,稳定时 间非常长。 对于本演示课程,我们只是将 ACQTx 设置为最大值 20TAD 或 111。 20 TAD 相当于 20 个 ADC 时钟周期,或 20 * 2us = 40us。 对于结果对齐方式,我们选择位 ADFM = 0 以使结果左对齐,这使得可以非常轻松地 从 ADRESH 获得结果的高 8 位。 因此, ADCON2 配置值为: ADCON2 = 0b00111000 #4:演示板上的电位器与 AN0 相连,所以在 ADCON0 中选择了通道 0。 ADON 位设 置为 1 以开启 ADC 外设。 GO/DONE 位保留清零状态,因为我们还不想启动转换。 ADCON0 = 0b00000001 图 3-38: ADCON0:A/D 控制寄存器 0

? 2009 Microchip Technology Inc.

DS41370C_CN 第 47 页

PICkit? 3 Debug Express
#5:要开始 ADC 转换,请将 ADCON0 的 bit 1 (即 GO/DONE 位)置 1。 转换完成时 硬件将清零该位,所以稍后可查询 GO/DONE 以等待转换完毕。 转换完成且 GO/DONE = 0 时,可从 ADRESH 和 ADRESL 读 ADC 转换结果。

3.7.3

探究第 7 课的源代码

在 MPLAB 编辑器窗口中打开课程源文件 07 ADC.c 和 07 ADC.h (如果还未打开的 话) 。 请注意, Timer0 设置代码已转移到函数中并被一个函数调用代替。添加了两个新的函 数以支持 ADC。
void Timer0_Init(void) void ADC_Init(void) unsigned char ADC_Convert(void)

函数原型也已添加到头文件 07 ADC.h 中。 在 main() 中进入 while(1) 循环之前,程序提供了两个函数调用以分别使用 Timer0_Init() 和 ADC_Init() 设置 Timer0 和 ADC 外设。 要使用电位器更改 LED 轮流点亮的速度,请使用 ADC 转换值在 Timer0 溢出后设置 Timer0。 因为定时器是从所写入的值开始计数,所以写入 Timer0 的值越高,再次溢出 所需的时间就越少。 这可以在 while(1) 循环的底部使用两个新语句来完成:
TMR0H TMR0L = ADC_Convert(); = 0; // // MSB from ADC LSB = 0

可用 ADC 转换的高 8 位写 TMR0H 缓冲区,然后在 TMR0L 赋值语句中用 0 写 Timer0 的低字节。回顾第 5 课,由于 TMR0H 实际上是一个缓冲区,不是定时器的高 字节,是在写 TMR0L 时被写入定时器。 因此,必须像本课程一样首先写入 TMR0H。 对于一个给定的 ADC 值,如果已知 Timer0_Init() 将 TMR0 预分频比设置为 1:4, 振荡器频率为 1MHz,那么可以计算出延时时间。 Timer0 将以 4 * 指令速率进行计数, 即 4 * 1/(FOSC/4) = 4 * 1/(1MHz/4) = 4 * 1/250kHz = 16 us。 溢出发生前的计数值为 0x10000– ( 起始计数值 ),其中 ( 起始计数值 ) 是写入 TMR0 的值,即高字节中的 ADC 结果和低字节中的 0x00。 然后总延时等于计数值乘以计数速率。 如果 ADC 结果 为 0x81,则延时为 (0x10000 – 0x8100) * 16 us = 0x7F00 * 16 us = 32512 * 16 us = 0.52 秒。

3.7.4

使用 PICkit 3 Debug Express 编译和运行第 7 课的代码

编译和编程第 7 课的项目,然后在调试器中运行应用程序。旋转演示板上的电位器会 影响 LED 的轮流点亮速度。可按下开关反转轮流点亮的方向。 暂停第 7 课的程序。请注意已经有几个 SFR 和变量添加到 Watch 窗口。 使用断点和 单步运行命令来探究代码。 观察 ADRESH 中的 ADC 结果如何受电位器电压的影响以 及如何将此结果复制到 TMR0。

DS41370C_CN 第 48 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
更多关于 ADC 外设的信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN) 中的第 19.0 节 “10 位数模数转换器 (A/D)模块” 。 注: 如果 TMR0L 已添加到 Watch 窗口,它将导致在单步执行以下 2 行代码后 工作不正常: TMR0H = ADC_Convert(); TMR0L = 0; 这是由 TMR0H 的缓冲性质引起的。当单步跳过 TMR0H 赋值语句时, MPLAB IDE 将读 TMR0L 寄存器以更新 Watch 窗口中的值。 读 TMR0L 时, TMR0 的高字节被装入 TMR0H 缓冲区,擦掉了上个 TMR0H 赋值语句 写入的值。 一种能够将 TMR0L 添加到 Watch 窗口的变通方法是确保不会从 TMR0H 语 句运行到 TMR0L 语句。 在 TMR0L 赋值语句上设置断点,并从 TMR0H 赋 值语句运行。

3.8

第 8 课: 中断
本课程修改了第 7 课的代码以使用开关按键和 Timer0 事件中断 (以取代查询操作) 。 开关使用 RB0/INT0 外部中断功能。 重要概念 - 中断是 “中断”程序代码以执行特殊功能的硬件事件。 退出中断功能时,程 序执行返回到被中断点处。 - PIC18FXXXX 支持一或两级的中断优先级。 - 低优先级中断可中断主程序。高优先级中断可中断主程序或低优先级中断。 - 伪指令 #pragma interruptlow 和 #pragma interrupt 用于定义中断 函数。

3.8.1

PIC18FXXXX 中断架构

当外设需要服务或发生某一事件时,它会将中断标志置 1。 每个标志都有一个中断允许 位,用于确定是否向单片机产生中断。 在之前的课程中,都是查询 TMR0IF 等中断标 志,但并没有产生中断,这是因为其中断允许位未置 1。中断允许位只允许选定的事 件引起中断。首先是所有的中断一起进行逻辑 “或”操作,然后与全局中断允许位进 行逻辑 “与”操作。 图 3-39: 简单的中断逻辑

? 2009 Microchip Technology Inc.

DS41370C_CN 第 49 页

PICkit? 3 Debug Express
当中断发生且主中断信号有效时, PIC 单片机完成当前指令的执行、将下一个地址存 储在返回地址堆栈中,然后跳转到中断向量处。 在中断向量处,它开始执行标记为中 断服务程序的函数。 退出此函数时,程序执行返回到返回地址堆栈中存储的地址处。 因为中断会导致立即执行专用代码,所以中断使得硬件事件操作得以非常快速地执行, 并且与主程序的状态无关。 PIC18FXXXX 架构支持最多两级的中断优先级,其中每一级都具有类似于图 3-37 中 的逻辑结构。大多数中断都具有与中断标志相关联的优先级位,可为其分配两个优先 级之一。 可以选择是否使用优先级, PIC18FXXXX 可以配置为只使用一级优先级。 使用两级中断优先级时,任一中断优先级都可以中断主程序。 但是,只有高优先级中 断可以中断低优先级中断,且没有什么操作可以中断高优先级中断。 如图 3-38 所示, 在执行主程序代码的 statement3 期间发生低优先级的中断事件时,程序发生跳转以 开始执行低优先级的中断函数。 在执行 lo_statement2 期间,发生高优先级的中断 事件时,可导致程序执行跳转到高优先级的中断函数。当高优先级的函数执行完毕并 退出时,程序执行返回到低优先级函数中被中断点处。 类似地,当低优先级函数执行 完毕并退出时,程序执行返回到主程序代码中被中断点处即 statement4。 图 3-40: 优先级中断执行流程图

高优先级中断向量位于程序存储器地址 0x0008 处。低优先级中断向量位于程序存储器 地址 0x0018 处。 如果不使用中断优先级,则所有中断跳转到 0x0008 处的高优先级向 量。

3.8.2

探究第 8 课的源代码

要注意的第一件事情是 Directions 变量现在是全局变量,所以可在中断服务程序函 数中访问到它。 使用中断时,必须使用 #pragma 代码伪指令在合适的向量地址处定义和放置中断向 量。 行内汇编 GOTO 语句可将程序执行重定向到其名称为 GOTO 参数的中断函数处。

DS41370C_CN 第 50 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-41:
/** I N T E R

定义中断向量
R U P T S ***********************************************/

//---------------------------------------------------------------------------// High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptServiceHigh //jump to interrupt routine _endasm } //---------------------------------------------------------------------------// Low priority interrupt vector #pragma code InterruptVectorLow = 0x18 void InterruptVectorLow (void) { _asm goto InterruptServiceLow //jump to interrupt routine _endasm }

接着,中断服务程序函数本身用 #pragma interrupt 伪指令声明高优先级向量,用 #pragma interruptlow 声明低优先级向量。请注意, 向量 GOTO 参数、 #pragma 属 性和函数声明名之间的名称必须相匹配。 中断函数可以调用源代码中任何位置定义的 其他函数 (虽然本课程的源代码没有这么做) 。 图 3-42: 中断服务函数
pragma for high priority

// Iterrupt Service Routines #pragma interrupt InterruptServiceHigh// "interrupt" void InterruptServiceHigh(void) { //function statements } // return from high-priority interrupt

#pragma interruptlow InterruptServiceLow // "interruptlow" pragma for low priority void InterruptServiceLow(void) { //function statements } // return from low-priority interrupt

由于优先级相同的所有中断的向量都指向同一函数,所以有必要在函数中检查是哪个 已允许中断标志导致了中断。在发现此标志以使相应的外设或事件得到服务后,软件 必须将该中断标志位清零以复位此中断。 在本课程的源代码中,高优先级的中断程序 查找 INT0 引脚中断标志位 INT0IF。 源代码中给出了如何检查其他已允许中断 (例如 Timer1 TMR1IF 和 ADC ADIF)的示例 (虽然在本课程代码中这两个中断都未被允 许) 类似地,低优先级的向量检查 Timer0 标志 TMR0IF。 。 设置中断 既然源代码已定义了中断向量,并具有处理这些中断的函数,那么它必须正确设置和 配置中断逻辑并允许要使用的各个中断。 可使用 INTCONx 特殊功能寄存器设置 Timer0 和外部引脚中断。 可通过一组外设中断 SFR 来设置其他中断: PIRx、 PIEx 和 IPRx。 PIRx 寄存器包含中断标志。相应的中断

? 2009 Microchip Technology Inc.

DS41370C_CN 第 51 页

PICkit? 3 Debug Express
允许位位于 PIEx 寄存器中, IPRx 寄存器中的位设置中断优先级为低或高。关于这些 寄存器中位的详细信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN)中的 第 9.0 节 “中断” 。 图 3-43: 第 8 课中断初始化
interrupt = 0; = 0; = 1; ALWAYS a INT0 // interrupt on falling edge // ensure flag is cleared // enable INT0 interrupt high priority interrupt on of INT0 (switch pressed)

// Set up switch INTCON2bits.INTEDG0 INTCONbits.INT0IF INTCONbits.INT0IE // NOTE: INT0 is

// Set up global interrupts RCONbits.IPEN = 1; INTCONbits.GIEL = 1; INTCONbits.GIEH = 1; void Timer0_Init(void) { // Set up Interrupts for timer INTCONbits.TMR0IF = 0; INTCON2bits.TMR0IP = 0; INTCONbits.TMR0IE = 1;

// // //

Enable priority levels on interrupts Low priority interrupts allowed Interrupting enabled.

// // //

clear roll-over interrupt flag Timer0 is low priority interrupt enable the Timer0 interrupt.

按下 Demo Board 按钮时需要中断。 因此,程序利用 RB0 引脚的 INT0 功能,将此引 脚用作外部中断输入引脚。此中断是边沿触发的,我们希望在下降沿触发中断以检测 首次开关按键。 可使用 INTCON2bits.INTEDG0 设置边沿方向。 INT0 始终为高优先 级中断。在使用 INT0IE 允许中断之前先清零 INTCON 中的标志位 INT0IF。 在此为简 单起见忽略了开关去抖,但是在实际产品应用中建议不要忽略。 Timer0 的中断配置已添加到 Timer0_Init() 函数中。首先确保已清零标志位 TMR0IF, 使用 TMR0IP 将优先级设置为低 (0)并接着使用 TMR0IE 允许中断。 在允许全局中断之前,对各个中断的允许是无效的。 首先, RCON 中的 IPEN 位用于 允许或禁止中断优先级。 在第 8 课中,它被置 1 以允许中断优先级。使用 GIEL 允许 低优先级中断,使用 GIEH 允许单片机中断。 请注意,因为 GIEH 为 0 时会同时禁止 这两个优先级的中断,所以不能使用这两个位单独允许高优先级中断和低优先级中断:
INTCONbits.GIEH INTCONbits.GIEL 中断功能 0 0 无中断;禁止所有中断。 0 1 无中断;禁止所有中断。 1 1 0 1 仅允许高优先级中断。 允许这两个级别的中断。

因此可以只使用一个位 (INTCON 中的 GIEH)来禁止所有中断。

DS41370C_CN 第 52 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-44: 第 8 课的中断 SFR

在第 8 课的源代码中,所有用于更改轮流点亮方向的语句都包括在 INT0 开关中断函数 中,用于轮流点亮 LED 显示的语句包括在 TMR0 中断函数中。 主程序中只有一个使用 LED_Display 更新 PORTD 寄存器的 while() 循环。 该语句也可以放到 TMR0 中断 函数中,但仍将它保留在主程序中是为了说明主程序如何连续运行和与中断交互。 单优先级中断 如果仅使用单优先级中断 (RCON 位 IPEN = 0) ,那么只需要定义 0x0008 处的中断 向量以及一个具有 #pragma 中断伪指令的中断服务程序函数。 忽略所有优先级位的设 置。 INTCON 位 GIEH 和 GIEL 的功能分别变成了具有以下功能的 GIE 和 PEIE:
INTCONbits.GIE 0 0 1 1 INTCONbits.PEIE 中断功能 0 无中断;禁止所有中断。 1 无中断;禁止所有中断。 0 1 仅允许 INTCONx 中已允许的中断。 所有 PIEx 中断保持禁止状态。 允许所有中断,包括 PIEx 寄存器中允许 的中断。

3.8.3

使用 PICkit 3 Debug Express 编译和运行第 8 课的代码

编译和编程第 8 课的项目,然后在调试器中运行应用程序。 旋转演示板的电位器会影 响 LED 的轮流点亮速度。 可按下开关反转轮流点亮的方向。 使用断点探究中断功能。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 53 页

PICkit? 3 Debug Express
3.9 第 9 课: 内部振荡器 本课程讨论 PIC18F45K20 的片内振荡器和锁相环 (Phase Locked Loop, PLL)的使 用。 无需外部振荡器元件就可以产生从 31 kHz 至最高 64 MHz 的时钟。 重要概念 - 要使用内部振荡器模块,请将 OSC 配置位设置为 INTIO67 或 INTIO7。 后者 可在 RA6 引脚上输出时钟信号 CLKO。 - OSCCON 特殊功能寄存器用于设置内部振荡器基频:从 31 kHz 至最高 16 MHz。 - OSCTUNE 寄存器允许微调内部振荡器频率以及使能或禁止 PLL。 - 仅当在 OSCCON 中选择基频为 8 MHz 或 16 MHz 时使用 4x PLL。 使能 PLL 对基频 4 倍频,可分别提供 32 MHz 和 64 MHz 的时钟。

3.9.1

内部振荡器模块

PIC18F45K20 的内部振荡器模块可产生两种不同的时钟信号。主输出 INTOSC 是经过 出厂校准的带后分频器的 16 MHz 时钟源,可提供低至 31 kHz 的时钟频率范围。 另一输出 INTRC 是标称 31 kHz 时钟源,可驱动上电延时定时器、故障保护时钟监视 器和看门狗定时器之类的外设并提供双速启动功能。 当设置振荡器模块以便为单片机提供 31 kHz 的时钟时,可选择为 INTOSC 的后分频输 出以实现校准精度;或选择为 INTRC 以实现低功耗。 振荡器模块还包含一个可将单片机时钟源的频率增加到最高 32 MHz 的 4x PLL (锁相 环)倍频器。 PLL 仅在内部振荡器模块所选择的输出为 8 MHz 或 16 MHz 时可用。 它 会将 4 MHz 的基频信号 4 倍频得到 32 MHz,和从 8 MHz 的基频时钟得到 64 MHz。 这使得内部振荡器模块能提供 10 种不同的频率 (可用软件选择) :31 kHz、 250 kHz、500 kHz、1 MHz、2 MHz、4MHz、8 MHz、16 MHz 以及(通过 PLL 得到)32 MHz 和 64 MHz。 回顾之前的课程,可知其复位时的默认频率为 1 MHz。 图 3-45: 内部振荡器模块的简化框图

CPU 和外设 后 分 频 器

DS41370C_CN 第 54 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.9.2 配置内部振荡器
通过配置位将内部振荡器模块选为主振荡器。 CONFIG1H 配置字中的 OSC 位设置为 INTIO67 或 INTIO7。 选择 INTIO67 时,内部振荡器是主振荡器,且外部振荡器引脚 OSC2 和 OSC1 可用作 RA6 和 RA7 I/O 引脚。OSC = INTIO7 时惟一的不同是 RA6 不 可用;此时内部指令时钟在该引脚上以 CLKO 形式输出。 提供了两个用软件控制内部振荡器模块的特殊功能寄存器 OSCCON 和 OSCTUNE, 分别如图 3-44 和 3-45 所示。 图 3-46: OSCCON: 振荡器控制寄存器

OSCCON 中的 IDLEN 位影响振荡器在功耗管理模式下的工作,这里不作深入讨论。 IRFCx 位决定内部振荡器的频率。 这些都是后分频器的输出。如图 3-46 中的注 2 所述, 31 kHz 的时钟可选择为 INTOSC 8 MHz 振荡器的后分频形式 (所有其他频率以此频率 为基频)或为 INTRC 低功耗 31 kHz 振荡器,如第 3.9.1 节所述。使用 OSCTUNE 寄存 器中的 INTSRC 位进行选择。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 55 页

PICkit? 3 Debug Express
在程序执行期间,可通过软件更改 IRFCx 位,允许程序根据当前处理的需要 “调节” 单片机执行速度。 在不需要很快的时钟速度时,这可以节省功耗。 OSTS 和 IOFS 位是只读状态位。 PIC18F45K20 可选择以内部振荡器提供的时钟启动 运行, 直到外部振荡器电路稳定为止。 这使得具有外部振荡器的单片机能够快速启动。 OSTS 用于告知软件时钟源何时切换到外部主振荡器。本课程不对此功能进行深入讨 论。 SCSx 位允许软件将单片机时钟源切换到内部振荡器模块,即使用配置位选择了外部 振荡器也是如此。 也可以选择辅助振荡器,该振荡器是 Timer1 中的低速低功耗振荡 器,通常在实时时钟 (Real-Time Clock, RTC)应用中依靠 32 kHz 晶振运行。 在本 课程中,已通过配置位将内部振荡器选为了主振荡器,即 SCS1:SCS0 = 00。 图 3-47: OSCTUNE:振荡器调节寄存器

OSCTUNE 中的 6 个 TUNx 位用于对 INTOSC 振荡器频率进行微调。 这用于将频率校 准得比出厂校准更为精确以及调节随 VDD 和温度变化引起的漂移。 PLLEN 位用于使能 PLL (4 倍频 INTOSC 输出) 。请注意 PLL 仅在 INTOSC = 8 MHz 或 INTOSC = 16 MHz 的情况下使能。 使能 PLL 时,基频为 4 MHz 会提供 16 MHz 的 时钟,基频为 16 MHz 会提供 64 MHz 的时钟。 更多关于内部振荡器模块的信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN) 的第 2.6 节。

DS41370C_CN 第 56 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.9.3 探究第 9 课的源代码
第 9 课的程序代码在 main() 函数中具有一个简单的后台循环,用以在演示板 LED 上 显示二进制计数,如图 3-48 所示。每个计数递增延迟 64,000 个指令周期。 时钟频率 的变化会导致指令速率也会变化,因此随着时钟频率的增加总延时 (以秒计)会变 短。 其结果就是 LED 显示将随着时钟速度的增加而加快计数速率。 在程序开始执行时,内部振荡器以 250 kHz 的频率运行。 每次按下演示板开关都会产 生一个中断,使时钟频率以 2 的因数增长,最高达 64 MHz,然后返回到 250 kHz。 图 3-48:
while (1) {// delayand

源代码后台循环
counton LEDs here.Interrupt handles switch and freqchanges

LATD =LED_Count++; Delay1KTCYx(32); }

//output countto PORTD LEDs //delay 32,000cycles or about

1

secat

125kHz

第 9 课源代码中还有几点值得注意: ? 中断配置为只有一个优先级,禁止了中断优先级。 这与第 8 课源代码是不同的, 在第 8 课源代码中允许了中断优先级。 ? 第 9 课源代码没有像在之前的课程中一样使用 ADCON1 将开关输入 RB0 配置为 数字输入,而是将配置位 PBADEN 设置为 OFF。 这会导致所有 PORTB 引脚在复 位时默认为数字输入,而不是模拟输入。 ? 第 9 课中断服务函数 void InterruptService(void) 演示了从中断服务代码 内调用另一个函数 void SetIntOSC(IntOSCFreq *ClockSet)。

3.9.4

使用 PICkit 3 Debug Express 编译和运行第 9 课的代码

编译和编程第 9 课的项目,然后在调试器中运行应用程序。 按下演示板开关会导致程 序在执行期间更改振荡器频率。 振荡器频率增加时, LED 计数的速率也会增加。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 57 页

PICkit? 3 Debug Express
3.10 第 10 课:使用内部 EEPROM
PIC18F45K20 单片机包含一个 256 字节的片内 EEPROM,用于存储数据。 本课程讨 论如何用软件读写内部 EEPROM。 重要概念 - 控制 EEPROM 操作的 4 个 SFR 分别是 EECON1、 EECON2、 EEDATA 和 EEADR。 - 一次只能读写内部 EEPROM 的一个字节。 - 要写 EEPROM,必须将短代码序列写入 EECON2,然后紧接着启动写操 作。这可以防止意外的 EEPROM 写操作。 - 向 EEPROM 写一个字节需要花费一段时间才能完成写周期。 在 EEPROM 写周期期间,单片机继续执行代码。

3.10.1

从 EEPROM 读一个数据字节

EECON1 特殊功能寄存器控制对内部 EEPROM 以及程序存储器闪存阵列的操作。 图 3-49: EECON1:EEPROM 控制寄存器 1

DS41370C_CN 第 58 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
通过清零 EECON1 中的 EEPGD 位开始读 EEPROM 字节操作,这便选择了要访问数 据 EEPROM 阵列。 在 EEPROM 访问期间也应该清零 CFGS 位;仅在访问配置位地 址单元时才置 1 该位。 将要读取的数据 EEPROM 地址单元的字节地址装入 EEADR 寄存器。 然后,将 EECON1 中的 RD 位置 1 以执行读操作。 在下一个指令周期,将读到的 EEPROM 地 址单元的值保存在 EEDATA 寄存器中。图 3-50 给出了用于读 EEPROM 字节的函数。 图 3-50: 读数据 EEPROM

unsigned char EEPROM_Read(unsigned char address) { // reads and returns the EEPROM byte value at the address given // given in "address". EECON1bits.EEPGD EECON1bits.CFGS= EEADR = = 0;// Set toaccessEEPROMmemory 0;// Do notaccessConfigregisters EEADRwith address of location to write.

address;//Load read 1;//Set is

// execute the EECON1bits.RD = //The value //needed. return } read

the the

RDbit next

to

execute

the cycle

EEPROM in

read No wait is

ready

instruction

EEDATA.

EEDATA;

3.10.2

向 EEPROM 写数据字节

与读操作类似,写内部 EEPROM 必须清零 EECON1 中的 EEPGD 和 CFGS 位以访问 内部 EEPROM 阵列。 然后将要写入的数据值写入 EEDATA 寄存器。 将要写入的字节 的地址装入 EEADR。 在执行写操作之前必须将 EECON1 中的 WREN 位置 1,否则无法执行写操作。 还必 须在将双字节序列 (值 0x55 和 0xAA)写入 EECON2 后,立即通过将 EECON1 中的 WR 位置 1 开始写操作。WREN 位和 EECON2 序列都是为了防止对 EEPROM 进行意 外写操作和确保 EEPROM 值的完整性。 此三个步骤的序列为:
EECON2 = 0x55; EECON2 = 0xAA; EECON1bits.WR = 1;

必须以此顺序完成,没有其他语句或中断,否则写操作无法执行。 因此,如果允许了 中断,应在 WR 位置 1 之后此序列之前禁止这些中断然后重新允许这些中断。 EEPROM 写操作需要一些时间擦除和编程阵列中的字节。 此时间在 PIC18F45K20 数 据手册第 26.0 节 “电气特性”中以参数 D122 的形式列出,通常为几毫秒。在此时间 内, PIC18F45K20 单片机继续执行程序代码。 程序可以通过查询或通过 EEPROM 模 块产生的中断来确定写操作何时完成。 在图 3-49 中的写函数示例中,代码通过查询 EECON1 的 WR 位来等待 EEPROM 写 操作完成。 写操作完成时,该位将清零。 或者通过中断告知程序写操作已经完成。 写 操作完成时, EEPROM 模块会将 PIR2 中的 EEIF 位置 1。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 59 页

PICkit? 3 Debug Express
更多关于数据 EEPROM 存储器的信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN)的第 7.0 节。 图 3-51: 写数据 EEPROM

void EEPROM_Write(unsigned char address, unsigned char databyte) { // writes the "databyte" value to EEPROM at the address given // location in "address". EECON1bits.EEPGD = 0; // Set to access EEPROM memory EECON1bits.CFGS = 0; // Do not access Config registers EEDATA = databyte; // Load EEDATA with byte to be written EEADR = address; EECON1bits.WREN = INTCONbits.GIE = // // // // Load EEADR with Enable writing Disable Begin interrupts Write sequence EEPROM write address of location to write.

1; 0;

EECON2 = 0x55; EECON2 = 0xAA; EECON1bits.WR = 1; INTCONbits.GIE = 1; while (EECON1bits.WR { // wait for }; EECON1bits.WREN = }

// Set WR bit to begin // re-enable interrupts == 1) to // complete. Disable writing as a

write 0;

precaution.

3.10.3

探究第 10 课的源代码

第 10 课的程序写数据 EEPROM 存储器的所有 256 字节,使用 “值 = 255 – 地址”来 写每个地址单元。 例如,地址 0x09 处的 EEPROM 字节写入了值 0xF6 = 246。 写完了所有地址单元后,程序以无限 while(1) 循环结束。

3.10.4

使用 PICkit 3 Debug Express 编译和运行第 10 课的代码

编译和编程第 10 课的项目,然后在调试器中运行应用程序。可选择 view > EEPROM (视图 > EEPROM)在 MPLAB IDE 中查看 EEPROM 存储器。 注: 调试期间, MPLAB IDE 中的 EEPROM 窗口不会更新为新的 EEPROM 值。

由于调试期间 EEPROM 存储器窗口不会更新为更改的 EEPROM 字节值,所以需要选 择 Debugger > Read (调试器 > 读)来查看数据 EEPROM 存储器的当前内容。 但 是,这样做会导致程序复位。

DS41370C_CN 第 60 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.11 第 11 课:程序存储器操作
本课程中涉及的主题包括读、写和擦除闪存程序存储器中的地址单元、通过配置位保 护程序存储器的存储区以及使用指向程序存储器的 C 指针的注意事项。 重要概念 - 使用 ROM 关键字声明的指针指向程序存储器地址单元。 - EECON1 和 EECON2 SFR 控制程序存储器的擦除和写操作。 - 与数据 EEPROM 存储器不同,闪存程序存储器必须被显式擦除才能对其执 行写操作。 - CPx (代码保护)配置位用于防止编程器读单片机的程序存储器范围。 - WRTx 配置位用于防止软件对程序存储器范围执行写操作, EBTRx 位用于防 止软件对程序存储器范围执行读操作。 - ROM 指针和读闪存程序存储器 MPLAB C 编译器通过允许指针指向要声明的程序存储器来简化对存储在程序存储器中 数据的处理。指针地址长度为 16 或 24 位,这取决于项目设置中选择了哪种 “代码模 型” “小代码模型”将产生 16 位指针,而 “大代码模型”产生 24 位指针。 要获得 。 最佳单片机性能,应使用产生 16 位指针的 “小代码模型” 对于具有大于 64 KB 的闪 。 存程序存储器的器件需使用 “大代码模型” ,以能够指向大于前 64 KB 程序存储器范 围的地址。 (16 位值的最大地址为 65536,即 64 x 1024 或 64K) 。 在 MPLAB IDE 中,可通过选择 Project > Build Options… > Project (项目 > 编译选项 ...> 项目)来更改代码模型设置。 这会弹出编译选项对话框。选择 MPLAB C18 选项 卡,然后从 “Categories” (类别)下拉框中选择 “Memory Model” (存储模型) , 如图 3-52 所示。 各指针声明还可以使用关键字 near 或 far 明确指定指针地址长度。 这两个关键字的 使用将改写代码模型设置。
near rom char *rom_pointer; // 16-bit pointer to program memory far rom char *rom_pointer; // 24-bit pointer to program memory

更多关于项目存储模型的信息,请参见 《MPLAB? C18 C 编译器用户指南》 (DS51288J_CN)的第 3 章。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 61 页

PICkit? 3 Debug Express
图 3-52: 项目代码模型设置

指向程序存储器的指针在声明后可指向程序存储器中的已声明地址单元 (例如 #pragma romdata 阵列)或明确地址。
#pragma romdata mystrings = 0x100 rom char hello_str[] = "Hello!"; rom_pointer char letter = = hello_str; *rom_pointer // = &hello_str[0]

现在 rom_pointer 指向程序存储器中 hello_str[] 阵列的首字母 “H” 变量 。 letter 的值现在为 “H” 。
rom_pointer = (near rom char *)0x320;

现在, rom_pointer 指向地址 0x320 处的程序存储器字节。 然后读闪存程序存储器只需要声明 ROM 指针和使用赋值语句来读指针值。

DS41370C_CN 第 62 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
3.11.1 擦除和写闪存程序存储器
写闪存程序存储器与写数据 EEPROM 存储器不同,它需要首先擦除要写的地址单元。 擦除时,程序存储器地址单元中的所有位置为 1。因此擦除的字节具有十六进制值 0xFF。 写程序存储器地址会将相应的位置为 0,但是写操作无法将某个位置为 1。与 EEPROM 操作还有一点不同:无法对程序存储器的一个字节执行擦除和写操作,只能 对指定数量的字节 “块”执行擦除和写操作。 PIC18F45K20 擦除操作的块大小为 64 字节。 这表示它将始终一次擦除 64 个连续字 节,且块的起始地址必须是 64 的倍数。例如,我们可以一次擦除从 128 至 191 的地 址范围内的 64 个字节,但是无法擦除从 100 至 163 的地址范围内的 64 个字节。 要擦除程序存储器的 64 字节块,我们使用 rom 指针设置要擦除的块的地址,并使用 EECON1 控制擦除操作。 设置指针地址会将地址置于 TBLPTRx 特殊功能寄存器中。 这三个寄存器保存使用 TBLRD 和 TBLWR 汇编指令对程序存储器执行操作的地址。 MPLAB C 编译器处理这些任务。 由于 EECON1 中的 EEPGD 位置为 1,所以这些操 作对程序存储器有效,对数据 EEPROM 无效。 由于我们不想选择配置位,所以 CFGS 位置为 0。 要选择与写操作相对的擦除操作,请先将 EECON1 的 FREE 位置为 1,然后将 WREN 位置为 1 以使能写 / 操擦除作。
// point to address 2176, which is a multiple of 64 rom_pointer = (near rom char *)0x880; EECON1bits.EEPGD = 1; EECON1bits.CFGS = 0; EECON1bits.FREE = 1; EECON1bits.WREN = 1; // // // // point to flash program memory not configuration registers we're erasing enable write/erase operations

接下来,与数据 EEPROM 的写操作一样,必须紧接 EECON2 序列,并将 EECON1 的 WR 位置 1 以启动写操作。
INTCONbits.GIE = 0; EECON2 = 0x55; EECON2 = 0xAA; EECON1bits.WR = 1; INTCONbits.GIE = 1; // // // // Disable interrupts Begin Write sequence Set WR bit to begin EEPROM write re-enable interrupts

与数据 EEPROM 的写操作一样,对闪存程序存储器的擦除或写操作需要多达几毫秒 才能完成。 在对程序存储器执行实际的擦除或写操作时,单片机的所有程序执行都被 暂停,因为单片机可能尝试从在被执行擦除或写操作的地址单元执行指令。 这是非法 的,因为在操作完成之前程序存储器地址单元的值处于未知状态。 PIC18F45K20 要写的块大小为 32 字节。 这要求我们一次写 32 个连续字节。与擦除一 样,第一个字节所在的地址必须是块大小 32 的倍数。 写程序存储器的顺序与擦除操作非常类似。 区别就是使用 ROM 指针写 32 个地址单元 且 EECON1 中的位 FREE 被清零以选择写操作。不要忘记必须首先擦除要写入的地址 单元!

? 2009 Microchip Technology Inc.

DS41370C_CN 第 63 页

PICkit? 3 Debug Express
使用指针写 32 个地址单元时,在整个序列完成之后才会发生对程序存储器的实际写操 作。 实际上,指针写操作将数据存储在 32 个临时硬件寄存器中。 执行实际的写序列 时,写入程序存储器阵列的是此 32 字节缓冲区的内容。 例如,我们可使用 for 循环 通过 ROM 指针将 RAM 阵列的内容写入这些缓冲区。
for (i = 0; i < 32; i++) { *(rom_pointer + i) = ram_array[i];// } write to the holding registers

实际上,数据尚未保存在程序存储器中,直到整个写序列完成之后才会保存到存储器 中,如图 3-51 所示。 注: 要写入哪个程序存储器块由 TBLPTRU:TBLPTRH:TBLPRTL 特殊功能寄存 器 (不包括低 5 位)中的地址决定。 不包括这 5 个位是为了确保块写操作 从 32 字节边界开始。 因此,指针地址不能递增到超出块的最后一个地址, 这一点非常重要。 如果超出了最后一个地址,则 32 个字节不会写入要写的 那一个块,而是写入它的下一个块边界。

我们来举例说明上面的 “注” ,假设使用以下代码写入程序存储器中从地址 0x100 到 0x11F 的 32 字节块。 由于指针在上一个写操作后递增到地址 0x120,所以数据实际上 被写入地址 0x120。
rom_pointer = (near rom unsigned char *)0x100; for (i = 0; i < 32; i++) { *(rom_pointer++) = ram_array[i]; // write to the holding registers } // after the for loop, the rom_pointer address value is 0x120.

如果 rom_pointer 值为 0x11F,那么数据将写入所需的以 0x100 为起始地址的块。

DS41370C_CN 第 64 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-53: 程序存储器写函数示例
unsigned char ProgMemWr32(unsigned int address, unsigned char *buffer_ptr) { // NOTE: program memory must also be erased first. near rom unsigned char *ptr; char i; ptr = (rom unsigned char *)(address & 0xFFE0);// ensure write starts for (i = 0; i < 32; i++)

on

32-byte

boundary

{ *(ptr + i) = buffer_ptr[i]; } EECON1bits.EEPGD = 1; EECON1bits.CFGS = 0; EECON1bits.FREE = 0; EECON1bits.WREN = 1; // execute code sequence, INTCONbits.GIE = 0;

// // // // //

write write

the to

data flash

into

the

holding memory

registers

program

which // // // //

cannot Disable Begin

not configuration registers we're not erasing now. enable write/erase operations be interrupted, then execute

write32

interrupts Write sequence

EECON2 = 0x55; EECON2 = 0xAA; EECON1bits.WR = 1; INTCONbits.GIE = 1; EECON1bits.WREN = 0; }

Set WR bit to begin 32-byte write re-enable interrupts // disable write/erase operations

3.11.2

通过配置位保护程序存储器

程序可划分为多个段,可通过将相应的配置位置 1 来单独保护每个段。提供的保护有: 代码保护 ——CPx 位可防止单片机编程器 (例如 PICkit 3)读程序存储器中与特 定 CPx 配置位相关的地址范围内的内容。 如果编程器尝试读存储器中受代码保护 的段,所有地址单元都将读为值 0x00。 这可以防止其他方盗取程序代码。 写保护——WRTx 配置位为 ON 时,禁止对相关程序存储器范围执行擦除或写操 作。 这可用于防止自举程序因应用程序对程序存储器的意外写或擦除操作而损坏。 表读保护 ——EBTRx 位有效时,可防止程序存储器地址单元被在程序存储器中其 他块中执行的指令读取。 例如,如果 EBTR3 有效,那么程序存储器中从 0x6000 到 0x7FFF 的地址不会被在程序存储器中从 0x0000 到 0x5FFF 地址范围内执行的 任何代码读取。 但块 0x6000 到 0x7FFF 内的地址单元仍然可以被在该块内执行的 代码读取。 例如,这可用于防止使用自举程序读出敏感的代码保护数据。 这些保护配置位有效 (设置为 ON)时,只有在编程器对单片机执行批量擦除操作 (即擦除所有程序存储器和数据 EEPROM 存储器)后,它们才能被关闭或更改。 使用 WRTC 配置位对器件进行首次编程之后可防止其他配置位被更改。

? 2009 Microchip Technology Inc.

DS41370C_CN 第 65 页

PICkit? 3 Debug Express
3.11.3 使用 PICkit 3 Debug Express 探究第 11 课的源代码
在编译期间,编译项目时,第 11 课的源代码会将 3 个字符串放在闪存程序存储器的地 址 0x100 处:
#pragma romdata mystrings = 0x100 rom char hello_str[] = "Hello!"; rom char mchp_str[] = "Microchip"; rom char fill_60[] = "012345678901234567890123456789012345678901234567890123456789";

编译项目后,在 MPLAB IDE 中使用 View > Program Memory (视图 > 程序存储器) 打开 Program Memory 窗口,可在程序存储器中看到这些字符串。 图 3-54: 程序存储器中的字符串

程序代码从地址 0x280 处开始。 编译并编程第 11 课的代码并在第一条指针赋值语句上设置断点,如图 3-55 所示。 图 3-55: 指针赋值语句上的断点

运行程序直到在断点处停止。单步执行图 3-55 中的 do while 循环并观察一次将字符 串 hello_str[] 的一个字符读到 singlechar 变量直到遇到该字符串的终止 0 值为 止的整个过程。 下一条语句演示了使用函数从明确的程序存储器地址读取字符的过程:
singlechar = ProgMemRdAddress(0x107); // returns 'M' from "Microchip".

DS41370C_CN 第 66 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
单步执行以下语句并单步运行用于擦除存储此字符串的 64 字节存储器块的函数。
// Erase the 64 bytes starting at 0x100 ProgMemErase64(0x100);

完成擦除后,选择菜单 Debugger > Read。 在 Program Memory 窗口中,擦除了存储 此字符串、起始地址为 0x0100 的 64 字节程序存储器块,如图 3-56 所示。 图 3-56: 被擦除的 0X0100 至 0X013F

其余代码在 RAM 中创建了一个 32 字节的缓冲区,并填充了大写的字母字符以及末尾 的几个标点字符。然后将此缓冲区的内容写入程序存储器中起始地址为 0x0100 的刚被 擦除的 32 字节块。 由于我们要读程序存储器,所以必须复位调试器。 选择 Debugger > Reset > Processor Reset。 在源代码上右键单击并从弹出的菜单中选择 Breakpoints > Remove All Breakpoints (断点 > 删除所有断点)以清除我们之前设置的断点。 运行 程序。 在运行几秒钟后,选择 Debugger > Halt。 程序应在最后的 while(1) 循环处停 止。 再次选择 Debugger > Read,我们可看到对程序存储器的写操作成功。 图 3-57: 程序存储器写操作的结果

? 2009 Microchip Technology Inc.

DS41370C_CN 第 67 页

PICkit? 3 Debug Express
3.12 第 12 课:使用 CPP 模块的 PWM 功能
本课程简要介绍了如何使用 PIC18F45K20 的捕捉 / 比较 /PWM (Capture/Compare/PWM, CCP)外设的脉宽调制 (Pulse Width Modulation, PWM)功能。 重要概念 PWM 时基 (频率)由 Timer2 和 PR2 特殊功能寄存器确定。 通过 CCPxCON SFR 选择 CCP 模块的 PWM 操作方式。 分辨率高达 10 位,CCPRxL 保存占空比的高 8 位,CCPxCON 保存低 2 位。 实际占空比的分辨率位数取决于 PR2 寄存器的值。

3.12.1

PWM 概述

简单的说,脉宽调制是一种占空比可变的给定频率的方波。 占空比是信号高电平时间 与整个周期时间的比值。 例如,频率为 250 Hz 的波形其周期为 4 ms。 对于占空比为 25% 的 PWM 信号,波形的高电平时间为 1ms,低电平时间为 3 ms (然后依次重 复) 占空比为 50% 的 PWM 信号,其高电平时间为 2 ms,低电平时间也是 2 ms ; 。 而 75% 的占空比则会使高电平时间为 3 ms,低电平时间为 1 ms。 图 3-58: PWM 占空比示例

脉宽调制功能用于许多应用中,包括通信、电机控制、音频和模拟输出以及照明应用。 在本课程中,将使用 PWM 的输出控制演示板上 LED 的亮度。 LED 仅在 PWM 周期的 高电平时间内点亮,在低电平时间内熄灭。 随着占空比的减小, LED 点亮的时间相对 于 PWM 周期越来越短,灯光也越来越暗。 但由于频率设置得足够高,故人的肉眼无 法检测到每个周期的各次闪烁,只会看到 LED 灯一直亮着。

3.12.2

使用 CPP 模块

Timer2 用于设置 PWM 波形的周期或频率。 Timer2 的工作原理与第 5 课中讨论的 Timer0 非常类似,只有一点区别,即 Timer2 始终为 8 位定时器。

DS41370C_CN 第 68 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
Timer2 也具有后分频器,但是后分频器不会影响 CPP 模块对 PWM 时基的操作,所 以其设置无关紧要。 Timer2 模块也具有周期寄存器,名为 PR2。 此特殊功能寄存器提 供了 Timer2 复位为 0 之前可计数到的最大值。 通常情况下, 8 位定时器将计数到 255,然后复位为 0,之后再次开始计数。PR2 寄存 器使得该定时器计数到最高为 PR2 中的值。 在到达该值后,定时器复位为 0。例如, 如果 PR2 = 3,则 Timer2 的计数过程为 0-1-2-3-0-1-2-3-0-1-2-3- 等。 计数周期 (从零开始向上计数直到 Timer2 到达 PR2 中的值)和定时器预分频器 (确 定定时器每个计数所花的时间)一起决定 PWM 频率。Timer2 每两次复位为 0 之间的 时间间隔就是 PWM 周期。 例如,假设需要的 PWM 频率为 62.5 Hz,周期为 16 ms。 时钟默认为 1 MHz 内部振荡器模块,其指令速率为 250 kHz。 250,000 Hz/62.5 Hz = 4000。因此,在 250 kHz 时,每次 Timer2 复位之前需要计数 4000 次。 但是, Timer2 是 8 位的,最大只能计数到 255。所以必须使用预分频器以放慢计数速率。 Timer2 有 3 个预分频比选项:1:1、 1:4 或 1:16 (图 3-59) 4000/256 = 15.6,所以需要 1:16 的 。 预分频比。 如果预分频比设置为 1:16,那么 Timer2 的计数频率为 250,000 Hz/16 = 15625 Hz。 要 得到 62.5 Hz 的 PWM 频率, Timer 2 必须计数 15625/62.5 = 250 次。 由于 Timer2 从 0 开始计数,设置 PR2 = 249,使其从 0 计数到 249 (250 次计数) ,复位为 0,然后 又从 0 计数到 249。图 3-60 给出了 PWM 模块的简化框图。 图 3-59: T2CON:TIMER2 控制寄存器

? 2009 Microchip Technology Inc.

DS41370C_CN 第 69 页

PICkit? 3 Debug Express
图 3-60: PWM 模块简化框图

既然确定了频率,就需要使用 CCP1CON 寄存器将 CCP1 模块设置为 PWM 模式。位 CCP1Mx 确定模块模式;只有一个值可用来选择 PWM 模式,CCP1Mx = 0b11xx,其 中 “x”位是 “无关位” ,所以 0b1100 有效。 CCP1CON 中的 2 个 DC1Bx 位是 10 位 PWM 占空比值的低 2 位。 此 10 位占空比值的高 8 位写入 CCPR1L。 占空比值由占空比百分比值 (DC%)乘以 10 位时基 (PR2 * 4)确定。 占空比值 = DC% * (PR2 * 4)。 例如,要获得 50% 的占空比,占空比值为 50% * (250 * 4) = 500。 十进制的 500 相当于十六进制的 0x1F4 或二进制的 0b01 1111 0100。高 8 位 0b01 1111 01 或 0x7D 被写入 CCPR1L, 2 位分别写入 CCP1CON 中的 DC1B1 和 DC1B0 低 位。

DS41370C_CN 第 70 页

? 2009 Microchip Technology Inc.

PICkit? 3 Debug Express 课程
图 3-61: CCPXCON:CCPX 控制寄存器

更多关于 Timer2 的信息,请参见 《PIC18F45K20 数据手册》 (DS41303C_CN)的 第 13.0 节 “Timer2 模块” 更多关于 CCP 模块 PWM 功能的信息可在第 15.0 节 。 “捕捉 / 比较 /PWM (CCP)模块”和第 15.4 节 “PWM 模式”中找到。

3.12.3

探究第 12 课的源代码

通常在 CCP1/RC2 引脚上输出 CCP1 模块的 PWM 信号。 但是,此引脚未与任何演示 板 LED 连接。 要在 LED 引脚上输出信号,可使用 PIC18F45K20 上的增强型 CCP 模 块 (ECCP) 通过 CCP1CON 的高 2 位 (P1Mx)选择此功能,将 P1Mx 置为 0b01 。 以在 P1D/RD7 上输出调制后的 PWM 信号,从而驱动 LED 7。不使用增强型 PWM 功 能的任何其他功能;更多信息请参见第 16.0 节 “增强型捕捉 / 比较 /PWM (ECCP) 模块” 。 本课程源代码中要做的第一件事情是将 PWM 引脚 RD7 设置为输出。
TRISDbits.TRISD7 = 0;

接着配置 Timer2 以产生如本课程先前部分所述的 16 ms 的 PWM 周期。
T2CON = 0b00000111;// Prescale = 1:16, timer on PR2 = 249;// Timer 2 Period Register = 250 counts

? 2009 Microchip Technology Inc.

DS41370C_CN 第 71 页

PICkit? 3 Debug Express
最后,配置 CCP1 模块,以执行如本课程先前部分所述的占空比为 50% 的 PWM 操 作:
CCPR1L = 0x7D; // The 8 most significant bits of the period are 0x7D CCP1CON = 0b01001100; // The 2 LSbs are 0b00, and CCP1Mx = 110 for PWM

模块中的程序运行到这里时,将在 RD7/P1D 上产生并输出占空比为 50%、频率为 62.5 Hz 的 PWM 信号。 要使 LED 先变亮再变暗,我们可使用循环来更改占空比。 第 1 个 do while 循环通过 增加占空比来增加 LED 的亮度 2 秒钟。 随着占空比的增加, LED 点亮的时间更长,因 而更亮。 请注意,为了简便起见,本课程的程序只更改了 CCPR1L 中占空比值的高 8 位。 第 2 个 do while 循环通过减少占空比来降低 LED 的亮度 2 秒钟。 随着占空比的减 小, LED 点亮的时间越来越短,也越来越暗。

3.12.4

使用 PICkit 3 Debug Express 编译和运行第 12 课的代码

编译和编程第 12 课的项目,然后在调试器中运行应用程序。您将看到演示板上的 LED 7 不断重复先变亮再变暗的过程。 如果您有示波器,请将探针连接到演示板上的 其中一个 RD7 信号点以查看 PWM 波形的变化。

DS41370C_CN 第 72 页

? 2009 Microchip Technology Inc.

图 A-1:

+V
R1 1K?
RB0
INT0

C1 0.1?F
+V R2 10K? R3 1K?
RA0

C2 0.1?F

P1 ICSP?

SW1

X1 10 MHz
32 35 RC1/T1OSI/CCP2

Rf 1M?
RD1

8 9 10 11 14 15 16 17 RB0 RB1 RB2 RB3 RB4 RB5 RB6 RB7
RC0

RC1

? 2009 Microchip Technology Inc.
AUX U1 PIC? 44 引脚系列
7 VDD 28 VDD RA0/AN0 RA1/AN1 RA2/AN2/VREFRA3/AN3/VREF+ RA4/T0CKI RA5/AN4/SS 18 MCLR/VPP RB0/INT0 RA0 RA1 RA2 RA3 RA4 RA5 19 20 21 22 23 24

+V

1 2 3 4 5 6 VPP VDD GND ICSPDAT ICSPCLK AUX
C3 0.1?F RP1 10K??

RA7

REXT 10K?

CEXT 0.1?F

C4 22pF

DS1 RD0 DS2

RB1/INT1 RB2/INT2 RB3 RB4 30 OSC1/CLKIN RB5 RB6/PGC RB7/PGD 31 OSC2/CLKOUT RC0/T1OSO/T1CKI

X2 R4 32 kHz 220K?

C6 12pF

R5 750? R6 750? R7 750?

DS3 RD2 DS4

附录 A 原理图

C5 22pF

R8 750?

RC2/CCP1 RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT RC2 RC3 RC4 RC5 RC6 RC7

36 37 42 43 44 1

RA6
12 NC 13 NC 33 NC 34 NC 6 29 VSS RE0/RD/AN5 25 RE1/WR/AN6 26 RE2/CS/AN7 27 RE0 RE1 RE2 VSS RD0/PSP0 RD1/PSP1 RD2/PSP2 RD3/PSP3 RD4/PSP4 RD5/PSP5 RD6/PSP6 RD7/PSP7 RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7 38 39 40 41 2 3 4 5

C7 12pF

RD3 DS5 RD4 DS6 RD5 DS7 RD6 DS8 RD7
R12 750? R11 750? R10 750? R9 750?

P2 PWR +V

JP1

带有 PIC18F45K20 的 PICKIT 3 DEBUG EXPRESS 44 引脚演示板的原理图

PICkit? 3 DEBUG EXPRESS

DS41370C_CN 第73 页

1 2

全球销售及服务网点
美洲
公司总部 Corporate Office 2355 West Chandler Blvd. Chandler, AZ 85224-6199 Tel: 1-480-792-7200 Fax: 1-480-792-7277 技术支持: http://support.microchip.com 网址:www.microchip.com 亚特兰大 Atlanta Duluth, GA Tel: 678-957-9614 Fax: 678-957-1455 波士顿 Boston Westborough, MA Tel: 1-774-760-0087 Fax: 1-774-760-0088 芝加哥 Chicago Itasca, IL Tel: 1-630-285-0071 Fax: 1-630-285-0075 克里夫兰 Cleveland Independence, OH Tel: 216-447-0464 Fax: 216-447-0643 达拉斯 Dallas Addison, TX Tel: 1-972-818-7423 Fax: 1-972-818-2924 底特律 Detroit Farmington Hills, MI Tel: 1-248-538-2250 Fax: 1-248-538-2260 科科莫 Kokomo Kokomo, IN Tel: 1-765-864-8360 Fax: 1-765-864-8387 洛杉矶 Los Angeles Mission Viejo, CA Tel: 1-949-462-9523 Fax: 1-949-462-9608 圣克拉拉 Santa Clara Santa Clara, CA Tel: 408-961-6444 Fax: 408-961-6445 加拿大多伦多 Toronto Mississauga, Ontario, Canada Tel: 1-905-673-0699 Fax: 1-905-673-6509

亚太地区
亚太总部 Asia Pacific Office Suites 3707-14, 37th Floor Tower 6, The Gateway Harbour City, Kowloon Hong Kong Tel: 852-2401-1200 Fax: 852-2401-3431 中国 - 北京 Tel: 86-10-8528-2100 Fax: 86-10-8528-2104 中国 - 成都 Tel: 86-28-8665-5511 Fax: 86-28-8665-7889 中国 - 香港特别行政区 Tel: 852-2401-1200 Fax: 852-2401-3431 中国 - 南京 Tel: 86-25-8473-2460 Fax: 86-25-8473-2470 中国 - 青岛 Tel: 86-532-8502-7355 Fax: 86-532-8502-7205 中国 - 上海 Tel: 86-21-5407-5533 Fax: 86-21-5407-5066 中国 - 沈阳 Tel: 86-24-2334-2829 Fax: 86-24-2334-2393 中国 - 深圳 Tel: 86-755-8203-2660 Fax: 86-755-8203-1760 中国 - 武汉 Tel: 86-27-5980-5300 Fax: 86-27-5980-5118 中国 - 厦门 Tel: 86-592-238-8138 Fax: 86-592-238-8130 中国 - 西安 Tel: 86-29-8833-7252 Fax: 86-29-8833-7256 中国 - 珠海 Tel: 86-756-321-0040 Fax: 86-756-321-0049 台湾地区 - 高雄 Tel: 886-7-536-4818 Fax: 886-7-536-4803 台湾地区 - 台北 Tel: 886-2-2500-6610 Fax: 886-2-2508-0102 台湾地区 - 新竹 Tel: 886-3-6578-300 Fax: 886-3-6578-370

亚太地区
澳大利亚 Australia - Sydney Tel: 61-2-9868-6733 Fax: 61-2-9868-6755 印度 India - Bangalore Tel: 91-80-3090-4444 Fax: 91-80-3090-4080 印度 India - New Delhi Tel: 91-11-4160-8631 Fax: 91-11-4160-8632 印度 India - Pune Tel: 91-20-2566-1512 Fax: 91-20-2566-1513 日本 Japan - Yokohama Tel: 81-45-471- 6166 Fax: 81-45-471-6122 韩国 Korea - Daegu Tel: 82-53-744-4301 Fax: 82-53-744-4302 韩国 Korea - Seoul Tel: 82-2-554-7200 Fax: 82-2-558-5932 或 82-2-558-5934 马 来西 亚 Malaysia - Kuala Lumpur Tel: 60-3-6201-9857 Fax: 60-3-6201-9859 马来西亚 Malaysia - Penang Tel: 60-4-227-8870 Fax: 60-4-227-4068 菲律宾 Philippines - Manila Tel: 63-2-634-9065 Fax: 63-2-634-9069 新加坡 Singapore Tel: 65-6334-8870 Fax: 65-6334-8850 泰国 Thailand - Bangkok Tel: 66-2-694-1351 Fax: 66-2-694-1350

欧洲
奥地利 Austria - Wels Tel: 43-7242-2244-39 Fax: 43-7242-2244-393 丹麦 Denmark-Copenhagen Tel: 45-4450-2828 Fax: 45-4485-2829 法国 France - Paris Tel: 33-1-69-53-63-20 Fax: 33-1-69-30-90-79 德国 Germany - Munich Tel: 49-89-627-144-0 Fax: 49-89-627-144-44 意大利 Italy - Milan Tel: 39-0331-742611 Fax: 39-0331-466781 荷兰 Netherlands - Drunen Tel: 31-416-690399 Fax: 31-416-690340 西班牙 Spain - Madrid Tel: 34-91-708-08-90 Fax: 34-91-708-08-91 英国 UK - Wokingham Tel: 44-118-921-5869 Fax: 44-118-921-5820

03/26/09

DS41370C_CN 第74 页

? 2009 Microchip Technology Inc.


相关文章:
Pickit3 烧录步骤
1 打开 MPLAB 程序 2 MPLAB 开启界面 3 导入 HEX 代码 File->Import 弹出“打开” 选择 A-5703410c.HEX,单击“打开” 4 选择 Programr->Pickit 3 单击”...
使用PICkit3下载程序_MplabIDE
使用PICkit3下载程序_MplabIDE_计算机软件及应用_IT/计算机_专业资料。mplab ide...DL03 程序下载器使用说明... 3页 2下载券 串口下载程序工具软件V1... 6...
使用PICkit3下载程序_MplabXide
使用PICkit3下载程序_MplabXide_计算机硬件及网络_IT/计算机_专业资料。Mplab x ide,pickit3 1. 2. 3. 4. 5. 6. 7. 双击 MPLAB X IPE Family 档选择...
PICKIT3脱机烧写
PICKIT3脱机烧写_计算机软件及应用_IT/计算机_专业资料。介绍了PICKIT3的不...PICKIT3脱机烧写指导书 3页 免费 PICKIT3脱机烧写说明书 6页 2下载券 ...
使用MPLAB烧写PIC单片机程序步骤KIT3
使用MPLAB烧写PIC单片机程序步骤KIT3_电子/电路_工程科技_专业资料。1、 加载...PIC单片机的程序 3页 免费 喜欢此文档的还喜欢 PICKIT3中文说明书 98页 免费...
CG3000使用手册中文(新)
CG3000使用手册中文(新)_信息与通信_工程科技_专业资料。这是BG6CG设计生产的全...PICKit3 中文使用手册 78页 1下载券 中文使用手册 14页 免费喜欢...
shinehawk 自编pickit3连接教程
shinehawk 自编pickit3连接教程_信息与通信_工程科技_专业资料。专业 pic单片机使用...PICKit3 中文使用手册 78页 1下载券 PicKIT3连机烧写IC说明 7页 免费©...
PICKIT3脱机生产烧录
PICKIT3脱机生产烧录_信息与通信_工程科技_专业资料。PICKIT3 烧录程序一、PIC...PICkit3烧录与脱机烧录说... 5页 1下载券 PICKIT3使用说明-连机、... 5...
kontakt2 中文使用手册修订版
PICKit3 中文使用手册 78页 1下载券 590+中文使用手册 307页 1下载券喜欢...​k​o​n​t​a​k​t​2​ ​中​文​使​用​...
6060N-6220N使用手册中文
《旗帜》中文使用手册 32页 免费 PICKit3 中文使用手册 78页 1下载券 590+中文...同时考虑到引导警报, 以及任何人员或设备,而使用的工作,他的工作手段,可以采取...
更多相关标签:
pickit3中文说明书 | pickit3使用说明 | jenkins中文使用手册 | dhtmlx中文使用手册 | kibana4 中文使用手册 | iphone使用手册中文版 | winbugs使用手册中文 | 奔驰glc 中文使用手册 |