30
2009 Microchip Technology Inc. DS41375A_CN 1 简介 PIC12/16 中档单片机取得多年成功之后,我们对其 设计进行了更新,以使它更适合于 C 语言编程,以及提 高它对于许多典型应用的性能。 这些变化包括: 新增的指令 更大的存储器 新的间接寻址模式 尽管我们尽最大努力确保原有代码库的向前兼容性,但 在少数情况下,还是必须通过软件调整来消除一些差 异。本文档 (即 《PIC1XF1XXX 软件移植》)包含三 个部分,分别描述新的设计、指导如何移植现有软件, 以及介绍许多软件优化技术。 架构 新特性 增强型 PIC12/16 器件在架构中扩展了以下特性: 程序存储器扩展为 32 KW 56 KB数据存储器扩展为 2 KB • 14 条新指令 线性映射 简化的核心寄存器映射 增强的间接寻址功能 自动中断现场保护 这些增强功能可以提高许多应用的性能,同时在很大程 度上与现有软件保持兼容。 核心寄存器 PIC12/16 系列的所有器件都具有一组核心寄存器。增强 版本的一个目标是将这些核心寄存器汇集到一个标准位 置。每个存储区的前12 SFR 地址现在是核心寄存器, 如表 1 中所示。 注: 该器件设计为按照数据手册上的参数 来工作。它已通过电气规范测试,该规 范用于确定器件是否符合这些参数。 由于存在器件生产工艺上的差异,其 工作特性可能与其早期版本的产品有 所不同。这些不同可能导致该器件与 其早期版本在应用中的性能差异。 注: 用户应验证器件振荡器是否按照期望 启动并振荡。用户可能需要调整负载 电容值和 / 或振荡器模式。 PIC1XF1XXX 软件移植

PIC1XF1XXX 软件移植 - ww1.microchip.com

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

Page 1: PIC1XF1XXX 软件移植 - ww1.microchip.com

PIC1XF1XXX 软件移植

简介

在 PIC12/16 中档单片机取得多年成功之后,我们对其设计进行了更新,以使它更适合于 C 语言编程,以及提高它对于许多典型应用的性能。

这些变化包括:

• 新增的指令

• 更大的存储器

• 新的间接寻址模式

尽管我们尽 大努力确保原有代码库的向前兼容性,但在少数情况下,还是必须通过软件调整来消除一些差异。本文档 (即 《PIC1XF1XXX 软件移植》)包含三个部分,分别描述新的设计、指导如何移植现有软件,以及介绍许多软件优化技术。

架构

新特性

增强型 PIC12/16 器件在架构中扩展了以下特性:

• 程序存储器扩展为 32 KW (56 KB)• 数据存储器扩展为 2 KB• 14 条新指令

• 线性映射

• 简化的核心寄存器映射

• 增强的间接寻址功能

• 自动中断现场保护

这些增强功能可以提高许多应用的性能,同时在很大程度上与现有软件保持兼容。

核心寄存器

PIC12/16系列的所有器件都具有一组核心寄存器。增强版本的一个目标是将这些核心寄存器汇集到一个标准位置。每个存储区的前12个SFR地址现在是核心寄存器,如表 1 中所示。

注: 该器件设计为按照数据手册上的参数来工作。它已通过电气规范测试,该规范用于确定器件是否符合这些参数。由于存在器件生产工艺上的差异,其工作特性可能与其早期版本的产品有所不同。这些不同可能导致该器件与其早期版本在应用中的性能差异。

注: 用户应验证器件振荡器是否按照期望启动并振荡。用户可能需要调整负载电容值和 / 或振荡器模式。

2009 Microchip Technology Inc. DS41375A_CN 第 1 页

Page 2: PIC1XF1XXX 软件移植 - ww1.microchip.com

表 1: SFR 地址

除了增加了第二个 FSR/INDF、增加了 BSR,以及将 W寄存器映射到 WREG 之外,增强型 PIC12/16 器件中的核心寄存器与原有寄存器是相同的。STATUS 寄存器中不再提供 IRP、RP0 和 RP1 位,因为现在提供了 BSR寄存器,并且 FSR 现在的位宽是 16 位。

新指令

这些新指令可以提高算术运算速度、简化分页与分区,以及扩展间接寻址模式的功能。

表 2: 新指令

设计这些指令是为了填补现有 14 位指令字的空白。通过适应现有的存储器设计,增强型器件的成本可以与现有 PIC12/16 器件保持相近,因而,无需犹豫就会欣然选择使用新的产品。

地址 寄存器 说明

0x00 INDF0 间接文件寄存器 00x01 INDF1 间接文件寄存器 10x02 PCL 程序计数器低字节

0x03 STATUS ALU 状态寄存器

0x04 FSR0L INDF0 低字节的间接地址

0x05 FSR0H INDF0 高字节的间接地址

0x06 FSR1L INDF1 低字节的间接地址

0x07 FSR1H INDF1 高字节的间接地址

0x08 BSR 存储区选择寄存器

0x09 WREG W 寄存器

0x0A PCLATH 程序计数器高字节锁存器

0x0B INTCON 中断控制寄存器

助记符 操作数 说明 周期数 (1) 受影响的状态位

ADDFSR k 将立即数与 FSRn 相加 1 —

ADDWFC f,d 将 W 与 F 相加(带进位) 1 C,DC,Z

SUBWFB f,d F 减去 W (带借位) 1 C,DC,Z

ASRF f,d 算术右移 1 C

BRA k 相对跳转 2 —

BRW - 使用 W 进行相对跳转 2 —

CALLW - 使用 W 进行绝对调用 2 —

LSRF f,d 逻辑右移 1 C

LSLF/ASRF f,d 逻辑左移 1 C

MOVLB k 传送立即数到 BSR 1 —

MOVLP k 传送立即数到 PCLATH 1 —

MOVIW * 将 INDFn 的内容传送到 W 1 Z

MOVWI * 将 W 的内容传送到 INDFn 1 —

RESET - CPU 复位 1 C,DC,Z

注 1:如果文件地址指向 INDF (0或 1),并且 FSR 指向程序存储器,则所有周期数递增 1。

DS41375A_CN 第 2 页 2009 Microchip Technology Inc.

Page 3: PIC1XF1XXX 软件移植 - ww1.microchip.com

堆栈

原有的 8 级堆栈被扩展为 16 级堆栈。在发生上溢或下溢时,与原有堆栈一样,堆栈会折回到栈首。堆栈可以配置为在发生上溢或下溢时引起复位;此外,堆栈可以通过 Bank 31 中的堆栈访问寄存器进行访问。

堆栈操作

堆栈指针总是指向放入堆栈中的 后一个值。如果发生调用或中断,堆栈指针会递增,然后程序计数器(Program Counter,PC)的下一个值被保存到堆栈中。

2009 Microchip Technology Inc. DS41375A_CN 第 3 页

Page 4: PIC1XF1XXX 软件移植 - ww1.microchip.com

图 1: 堆栈操作

初始堆栈配置

复位之后,堆栈为空。空堆栈会被初始化,使堆栈指针指向 0x1F。如果使能了堆栈溢出复位,则 TOSH/TOSL 寄存器将返回 0。

如果堆栈溢出复位被禁止,则 TOSH/TOSL寄存器将返回堆栈地址 0x0F 的内容。

0x0000

0x0F

0x0E

0x0D

0x0C

0x0B

0x0A

0x09

0x08

0x07

0x06

0x05

0x04

0x03

0x02

0x01

0x00

0x1F

返回地址

0x0F

0x0E

0x0D

0x0C

0x0B

0x0A

0x09

0x08

0x07

0x06

0x05

0x04

0x03

0x02

0x01

0x00

该图显示了第一次调用或单次中断后的堆栈配置。如果执行了返回指令,则返回地址将被放入程序计数器,并且堆栈指针递减为空堆栈状态 (0x1F)。

STKPTR 0X1F

STKPTR 0X00

STKPTR 0X1F

堆栈复位被禁止 (STVREN = 0)

堆栈复位被使能 (STVREN = 1)

DS41375A_CN 第 4 页 2009 Microchip Technology Inc.

Page 5: PIC1XF1XXX 软件移植 - ww1.microchip.com

图 2: 堆栈操作

七次调用或六次调用加一次中断之后,堆栈配置类似于左图。一系列返回指令会重复地将返回地址放入程序计数器。

在堆栈满时,下一个调用或中断会将堆栈指针设置为 0x10。它等同于地址 0x00,所以堆栈将返回到栈首进行操作。如果使能了溢出复位,则会发生复位。

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

0x0F

0x0E

0x0D

0x0C

0x0B

0x0A

0x09

0x08

0x07

0x06

0x05

