1、第四章,PIC16F877A 功能及其编程制作:王骞,2015.9,4.1 输入输出端口 4.2 中断 4.3 定时/计数器TMR0 4.4 定时/计数器TMR1 4.5 定时/计数器TMR2 4.6 A/D转换器 4.7 CCP模块(Capture/Compare/PWM) 4.8 异步串行通信(USART) 4.9 EEPROM的读写 4.10 SLEEP工作方式,4.1 输入输出端口,877A有33根IO引脚。有A、B、C、D、E共5个端口,其中A端口的有6个引脚,B、C、D口各8个引脚,E口3个引脚。各自端口的方向控制寄存器TRISA、TRISB、TRISC、TRISD、TRISE,控
2、制其相应的端口是作为输出还是输入。0:输出;1:输入所有的I/O端口,上电复位默认值均为1,即为输入口。,每个IO引脚的最大输出电流(拉电流)为20mA,最大输入电流(灌电流)为25mA。端口A、B、E的最大输入电流总和与输出电流总和均为200mA;端口C、D的最大输入电流总和与输出电流总和也为200mA。,对I/O 端口的写操作是一个读修改写的过程。一条写IO引脚的指令如RB3=1,实际上是在指令的开头读入整个B端口,并在指令周期的末尾时刻把1写入RB端口3的输出锁存器。如果立即对同一端口操作,如x=PORTB,在指令周期的开始处,由于前一指令产生在IO口的电平尚未稳定,读入的可能是引脚的前
3、一个状态而不是新状态值。,因此连续对同一端口的操作时,最好用一个NOP 指令或者其他不访问该I/O 端口的指令隔开。 RA31;NOP();RA4=0;,4.1.1 端口A,因此,在使用RA口时,除了要设置TRISA外,有时相关寄存器也要设置。注意:在上电复位时,与AN有关的端口的默认设置是作为模拟端口,即ADCON1(见4.6)中默认值为0b00xx0000,这个值的设置结果是除RA4外的所有的RA引脚都作为模拟输入。,1、端口B有8个引脚: RB0/INT:IO引脚、INT中断; RB1、RB2、RB4、RB5:IO引脚; RB3/PGM:IO引脚、低电压编程电压引脚; RB6/PGC:I
4、O引脚、编程时钟线; RB7/PGD:IO引脚、编程数据线。 2、如果使用PIC KIT3作为调试工具,RB6、RB7引脚将被调试系统占用,因此在调试时此二个引脚暂不能使用。,4.1.2 端口B,3、8个引脚具有内部弱上拉使能控制 由OPTION_REG寄存器的第7位RBPU控制,如果弱上拉使能,作为输入的RB口在端口悬空时将被上拉到高电平。以RB0为例,如下图所示:,4、RB0/INT具有外部中断功能。 5、RB的的高4位还具有电平变化中断功能当RB4RB7引脚做为输入时,只要有一个引脚的逻辑电平发生变化,就会使RB电平中断标志位置1。这些功能的设置,与OPTION、INTCON有关,参见相
5、关各章节。,4.1.3 端口C,RC0/T1OSO/T1CKI:IO引脚、TMR1振荡输出、TMR1外部脉冲输入; RC1/T1OSI/CCP2:IO引脚、TMR1振荡输入、CCP2; RC2/CCP1:IO引脚、CCP1; RC3/SCK/SCL:IO引脚、SPI的时钟线、I2C的时钟线; RC4/SDI/SDA:IO引脚、SPI的数据输入、I2C的数据线; RC5/SDO:IO引脚、SPI的数据输出; RC6/TX/CK:IO引脚、异步串行通信的发送、同步串行通信的时钟线; RC7/RX/DT:IO引脚、异步串行通信的接收、同步串行通信的数据线。,4.1.4 端口D,端口D有8个引脚,它除
6、了作为普通IO口外,还能作为并行从动口使用。,4.1.5 端口E,端口E只有3个引脚,它们都可以作为AD转换的模拟电压输入口,功能如下:RE0/RD/AN5:IO引脚、并行从动口的读控制、模拟电压输入通道AN5; RE1/WR/AN6:IO引脚、并行从动口的写控制、模拟电压输入通道AN6; RE2/CS/AN7:IO引脚、并行从动口的片选控制、模拟电压输入通道AN7。,4.2 中断,中断的概念:正常程序运行时发生了事先设定的事件,需要暂停原来运行的程序而转到处理目前需要马上处理的事件。 中断的特点:可返回性。中断处理结束后必须能回到原先的程序,并且能继续运行原先的程序,这就需要在中断时能进行现
7、场保护与恢复。,中断的执行过程,中断发生:程序执行到某行,突然事件(能够产生中断的事件)发生,产生中断。 断点保护:CPU自动将中断时刻即将要执行的下一条指令的地址压入堆栈。 中断响应:CPU自动将PC强制设为0X0004,且GIE0。执行中断服务程序(自动完成现场保护与恢复,手动清中断标志位)。 中断返回:程序执行到”RETFIE”时,按照后入先出的原则,自动从堆栈中弹出地址给PC,GIE1,程序返回到中断前要执行的程序,程序恢复中断前程序的运行状态。,PIC16F877A有15个中断源,每个中断源都有自己的使能控制位(IE)和中断标志位(IF)。,中断逻辑示意图,只有在SLEEP状态下能运
8、行的模块产生中断才能唤醒SLEEP。,中断CPU 当前的程序,唤醒CPU (如果当前处于睡眠模式),PEIE控制了12个中断源,与门:只有所有的输入为1,输出才为1 或门:只要有一个输入为1,输出就为1,GIE,+,+,GIE控制所有的中断源,中断控制寄存器:INTCON相应使能位为1,允许中断;为0,禁止中断。相应标志位为1,表示有中断发生,必须用软件清0。,第一外围中断控制寄存器 PIE1:,第一外围中断标志寄存器 PIR1:,第二外围中断控制寄存器 PIE2:,第二外围中断标志寄存器 PIR2:,选项寄存器OPTION_REG:与中断直接相关的位为INTEDG,它涉及到外部中断(RB0/
9、INT)的中断边沿选择,0为下降沿。OPTION_REG=0b10111111; /等效 INTEDG=0,进入中断后硬件自动屏蔽全局中断,即中断后GIE=0,中断返回后自动恢复全局中断允许,GIE=1。因此,PIC16单片机不允许中断嵌套!也就是说,在中断服务程序未退出时,即使有新的中断发生,也不能进入中断。等当前的中断处理完成退出中断后才能重新进入中断。,注意:,每按一次按键,LED翻转亮,/例 用RB0/INT按键,每按一下,LED翻转亮 #include _CONFIG(0x3F39); #define LED RB7 char A=0; /全局变量,保存LED状态void DELAY
10、(unsigned int); void interrupt ISR(void);void main(void) OPTION_REG=0b00000000; /RB0为下降沿触发中断TRISB =0b00000001; /设定RB0为输入,RB7为输出INTCON=0b10010000; /允许RB0/INT中断LED=0; /初始状态LED灭while(1); /原地等待 ,/=中断服务程序 void interrupt ISR(void) if (INTF=1) DELAY(30); /延时30ms,躲过抖动时间INTF=0; /清中断标志位,须在延时之后!LED=!LED; ,/=延时
11、(n)ms,4MHz晶振下 void DELAY(unsigned int n) unsigned int j;char k;for (j=0;j0;k-) NOP(); 以后此程序略,可参见附录:公用子程序。,4.3 定时/计数器TMR0,TMR0是个8位计数/定时器自带可编程预分频器,可对外部脉冲计数或对内部指令脉冲计数(1:11:256)工作原理:递加计数。即由计数初值开始,每来若干个计数脉冲(和预分频比有关),计数值+1,直到255。若再加1,溢出,同时使计数当前值等于0TMR0有溢出中断功能,T0IF将自动置1,若要对外部脉冲计数,必须 编程OPTION_REG ,()置1 编程TR
12、ISA , RA4/T0CKI引脚设置为输入 硬件电路:符合一定要求的外部脉冲送RA4/T0CKI,与TMR0有关的寄存器,TMR0、OPTION_REG、INTCON 、TRISA初值 控制字 中断 端口,OPTION_REG分频器倍率选择位,TMR0的预分频系数范围为2-256,如何获得1:1的倍率?,采用4MHz晶振,用TMR0最大延时多少?,例:假设晶振振荡频率fosc=4MHz,求TMR0最大延时时间是多少? 解:则指令周期Tcy=1us TMR0的最大延时时间为:256256Tcy=65536Tcy=65536us。,TMR0延时常数计算示例,例:假设现要延时12ms,即12000
13、us. 首先要先计算预分频系数K:256KTcy=12000,得K=48.9,取比其大的预分频系数64。再计算延时常数X:(256X) KTcy=12000,得X=68.5,四舍五入取整X=69。即:TMR0=69,在允许的情况下,分频比倍率越小越好,分辨率越高!,编程举例!注意:在初始化编程中TMRO须赋初值!在程序适当的地方(如中断服务子程序中)还必须重装初值!,福州大学电气工程与自动化学院,4.4 定时/计数器TMR1,TMR1是由2个8位寄存器TMR1H(0FH)、TMR1L(0EH)组成的16位计数/定时器自带可编程预分频器,可对外部脉冲计数或对内部指令脉冲计数(分频比1、 2、 4
14、 、8)工作原理:递加计数。其计数值由0000H到0FFFFH循环增加,当它从0FFFFH加1时变为0000HTMR1有溢出中断功能,PIR1.TMR1IF将自动置1,相关的寄存器有:TRISC、TMR1H、TMR1L 、T1CON、INTCON若要对外部脉冲计数,必须 编程T1CON,()置1 编程TRISC , RC0/T1CKI引脚设置为输入 硬件电路:符合一定要求的外部脉冲送RC0/T1CKI与TMR0不同的还有,它有一个控制定时器走/停的控制位T1CON.TMR1ONTMR1还是CCP模块中的比较和捕捉工作的时基(参见4.7),TMR1控制寄存器T1CON,TMR1延时常数的计算,计
15、算出初值后,要转换为十六进制 TMR1H=155368; TMR1L=15536;,读取TMR1当前值时要特别注意的问题:,在读取TMR1H、TMR1L的值时,要注意是否在读期间发生了从低字节向高字节进位。 假设当前TRM1H、TMR1L0x01FF,则在读取TMR1时就可能发生错误: 如先读低字节,得到0xFF,假设此时发生进位,则再读高字节时得到0x02,总的结果是0x2FF,显然是错误的。 如先读高字节,得到0x01,假设此时发生进位,则再读低字节得到0x00,总的结果是0x100,也是错误的。,如果允许的话,在读之前让TMR1停止计数; 如果不允许停止计数,则先读高字节,再读低字节,再
16、读一次高字节,如果前后2次读的高字节不同,说明在读期间发生了进位A=TMR1H; /先读高字节 B=TMR1L; /再读低字节 C=TMR1H; /再读高字节 if(A=C) /判断读期间是否发生从低字节向高字进位X=(A8)+B; /没有进位,就用第一次读高字节的结果 elseX=(C8)+0; /发生进位,用第二次读高字节的结果,编程举例,TMR2是8位定时器,它不能为外部脉冲计数。与TMR1相同,它有一个控制定时器走/停的控制位T2CON.TMR2ON。它既有前(预)分频(1,4,16),还有后分频(116)即溢出多少次后产生中断。,4.5 定时/计数器TMR2,它还有一个周期寄存器PR
17、2(0x92)。PR2可以编程设置为不同的值,当TMR2的值等于PR21时产生溢出中断标志,且TMR2自动清零。 PR2复位值为0xFF,如果不对PR2值设置,相当于TMR0。常用方法:无须对TMR2设初值,即初值固定为0X00,而通过设置PR2实现不同时间定时TMR2还是CCP模块中的PWM工作方式的时基(参见4.7),4.5 定时/计数器TMR2,TMR2控制寄存器T2CON,TMR2延时常数的计算,TMR2既有前分频,又有后分频,其最大延时时间为2561616Tcy=65536Tcy例:已知4MHz主频,要求延时1ms 解:则(PR2+1)*K1*K2*Tcy=1000 常用做法:先将K
18、2设为1,确定PR2和K1,不够的时候在调整。K1、K2可优化设计。,用定时器延时和用软件延时的方法,应用上有何区别?,小结:3个定时器比较异同,定时器0和2是8位,定时器1是16位 定时器0、1可对外部脉冲计数,有相应的引脚对应RA4/T0CKI 、 RC0/T1CKI,定时器2无 三者都有预分频器,定时器2还有后分频器 定时器0的预分频器和看门狗WDT共用,定时器1:T1CON,定时器2:T2CON 预分频比不同:定时器0:8种、定时器1:(1,2,4,8)定时器2:(1,4,8) 定时器1和2都有控制停和走的控制位,定时器0无 定时器2有周期寄存器PR2,定时器0和1无,AD转换使得单片
19、机能够识别模拟量8路模拟输入通道,分别在A口(5个)与E口(3个),但同一时刻只能有一路模拟信号进行AD转换10位AD,能分辨的电压值为Vcc/210,当Vcc=5V时,能分辨的电压值是5V/10244.883mVAD转换结果将按照设定的格式放在ADRESH和ADRESL,设定的格式有左对齐和右对齐,4.6 A/D转换器,与AD有关的寄存器有: TRISA,TRISE,PORTA,PORTE,ADCON0,ADCON1,ADRESH , ADRESL 与AD中断有关的寄存器有: INTCON,PIE1,PIR1,AD转换模块内部结构示意图,控制寄存器ADCON0,除In-RC外, 须保证Tad
20、=1.6us,PIC16系列单片机的AD采集时间,AD转换过程:先打开AD通道,被转换电压对AD模块的保持电容充电,待电容充满电,才能进行AD转换AD采样时间Tsamp=(采集时间Tacq)+(AD转换时间) 采集时间Tacq:即充电时间,是由于内部的保持电容充电所要求的,Tacq要求在20us(AD转换时间)=(N+2)Tad=12Tad,N为AD位数,N=10除了以RC作为采样时钟外,Tad最小为1.6us。即在选择AD时钟时,要根据单片机的工作频率选取。常用4M晶振,选8TOSC=2us1.6us,满足要求!,Tad与PIC单片机的最大工作频率(标准F型),控制寄存器ADCON1,AD结
21、果对齐示例,显然,上表的设计不是很合理,它不能由用户任意选定哪些引脚做AD转换,哪些引脚做普通IO口,在PIC16F887中已经对此进行了改进。,对AD参考电压与输入电压的要求,单位V,A/D转换步骤(采用查询的方法),1禁止A/D中断(PIE1.ADIE=0); 2设置有关的I/O口:TRISA或TRISE设置为输入; 3设置ADCON1:对模拟引脚/基准电压/数字I/O进行设置,选择A/D结果格式; 4设置ADCON0:选择A/D通道、时钟, A/D模块使能; 5延时约20us:使得输入电压对保持电容充电达到稳定; 6启动A/D转换:(GO=1); 7等待A/D转换结束:查询(PIR1.A
22、DIF=0或GO=1), PIR1.ADIF软件清零,GO自动清零; 8读A/D转换结果:(ADRESH、ADRESL),AD转换值输入模拟电压Vin1023(Vref+Vref-)例:某一输入的模拟电压为2V,如果参考电压是VddGND, 解:若Vdd=5V,AD值210235409Vdd=2.5V,AD值 210232.5818结论:同样的输入电压,若参考电压不同,计算得到的数值(理论值)也不同。所以,要求参考电压要稳定!,编程举例,4.7 CCP模块(Capture/Compare/PWM),共有两个CCP模块:CCP1、CCP2CCP模块对应的引脚为CCP1RC2,CCP2RC1CCP
23、模块各有一个16位的可读写的寄存器CCPRxH、CCPRxL,且各有相应的控制寄存器为CCPxCON与CCP有关的寄存器有: TRISC、PORTC、CCP1CON、CCP2CON、 CCPR1H、CCPR1L、CCPR2H、CCPR2L、 中断相关的寄存器、以及TMR1,TMR2相关的寄存器,CCP1和CCP2,除了触发特殊事件不同外,两者在功能上没有其他不同。因此,以下内容常以CCP1为例说明!,CCP模块的时钟源,控制寄存器CCP1CON/CCP2CON,CCP模块工作方式设置,4.7.1 捕捉模式,工作原理:有事先设定的事件在RC2/CCP1上发生时,CCPR1H、CCPR1L就捕捉1
24、6位寄存器TMR1的值可以捕捉的事件为以下之一:每个下降沿 每个上升沿每4个上升沿每16个上升沿所谓捕捉,就是把当设定的事件发生时的TMR1H、TMR1L的值自动送给CCPR1H、CCPR1L。在此过程中,定时器1一直保持工作。,捕捉方式结构图,例:每4个上升沿捕捉一次的工作情况,当产生一次捕捉时,相应的中断标志位被置1,必须由软件清0。 如果在一个捕捉未读取时又产生一个捕捉,则前一个捕捉值被取消。 在捕捉模式中,必须把RC2/CCP1(PC1/CCP2)定义成输入。 而TMR1必须定义为定时器或同步计数器,如果定义为异步计数器,则捕捉无法工作。 所谓同步计数器,指的是在一个指令周期中的4个
25、节拍中,TMR1可以在任何节拍时与外部脉冲同步加1,而异步计数时,TMR1都要等到指令周期结束时才加1。,说明:,如果CCPx从捕捉模式改变为其它模式时,会产生一个错误的捕捉中断,因此用户要先屏蔽其中断,即对CCPxIE清0。且在捕捉模式改变后对CCPxIF清0。 如果用户程序改变捕捉预分频率,也会产生一个错误的中断请求,且预分频器不会清0。以下的程序可以清预分频器并且不会引起错误的中断请求:CCP1CON=0; /关闭CCP1模块(CCP1复位) CCP1CON=NEW_CAPT_PS; /选择新的预分频系数,编程举例,4.7.2 比较模式,工作原理:CCPRxH、CCPRxL不停地与TMR
26、1H、TMR1L进行比较,当二者相等时,将在CCPx(RC2/CCP1,RC1/CCP2)产生以下的事件: 1000:CCPx引脚输出高电平,CCPxIF置11001:CCPx引脚输出低电平,CCPxIF置11010:CCPx引脚状态不变,CCPxIF置11011:触发特殊事件 CCP1:复位TMR1, CCP1IF置1 CCP2:复位TMR1, 自动启动A/D转换 (注:复位TMR1,即将TMR1H,TMR1L清零),4.7.2 比较模式,CCP2触发特殊事件应用:要求在此之前先使能 A/D 模块 (ADON 位置 1)。触发时, GO/DONE 位被自动置1,启动A/D 转换。自动复位TM
27、R1 可实现A/D 采集周期的自动重复。在比较模式中,必须把RC2/CCP1(PC1/CCP2)定义成输出。在本模式下,对TMR1的要求同捕捉模式,即要做为定时器或同步计数器。,4.7.2 比较模式,工作原理:CCPRxH、CCPRxL不停地与TMR1H、TMR1L进行比较,当二者相等时,将在CCPx(RC2/CCP1,RC1/CCP2)产生以下的事件: 变为高电平 变为低电平 保持不变 触发特殊事件 在比较模式中,必须把RC2/CCP1(PC1/CCP2)定义成输出。 比较匹配时,TMR1清零,同时PIRx.CCPxIF被置1。 在本模式下,对TMR1的要求同捕捉模式,即要做为定时器或同步计
28、数器。,比较方式结构图,TMR1在工作,即TMR1值在增加。当TMR1值与CCPRx相等时便产生了匹配。,事先设定的CCPRx之值,触发特殊事件:不影响CCPx引脚状态,都会对TMR1清0,都不会对TMR1IF置1; CCP1和CCP2唯一的不同: CCP1:置CCP1IF为1; CCP2:置CCP2IF为1,启动A/D 转换。 要求在此之前先使能 A/D 模块 (ADON 位置 1)。触发时, GO/DONE 位被自动置1,启动A/D 转换。复位TMR1 可实现A/D 采集周期的自动重复。,比较模式下触发特殊事件,编程举例,4.7.3 PWM模式,在PWM模式下,TMR2为其时基。根据不同的
29、设置值,从CCPx脚输出周期和脉宽一定的矩形波。周期 Tp=(PR2)+1*4Tosc*(TMR2预分频值) 脉宽 Td=DC1*Tosc*(TMR2预分频值) 其中DC1=(CCPR1L:CCP1CON),10位的数,PWM模式参数计算,周期 Tp=(PR2)+1*4Tosc*(TMR2预分频值) 脉宽 Td=DC1*Tosc*(TMR2预分频值) 其中DC1=(CCPR1L:CCP1CON)已知:周期Tp和脉宽Td 解: 第一步计算周期:先假定PR2=255,TMR2预分频值查表选择略大于计算值的可选项再计算PR2=? 第二步计算脉宽:利用上步计算得到的预分频值代入脉宽公式计算DC1(10
30、位的数),PWM编程步骤:,1. 将PWM的周期值写入PR2。 2. 将PWM的脉宽值写入(CCPRxL和CCPxCON) 3. 设置TRISC,使得CCPx为输出。 4. 设置TMR2预分频值,置T2CON.TMR2ON=1,TMR2开始计时。 5. 设置CCPxCON,定义CCPx为PWM模式。,PWM输出示意(CCP1X=CCP1Y=0),8位工作循环周期值写入CCPRxL,当循环开始时CCPx输出1,8位数据CCPRxL就传送到CCPRxH中,CCPRxH与TMR2进行比较,相等时CCPx脚输出0,然后TMR2再与PR2比较,当TMR2+1=PR2时CCPx脚输出1,TMR2自动清0,
31、不产生CCPxIF中断标志位,下一周期开始。,编程举例,4.8 异步串行通信(USART),可在单片机与单片机之间,单片机与计算机之间进行通信,异步串行通信是最常用的通信方法。 “异步”指的是在通信的每个字节之间的间隔时间可以不一样,但每一位的时间宽度是严格按照通信波特率要求的。而同步通信要有一个同步脉冲信号,每个字节中的每一位是要严格按通信时钟的上下沿的有关规定进行的。 “串行”指的是进行通信的每个字节是由一位一位发出或接收的。 它只需要RX,TX,GND三根线就可以进行通信。 RC7/RX,RC6/TX是877A的异步串行通信脚。,与异步串行通信有关的寄存器有: TRISC、PORTC R
32、CSTA、TXSTA、 SPBRG、 RCREG、TXREG 及中断相关的寄存器INTCON、PIE1(RCIE,TXIE)、PIR1(RCIF,TXIF)。,上图为发送一个0xEA (0b11101010),采用偶校验的情况。,偶校验:即发送的为1的位数必须为偶数,通过改变校验位使得整个帧中为1的位数为偶数。 奇校验:就是调整校验位,使得发送的1帧数中为1的位数为奇数。 也可以采用校验位恒1,恒0等方式。,例4.14 奇偶校验程序,例:要求奇校验,有一个字符型变量A,判断其二进制数中1的个数N,如N为奇数,令TX9D=0,反之为1。 N=PARITY_CHECK(A); If(N=1)TX9
33、D=0; else TX9D=1; /奇偶校验,实际是计算字符型变量中1的个数 Char PARITY_CHECK(char X) char i,j=0;for(i=0;i1; /计算1位后整个数右移1位,下次仍判断0位if(j / j是奇数,返回1 ,波特率设置,异步模式下,在低速时,即TXSTA.BRGH=0时,波特率计算公式为:波特率=Fosc/(64(X+1) 高速即TXSTA.BRGH=1时,波特率计算公式为:波特率=Fosc/(16(X+1) 这里X为波特率因子,即SPBRG之值,Fosc为晶振的振荡频率。 应用:已知波特率,通过计算波特率因子,选择采用高速或低速方式(导致精度不同
34、),波特率计算示例,例:已知晶振的振荡频率为4MHz,拟采用9600波特率 解: 低速方式:9600=4000000/(64(X+1),得X=5.51,取6验证:4000000/(64*(6+1)=8928.6 高速方式:9600=4000000/(16(X+1),得X=25.04,取25验证:4000000/(16*(25+1)=9615.4比较二者的误差: 低速:(8928.6-9600)/9600=-6.99% 高速:(9615.4-9600)/9600=0.16% 对这种情况,选高速。,TXSTA:发送状态和控制寄存器,RCSTA:接收状态和控制寄存器,注意:即便一个程序中不是同时包含
35、接收和发送程序(也就是说只有接收或者只有发送功能),但是在程序中仍然要对RCSTA和TXSTA都进行定义!,福州大学电气工程与自动化学院,发送接收步骤(发送:查询方式;接收:中断方式),禁止发送中断,允许接收中断; 由所要求的波特率计算、选择高速、低速方式 (TXSTA.BRGH)及波特率因子SPBRG; 将0b0X100Y00送给TXSTA,设置结果是发送允许,其中X根据要发送的数据位数(8或9位)决定,Y由波特率计算误差判断决定是高速还是低速; 将0b1X010000送给RCSTA,设置结果是串口使能,允许接收,其中X根据要发送的数据位数(8或9位)决定; 如为9位数据,先把第9位数送入T
36、XSTA.TX9D,再把要发送的数送入TXREG,开始发送; 查询发送是否结束(PIR1.TXIF=0或TXSTA.TRMT=0),如结束,清PIR1.TXIF; 查询是否有接收中断标志(PIR1.RCIF),如有,则读入RCREG,如为9位数据,还要读入第9位(在RCSTA.RX9D),清接收中断标志。,编程示例,EEPROM是单片机应用中一个重要的资源,它的主要特点是在掉电时数据仍能保持不变,通常作为保存仪器、设备的各种设定值。Microchip公司所给的PIC16F877A的EEPROM的参数是保证100万次的擦除,数据保存时间大于40年。 并非所有的单片机都有EEPROM。 PIC16
37、F877A 有256个字节的EEPROM,地址为 0255(00FFH)。,4.9 EEPROM的读写,下面是“PIC.H”中的EEPROM_READ宏定义,#define EEPROM_READ(addr) (EEADR=(addr),(EECON1 while(0),EEPROM的读、写的宏定义调用格式如下: EEPROM_WRITE(addr, value); X=EEPROM_READ(addr); 其中的“addr”为要读或写的EEPROM的地址(0255),“value”为要写入EEPROM的数据。例: EEPROM_WRITE(0x34, 0x9A); X=EEPROM_READ
38、(0x34);,可以使用下列语句对EEPROM的数据进行初始化,即将相关的数据在芯片烧写时写入EEPROM:_EEPROM_DATA(D0,D1,D2,D3,D4,D5,D6,D7); 其中的D0D7为要写入的常数,这些数据分别被写入EEPROM的单元0单元7。此方法只能按顺序从EEPROM的单元0开始逐一定义。如果要在EEPROM后面的单元定义初值,则也要从0单元开始定义。,还可以对程序存储器进行读写,同样也是用PICC中的宏定义,可参考本书中的相关内容。,4.14.2 SLEEP工作方式,在SLEEP工作方式下,可以节省电源,特别适合于使用电池的场合。在5V工作电压,4M晶振下,不考虑外围
39、电路的工作电流,正常的工作电流约为1.5-4mA,而在SLEEP工作方式下,工作电流约为1.5-20uA(WDT不工作)或10-40uA(WDT工作)。 在SLEEP工作模式下,可以提高A/D转换的精度。 为了降低工作电流,在进入SLEEP之前,必须将所有的I/O口置为高电平或低电平。,可以唤醒SLEEP的事件:,WDT溢出(如果WDT使能的话) INT(RB0)引脚中断 USART同步从属模式的发送与接收中断 A/D转换(采用内部RC振荡)中断 TMR1溢出中断(必须在异步模式) EEPROM写操作完成中断 CCP模块中断(常为捕捉模式) SSP开始位检测中断 PSP读或写中断 SSP从属模
40、式下的发送与接收中断 MCLR复位;(唤醒后从0X0000开始执行),还有一些中断无法唤醒SLEEP,这是由于它们的工作要用到内部时钟,而在睡眠时内部时钟已停止工作,这样,这些模块也停止工作。,1、执行SLEEP和从SLEEP唤醒会影响状态字STATUS的PD和TO位,从中可以判断何事件发生。 2、MCLR复位唤醒SLEEP,程序从0000H开始执行。 3、在SLEEP方式WDT溢出,则从“SLEEP”后的语句继续执行。而在非SLEEP方式时,WDT溢出则从0000H开始执行。 4、要使有关中断能唤醒SLEEP,必须使相应的中断允许,例如要使A/D转换能唤醒SLEEP,除了使用内部RC振荡器作为A/D转换的时钟外,应该置INTCON.PEIE=1和PIE1.ADIE=1。,要点:,5、INTCON.GIE是否为1不会影响唤醒SLEEP。它只影响在唤酲SLEEP之后,是进入中断服务程序,还是执行“SLEEP”之后的语句。 在GIE=0时,唤醒SLEEP后,执行“SLEEP”之后的语句。 在GIE=1时,唤醒SLEEP后,先执行“SLEEP”之后的一条语句,然后才进入中断服务程序。因此,如果不希望唤醒后执行“SLEEP”之后的那条指令,则在“SLEEP”之后加上“NOP()”指令。,理解、分析P217 例4.24,END,福州大学电气工程与自动化学院,