2.1 PIC单片机的CPU
微芯公司生产的PIC16F87X系列单片机的CPU具有以下特色:
● 振荡器可选。
● 多种复位功能。
● 多种中断方式。
● 监视定时器。
● 睡眠模式。
● 在线调试功能。
● 代码保护。
● 可编程ID识别码。
● 在线串行编程。
2.1.1 系统配置
在PIC系列单片机的程序存储区中,一般留出了6个具有特殊功能的单元,由用户自行配置,从而实现一些特殊的功能。这几个存储单元不在常规用户程序存储空间,且不能被用户程序访问到,而只能在对单片机进行编程或校验时,由编程器烧入或读出。在这6个特殊功能的存储单元中,位于2007H的单元为系统配置字;位于2006H的单元存放器件识别码;位于2000H~2003H的4个单元存放用户识别码。
对于PIC16F87X单片机中位于2007H的系统配置字①,可用来定义一些系统性能,具体定义如下所示:
● bit 13~bit 12 CP1~CP0:程序存储器代码保护位②。
● bit 5~bit 4 CP1~CP0:
➢ 11:代码保护功能关闭。
➢ 10:1F00h~1FFFFh的代码被保护(对于PIC16F877/876)。
➢ 10:0F00h~0FFFh的代码被保护(对于PIC16F874/873)。
➢ 10:不支持(对于PIC16F870/871/872)。
➢ 01:1000h~1FFFFh的代码被保护(对于PIC16F877/876)。
➢ 01:0800h~0FFFh的代码被保护(对于PIC16F874/873)。
➢ 01:不支持(对于PIC16F870/871/872)。
➢ 00:0000h~1FFFh的代码被保护(对于PIC16F877/876)。
➢ 00:0000~0FFFh的代码被保护(对于PIC16F874/873)。
➢ 00:0000~07FFh的代码被保护(对于PIC16F870/871/872)。
● bit11 DEBUG:在线调试模式。
➢ 1:关闭在线调试功能,RB6和RB7为普通I/O端口。
➢ 0:开启在线调试功能,RB6和RB7被调试功能占用。
● bit 10未被使用,读作1。
● bit 9 WRT:程序存储器写使能位。
➢ l:未被保护的程序存储器,可以通过EECON寄存器控制被烧写。
➢ 0:未被保护的程序存储器,不可以通过EECON寄存器控制被烧写。
● bit 8 CPD:E2PROM数据存储器代码保护。
➢ 1:关闭保护功能。
➢ 0:开启代码保护功能。
● bit 7 LVP:低电压在线串行编程使能位。
➢ 1:RB3/PGM引脚为PGM功能,低电压编程被使能。
➢ 0:RB3引脚为数字I/O端口功能,MCLR引脚必须加高电压,用于编程。
● bit6 BODEN:掉电锁存复位使能位③。
➢ 1:允许掉电锁存复位。
➢ 0:禁止掉电锁存复位。
● bit 3 PWRTE:上电定时器使能位③。
➢ 1:上电定时器被关闭。
➢ 0:上电定时器被使能。
● bit 2 WDTE:看门狗使能位。
➢ 1:看门狗被使能。
➢ 0:看门狗被关闭。
● bit 1~bit 0 FOSC1~FOSC0:振荡器模式选择位。
➢ 11:选择RC阻容振荡器模式。
➢ 10:选择HS高速振荡模式。
➢ 01:选择XT标准振荡器模式。
➢ 00:选择LP低速振荡模式。
注:① 没有被编程/近擦除过的配置字的内容为3FFFh。
② 为了起到代码保护功能,配置字中的两个CP1:CP0位对的赋值必须相同。
③ 无论PWRTE位为何值,使能掉电锁存复位都会自动使能上电定时器(PWRT)。当掉电复位被使能时,要确保上电定时器被使能。
2.1.2 振荡器配置
1.振荡方式
PIC16F87X系列单片机可工作于4种不同的振荡模式下。用户可通过对系统配置字中的FOSC1和FOSC0两位的编程来选择4种振荡模式中的任意一种。这4种振荡模式如下:
● LP低功耗振荡(LOW Power)
● XT标准晶体振荡(Crystal/Resonator)
● HS高速晶体振荡(High Speed)
● RC阻容振荡(Reastor/Capacitor)
2.晶体振荡器/陶瓷谐振器
在LP、XT和HS模式下,PIC单片机既可以使用集成在片内的振荡器,也可以使用外部时钟源。当使用片内振荡器时,需要一个晶体谐振器或陶瓷谐振器连接到单片机的OSC1/CLKIN和OSC2/CLKOUT引脚上,以建立振荡,如图2-1所示。
图2-1 晶体或陶瓷振荡电路
电容C1和C2的选择可参考表2-1和表2-2。选择C1、C2理想的情况是保证系统在高温和最低工作电压下能够正常工作,使得电容在数据手册推荐的范围内最小。同时应使C2比C1大一些以加大相移,使其有利于振荡电路的上电启动。在HS模式和XT模式中,电阻RS可以用来防止晶振被过分驱动。当晶振、振荡类型和电容值都确定后,就需要决定RS的值了。简单的办法就是使系统工作在最低温度和最大电压情况下,此时得到的即是时钟电路最大输出幅度。用示波器观察引脚OSC2的输出波形(注意,示波器的探头将为电路引入一个电容,一般为几个pF),如果发现正弦波的峰(接收VDD处)和谷(接收Vss处)被削或压扁,则表明驱动过载,需要在OSC2和C2间加入1个电阻Rs。选择电阻Rs值大小的最简单的方法就是串联一个5kΩ或10kΩ的微调电阻,从0开始慢慢调高,一直到正弦波不再被削平为止。通过此办法就可以找到最接近的电阻RS值。需要注意的是,RS不宜过大,过大将使得输入和输出产生隔离,从而产生较大的噪声。当需要一个较大的RS才能消除过载驱动时,可以通过增加负载电容C2进行补偿。
表2-1 外接陶瓷谐振器时电容值的选择
表2-2 外接晶体谐振器时电容位的选择
当接外部振荡器时,外部时钟信号从OSC1端输入,OSC2开路,如图2-2所示。外部振荡器一般使用有源晶振(也称晶体振荡器),有VCC、GND、CLK和NC(No Connect)4个引脚,只要接上电源和地即可使用。与无源晶体(也称晶体谐振器)相比,有源晶振信号比较稳定,但体积较大,不过随着SMD(Surface Mount Device)技术的不断发展,该问题已经逐渐得到解决。
图2-2 外部时钟输入模式
3.RC振荡电路
在对振荡精度要求不高的系统中,使用RC振荡可以节省成本。RC振荡电路如图2-3所示。其振荡频率与供电电压VDD、外接电阻REXT、外接电容CEXT和工作温度有关。此外,对于同种型号不同封装的芯片,阻容振荡频率也会不同,尤其是当CEXT较小时。另外,外接电阻和外接电容的精度也是影响阻容振荡频率的一个因素。
图2-3 RC振荡电路
2.1.3 复位
复位就是要单片机应用系统在正式工作前处于一种特定的状态,只有以该状态为起点,随后的工作才有可能是正常与可靠的。复位电路增加了系统的可靠性,对于单片机来说它不可或缺。
1.PIC16F87X系列单片机的复位类型
PIC16F87X系列单片机的一个突出的优点就是提供了强大的片上复位功能,如图2-4所示。归纳起来共有6种不同的复位方式,如下所列,其复位源可通过软件来设置。
图2-4 PIC16F87X系列单片机片上复位电路简易原理图
注:此振荡器与CLKIN端的RC振荡器不同。
● 上电复位POR(Power-On Reset)。
● 正常状态下的人工复位MCLR。
● 睡眠状态下的人工复位MCLR。
● 正常状态下的看门狗复位。
● 睡眠中的看门狗唤醒。
● 掉电锁存复位BOR(Brown-Out Reset)。
(1)上电复位(POR)。PIC16F87X单片及内部有上电检测电路,当检测到电源电压VDD上升到1.2~1.7V时,芯片就会产生一个复位脉冲,可以把MCLR引脚直接接到VDD或通过一个电阻上拉到VDD,而不必像其他类型的单片机应用系统那样需要搭一个RC电路来实现上电复位功能(注意,为保证上电复位功能的实现,电源电压VDD的上升速率应大于0.05V/ms)。
(2)正常状态下的人工复位MCLR。单片机在正常工作状态下,当MCLR引脚为低电子时,就会使单片机复位。
(3)睡眠状态下的人工复位MCLR。单片机在睡眠状态下,当MCLR引脚为低电平时,也会使单片机复位。
(4)正常状态下的看门狗复位。在正常工作状态下,如果没有定期“喂狗”(即没有对看门狗定时器WDT进行周期性的、及时的清零),就会引起单片机复位。
(5)睡眠中的看门狗唤醒。在睡眠状态中,看门狗定时器WDT时间一到,单片机就会从睡眠状态中被唤醒,进入正常工作状态,而不会引起复位。
(6)掉电锁存复位。如果掉电锁存复位电路被使能,则当VDD下降到低于VBOR(约4V)并持续时间超过TBOR(100μs)时,就会使单片机复位。
2.复位状态
单片机复位而进入初始化状态后,其内部的特殊功能寄存器的值如表2-3~表2-7所示。
表2-3 电源控制寄存器和状态寄存器的复位值
注:x:不考虑;u:不变。
表2-7 PIC16F873/874/876/877寄存器的复位状态
续表
注:① INTCON、PIR1和/或PIR2中的一位或多位会受到影响(引起唤醒)。
② 由中断引起唤醒时,PC指针中装载的是中断矢量0004H。
③ 程序计数器、状态寄存器和电源控制寄存器的复位值见表2-4。
表2-4 程序计数器、状态寄存器和电源控制寄存器的复位值
注:x:随机;u:不变;-:未用的位,读作“0”。
① 当由中断引起唤醒时,PC指针装载的是中断矢量(0004H)。
表2-5 PIC16F870/871寄存器的复位状态
续表
注:x:不确定;u:不变;r:保留;-:不可用,读作0;q:该位的值视情况而定。若无特殊说明,本书中所有与寄存器相关的表格中出现的上述符号/字母均作此解释。
① INTCON、PIR1和/或PIR2中的一位或多位会受到影响(引起唤醒)。
② 由中断引起唤醒时,PC指针中装载的是中断矢量0004H。
③ 程序计数器、状态寄存器和电源控制寄存器的复位值见表2-4。
表2-6 PIC16F872寄存器的复位状态
注:① INTCON、PIR1和/或PIR2中的一位或多位会受到影响(引起唤醒)。
② 由中断引起唤醒时,PC指针中装载的是中断矢量0004H。
③ 程序计数器、状态寄存器和电源控制寄存器的复位值见表2-4。
2.1.4 中断
PIC16F87X系列单片机有多达14个中断源,丰富的中断资源为用户程序的开发带来很大的灵活性。在嵌入式系统中,中断是一个很重要的概念。为此,在2.2节将对中断进行专门介绍,此处不再赘述。
2.1.5 监视定时器WDT
在工业环境中,单片机会因为干扰的存在引起PC错误,导致程序跑飞或陷入死循环,此时指令冗余技术和软件陷阱技术均已无法解决问题,这时可以采用程序监视定时器WDT(Watchdog Timer),俗称“看门狗”措施。WDT通过不断监视程序每周期的运行事件是否超过正常状态下所需的时间,从而判断程序是否进入了死循环,并对系统进行复位。WDT可以由硬件来实现,也可以由软件来实现,还可以将两者结合起来实现。由于受篇幅影响,这里只介绍PIC16F87X中的WDT技术。
1.看门狗工作原理
PIC16F87X单片机中包含硬件看门狗,其原理图如图2-5所示。WDT定时器的时钟由芯片内部独立的RC振荡器提供,无须外接任何元件即可运行。注意,WDT定时器的RC振荡器与OSC1/CLKIN引脚上的RC振荡器无关,即使OSC1和OSC2引脚上的时钟停止工作(如睡眠状态),看门狗依然可以工作。
图2-5 监视定时器原理框图
注:PSA和PS2∶PS0在OPTION寄存器中。
由于看门狗的时钟由RC振荡电路提供,所以它的准确度受环境因素影响较大。在不考虑预分频器的情况下,看门狗的定时周期为7~33ms,典型值为18ms。如果需要更长的时间,就需要把预分频器分配给看门狗。预分频器的最大分频比为1:128,这样可使看门狗的定时时间扩大128倍,达到2.3s。故看门狗的定时常数可设置为18ms~2.3s。
在正常工作状态下,WDT时间一到就会产生一个复位信号(即看门狗复位)。如果单片机处于睡眠模式,WDT超时会把芯片唤醒,然后继续正常工作。若WDT超时,则STATUS寄存器中的TO位将被清零。注意,看门狗只能由芯片配置字中的WDTE位使能或关闭,而不被软件控制。
如果把预分频器配置给WDT,用CLRWDT和SLEEP指令可以同时对WDT和预分频器清零,从而防止计时溢出引起芯片复位,所以,在正常情况下,必须在每次计时溢出之前执行一条CLRWDT指令(即喂一次“狗”),以避免引起芯片复位。当系统受到严重干扰处于失控状态时,就不可能在每次计时溢出之前执行一条CLRWDT指令,WDT也就产生计时溢出,从而引起芯片复位,使其摆脱失控状态而重新进入正常运行状态。
2.与WDT有关的寄存器
与看门狗有关的寄存器有3个:芯片配置字(地址为2007H)、状态寄存器STATUS(地址为03H/83H/103H/183H)和选择寄存器OPTION_REG(地址为81H/181H)。
OPTION_WDT中与WDT有关的位定义如下:
注:R:0可读位;W可写位:U:未使用位;-n:POR复位值;x:未知。若无特殊说明,本书中所有与寄存器相关的表格中出现的上述符号/字母均作此解释。
● bit 3 PSA:预分频器分配位。
➢ 1:预分频器分配给WDT。
➢ 0:预分频器分配给Timer0模式。
● bit 2~bit 0 PS2:PS0:预分频器分频比选择位如下:
➢ 状态寄存器STATUS中与WDT有关的位的定义如下:
● bit 3 TO:超时标志位。
➢ 1:单片机初始加电或执行了看门狗清零指令(CLRWDT)或执行了睡眠指令(SLEEP)后,该位置1。
➢ 0:看门狗超时溢出时,自动清零。
● bit 2 PD:掉电标志位。
➢ l:单片机初始加电或执行了CLRWDT指令后,该位置1。
➢ 0:单片机执行SLEEP指令后,自动清零。
3.看门构设计中的注意事项
(1)看门狗清零指令(CLRWDT)和睡眠指令(SLEEP),不仅可以使看门狗定时器清零,还可以同时把预分频器清零(如果预分频器已经分配给WDT使用)。但是,预分频器的分频比以及配置关系不会改变。
(2)“喂狗”的时机。“喂狗”就是指看门狗定时器清零,使看门狗电路继续起作用。“喂狗”一般安排在等待查询的循环体内部、耗时很大的函数体内部或主程序任务队列中,而不安排在定时器中断服务程序中。
死机多发生在程序的指令和数据错位、PC跑飞等场合。因为处理器速度很快,如果跑飞的程序不被死循环套住,则很容易自动重新复位,但是很多情况下偏偏会被死循环套牢,那么就必须将看门狗复位了。如果用定时器中断实现喂狗,则即使主程序死循环,定时器必定依旧正常喂狗,这样看门狗仍然无法复位。
(3)在噪声环境下工作时,OPTION寄存器可能会受到干扰而改变,所以应每隔一段时间就将其重新设置。
2.1.6 睡眠模式
低功耗设计是嵌入式系统的发展方向之一。在PIC系列单片机中,除了在硬件上使用CMOS电路降低功耗外,在软件上也进行了低功耗设计,这就是睡眠模式。在睡眠模式中,芯片处于最小耗电状态,振荡电路停止工作,芯片无系统时钟信号。除了必要的功能模块运行之外,其他功能都处在“睡眠”模式,一旦有事件发生,才被“唤醒”到正常的工作状态。
1.进入睡眠模式
单片机执行一条SLEEP指令就可以进入睡眠模式。进入睡眠模式后,WDT被清零但仍处于工作状态;状态寄存器STATUS中的PD位被清零,TO位被置1;主振荡器(OSC1端的振荡电路)停止工作;所有的I/O端口保持睡眠前的状态。
在睡眠模式中,为使电流最小,应使所有的I/O端口处于高电平VDD或低电平VSS,确保没有外部电路从I/O端口吸收电流,关闭ADC模块并且关闭外部时钟。在外部将所有的高阻抗输入I/O引脚上拉或下拉,以避免悬空引起的开关电流损耗。为降低电流损耗,T0CK1输入引脚也应该接到VDD或VSS。MCLR引脚必须处于高电平状态。
2.睡眠中的唤醒
可以通过以下事件将单片机从睡眠中唤醒:
● MCLR引脚上外加低电平复位信号。
● 看门狗唤醒(如果WDT处于工作状态)。
● 外部中断(INT)。
● PB口电平变化中断。
● 外围接口中断,包括:PSP的读写操作(仅对PIC16F874/877有效)、工作在异步计数方式下的TMR1中断、CCP捕捉模式中断、特殊事件触发中断(Timerl工作于外部时钟异步模式)、SSP起始位/停止位检测中断、从模式下的SSP发送/接收中断(SPI/I2C)、同步从动模式下的USART收发中断、A/D转换中断(当A/D时钟源为RC振荡器时)和E2PROM写操作完成引起的中断。除此之外,其他外围模块不能引发中断,因为在睡眠模式下,芯片内部没有时钟。
当执行SLEEP指令时,下一条指令(PC+1)被取出。如果要用中断唤醒单片机,则在进入睡眠前,该中断使能位必须被置1(即允许该中断),至于全局中断允许位GIE则不会影响中断唤醒功能,但GIE却会影响中断唤醒后单片机动作的走向:当GIE=0(禁止中断)时,单片机被中断唤醒后会沿着原来的SLEEP指令继续执行;当GIE=1(开启中断)时,单片机被中断唤醒后会首先执行完SLEEP后的一条指令,然后跳到中断矢量入口(0004H)执行中断服务程序。如果不希望SLEEP后的一条指令在中断唤醒后被执行,可以在SLEEP指令后插入一条NOP空操作指令。
3.中断唤醒的影响
当全局中断被禁止,所有中断源的中断允许位和中断标志位被置1,则中断唤醒时会出现下面的情况:
● 如果中断发生在SLEEP指令执行前,则SLEEP指令就相当于一条NOP空操作指令。因此,WDT和WDT后分频器不会被清零,TO位不会被置1,PD位也不会被清零。
● 如果中断发生在SLEEP指令执行中或执行后,则单片机就会立即从睡眠状态中被唤醒,而SLEEP指令则会在芯片被唤醒前继续执行。所以,WDT和WDT后分频器会被清零,TO位将被置1,PD位将被清零。
即使在SLEEP指令执行前对标志位进行检查,但在SLEEP指令结束前标志位仍有可能被置1,此时可通过检查PD位来判断SLEEP指令是否被执行。如果PD位被置1,则SLEEP指令只当作一条NOP指令被执行。
为确保WDT被清零,在SLEEP指令前应先执行一条CLRWDT指令。中断唤醒时序图如图2-6所示。
图2-6 中断唤醒时序图
2.1.7 在线调试
PIC16F87X系列单片机的一个重要特色就是具有片内调试电路。任何一款PIC16F87X单片机,无论封装如何,其本身都是一个调试器。当芯片配置字中的DEBUG位被编程为0时,在线调试功能就被使能。该功能允许使用MPLAB-ICD进行一些简单功能的调试,为用户的低成本开发提供了一个解决方案。当使用在线调试功能时,单片机的一些资源将会被占用,如表2-8所示。
表2-8 在线调试所占用的资源
为了可以使用在线调试功能,电路中必须具备在线串行编程连接设计:MCLR/VPP、VDD、GND、RB7和RB6,这样就可以和微芯公司或第三方的开发工具接口统一起来。
2.1.8 程序代码保护
PIC的程序加密功能又是PIC单片机的一个亮点。当芯片配置字的代码保护位没有被编程时,片上程序存储区的内容可以被读出并修改。当选择将芯片的代码保护位熔丝熔断(写入0)后,程序存储区中的程序代码(14位宽)的高10位将被屏蔽。也就是说,当加密后,每一个程序代码都呈现000XH的形式。这样,高10位被0替代了,而低4位也是经过加密运算后的值,他人就无法恢复这些被加密的代码,也就无法进行代码复制了。当然,加密后单片机的功能是不会受到影响的,加密后的程序代码继续在单片机内运行,只是不能被还原读出罢了。目前尚无办法对PIC芯片进行解密。
2.1.9 用户标识码
在PIC系列单片机内部有一个由4个14位长的专用程序存储器单元组成的存储区,其地址为2000H~2003H。该存储区允许用户烧入自己定义的4位十六进制码,用作单片机的标识码(Identification Code)。该标识码不影响单片机的正常工作,只起标识作用。用户可用它来标识软件的版本号或产品的批次等信息。
2.1.10 在线串行编程技术ICSP(In-Circuit Serial Programming)
PIC16F87X系列单片机在最终的应用电路中可以进行在线串行编程,该功能的实现只需时钟、数据、电源、地和编程电压5根线即可。这样就允许用户先做好没有编程的电路板,在装箱运输时再把软件固化到单片机中,也允许采用最新的固件或客户的固件编程。
当使用串行编程时,如果要执行块擦除,芯片的供电电压必须在4.5~5.5V之间。对于所有其他的ICSP,芯片都在正常的工作电压下进行编程。这就意味着校对值、用户ID或用户代码可以串行编程或添加。
芯片配置字中的LVP位允许芯片进入低电压编程模式。该模式允许单片机在VDD正常范围供电的情况下进行在线串行编程。LVP意味着VPP不需要高电压。在这种模式中,RB3/PGM引脚被用作编程功能,而不再作为普通I/O端口使用。在编程期间,MCLR引脚接到VDD。为进入编程模式,RB3/PGM引脚必须接到VDD,以使LVP位置1。出厂时,LVP位默认为1,允许LVP编程模式。用户可通过对芯片配置字中的LVP位清零来禁止低电压编程。
如果不使用低压编程模式,RB3/PGM引脚恢复为数字I/O引脚。LVP位只有在MCLR引脚上加高电压进行编程时才会被置1。
应该引起注意的是,一旦LVP位被清零,则只有高电压编程模式有效,且只有高电压编程模式可以对芯片进行编程。无论LVP为何值,只要在MCLR#引脚加编程高压,高压编程模式即可生效。