0x04

0x03

0x02

0x01

0x00

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

返回地址

0x0F

0x0E

0x0D

0x0C

0x0B

0x0A

0x09

0x08

0x07

0x06

0x05

0x04

0x03

0x02

0x01

0x00

STKPTR 0x06

STKPTR 0x10

2009 Microchip Technology Inc. DS41375A_CN 第 5 页

Page 6: PIC1XF1XXX 软件移植 - ww1.microchip.com

上溢 / 下溢

新堆栈有 16 级深,但具有一个 5 位的堆栈指针。该堆栈指针可通过 Bank 31 中的 STKPTR 寄存器访问。如果在发生调用或中断之后, STKPTR 的 MSb 置 1,则认为堆栈发生上溢。如果使能了可选的复位功能,则程序计数器会立即变为 0,并且 PCON 中的复位状态标志会指示发生了堆栈复位。如果 STKPTR 值为 31 (所有位均置 1),则认为堆栈为空。堆栈为空时,执行返回操作(RETURN、 RETLW和 RETFIE)会导致下溢。如果使能了可选的复位功能,则程序计数器会立即变为0x0000,并且 PCON 中的复位状态标志会指示发生了堆栈复位。如果未使能可选的复位功能,则在发生下溢和上溢时堆栈将继续工作,但堆栈指针将只是围绕16级堆栈进行回绕。可以对堆栈上溢和下溢位进行检查,以确定堆栈是否超出边界。

调试访问

原有 PIC12/16 器件与在线调试固件一起共用 8 级堆栈。这可能会产生很大的限制。增强型 PIC12/16 器件具有为调试固件保留的附加堆栈。这可以消除在使用调试模式时堆栈用尽的可能性。在调试时,堆栈复位选项变为一个断点,用以帮助确定堆栈问题的原因。此外,调试器还具有堆栈访问机制,工程师可借助该机制查看软件从一开始到其当前状态的调用过程。

用户访问

用户对 16 级用户堆栈具有完全访问权,但不可以访问调试堆栈。可通过三个寄存器对堆栈进行访问:堆栈指针 (STKPTR)、栈顶高字节 (TOSH)和栈顶低字节(TOSL)。这些寄存器位于 Bank 31 中。

修改堆栈

如果要修改堆栈,则需要将 STKPTR 调整为指向需要更新的堆栈级,并更改TOSH/TOSL来执行修改。STKPTR寄存器总是指向放入堆栈中的 后一个条目。执行调用或中断之后, STKPTR 寄存器会递增,并且 PC 会被存储在新的 TOSH/TOSL 单元。在修改堆栈之前,请确保先禁止中断。

相对跳转

相对跳转是指基于当前地址跳转到目标地址。对于原有PIC12/16 器件,经常需要编写如下形式的代码:

编写 $-1 表示请求进行相对跳转,除非汇编器将它转换为绝对跳转。由于 CALL 和 GOTO 的有效访问范围所产生的页大小为2k,所以CALL和GOTO会导致分页问题。

增强型 PIC12/16 器件增加了 BRA 和 BRW 相对跳转指令。BRA允许从当前程序计数器位置跳转 +256 或 -255条指令。上面的代码示例将变为:

因为Label是绝对地址,所以汇编器会通过从目标地址中减去当前程序计数器值来将绝对地址转换为相对地址。如果使用 $-1 语法,则会以相同方式工作。如果向BRA提供常量 “-1”,则它将无法工作,因为 “-1”指定的是一个位于程序存储器末尾的地址,该地址很可能超出范围。

更快速的表读操作

BRW 指令也是相对跳转指令,但其访问范围是从 0 至255。BRW的相对地址包含在 W 寄存器中。这使得可以无需考虑表的位置,更快速地执行传统的表读方法。

例 1:

在以上示例中,将向调用函数返回字母 “t”。

LabelDECFSZ delay

GOTO $-1

Label

DECFSZ delay

BRA Label

Table

MOVLW 3

BRW

RETLW ‘a’

RETLW ‘ ‘

RETLW ‘s’

RETLW ‘t’

RETLW ‘r’

RETLW ‘i’

RETLW ‘n’

RETLW ‘g’

DS41375A_CN 第 6 页 2009 Microchip Technology Inc.

Page 7: PIC1XF1XXX 软件移植 - ww1.microchip.com

无意想不到的分页问题

使用相对跳转的主要优点是可以消除这种可能性:软件在添加附加代码后无法正确工作。有时,简单的延时循环会发生失败,因为插入到循环前面的代码将循环推挤到跨越页边界的位置。使用相对跳转可以消除这些问题。

间接寻址

间接寻址允许在运行时计算地址,并且允许修改数据。访问阵列和其他存储器缓冲区通常需要间接寻址。原有PIC12/16器件为间接寻址提供了非常基本的支持,仅使用单个 FSR/INDF。增强型 PIC12/16 器件为间接寻址提供了大量支持。

图 3: FSR 存储器映射

FSR 存储器映射

新的 FSR 具有很大的寻址空间,支持访问 GPR 和 SFR存储空间之外的更多存储空间(见图 3)。FSR 存储器映射包含了原有的 GPR/SFR 空间。此外,GPR 存储器被镜像到线性区域中,以便可以通过间接寻址模式访问很大的存储器块。 后,每个程序存储器地址的低字节也被映射到FSR地址空间中。由于对存储器映射增加了

这两个特性,所以支持很大的存储器块,以及支持访问RAM和闪存的指针。这些变化可以极大地提高大数据应用的性能。

0x0000

FSR 地址

0x0FFF

SRF&

GPR

0x0000

BSR + 文件寄存器地址

0x0FFF0x10000x1FFF

保留

0x2000

0x29FF

线性GPR 区 只能通过

FSR 访问

0x2A000x7FFF

保留

0x8000

FSR 地址 (1)

0xFFFF

程序存储器

0x0000

程序计数器 地址 (1)

0x7FFF

注 1:通过 FSR 访问这些地址会使指令所需的周期数递增 1。

2009 Microchip Technology Inc. DS41375A_CN 第 7 页

Page 8: PIC1XF1XXX 软件移植 - ww1.microchip.com

FSR 指令支持

增强型PIC12/16器件上的间接寻址系统包含两个 16位文件选择寄存器(File Select Register, FSR)和两个间接文件寄存器(Indirect File Register,INDF)。除了新增的 FSR/INDF 之外,还增加了三条新指令,用于提高间接操作的效率。三条新指令是:

1. ADDFSR——将介于 -32与31之间的立即数与指定的 FSR 相加。

2. MOVIW—— 将指定 INDF 寄存器中的值传送到 W中。

3. MOVWI——将W中的值传送到指定 INDF寄存器中。

MOVIW和MOVWI指令很特殊,因为它们能够对FSR执行预 / 后递增 / 递减操作。此外,它们还能够执行相对间接寻址。

使用 MOVIW/MOVWIMOVIW和 MOVWI具有以下语法:

例 2: MOVIW和 MOVWI

前 / 后递增 / 递减是非常简单的增强功能。相对偏移稍微复杂一些。对于相对偏移,介于 -32 与 +31 之间的常量会与 FSR 相加,以产生有效地址。INDF 会访问该有效地址。访问 (读或写)完成之后,有效地址会丢失,而 FSR 保持不变。

线性 RAM 访问

为了简化大存储器块的使用,FSR 还提供了一种将数据存储器重映射到连续 RAM 块中的方法。FSR 可以提供一种替代映射方式,即利用64 KB的地址空间来将GPR的不同映射定位到不同存储区。

GPR 和 SFR 被映射到 FSR 中前 2 KB 的地址空间。在GPR/SFR 映射后面是一个保留区域(读为 0),然后是位于地址 0x2000 处的 GPR 数据空间的新视图,如图 4所示。

图 4: 线性存储器访问

MOVIW ++FSR0 ; 预递增 FSR0,然后 INDF0 -> W

MOVIW FSR0++ ; INDF0 -> W,然后后递增 FSR0

MOVIW --FSR0 ; 预递减 FSR0,然后 INDF0 -> W

MOVIW FSR0-- ; INDF0 -> W,然后后递减 FSR0

MOVIW 4[FSR0] ; FSR0+4 INDF0 -> W。 FSR0不变

SFR

SFR

GPR

DS41375A_CN 第 8 页 2009 Microchip Technology Inc.

Page 9: PIC1XF1XXX 软件移植 - ww1.microchip.com

在新视图中,80 字节的 GPR 存储器块堆叠在一起,不会被公共存储器区 SFR 分隔开。因此, 90 字节的数据结构可以分跨两个存储区,而无需担心会覆盖不相关的存储单元。要使用这种 GPR 存储器视图,只需将一个FSR 指向 0x2000 后面的单元即可。

