1、PIC16F877单片机运算子程序PIC16F877单片机运算子程序1PIC16F877汇编语言程序主体框架以下是一个典型的程序结构:;*程序说明区*LISTp=16f877;指定微控制器型号和文件输出格式INCLUDEp16f877.inc;读入MPLAB提供的定义文件P16F877.INC;*片内RAM常用资源、变量定义和相应的说明*ACCALOEQU20;存放加数或减数低8位ACCAHIEQU21;存放加数或减数高8位ACCBLOEQU23;存放被加数或被减数低8位ACCBHIEQU24;存放被加数或被减数高8位S_WEQU25;栈存W寄存器值S_STATUSEQU26;栈存STATUS
2、寄存器值;*芯片复位矢量*ORG0X0000;由于PIC16F877芯片复位矢量在0000h单;元,所以常在0000h单元处放置一条跳转;指令,使单片机复位后能跳过中断矢量,;直接执行主程序STARTGOTOMAIN;*中断矢量*ORG0X0004;由于PIC16F877的中断矢量为0004h,所以;当中断开放时,需在此处加入中断程序,;使单片机能在中断到来时及时进入相应的;中断服务程序。为了可靠起见,如果单片;机不使用中断,则常常在该中断矢量处放;置RETFIE指令,可以使单片机不会因;干扰产生误中断而导致程序跑飞CALLPUSH;调用保护现场子程序BTFSSPIR1,ADIFCALLAD;
3、若AD中断到,则执行中断服务程序.;此处可放多个中断子程序,并以软件安排;中断优先级CALLPOP;恢复中断现场RETFIE;中断返回;*主程序区*ORG0X0100;将主程序、子程序和中断服务程序等存放;在0100h单元之后,在中断矢量和主程序;区之间预留一些存储单元,以便写入判;跳指令和一些必要的现场保护程序。此外;用户也可以根据实际需要,使主程序从其;它地址开始存放MAINBSFSTATUS,RP0;选择存储体1MOVLW0XFF;定义RA口为输入端口MOVWFTRISABCFSTATUS,RP0;选择存储体0MOVLW0X04;初值化ACCALOMOVWFACCALOCALLDX;调用
4、DX子程序LOOP1;任务1;任务2:GOTOLOOP1;反复执行任务一和任务二等;*子程序区*DXMOVFACCALO,0;ACCB和ACCA低半字节相加ADDWFACCBLORETURN;子程序返回;*PUSHMOVWFS_W;保护W寄存器MOVFSTATUS,0;保护STATUS寄存器MOVWFS_STATUSRETURN;子程序返回;*POPMOVFS_STATUS,0;恢复STATUS寄存器MOVWFSTATUSMOVFS_W,0;恢复W寄存器RETURN;子程序返回;*中断服务子程序区*ADBCFPIR1,ADIF;清AD中断标志;中断服务主体程序RETURN;子程序返回END2四
5、则运算子程序2.11616位定点数加、减法子程序以下子程序实现2个1616位有符号数加、减运算,其和或差用一个16位数表示。在子程序中,减法是通过对减数求补后再与被减数相加来实现的。因此,当程序从D_sub进入子程序时为减法,当从D_add进入子程序时为加法。子程序的入口条件和出口条件如下:入口条件:16位被加数/被减数存放在ACCBHI、ACCBLO中;16位加数/减数存放在ACCAHI、ACCALO中;出口条件:16位和/差存放在ACCBHI和ACCBLO中。以下为1616位有符号数加、减法子程序。注意:在以下注释程序中均以ACCA代替ACCAHI、ACCALO两个字节,以ACCB代替AC
6、CBHI、ACCBLO两个字节。LISTp=16f877INCLUDEp16f877.incACCALOEQU20;存放加数或减数低8位ACCAHIEQU21;存放加数或减数高8位ACCBLOEQU23;存放被加数或被减数低8位ACCBHIEQU24;存放被加数或被减数高8位ORG0X0000STARTGOTOMAIN;*双字节减法子程序,入口地址ACCB-ACCA,出口地址ACCB*D_subCALLNEG_A;求ACCA的补码;*双字节加法子程序,入口地址ACCB+ACCA,出口地址ACCB*D_addMOVFACCALO,0;ACCB和ACCA低半字节相加ADDWFACCBLOBTFSC
7、STATUS,C;有进位否?INCFACCBHI;有,ACCB高字节加1,再加ACCAHIMOVFACCAHI,0;ACCA、ACCB高半字节相加ADDWFACCBHIRETURN;子程序返回;*ACCA取补子程序*NEG_ACOMFACCALO;ACCALO取反加1INCFACCALOBTFSCSTATUS,Z;低8位有进位吗?DECFACCAHI;有,ACCAHI减1,再取反COMFACCAHI;否则ACCAHI直接取反RETURN;子程序返回【校验举例1】19531+(-16594)=2937(十进制)化为十六进制数:4C46H+BF2EH结果:0B79H(十六进制)【校验举例2】262
8、22+3000=29222(十进制)化为十六进制数:666EH+0BB8H结果:7226H(十六进制)【例程】MAINMOVLW0X6E;被加数666EH送ACCBMOVWFACCBLOMOVLW0X66MOVWFACCBHIMOVLW0XB8;加数BB8H送ACCAMOVWFACCALOMOVLW0X0BMOVWFACCAHICALLD_add;调用双字节加法子程序,求和END2.21616位定点数乘法子程序子程序采用部分积右移加法实现乘法运算。乘数和被乘数分别为16位二进制有符号数(均采用补码表示,第16位为符号位),积为32位二进制有符号数,第32位为符号位。子程序的入口条件和出口条件如
9、下:入口条件:被乘数存放在ACCBHI和ACCBLO单元中,乘数存放在ACCAHI和ACCALO单元中。出口条件:积存放在ACCBHI、ACCBLO、ACCCHI和ACCCLO单元中,ACCB为高16位,ACCC为低16位。以下为本子程序的程序清单:LISTp=16f877INCLUDEp16f877.incACCALOEQU20;存放乘数低8位ACCAHIEQU21;存放乘数高8位ACCBLOEQU23;存放被乘数低8位和乘积第1623位ACCBHIEQU24;存放被乘数高8位和乘积第2431位ACCCLOEQU26;存放乘积低8位ACCCHIEQU27;存放乘积高8位ACCDLOEQU28
10、;临时寄存器ACCDHIEQU29;临时寄存器TEMPEQU2A;临时寄存器SIGNEQU2B;存放乘积的符号ORG0X0000STARTGOTOMAIN;*1616位乘法子程序,入口地址ACCBACCA,出口地址ACCB和ACCC*ORG0X0100D_mpyCALLS_SIGN;求取乘积的符号,并对负数取补CALLSETUP;调用子程序,将ACCB的值送ACCDINCFTEMPCLRFACCCHI;清ACCCCLRFACCCLOMLOOPBCFSTATUS,C;清进位位RRFACCDHI;ACCD右移RRFACCDLOBTFSCSTATUS,C;判断是否需要相加CALLD_add;加乘数至
11、ACCB,见加法程序BCFSTATUS,C;清进位位RRFACCBHI;右移部分乘积RRFACCBLORRFACCCHIRRFACCCLODECFSZTEMP;乘法完成否?GOTOMLOOP;否,继续求乘积BTFSSSIGN,7;是,确定乘积的符号GOTOOVER;为正,乘法结束COMFACCCLO;为负,乘积取补INCFACCCLOBTFSCSTATUS,ZDECFACCCHICOMFACCCHIBTFSCSTATUS,ZNEG_BDECFACCBLO;COMFACCBLOBTFSCSTATUS,ZDECFACCBHICOMFACCBHIOVERRETURN;子程序返回;*SETUPMOVL
12、W.15;初始化TEMP寄存器MOVWFTEMPMOVFACCBHI,0;ACCB送ACCDMOVWFACCDHIMOVFACCBLO,0MOVWFACCDLOCLRFACCBHI;清ACCBCLRFACCBLORETURN;子程序返回;*乘法运算确定结果符号判断子程序*S_SIGNMOVFACCAHI,0;ACCAHI异或ACCBHI,结果送SIGN单元XORWFACCBHI,0MOVWFSIGNBTFSSACCBHI,7;ACCB为负吗?GOTOCHEK_A;否,检查ACCACALLNEG_B;是,求取ACCB绝对值CHEK_ABTFSCACCAHI,7;ACCA为负吗?CALLNEG_A
13、;ACCA为负,求取ACCA绝对值,;见双字节加法程序RETURN;ACCA和ACCB均为正,返回【校验举例1】:-24555(-7391)=181486005(十进制)化为十六进制数:A015HE321H结果:0AD141B5H(十六进制)【校验举例2】1640513089=214725045(十进制)化为十六进制数:4015H3321H结果:0CCC71B5H(十六进制)【例程】MAINMOVLW0X15;被乘数4015H送ACCBMOVWFACCBLOMOVLW0X40MOVWFACCBHIMOVLW0X21;乘数3321H送ACCAMOVWFACCALOMOVLW0X33MOVWFAC
14、CAHICALLD_mpy;调用双字节乘法子程序,求积END2.31616位定点数除法子程序子程序采用反复的减法算法,除数和被除数分别为16位二进制有符号数(均采用补码表示,第16位为符号位),商为16位二进制有符号数,第16位为符号位。子程序的入口条件和出口条件如下:入口条件:被除数存放在ACCBHI、ACCBLO单元中;除数存放在ACCAHI、ACCALO单元中。出口条件:商存放在ACCBHI、ACCBLO单元中;余数存放在ACCCHI、ACCCLO单元中。LISTp=16f877INCLUDEp16f877.incACCALOEQU20;存放除数低8位ACCAHIEQU21;存放除数高8
15、位ACCBLOEQU22;存放被除数和商的低8位ACCBHIEQU23;存放被除数和商的高8位ACCCLOEQU24;存放余数低8位ACCCHIEQU25;存放余数高8位ACCDLOEQU26;临时寄存器ACCDHIEQU27;临时寄存器TEMPEQU28;临时寄存器SIGNEQU29;存放商的符号ORG0X0000STARTGOTOMAIN;*1616位数除法子程序,入口地址ACCB/ACCA,出口地址ACCB*ORG0X0100D_divCALLS_SIGN;确定商的符号,并将负数取补CALLSETUP;初始化TEMP,将被除数移至ACCD,;(SETUP子程序请参见1616位定点数;乘法
16、子程序SETUP)INCFTEMPCLRFACCCHI;清余数寄存器CLRFACCCLODLOOPBCFSTATUS,C;清进位位RLFACCDLO;被除数、余数左移1位RLFACCDHIRLFACCCLORLFACCCHIMOVFACCAHI,0;ACCCHI-ACCAHISUBWFACCCHI,0BTFSSSTATUS,Z;ACCCHI=ACCAHI?GOTONOCHKMOVFACCALO,0;是,ACCCLO-ACCALOSUBWFACCCLO,0NOCHKBTFSSSTATUS,C;ACCCACCA?GOTONOGOMOVFACCALO,0;是,余数减除数SUBWFACCCLOBTFS
17、SSTATUS,CDECFACCCHIMOVFACCAHI,0SUBWFACCCHIBSFSTATUS,C;置进位位NOGORLFACCBLO;商左移1位RLFACCBHIDECFSZTEMP;循环完毕?GOTODLOOPBTFSSSIGN,7;是,确定商的符号GOTODIVOVER;为正,除法结束,跳转到结束行COMFACCCLO;为负,商和余数分别取补INCFACCCLOBTFSCSTATUS,ZDECFACCCHICOMFACCCHICALLNEG_B;见乘法程序中间NEG_BDIVOVERRETURN;子程序返回;*除法运算确定结果符号子程序*S_SIGNMOVFACCAHI,0;AC
18、CAHI异或ACCBHI,结果送SIGN单元XORWFACCBHI,0MOVWFSIGNBTFSSACCBHI,7;ACCB为负?GOTOCHEK_A;否,检查ACCACOMFACCBLO;是,ACCB取补INCFACCBLOBTFSCSTATUS,ZDECFACCBHICOMFACCBHICHEK_ABTFSCACCAHI,7;ACCA为负?CALLNEG_A;ACCA为负,取补(NEG_A子程序请参见;1616位定点数乘法子程序NEG_A)RETURN;ACCA和ACCB均为负,返回【校验举例1】-23775(-240)=99.0625(十进制)化为十六进制数:A321HFF10H;结果:
19、(商)0063H,(余数)000FH(十六进制)。【校验举例2】7693856=0.199429(十进制)化为十六进制数:0301H0F10H;结果:(商)0000H,(余数)0301H(十六进制)。【例程】MAINMOVLW0X01;被除数0301H送ACCBMOVWFACCBLOMOVLW0X03MOVWFACCBHIMOVLW0X10;除数0F10H送ACCAMOVWFACCALOMOVLW0X0FMOVWFACCAHICALLD_div;调用双字节除法子程序,求商END33字节浮点四则运算子程序3.1浮点数加(减)法子程序以下为浮点加(减)运算例程:LISTp=16f877INCLUDEp16f877.incACCALOEQU20;存放加数或减数的尾数ACCAHIEQU21EXPAEQU22;存放加数或减数阶码ACCBLOEQU23;存放被加数或被减数尾数
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1