通过 FSR 读程序存储器

间接寻址系统的另一个有用功能是访问程序存储器的低8 位。

对程序存储器的访问从 FSR 地址 0x8000 开始。以下代码示例说明如何通过 FSR 访问存储器表。

例 3:

当标号引用程序存储器地址时,编译器会知道。如果程序存储器地址是 high 伪指令的操作目标,则 high 伪指令将返回 MSB 置 1 的地址的高半部分。这可以确保FSR 地址是用于访问程序存储器的正确地址。

通过 FSR 访问程序存储器时,每次读 INDF 寄存器需要2 个周期。第二个周期用于取数据。

分区和分页

分区和分页一直都是 PIC12/16 单片机的难题。为了进一步增强新的 PIC12/16 系列器件,增加了一些新指令来简化分页和分区。此外,这些新指令还允许页和存储区的数量分别增加到 32 个存储区和 16 个页。

分区指令

STATUS 寄存器中的 RP0 和 RP1 位限制了我们无法将存储区数量增加到 32 个。这些位已被去除,使用 BSR寄存器替代。伴随着 BSR,增加了一条新指令,用于

向 BSR 装入立即数。 MOVLB指令可以在一个周期中完成 BANKSEL 宏当前需要一条或两条指令(取决于器件存储器大小)来完成的工作。通过用一条指令来实现分区,分区所需的周期数 多可以降低 50%。

分页指令

需要分页的原因来自于 CALL和 GOTO指令。这两条指令可以访问 2K 字窗口中的任意地址。要离开该窗口,必须先更新 PCLATH,然后才能执行 CALL或 GOTO指令。为了提高编辑 PCLATH 的效率,增加了一条新指令MOVLP。MOVLP指令的功能与 PAGESEL 宏等价。在增强型 PIC12/16 器件中,可以在每条 CALL 或 GOTO 指令之前加上一条 MOVLP指令,构成一个 2 字、3 周期的操作,其访问范围可以是整个程序存储空间。

算术运算

PIC12/16器件上的算术运算一直都是非常简单的,但通过增加对于进位和算术移位的支持,可以进一步简化多字节运算。

带进位算术运算

加法和减法已经扩展为可支持进位或借位。只有针对文件寄存器的加法和减法支持进位或借位。除了在运算中包含了进位 / 借位标志之外,新指令的作用与原有指令完全相同。增强型 PIC12/16 器件中仍然提供原有的加法和减法指令。所有现有算法都可以在不进行更改的情况下工作,但通过选择性地使用新指令替换一些指令序列,可以提高算法的速度。

使用移位替代循环移位

原有 PIC12/16 器件具有一对 9 位循环移位指令。这两条指令会连同进位标志一起进行循环移位,所以进行 9次循环移位可以获得原始值。除了循环移位指令之外,新的 PIC12/16 器件还具有 3 条移位指令。

1. ASRF—— 算术右移

2. LSRF—— 逻辑右移

3. LSLF—— 逻辑左移

4. ASLF—— 算术左移,汇编后效果同 LSLF

Code

MOVLW high table_label

MOVWF FSR0H

MOVLW low table_label

MOVWF FSR0L

MOVF FSR0,W

...

Lots More Code

...

table_label

MOVLW 0xAA

MOVLW 0xAB

.. More Table Data ...

2009 Microchip Technology Inc. DS41375A_CN 第 9 页

Page 10: PIC1XF1XXX 软件移植 - ww1.microchip.com

移位操作与循环移位操作非常类似,不同之处在于补入位不是取自进位标志,而是取 0或取符号位。算术移位会执行符号位扩展,而逻辑移位则补入 0。符号位扩展意味着 高位(MSb)会被复制。这是非常有用的功能,因为负数进行右移后仍然为负数。如果对多字节值进行移位,则第一个字节进行移位,其他字节进行循环移位。它将正确地利用进位标志,从而所有位可以跨字节传递。循环移位和移位现在的功能更强了,因为 W 寄存器被映射为文件寄存器WREG。这使得可以直接对W寄存器进行循环移位和移位操作。

表 3: 逻辑移位操作

上面的表 3 列出了不同移位操作之间的差别。

中断

增强型 PIC12/16 器件上的中断功能基本未变,只是增加了硬件现场保护功能。所以,现在不需要在中断服务程序(Interrupt Service Routine, ISR)开始时保存关键寄存器(例如 W 或 STATUS)和在结束时恢复它们,从而降低中断开销。

硬件现场保护

硬件现场保护系统包含一些位于 Bank 31 中的寄存器。这些寄存器中含有已保存现场的备份副本,并作为恢复现场的数据源。表 4 列出了保存的寄存器。

表 4: 硬件现场影子单元

如果需要对现场数据进行动态调整,则需要通过现场保护寄存器来完成。

起始值 操作 终值

0x7F ASRF 0x3F, C = 10x80 ASRF 0xC0, C = 00x7F LSRF 0x3F, C = 10x80 LSRF 0x40, C = 00x7F LSLF/ASLF 0xFE, C = 00x80 LSLF/ASLF 0x00, C = 1

寄存器 现场保护寄存器 Bank 31 地址

WREG WREG_SHAD 0xFE5

STATUS STATUS_SHAD 0xFE4

FSR0L FSR0L_SHAD 0xFE8

FSR0H FSR0H_SHAD 0xFE9

FSR1L FSR1L_SHAD 0xFEA

FSR1H FSR1H_SHAD 0xFEB

BSR BSR_SHAD 0xFE6

PCLATH PCLATH_SHAD 0xFE7

DS41375A_CN 第 10 页 2009 Microchip Technology Inc.

Page 11: PIC1XF1XXX 软件移植 - ww1.microchip.com

增强型 PIC12/16 器件的编码机制

分页 小化技术

可以通过以下方式 大程度减少分页:

1. 尽可能采用相对跳转。

2. 更新 RETLW表,改为使用 BRW或 FSR/INDF 程序存储器读功能。

大多数应用程序都可以通过使用相对跳转来 大程度降低分页影响。

推荐的做法

如果您的代码当前使用了 PAGESEL 宏,则它现在会产生一条MOVLP指令。如果您的代码当前使用了BANKSEL宏,则它现在会产生一条 MOVLB指令。使用 PAGESEL/BANKSEL可以在工作量 少的情况下产生可移植代码。

可靠编程

可靠编程在许多领域中都是非常重要的问题。为了更好地支持可靠编程,增加了 RESET指令、包含了可选的堆栈复位功能,以及增加了检查堆栈的功能。

软件复位

RESET指令会执行完全的系统复位。它用于代替先前的等待看门狗定时器产生复位的做法。应当在关键代码块附近放置复位指令,以降低程序计数器混乱导致代码错误执行的可能性。

堆栈复位

堆栈复位使应用可以在堆栈上溢或下溢时复位。在诸如医疗或航空之类的关键应用中,可以通过堆栈监视器来大程度减少错误行为。

复位监视

由于存在太多的复位方式,所以确定复位源以进行正确恢复可能会是一个难题。

PCON 寄存器已经进行了扩展,可以显示:

• 堆栈上溢

• 堆栈下溢

• 指令复位

• POR 复位

• MCLR 复位

软件移植

软件移植会是一个棘手的问题。我们已经尽了 大的努力, 大程度降低转换原有代码以使之在增强型PIC12/16 器件上正确运行的复杂性。

从 PIC1XFXXX 移植到 PIC1XF1XXX将软件从原有PIC12/16器件移植到增强型PIC12/16器件涉及到以下方面:更改分页 / 分区功能、调整中断现场保护功能,以及修改间接存储器访问功能。在软件正常运行之后,还可以进行一些其他更改来进一步提高性能。

分区

要针对新器件调整分区,必须将对 RP0 和 RP1 的所有引用都替换为 MOVLB指令。对 RP0和 RP1的引用通常包含在一些宏中,例如 BANKSEL 或直接是 BANK0。MPASM™汇编器提供了BANKSEL宏,对于原有PIC12/16 器件,它会插入正确的 RP0和 RP1写操作。在增强型 PIC12/16 器件上,对于 BANKSEL,MPASM 汇编器会插入 MOVLB指令。如果您的软件使用自制的 BANKx类型的宏,则只需编写使用 MOVLB的新版本,或将所有BANKx 宏替换为 BANKSEL 宏。 好的通用解决方案是只使用内建的 BANKSEL 宏。

分页

有两种方式可以处理分页问题。第一种方式是查找所有对 PCLATH 的写操作,然后调整它们。大部分写操作都可以继续正确工作,但使用MOVLP指令可以加快它们的速度。如果您的代码使用了内建的 MPASM 汇编器宏PAGESEL,则会自动使用 MOVLP。要进一步加速,可以使用BRA和BRW指令,省去使用许多PAGESEL/GOTO组合的必要。

中断

自动现场保护

中断可以保持不变,但通过除去现场保护代码,可以显著地减少现场保护时间。对于大多数中断服务程序,除了由硬件保存的寄存器之外,不需要保存任何其他现场数据。只需删除现场保护代码就可以减少现场切换时间,大约可以减少 12 个指令周期。

2009 Microchip Technology Inc. DS41375A_CN 第 11 页

Page 12: PIC1XF1XXX 软件移植 - ww1.microchip.com

不恢复现场即返回

如果应用程序需要不恢复现场即返回,可以使用以下代码:

您的应用程序必须处理现场恢复。该指令序列可以正确工作,因为始终都会执行 GIE 置 1 之后的指令。

间接存储器访问

间接存储器访问使用 FSR/INDF 寄存器来访问存储器的各个部分。在原有 PIC12/16 器件中, FSR 的位宽为 9位,第 9 位以 IRP 存储在 STATUS 寄存器中。增强型PIC12/16 器件具有 16 位宽的 FSR, 高位存储在FSRnH 寄存器中。要访问整个 RAM,需要对 高位进行调整。这通常使用 BANKISEL 宏来完成。BANKISEL宏会根据需要置 1 或清零 IRP 位。在增强型 PIC12/16器件上, BANKISEL 宏会根据需要置 1 或清零 FSRnH中的每个位。这将需要 8 个指令周期。如果希望写 W 寄存器,则可以通过 MOVLW和 MOVWF在两个周期中完成更新,或者使用 ADDFSR或带相对偏移的 MOVIW/WI完成更新。

从 PIC18FXXX 器件移植到PIC1XF1XXX 器件

从 PIC18 器件向后移植到增强型 PIC12/16 器件不同于从原有 PIC12/16 器件进行向前移植。增强型 PIC12/16器件缺少一些资源:

• 只有 16 个堆栈单元,而不是 31 个

• FSR 相对寻址机制不同(通过指令而不是寄存器)

• 无乘法指令

• CALL/GOTO指令的访问范围较小

• 只有 2 个 FSR,而不是 3 个

分区

PIC18 器件上的分区经常被误解。 PIC18 器件对 RAM空间进行了分区,以方便快速对其进行访问。它还具有一个几乎包含所有 SFR 的特殊存储区。 PIC18 器件上的每个存储区都更大 (256 字节),所以用于分区的时间较少。增强型PIC12/16器件的存储区大小仍然为128字节,并且没有快速操作存储区。转换软件需要对许多SFR 访问和 RAM 访问使用 BANKSEL 宏,以确保正确配置存储区。

分页

在 PIC18 器件上, CALL和 GOTO是双字指令,这消除了分页问题。由于指令的有效访问范围较大,所以CALL和 GOTO 能够访问存储器中的任意指令。只需在所有CALL和GOTO前面添加PAGESEL,即增加一个指令周期的时间,增强型PIC12/16器件就可以实现相同的功能。增强型 PIC12/16 器件上也提供了 PIC18 器件的相对跳转指令 (BRA)。在一些情况下,需要将 BRA 替换为GOTO,因为 PIC18 BRA的访问范围比 PIC12/16 BRA的访问范围大。

PIC18器件上的所有指令地址都是偶编号地址,因为 16位指令存储器按字节进行访问。这对增强型 PIC12/16器件的软件转换可能会产生影响,因为它的程序存储器是按字进行访问的,所以所有指令按顺序寻址。

中断

PIC18 器件具有 2 级中断结构。中断具有快速现场保护功能,但现场恢复是可选的,取决于是否使用从中断快速返回指令。所有中断都需要进行调整,以识别增强型PIC12/16 器件的单级中断结构;此外,还需要删除所有现场恢复代码。

间接存储器访问

PIC18 器件具有 3 个 FSR、用于寻址的特殊寄存器,以及用于递增和递减的 INDF SFR。在增强型PIC12/16器件上,可以适当使用MOVIW和MOVWI指令来替代它们。

程序存储器表

PIC18 器件具有表读指令,用于从程序存储器中取 2 个字节。

增强型 PIC12/16 器件可以通过使用 FSR/INDF 访问程序存储器来从程序存储器中取 1 个字节。

软件优化 将软件移植到增强型 PIC12/16 器件上之后,还可以利用新特性来提高性能。增强型 PIC12/16 器件的软件优化可以根据对以下方面的更改进行分类:

1. 算术运算

2. ROM 表访问

3. RAM 缓冲区访问

4. 数据结构

bsf INTCON,GIE

return

DS41375A_CN 第 12 页 2009 Microchip Technology Inc.

Page 13: PIC1XF1XXX 软件移植 - ww1.microchip.com

算术运算

PIC12/16器件上的算术运算是非常基本的功能,但在进行多字节数据运算时,会遇到不少问题。例如,原有ADD指令执行加法时不带进位,所以多字节运算需要额外的指令,根据前一次加法的结果对下一个高字节(MSB)进行预处理。增强型 PIC12/16 器件中新增的指令可以简化该工作,从通用算法中除去许多指令。

多字节加法

对于 PIC12/16 器件,将两个 16 位值相加通常使用如下方式:

该代码可以很好地工作,但由于缺少带进位加法,中间需要 2 个额外的周期。对于增强型 PIC12/16 器件,该代码可以转换为如下形式:

增强型版本可以节省两条指令。如果 16 位值大量使用,节省量可以累增。

多字节减法

减法与加法类似,因为在以下计算中必须处理借位标志。原有代码如下:

增强型版本如下:

增强型版本的减法可以节省两条指令。

移位

移位是乘以或除以 2 的整数幂的 快速方法,因此,移位比循环移位更加常用。通过对进位标志进行预处理,可以使循环移位指令像移位指令一样操作。原有代码如下:

该代码可以正确工作,但第一次循环会覆盖 W 寄存器的内容。ASRF指令通过在硬件中处理符号位来简化该问题。

它需要的代码较少,所以速度更快。 Arithmetic_Left_Shift 不需要执行符号位扩展。它只是简单地向 LSB 中补入 0。

如果不需要进行符号位扩展,则代码会较简单。

在执行循环移位操作之前清零进位标志可以产生逻辑移位的效果。这些示例可以转换为单条增强型 PIC12/16器件指令。

Add16

MOVF lsb_a,w

ADDWF lsb_b,f

MOVF msb_a,w

BTFSC STATUS,C

ADDLW 0x01

ADDWF msb_b,f

Add16_enhanced

MOVF lsb_a,w

ADDWF lsb_b,f

MOVF msb_a,w

ADDWFC msb_b,f

Sub16

MOVF lsb_a,w

SUBWF lsb_b,f

MOVF msb_a,w

BTFSS STATUS,C

ADDLW 0xFF

SUBWF msb_b,f

Sub16_enhanced

MOVF lsb_a,w

SUBWF lsb_b,f

MOVF msb_a,w

SUBWFB msb_b,f

Arithmetic_Right_Shift

RLF val,w ;将 MSB保存到进位位 (破坏 W)

RRF val,f ;循环右移 带符号扩展

ASRF val,f

Logical_Right_Shift

BCF STATUS,C

RRF val,f

Logical_Left_Shift

BCF STATUS,C

RLF val,f

2009 Microchip Technology Inc. DS41375A_CN 第 13 页

Page 14: PIC1XF1XXX 软件移植 - ww1.microchip.com

请注意,Arithmetic_left_shift和logical_left_shift的功能是相同的。增强型 PIC12/16 器件仅提供了logical_left_shift,如果在汇编语言中使用了ASLF,汇编器会将其替换为logical_left_shift。

表 5: 移位操作差别

上面的表 5 列出了不同移位操作之间的差别。

多字节移位

通过对第一个操作使用新的移位指令,对所有后续操作使用循环移位指令,可以产生多字节移位的效果。新指令会将移出的位移入进位标志中,而循环移位指令会将它移入下一个字节中。

ROM 表访问

许多应用程序都需要频繁地执行数据表访问。在 PIC12/16 器件上,传统方法是将表汇集到一系列 RETLW 指令中。通过将某个值与 PC 相加,可以向调用函数返回特定偏移位置处的值。增强型 PIC12/16 器件进行了一些改善。

通过 FSR 进行快速表访问

第一个技巧是使用 FSR/INDF 来返回保存在程序存储器中的值。当 FSRnH 寄存器中的 MSB 置 1 时,INDF 返回的值是FSR寄存器指定的程序存储器地址中的低字节(LSB)。通过使用 FSR 来指向程序存储器中的数据,利用MOVIW和MOVWI指令的功能可以让软件保持简短。通常,设置使用 FSR 需要 4 个周期,而每次取数据需要 2 个周期,因为从程序存储器取数据需要多一个周期。使用FSR从程序存储器取数据的主要优点是使用的指针是统一的。数据可以位于 GPR,也可以位于程序存储器,这都不会改变访问要求。

注: 如果标号引用了程序存储器中的地址,则HIGH伪指令会自动将 MSB 置 1。

起始值 操作 终值

0x7F ASRF 0x3F,C = 10x80 ASRF 0xC0, C = 00x7F LSRF/ASLF 0x3F, C = 10x80 LSRF/ASLF 0x40, C = 00x7F LSRF/ASLF 0xFE,C = 00x80 LSRF/ASLF 0x00, C = 1

LSRF val,f ; 逻辑右移

LSLF val,f ; 逻辑左移

ASLF val,f ; 算数左移

; 事实上是逻辑左移

ASRF_16

ASRF MSB_f

RRF LSB_f

code

MOVLW HIGH data_table

MOVWF FSROH

MOVLW LOW data_table

ADDWF data_index

MOVWF FSR0L

CLRW

ADDWFC FSR0H

MOVF INDF0, W

data_table

RETLW ‘m’

RETLW ‘y’

RETLW ‘ ‘

RETLW ‘d’

RETLW ‘a’

RETLW ‘t’

RETLW ‘a’

DS41375A_CN 第 14 页 2009 Microchip Technology Inc.

Page 15: PIC1XF1XXX 软件移植 - ww1.microchip.com

使用 BRW与 RETLW进行快速表访问

将 BRW 指令与 RETLW 指令结合使用可以确保,所有指令取数据只需要 4 个周期加上初始调用的周期数。如果将数据表分配在可以防止程序存储器页大小问题的位置,则传统方法也可以快速地进行表访问。

如果 CALL data_table和 data_table未被页边界分隔开,则不需要使用 PAGESEL 来确保 CALL可以进行访问。这种方法不需要将data_table对齐到任意存储器地址。由于省去了对齐要求,所以 BRW非常容易使用。根据是否使用 PAGESEL,这种表访问方法需要 6或 7 个周期的时间。

使用 CALLW与 RETLW进行快速表访问

CALLW 指令可以用于访问位于存储器任意位置的数据表,所需时间为固定的 6 个周期。 CALLW 是一条新指令,用于提高函数指针的效率。除了它的期望功能之外, CALLW还可以用于准备数据表。 CALLW的工作方式是将 W 中的值与 PCLATH 中的值连接,然后 “ 调用 ”所产生的地址。

通过将 RETLW 指令块分配到 256 字边界处(低地址字节为零),可以实现使用 CALLW来取数据。这是非常快速的查表方式。

该方法需要 6 个周期的时间来取得任意数据。

示例

附录 B:“IIR 滤波器转换示例 ” 中给出了完整的代码示例。在该示例中,一个从因特网上下载的 IIR 函数被转换为使用增强型 PIC12/16 器件的特性。所产生代码的运行速度几乎快一倍。

code

MOVLW data_index

PAGESEL data_table

CALL data_table

data_table

BRW

RETLW ‘m’

RETLW ‘y’

RETLW ‘ ‘

RETLW ‘d’

RETLW ‘a’

RETLW ‘t’

RETLW ‘a’

code

MOVLP HIGH data_table

MOVLW data_index

CALLW

ORG 0x??00

data_table

RETLW ‘m’

RETLW ‘y’

RETLW ‘ ‘

RETLW ‘d’

RETLW ‘a’

RETLW ‘t’

RETLW ‘a’

RETLW 0

2009 Microchip Technology Inc. DS41375A_CN 第 15 页

Page 16: PIC1XF1XXX 软件移植 - ww1.microchip.com

附录 A: 简单 GETHEX 函数优化

软件许可协议

Microchip Technology Incorporated(公司)随附提供的软件旨在提供给您(该公司的客户)使用,仅限于且只能在该公司制造的产品上使用。

该软件为公司和 / 或其供应商所有,并受适用的版权法保护。保留所有权利。任何违反前述限制的使用将使其用户遭受适用法律的刑事制裁,并承担违背此许可的条款和条件的民事责任。

该软件 “ 按现状 ” 提供。不提供任何保证,无论是明示的、暗示的还是法定的保证。这些保证包括(但不限于)对出于某一特定目的

应用此软件的适销性和适用性默示的保证。在任何情况下,公司都将不会对任何原因造成的特别的、偶然的或间接的损害负责。

; 原始代码

data

hex_temp res 1

code

gethex

GLOBAL gethex

ANDLW 0x0F

MOVWF hex_temp

MOVLW high hex

MOVWF PCLATH

MOVLW low hex

ADDWF hex_temp,W

BTFSC STATUS,C

INCF PCLATH,F

MOVWF PCL

hex

dt “0123456789ABCDEF”

; 增强代码

data

; 无需数据

code

gethex

GLOBAL gethex

ANDLW 0x0F

BRW

hex

dt “0123456789ABCDEF”

2009 Microchip Technology Inc. DS41375A_CN 第 16 页

Page 17: PIC1XF1XXX 软件移植 - ww1.microchip.com

附录 B: IIR 滤波器转换示例

以下代码是由 Tony Kubek 编写的 24 位 IIR,提取自www.piclist.org (http://www.piclist.org/techref/microchip/dsp/iir-24b-256s-tk.htm)。它是一个颇具价值的算法示例;通过利用增强型 PIC12/16 器件的新指令和 FSR 特性,可以加快该算法的运行速度。附录C:“24 位 256 阶 IIR 滤波器(原始代码) ” 中给出了原始代码。

需要检查的代码还真不少。现在先来看一些重要的代码块。首先,需要对开始处的 ADD_FSR_FILTER 宏进行调整。原始代码使用的是 FSR,所以应将它更新为使用FSR0L。进一步研究之后,可以发现该代码是 24 位加法,其源地址位于 FSR 中。这提供了进一步优化的可能性。可以使用MOVIW指令来消除冗余的FSR重新装入。可以使用 ADDWFC指令来消除进位传递。

可以注意到,指令数可以从 14-17 条指令立即降到 8 条指令。这意味着代码长度减少 50%,且运行速度加倍。该示例中的乘法和除法宏是下一个感兴趣的代码块。

ADD_FSR_FILTER MACRO

; 14-17条指令

; 将 FSR指向的值添加到滤波器中

MOVF INDF,W ; 取 低字节

ADDWF NewFilter+3,F ; 将 低字节

; 添加到滤波器和

DECF FSR,F

MOVF INDF,W ; 取下一个字节

SKPNC ; 如果溢出

INCFSZ INDF,W ; 递增源并将结果

ADDWF NewFilter+2,F ; 添加到目标寄存器

DECF FSR,F

MOVF INDF,W ; 取下一个字节

SKPNC

INCFSZ INDF,W

ADDWF NewFilter+1,F

DECF FSR,F

MOVF INDF,W ; 取 msb

SKPNC

INCFSZ INDF,W

ADDWF NewFilter,F

ENDM

ADD_FSR0_FILTER MACRO

; 8条指令

; 将 FSR指向的值添加到滤波器中

moviw 0[INDF0]

ADDWF NewFilter+3,F ; 将 低字节

; 添加到滤波器和

MOVIW -1[INDF0] ; 取下一个字节

ADDWFC NewFilter+2,F

MOVIW -2[INDF0] ; 取下一个字节

ADDWFC NewFilter+1,F

MOVIW -3[INDF0] ; 取 msb

ADDWFC NewFilter,F

ENDM

2009 Microchip Technology Inc. DS41375A_CN 第 17 页

Page 18: PIC1XF1XXX 软件移植 - ww1.microchip.com

;++++++++++++

;

; DIV_FILTER_BY2 - 将 NewFilter除以 2

;

;

DIV_FILTER_BY2 MACRO

; 5条指令

;将滤波器值右移 1位 (即除以 2)

BCF STATUS,C ; 清零进位位

; 除以 2

RRF NewFilter,F

RRF NewFilter+1,F

RRF NewFilter+2,F

RRF NewFilter+3,F

ENDM

;++++++++++++

;

; MUL_NEWOLD_BY2 - 将旧值和新值乘以 2

;

;

MUL_NEWOLD_BY2 MACRO

; 10条指令

; 将滤波器值右移 1位(即除以 2)

BCF STATUS,C ; 清零进位位

; 将旧值乘以 2

RLF OldFilter+3,F

RLF OldFilter+2,F

RLF OldFilter+1,F

RLF OldFilter,F

; 将新值乘以 2

BCF STATUS,C ; 清零进位位

RLF NewSample+3,F

RLF NewSample+2,F

RLF NewSample+1,F

RLF NewSample,F

ENDM

;++++++++++++

;

; DIV_FILTER_BY2 - 将 NewFilter除以 2

;

;

DIV_FILTER_BY2 MACRO

; 4条指令

; 将滤波器值右移 1位(即除以 2)

; 除以 2

LSRF NewFilter,F

RRF NewFilter+1,F

RRF NewFilter+2,F

RRF NewFilter+3,F

ENDM

;++++++++++++

;

; MUL_NEWOLD_BY2 -将旧值和新值乘以 2

;

;

MUL_NEWOLD_BY2 MACRO

; 8条指令

; 将滤波器值右移 1位(即除以 2)

; 将旧值乘以 2

LSLF OldFilter+3,F

RLF OldFilter+2,F

RLF OldFilter+1,F

RLF OldFilter,F

; 将新值乘以 2

LSLF NewSample+3,F

RLF NewSample+2,F

RLF NewSample+1,F

RLF NewSample,F

ENDM

DS41375A_CN 第 18 页 2009 Microchip Technology Inc.

Page 19: PIC1XF1XXX 软件移植 - ww1.microchip.com

在此例中,速度提升没有那么明显,但通过除去 “ 清零进位位再移位 ” 组合,可以节省 1 个周期的时间。在TWIST24 主函数中,每个循环需要使用这些宏 8 次。所以,节省 1 个指令也会有所帮助。

清理这些宏之后,下一个感兴趣的代码部分是 TWIST24函数中的 FSR 设置。每次执行主循环时,需要执行 8 次位测试,以确定 ADD_FSR_FILTER函数是与新值还是旧

值相加。这种条件切换通过更改FSR指向的地址来实现。这需要在主函数中执行装入 FSR、测试并重新装入 FSR这一组合 8次。更快速的方法是条件性地执行操作数为 4的 ADDFSR 指令。这样,只需一条指令(而不是两条指令)就可以将 FSR 值更改为下一个值。为了让代码更清晰,该示例中删除了注释。原始代码中保留了注释。

这是另一处极小的更改,但它会被执行8*UPDATE_COUNT(或 256)次。这也会产生明显的节省。

在程序末尾处,还有一个代码模式可以通过增强指令集进行加速。

此处改为使用带进位加法,从而可以删去 “ 进位位清零则跳过 ” 指令部分。它变为简单的带进位加法指令序列。

对该程序进行的更改是非常简单的;但所获得的效果是,函数运行速度几乎加倍,从而提升性能,或在保持性能不变时降低时钟速度和功耗。利用增强型PIC12/16 器件的特性来移植现有软件,无需花多大的努力,就可以极大地提高性能。

附录D:“针对增强型PIC12/16器件而修改的 24位 256阶 IIR 滤波器 ” 中给出了被修改函数的完整源代码。

MOVLW NewSample+3 MOVLW NewSample+3

MOVWF FSR MOVWF FSR0L

MOVLW OldFilter+3 btfsc FilterWeight,0

BTFSC FilterWeight,0 addfsr .4

MOVWF FSR ADD_FSR0_FILTER

ADD_FSR_FILTER ; 加法 MUL_NEWOLD_BY2

MUL_NEWOLD_BY2

; 将滤波器值加一实现正确舍入

MOVLW 0x01

ADDWF NewFilter+2,F

SKPNC

ADDWF NewFilter+1,F

SKPNC

ADDWF NewFilter,F

; 将滤波器值加一实现正确舍入

MOVLW 0x01

ADDWF NewFilter+2,F

ADDWFC NewFilter+1,F

ADDWFC NewFilter,F

2009 Microchip Technology Inc. DS41375A_CN 第 19 页

Page 20: PIC1XF1XXX 软件移植 - ww1.microchip.com

附录 C: 24 位 256 阶 IIR 滤波器(原始代码)

************************* TWIST24 ******************************

;

; 此程序旨在评估

;

; A*X0 + B*Y

; X1 = ---------

; A + B

;

; 例如 A+B = 2^n

;

; 简化后该公式变为

;

; A*X0 + ~A*Y + Y

; X1 = ---------------

; 2^n

;

; 其中:

; X1 - 是新的递归低通滤波器值

; X0 - 是以前的低通滤波器值

; Y - 是新值

; A和 B是权重因子,如果 A相对 B较大

; 则赋予平均 (经滤波的)值以更大权重。

; 如果 B大,则赋予 近一次采样以更大权重。

; ~A是 A的逐位取反

;

;

; X0、 X1和 Y是 24位变量

; 对于此程序, A+B = 2^8 = 256

;

; Tony Kübek于 2000-05-23根据 Scott Dattalo编写的

; 程序 “twist.asm” 改编 (顺便感谢共享 :-)

;

; ****************************************************************;

; NewSample = Y(4字节 ram, 3字节数据)

; OldFilter = X0(4字节 ram, 3字节数据)

; NewFilter = X1(4字节 ram, 3字节数据)

; FilterWeight = A(1字节 ram,旧滤波值的权重)

;

; * 并非真正需要而用于示例中的变量 *

; FilterCounter = 1字节,递增阶跃响应的计数器。

; UpdateCounter = 1字节, “ 全局 ” 更新之间的采样数

; AD_NewValue = 3字节 ram, 后 24位的读数来自 AD或类似来源

; (如果 AD_NewValue用于其他目的,则复制到 NewSample)

; AD_DataVal = 3字节 ram,在 UpdateCounter次采样后更新滤波值

; _AD_DataReady = 1位,在更新 AD_DataVal时置 1

;

DS41375A_CN 第 20 页 2009 Microchip Technology Inc.

Page 21: PIC1XF1XXX 软件移植 - ww1.microchip.com

#define UPDATE_COUNT 0x20 ; 全局更新之间 32次采样

#define FILTER_WEIGHT 0x80 ; 滤波器权重,即上例中的 “A”

CBLOCK 0x020

AD_NewValue:3

NewSample:4 ; AD_Newvalue的副本,局部使用

OldFilter:4 ; 以前的滤波值,(上次运行的 NewFilter)

NewFilter:4 ; 新的滤波值

FilterWeight:1 ; 旧值的权重

FilterCounter:1 ; 递增阶跃响应

UpdateCounter:1 ; 希望进行全局更新的频率

AD_DataVal:3 ; 全局更新位置

Bitvars:1

ENDC

#define _AD_DataReady BitVars,0

;++++++++++++

;

; ADD_FSR_FILTER - 添加 32位值,该值由 FSR指向 NewFilter

; FSR必须指向 低有效字节, FSR-3是 高有效字节

;

ADD_FSR_FILTER MACRO

; 14-17条指令

; 将 FSR指向的值添加到滤波器

MOVF INDF,W ; 取 低字节

ADDWF NewFilter+3,F ; 添加到滤波器和的 低字节

DECF FSR,F

MOVF INDF,W ; 取下个字节

SKPNC ; 如果溢出

INCFSZ INDF,W ; 递增源地址

ADDWF NewFilter+2,F ; 并添加到目标地址。

DECF FSR,F

MOVF INDF,W ; 取下个字节

SKPNC

INCFSZ INDF,W

ADDWF NewFilter+1,F

DECF FSR,F

MOVF INDF,W ; 取 msb

SKPNC

INCFSZ INDF,W

ADDWF NewFilter,F

ENDM

;++++++++++++

;

; DIV_FILTER_BY2 - 将 NewFilter的值除以 2

;

;

DIV_FILTER_BY2 MACRO

; 5条指令

; 将滤波器值右移 1位(除以 2)

2009 Microchip Technology Inc. DS41375A_CN 第 21 页

Page 22: PIC1XF1XXX 软件移植 - ww1.microchip.com

BCF STATUS,C ; 清零进位位

; 除以 2

RRF NewFilter,F

RRF NewFilter+1,F

RRF NewFilter+2,F

RRF NewFilter+3,F

ENDM

;++++++++++++

;

; MUL_NEWOLD_BY2 - 将 OldValue和 NewSample乘以 2

;

;

MUL_NEWOLD_BY2 MACRO

; 10条指令

; 将滤波器值右移 1位(即除以 2)

BCF STATUS,C ; 清零进位位

; 将旧值乘以 2

RLF OldFilter+3,F

RLF OldFilter+2,F

RLF OldFilter+1,F

RLF OldFilter,F

; 将新值乘以 2

BCF STATUS,C ; 清零进位位

RLF NewSample+3,F

RLF NewSample+2,F

RLF NewSample+1,F

RLF NewSample,F

ENDM

ORG 0x0000

GOTO INIT

; ** 用于数据收集的中断程序

ORG 0x0004

INT

; 从 AD取数据

CALL GET_AD_DATA ; 未包含!

; 对于每次采样,都复制到 AD_NewValue

; 并调用滤波器一次

CALL TWIST24

RETFIE

; 冷启动向量

INIT

; 此处只是 “ 假 ” 代码

BCF _AD_DataReady ; 清零数据就绪标志

; 请注意,该操作将初始化滤波器使之逐渐从

; 无滤波到 “ 完全 ” 滤波 (对于每次采样都递增一次)

;

MOVLW FILTER_WEIGHT

MOVWF FilterCounter

DS41375A_CN 第 22 页 2009 Microchip Technology Inc.

Page 23: PIC1XF1XXX 软件移植 - ww1.microchip.com

CLRF FilterWeight

MAIN_LOOP

; 等待来自 AD或类似来源的特定数据

BTFSS _AD_DataReady ; 检查数据是否就绪

GOTO MAIN_LOOP ; 未就绪

; 经滤波的数据就绪

; 执行必要的操作 ..

BCF _AD_DataReady ; 清零数据就绪标志

GOTO MAIN_LOOP

;++++++++++++

;

; TWIST24 - 可变的 24位低通滤波器,在 NewFilter中计算新的低通值,

; 这是通过根据 FilterWeight赋予以前的滤波器值和 NewSample以不同权重来实现的

; 如果 FilterWeight大,则赋予旧滤波值以更大权重

; FilterWeight的 大值是 255(即 8位变量)。

; FilterWeight = 0 -> NewFilter = OldFilter的 0/256 + NewSample的 256/256,即无滤波

; FilterWeight = 255 -> NewFilter = OldFilter的 255/256 + NewSample的 1/256,即完全滤波

; 注:以前的滤波值应保存在 NewFilter中,因为它将用于下次传递。

;

TWIST24

; 执行了约 252-285条指令 (含全局更新和新数据值的复制)

; 约 57 us,当晶振频率为 20 Mhz时

; !使用 FSR!

; 锯齿波功能,使用额外的 ram变量 FilterCounter,

; 用于递增 FilterWeight,直到它自己达到零

; 用法:初始化至 FilterWeight,然后将更快达到目标

; (阶跃响应)。运行期间,如果因为任何原因检测到高电平

; 锯齿波 (或读数丢失),它可以重新初始化为等于或小于

; FilterWeight的任何值,以达到更快的阶跃响应。

; 注:Filterweight也必须初始化,以满足以下条件:

; FilterCounter + FilterWeight = DesiredFilterWeight

MOVF FilterCounter,F

BTFSC STATUS,Z

GOTO TWIST_GO

DECFSZ FilterCounter,F

INCF FilterWeight,F

TWIST_GO

; 复制以前的滤波值 (请注意,以前的值已经乘以 256

; 即只复制源地址的头三个字节到目标地址的三个 低字节。)

MOVF NewFilter,W

MOVWF OldFilter+1

MOVF NewFilter+1,W

MOVWF OldFilter+2

MOVF NewFilter+2,W

MOVWF OldFilter+3

; 从 AD复制新值到 “ 局部 ” 变量并作为

2009 Microchip Technology Inc. DS41375A_CN 第 23 页

Page 24: PIC1XF1XXX 软件移植 - ww1.microchip.com

; 初始值添加到滤波器

MOVF AD_NewValue,W ; 取新读数的 高字节

MOVWF NewSample+1 ; 存储在局部变量中

MOVWF NewFilter+1 ; 也将该值作为初始值添加到新滤波器

MOVF AD_NewValue+1,W ;

MOVWF NewSample+2 ;

MOVWF NewFilter+2 ;

MOVF AD_NewValue+2,W ;

MOVWF NewSample+3 ;

MOVWF NewFilter+3 ;

CLRF NewFilter ;

CLRF OldFilter ; 清零 高字节(只有一个 24位滤波器)

CLRF NewSample

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,0 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值的地址已在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,1 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,2 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,3 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

DS41375A_CN 第 24 页 2009 Microchip Technology Inc.

Page 25: PIC1XF1XXX 软件移植 - ww1.microchip.com

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,4 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,5 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,6 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

MUL_NEWOLD_BY2 ; 上移旧值和新值, 10条指令

MOVLW NewSample+3 ; 取新值的地址

MOVWF FSR ; 设置 FSR

MOVLW OldFilter+3 ; 取旧值的地址,送入 W

BTFSC FilterWeight,7 ; 检查要添加的值是新值还是旧值

MOVWF FSR ; 旧值已添加到滤波器中,地址在 W中

ADD_FSR_FILTER ; 添加它

; 此处获得 235-268条指令

; 检查舍入

BTFSS NewFilter+3,7 ; 测试 低字节的 高位

GOTO TWIST24_EXIT

; 在滤波器上加 1,以实现正确的舍入

MOVLW 0x01

ADDWF NewFilter+2,F

SKPNC

ADDWF NewFilter+1,F

SKPNC

ADDWF NewFilter,F

; 此处获得 245 - 278条指令

TWIST24_EXIT

; 检查更新

DECFSZ UpdateCounter,F

RETURN

2009 Microchip Technology Inc. DS41375A_CN 第 25 页

Page 26: PIC1XF1XXX 软件移植 - ww1.microchip.com

; 更新全局滤波器

MOVF NewFilter+2,W

MOVWF AD_DataVal+2

MOVF NewFilter+1,W

MOVWF AD_DataVal+1

MOVF NewFilter,W

MOVWF AD_DataVal

; 置 1数据就绪标志

BSF _AD_DataReady

; 重新初始化更新计数器

MOVLW UPDATE_COUNT ; 全局更新之间的采样数

MOVWF UpdateCounter

RETURN

DS41375A_CN 第 26 页 2009 Microchip Technology Inc.

Page 27: PIC1XF1XXX 软件移植 - ww1.microchip.com

附录 D: 针对增强型 PIC12/16 器件而修改的 24 位 256 阶 IIR 滤波器

; ************************* TWIST24 ******************************

;

; 此程序旨在评估

;

; A*X0 + B*Y

; X1 = ---------

; A + B

;

; 例如 A+B = 2^n

;

; 简化后该公式变为

;

; A*X0 + ~A*Y + Y

; X1 = ---------------

; 2^n

;

; 其中:

; X1 - 是新的递归低通滤波器值

; X0 - 是以前的低通滤波器值

; Y - 是新值

; A和 B是权重因子,如果 A相对 B较大

; 则赋予平均 (经滤波的)值以更大权重。

; 如果 B大,则赋予 近一次采样以更大权重。

; ~A是 A的逐位取反

;

;

; X0、 X1和 Y是 24位变量

; 对于此程序, A+B = 2^8 = 256

;据

; Tony Kübek于 2000-05-23根据 Scott Dattalo编写的

; 程序 “twist.asm” 改编 (顺便感谢共享 :-)

;

; ****************************************************************

;

; NewSample = Y(4字节 ram, 3字节数据)

; OldFilter = X0(4字节 ram, 3字节数据)

; NewFilter = X1(4字节 ram, 3字节数据)

; FilterWeight = A(1字节 ram,旧滤波值的权重)

;

; * 并非真正需要而用于示例中的变量 *

; FilterCounter = 1字节,递增阶跃响应的计数器。

; UpdateCounter = 1字节, “ 全局 ” 更新之间的采样数

; AD_NewValue = 3字节 ram, 后 24位的读数来自 AD或类似来源

; (如果 AD_NewValue用于其他目的,则复制到 NewSample)

; AD_DataVal = 3字节 ram,在 UpdateCounter次采样后更新滤波值

; _AD_DataReady = 1位,在更新 AD_DataVal时置 1

;

#define UPDATE_COUNT 0x20 ; 全局更新之间 32次采样

#define FILTER_WEIGHT 0x80 ; 滤波器权重,即上例中的 “A”

CBLOCK 0x020

AD_NewValue:3

2009 Microchip Technology Inc. DS41375A_CN 第 27 页

Page 28: PIC1XF1XXX 软件移植 - ww1.microchip.com

NewSample:4 ; AD_Newvalue的副本,局部使用

OldFilter:4 ; 以前的滤波值(上次运行的 NewFilter)

NewFilter:4 ; 新的滤波值

FilterWeight:1 ; 旧值的权重

FilterCounter:1 ; 递增阶跃响应

UpdateCounter:1 ; 希望进行全局更新的频率

AD_DataVal:3 ; 全局更新位置

Bitvars:1

ENDC

#define _AD_DataReady BitVars,0

;++++++++++++

;

; ADD_FSRx_FILTER - 添加 32位值,该值由 FSR指向 NewFilter

; FSR必须指向 低有效字节, FSR-3是 高有效字节

; 两个版本,每个 FSR各一个

;

ADD_FSR0_FILTER MACRO

; 8条指令

; 将 FSR指向的值添加到滤波器

moviw 0[INDF0]

ADDWF NewFilter+3,F ; 添加到滤波器和的 低字节

moviw -1[INDF0] ; 取下个字节

addwfc NewFilter+2,F

moviw -2[INDF0] ; 取下个字节

addwfc NewFilter+1,F

moviw -3[INDF0] ; 取 msb

addwfc NewFilter,F

ENDM

;++++++++++++

;

; DIV_FILTER_BY2 - 将 NewFilter除以 2

;

;

DIV_FILTER_BY2 MACRO

; 4条指令

; 将滤波器值右移 1位 (即除以 2)

; 除以 2

LSRF NewFilter,F

RRF NewFilter+1,F

RRF NewFilter+2,F

RRF NewFilter+3,F

ENDM

;++++++++++++

;

; MUL_NEWOLD_BY2 - 将 OldValue和 NewSample乘以 2

;

;

MUL_NEWOLD_BY2 MACRO

; 8条指令

; 将滤波器值右移 1位 (即除以 2)

; 将旧值乘以 2

LSLF OldFilter+3,F

RLF OldFilter+2,F

DS41375A_CN 第 28 页 2009 Microchip Technology Inc.

Page 29: PIC1XF1XXX 软件移植 - ww1.microchip.com

请注意以下有关 Microchip 器件代码保护功能的要点:

• Microchip 的产品均达到 Microchip 数据手册中所述的技术指标。

• Microchip 确信:在正常使用的情况下, Microchip 系列产品是当今市场上同类产品中 安全的产品之一。

• 目前,仍存在着恶意、甚至是非法破坏代码保护功能的行为。就我们所知,所有这些行为都不是以 Microchip 数据手册中规定的

操作规范来使用 Microchip 产品的。这样做的人极可能侵犯了知识产权。

• Microchip 愿与那些注重代码完整性的客户合作。

• Microchip 或任何其他半导体厂商均无法保证其代码的安全性。代码保护并不意味着我们保证产品是“ 牢不可破” 的。

代码保护功能处于持续发展中。 Microchip 承诺将不断改进产品的代码保护功能。任何试图破坏 Microchip 代码保护功能的行为均可视

为违反了 《数字器件千年版权法案 (Digital Millennium Copyright Act)》。如果这种行为导致他人在未经授权的情况下,能访问您的

软件或其他受版权保护的成果,您有权依据该法案提起诉讼,从而制止这种行为。

提供本文档的中文版本仅为了便于理解。请勿忽视文档中包含

的英文部分,因为其中提供了有关 Microchip 产品性能和使用

情况的有用信息。Microchip Technology Inc. 及其分公司和相

关公司、各级主管与员工及事务代理机构对译文中可能存在的任何差错不承担任何责任。建议参考 Microchip TechnologyInc. 的英文原版文档。

本出版物中所述的器件应用信息及其他类似内容仅为您提供便

利,它们可能由更新之信息所替代。确保应用符合技术规范,是您自身应负的责任。Microchip 对这些信息不作任何明示或

暗示、书面或口头、法定或其他形式的声明或担保,包括但不

限于针对其使用情况、质量、性能、适销性或特定用途的适用性的声明或担保。 Microchip 对因这些信息及使用这些信息而

引起的后果不承担任何责任。如果将 Microchip 器件用于生命

维持和 / 或生命安全应用,一切风险由买方自负。买方同意在

由此引发任何一切伤害、索赔、诉讼或费用时,会维护和保障Microchip 免于承担法律责任,并加以赔偿。在 Microchip 知识

产权保护下,不得暗中或以其他方式转让任何许可证。

2009 Microchip Technology Inc.

商标

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、 ICEPIC、

Mindi、 MiWi、 MPASM、 MPLAB Certified 徽标、 MPLIB、MPLINK、 mTouch、 Omniscient Code Generation、 PICC、

PICC-18、PICkit、PICDEM、PICDEM.net、PICtail、PIC32

徽标、REAL ICE、 rfLAB、Select Mode、Total Endurance、TSHARC、 WiperLock 和 ZENA 均为 Microchip Technology Inc. 在美国和其他国家或地区的商标。

SQTP 是 Microchip Technology Inc. 在美国的服务标记。

在此提及的所有其他商标均为各持有公司所有。

© 2009, Microchip Technology Inc. 版权所有。

DS41375A_CN 第 29 页

Microchip 位于美国亚利桑那州 Chandler 和 Tempe 与位于俄勒冈州Gresham 的全球总部、设计和晶圆生产厂及位于美国加利福尼亚州和印度的设计中心均通过了 ISO/TS-16949:2002 认证。公司在 PIC®

MCU 与 dsPIC® DSC、KEELOQ® 跳码器件、串行 EEPROM、单片机外设、非易失性存储器和模拟产品方面的质量体系流程均符合 ISO/TS-16949:2002。此外, Microchip 在开发系统的设计和生产方面的质量体系也已通过了 ISO 9001:2000 认证。

Page 30: PIC1XF1XXX 软件移植 - ww1.microchip.com

DS41375A_CN 第 30 页 2009 Microchip Technology Inc.

美洲公司总部 Corporate Office2355 West Chandler Blvd.Chandler, AZ 85224-6199Tel: 1-480-792-7200 Fax: 1-480-792-7277技术支持:http://support.microchip.com网址:www.microchip.com亚特兰大 AtlantaDuluth, GA Tel: 678-957-9614 Fax: 678-957-1455波士顿 BostonWestborough, MA Tel: 1-774-760-0087 Fax: 1-774-760-0088芝加哥 ChicagoItasca, IL Tel: 1-630-285-0071 Fax: 1-630-285-0075克里夫兰 ClevelandIndependence, OH Tel: 216-447-0464 Fax: 216-447-0643达拉斯 DallasAddison, TX Tel: 1-972-818-7423 Fax: 1-972-818-2924底特律 DetroitFarmington Hills, MI Tel: 1-248-538-2250Fax: 1-248-538-2260科科莫 KokomoKokomo, IN Tel: 1-765-864-8360Fax: 1-765-864-8387洛杉矶 Los AngelesMission Viejo, CA Tel: 1-949-462-9523 Fax: 1-949-462-9608

圣克拉拉 Santa ClaraSanta Clara, CA Tel: 408-961-6444Fax: 408-961-6445加拿大多伦多 TorontoMississauga, Ontario, CanadaTel: 1-905-673-0699 Fax: 1-905-673-6509

亚太地区

亚太总部 Asia Pacific OfficeSuites 3707-14, 37th FloorTower 6, The GatewayHarbour City, KowloonHong KongTel: 852-2401-1200Fax: 852-2401-3431中国 - 北京Tel: 86-10-8528-2100 Fax: 86-10-8528-2104

中国 - 成都Tel: 86-28-8665-5511Fax: 86-28-8665-7889

中国 - 香港特别行政区Tel: 852-2401-1200 Fax: 852-2401-3431

中国 - 南京Tel: 86-25-8473-2460Fax: 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-4818Fax: 886-7-536-4803

台湾地区 - 台北Tel: 886-2-2500-6610 Fax: 886-2-2508-0102

台湾地区 - 新竹Tel: 886-3-6578-300Fax: 886-3-6578-370

亚太地区

澳大利亚 Australia - SydneyTel: 61-2-9868-6733 Fax: 61-2-9868-6755

印度 India - BangaloreTel: 91-80-3090-4444 Fax: 91-80-3090-4080

印度 India - New DelhiTel: 91-11-4160-8631Fax: 91-11-4160-8632

印度 India - PuneTel: 91-20-2566-1512Fax: 91-20-2566-1513

日本 Japan - YokohamaTel: 81-45-471- 6166 Fax: 81-45-471-6122韩国 Korea - DaeguTel: 82-53-744-4301Fax: 82-53-744-4302

韩国 Korea - SeoulTel: 82-2-554-7200 Fax: 82-2-558-5932 或82-2-558-5934

马来西亚 Malaysia - KualaLumpurTel: 60-3-6201-9857Fax: 60-3-6201-9859

马来西亚 Malaysia - PenangTel: 60-4-227-8870Fax: 60-4-227-4068

菲律宾 Philippines - ManilaTel: 63-2-634-9065Fax: 63-2-634-9069新加坡 SingaporeTel: 65-6334-8870 Fax: 65-6334-8850

泰国 Thailand - BangkokTel: 66-2-694-1351Fax: 66-2-694-1350

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

全球销售及服务网点

03/26/09