『壹』 51單片機各種位數定時器初值計算方法
對12MHz ,1個機器周期 1us ,12/fosc = 1us
。
方式0是13位定時器,最大時間間隔 = 2^13 = 8.192ms
方式1是16位定時器,最大時間間隔 = 2^16 = 65.536ms
方式2是8位定時器,最大時間間隔 = 2^8 = 0.256ms =256 us
方式3 僅適用於T0,此時T0分成兩個8位計數器,T1停止計數
當選用定時器的方式1時,設機器周期為Tcy,定時器產生一次中斷的時間為t,那麼需要計數的個數N=t/Tcy,裝入THX和TLX中的數分別為:
THX = (2^16 - N)/256 TLX = (2^16 -N )%256(此處的X為定時器0或定時器1)
公式為:(2^y - X)*Tcy = t
Tosc= 1/ fosc
一個機器周期 = 12個時鍾周期 = 12/fosc
溢出速率 = 1 / 溢出時間
故:初值X = 2^y – t/Tcy
THX = 高八位
TLX = 低八位
註:
X:定時器初值
N:計數值
y:定時器工作方式
fosc:晶振頻率
Tcy:機器周期,Tosc:時鍾周期
Tcy = 1/Tosc
『貳』 51單片機帶小數的多位元組乘除運算
對於多位元組數,估計你不會直接保存成數值而是要保存成字元串了吧,當然如果你保存成數值的話通過連續乘10直到結果為整數的方法計算小數點後的位數,對於小數相乘來說,兩個數的小數點位數相加就是結果的小數點位數。數值計算可以全當整數,按大數乘法計算。而除法可以通過同時向後移位小數位到全部都是整數,用大數除法的演算法解決。如果存的是數值,直接連續乘10.
附,大數計算,這個是在電腦上編的,不過都是C語言,可以參考,有不懂可以問我。
#include <stdio.h>#include <string.h>
//-----------------------------------------------//將字元串轉化為整形數組void str2int(char *a,char *b,int ia[1024],int ib[1024],int ir[1024]){ int i,len; //對數組初始化 for (i=0;i<1024;i++) { ia[i]=0; ib[i]=0; ir[i]=0; } //將a翻轉後輸入到數組 i=strlen(a); len=strlen(a); while(i) { i--; ia[len-i-1]=*(a+i)-48; } //將b翻轉後輸入到數組 i=strlen(b); len=strlen(b); while(i) { i--; ib[len-i-1]=*(b+i)-48; }}//-----------------------------------------------//比較大小int cmp(char *a,char *b){ int i,sg; if (strlen(a)>strlen(b)) { sg=0; } else if (strlen(a)<strlen(b)) { sg=1; } else { for (i=0;i<(int)strlen(a);i++) { if (*(a+i)>*(b+i)) { sg=0; break; } else if (*(a+i)<*(b+i)) { sg=1; break; } else sg=0; } } return sg;}//-----------------------------------------------//加法函數char *add(char *a,char *b){ int len,i,c; int ia[1024],ib[1024],ir[1024]; str2int(a,b,ia,ib,ir); if (strlen(a)>strlen(b)) len=strlen(a); else len=strlen(b); c=0; //加法運算 for (i=0;i<len;i++) { ir[i]=(ia[i]+ib[i]+c)%10; c=(ia[i]+ib[i]+c)/10; } if (c==1) { ir[len]=1; len++; } for (i=0;i<len;i++) { *(a+i)=ir[len-i-1]+48;//翻轉輸出 } *(a+len)='\0'; return a;}//-----------------------------------------------//減法函數char *sub(char *a,char *b){ int len,i,c,sg; int ia[1024],ib[1024],ir[1024]; char str[1024]; char *strrt; str2int(a,b,ia,ib,ir); //符號判斷 sg=cmp(a,b); if (sg==0) len=strlen(a); else len=strlen(b); c=0; //減法運算 for (i=0;i<len;i++) { if (sg==0) { if ((ia[i]-ib[i]-c)>=0) { ir[i]=ia[i]-ib[i]-c; c=0; } else { ir[i]=10+ia[i]-ib[i]-c; c=1; } } else { if ((ib[i]-ia[i]-c)>=0) { ir[i]=ib[i]-ia[i]-c; c=0; } else { ir[i]=10+ib[i]-ia[i]-c; c=1; } } } if (sg==1) str[0]='-'; for (i=0;i<len;i++) { str[i+sg]=ir[len-i-1]+48;//翻轉輸出 } str[len+sg]='\0'; strrt=str; //去零處理 if (sg==0) { while(len>1&&*strrt=='0') { strrt++; len--; } } if (sg==1) { strrt++; while(len>1&&*strrt=='0') { *strrt='-'; strrt++; len--; } strrt--; } strcpy(a,strrt); return a;}
//-----------------------------------------------//乘法函數char *mul(char *a,char *b){ int len,lena,lenb,i,j,c,jin; int ma[1024],mb[1024],mr[1024]; char stra[1024],strb[1024]; char *strrta,*strrtb; stra[0]='0'; stra[1]='\0'; strrta=stra; str2int(a,b,ma,mb,mr); //乘法運算 lena=strlen(a); lenb=strlen(b); for (j=0;j<lena;j++) { c=0; jin=0; for (i=0;i<lenb;i++) { mr[i]=(ma[j]*mb[i]+c)%10; c=(ma[j]*mb[i]+c)/10; } len=lenb; if (c>0) { strb[0]=c+48; jin=1; } for (i=0;i<len;i++) { strb[i+jin]=mr[len-i-1]+48; } for (i=len;i<len+j;i++) strb[i+jin]='0'; strb[len+j+jin]='\0'; strrtb=strb; add(strrta,strrtb); } strcpy(a,strrta); return a;}//--------------------------------------------------//除法函數char *div(char *a,char *b){ int len,lena,i,j; char stra[1024],strb[1024],strc[1024],strd[1024]; char *strbp; strbp=strc; strcpy(stra,a); strcpy(strb,b); strcpy(strd,a); if (cmp(stra,strb)==1) { //被除數小於除數 *a='0'; *(a+1)='\0'; strcpy(b,stra); } else { //被除數大於除數 mul(strb,"10"); len=strlen(a)-strlen(b); if (len==0||(len==1&&cmp(stra,strb)==1)) { strcpy(stra,a); strcpy(strb,b); i=1; strc[0]='1'; strc[1]='\0'; while(cmp(stra,strc)==0) { strc[0]=i+48; strc[1]='\0'; mul(strc,strb); i++; } *a=i+46; *(a+1)='\0'; strcpy(strc,a); mul(strc,strb); sub(stra,strc); strcpy(b,stra); } else { len=strlen(a)-strlen(b); for (j=0;j<=len;j++) { for (i=0;i<=(int)strlen(b);i++) { if ((i+j-1)<0) stra[i]='0'; else stra[i]=*(a+i+j-1); } stra[strlen(b)+1]='\0'; strcpy(strb,b); strbp=stra; lena=strlen(strbp); while(lena>1&&*strbp=='0') { strbp++; lena--; } div(strbp,strb); strc[j]=*strbp; strbp=strb; for (i=0;i<(int)(strlen(b)-strlen(strb));i++) { strbp--; *strbp='0'; } for (i=strlen(b)-1;i>=0;i--) { *(a+i+j)=*(strbp+i); } } strc[len+1]='\0'; strbp=strc; lena=strlen(strbp); while(lena>1&&*strbp=='0') { strbp++; lena--; } strcpy(a,strbp); mul(strbp,b); sub(strd,strbp); strcpy(b,strd); } } return a;}
void main(){ char a[1024],b[1024],c; c='0'; while(c!='q') { printf(">>請輸入命令\n>>+ 加\n>>- 減\n>>* 乘\n>>/ 除\n>>q 退出\n>>"); c=getchar(); getchar(); switch(c) { case 'q':break; case '+': printf(">>請輸入第一個加數\n>>"); gets(a); printf(">>請輸入第二個加數\n>>"); gets(b); printf(">>和為%s",add(a,b)); getchar(); break; case '-': printf(">>請輸入被減數\n>>"); gets(a); printf(">>請輸入減數\n>>"); gets(b); printf(">>差為%s",sub(a,b)); getchar(); break; case '*': printf(">>請輸入第一個乘數\n>>"); gets(a); printf(">>請輸入第二個乘數\n>>"); gets(b); printf(">>積為%s",mul(a,b)); getchar(); break; case '/': printf(">>請輸入被除數\n>>"); gets(a); printf(">>請輸入除數\n>>"); gets(b); div(a,b); printf(">>商為%s余數為%s",a,b); getchar(); break; default:break; } }}
『叄』 單片機乘法的實現
org 0000h
jmp start
start:
MOV SP,#60H
mov r2,#20h
mov r3,#34h
mov a,#99h
lcall bhd
lcall hbd
NOP
NOP
;三位元組除以單位元組子程序
;入口條件:被除數在R3、R4、R5中,除數在R7中。
;出口信息:OV=0 時,雙位元組商在R4、R5中,OV=1 時溢出。
;影響資源:PSW、A、B、R2~R7 堆棧需求: 2位元組
DV31:
CLR C
MOV A,R3
SUBB A,R7
JC DV30
SETB OV ;商溢出
RET
DV30:
MOV R2,#10H;求R3R4R5/R7-→R4R5
DM23:
CLR C
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV F0,C
CLR C
SUBB A,R7
ANL C,/F0
JC DM24
MOV R3,A
INC R5
DM24:
DJNZ R2,DM23
MOV A,R3 ;四捨五入
ADD A,R3
JC DM25
SUBB A,R7
JC DM26
DM25:
INC R5
MOV A,R5
JNZ DM26
INC R4
DM26:
CLR OV
RET ;商在R4R5中
;兩位元組除以單位元組子程序
;入口條件:被除數在R4、R5中,除數在R7中。
;出口信息:OV=0 時,單位元組商在R3中,OV=1 時溢出。
; 余數在r4中
;影響資源:PSW、A、R3~R7 堆棧需求: 2位元組
D457:
CLR C
MOV A,R4
SUBB A,R7
JC DV50
SETB OV;商溢出
RET
DV50:
MOV R6,#8 ;求平均值(R4R5/R7-→R3)
DV51:
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV F0,C
CLR C
SUBB A,R7
ANL C,/F0
JC DV52
MOV R4,A
DV52:
CPL C
MOV A,R3
RLC A
MOV R3,A
DJNZ R6,DV51
MOV A,R4 ;四捨五入
ADD A,R4
JC DV53
SUBB A,R7
JC DV54
DV53:
INC R3
DV54:
CLR OV
RET
;四位元組除以單位元組子程序
;入口條件:被除數在R2、R3、R4、R5中,除數在R7中。
;出口信息:a<ff 時三位元組商在R3、r4、r5中,a=ff 時溢出。
; 余數在r2中
;影響資源:PSW、A、R2~R7 堆棧需求:2位元組
;input dat1,dat2,dat3,r5 ;r0(h),:divisor dat2(h) dat3() r5(l):quotient
;dat1(h)dat2(l):resie
F_DIV:
clr c
mov a,r7
jz fd_over
fd_begin:
mov a,r2
subb a,r7
jc no_overflow
mov a,#0ffh
ret
no_overflow:
clr a
mov r6,#18h
fdiv0:
lcall rlc4
jc goushang
mov a,r2
subb a,r7
jc fdnext
inc r5
mov r2,a
fdnext:
djnz r6,fdiv0
jmp fdone
goushang:
mov a,r2
subb a,r7
inc a
inc r5
mov r2,a
jmp fdnext
fdone:
clr a
clr ov
ret
fd_over:
mov a,#0ffh
ret
rlc4:
clr c
mov a,r5
rlc a
mov r5,a
mov a,r4
rlc a
mov r4,a
mov a,r3
rlc a
mov r3,a
mov a,r2
rlc a
mov r2,a
ret
;DIVD功能:雙位元組二進制無符號數除法
;入口條件:被除數在R2、R3、R4、R5中,除數在R6、R7中。
;出口信息:OV=0 時,雙位元組商在R4、R5中,OV=1 時溢出。
; 余數在r2 r3中
;影響資源:PSW、A、B、R1~R7 堆棧需求: 2位元組
DIVD:
CLR C ;比較被除數和除數
MOV A,R3
SUBB A,R7
MOV A,R2
SUBB A,R6
JC DVD1
SETB OV ;溢出
RET
DVD1:
MOV B,#10H ;計算雙位元組商
DVD2:
CLR C ;部分商和余數同時左移一位
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
XCH A,R2
RLC A
XCH A,R2
MOV F0,C ;保存溢出位
CLR C
SUBB A,R7 ;計算(R2R3-R6R7)
MOV R1,A
MOV A,R2
SUBB A,R6
ANL C,/F0 ;結果判斷
JC DVD3
MOV R2,A ;夠減,存放新的余數
MOV A,R1
MOV R3,A
INC R5 ;商的低位置一
DVD3:
DJNZ B,DVD2;計算完十六位商(R4R5)
; MOV A,R4 ;商移到R2R3中
; MOV R2,A
; MOV A,R5
; MOV R3,A
CLR OV ;設立成功標志
RET
;雙位元組乘以雙位元組乘法
;入口條件:被乘數在R2、R3中,乘數在R6、R7中。
;出口信息:乘積在R2、R3、R4、R5中。
;影響資源:PSW、A、B、R2~R7 堆棧需求: 2位元組
MULD:
MOV A,R3 ;計算R3乘R7
MOV B,R7
MUL AB
MOV R4,B ;暫存部分積
MOV R5,A
MOV A,R3 ;計算R3乘R6
MOV B,R6
MUL AB
ADD A,R4 ;累加部分積
MOV R4,A
CLR A
ADDC A,B
MOV R3,A
MOV A,R2 ;計算R2乘R7
MOV B,R7
MUL AB
ADD A,R4 ;累加部分積
MOV R4,A
MOV A,R3
ADDC A,B
MOV R3,A
CLR A
RLC A
XCH A,R2 ;計算R2乘R6
MOV B,R6
MUL AB
ADD A,R3 ;累加部分積
MOV R3,A
MOV A,R2
ADDC A,B
MOV R2,A
RET
;雙位元組乘以單位元組乘法
;入口條件:被乘數在R2、R3中,乘數在R7中。
;出口信息:乘積在R2、R3、R4中。
;影響資源:PSW、A、B、R2~R7 堆棧需求: 2位元組
mul21:
mov a,r3
mov b,r7
mul ab
mov r4,a
mov r5,b
mov a,r2
mov b,r7
mul ab
add a,r5
mov r3,a
mov a,b
addc a,#00h
mov r2,a
ret
;功能:雙位元組十六進制整數轉換成雙位元組BCD碼整數
;入口條件:待轉換的雙位元組十六進制整數在R6、R7中。
;出口信息:轉換後的三位元組BCD碼整數在R3、R4、R5中。
;影響資源:PSW、A、R2~R7 堆棧需求: 2位元組
HB2:
CLR A ;BCD碼初始化
MOV R3,A
MOV R4,A
MOV R5,A
MOV R2,#10H ;轉換雙位元組十六進制整數
HB3:
MOV A,R7 ;從高端移出待轉換數的一位到CY中
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R5 ;BCD碼帶進位自身相加,相當於乘2
ADDC A,R5
DA A ;十進制調整
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
MOV R3,A ;雙位元組十六進制數的萬位數不超過6,不用調整
DJNZ R2,HB3 ;處理完16bit
RET
;入口條件:待轉換的單位元組BCD碼整數在累加器A中。
;出口信息:轉換後的單位元組十六進制整數仍在累加器A中。
;影響資源:PSW、A、B、R4 堆棧需求: 2位元組
BCDH:
MOV B,#10H ;分離十位和個位
DIV AB
MOV R4,B ;暫存個位
MOV B,#10 ;將十位轉換成十六進制
MUL AB
ADD A,R4 ;按十六進制加上個位
RET
;雙位元組BCD碼整數轉換成雙位元組十六進制整數
;入口條件:待轉換的雙位元組BCD碼整數在R2、R3中。
;出口信息:轉換後的雙位元組十六進制整數仍在R2、R3中。
;影響資源:PSW、A、B、R2、R3、R4 堆棧需求:4位元組
BH2:
MOV A,R3 ;將低位元組轉換成十六進制
LCALL BCDH
MOV R3,A
MOV A,R2 ;將高位元組轉換成十六進制
LCALL BCDH
MOV B,#100 ;擴大一百倍
MUL AB
ADD A,R3 ;和低位元組按十六進制相加
MOV R3,A
CLR A
ADDC A,B
MOV R2,A
RET
;標號: BHD功能:單位元組BCD碼小數轉換成單位元組十六進制小數
;入口條件:待轉換的單位元組BCD碼數在累加器A中。
;出口信息:轉換後的單位元組十六進制小數仍在累加器A中。
;影響資源:PSW、A、R2、R3 堆棧需求: 2位元組
BHD:
MOV R2,#8 ;准備計算一個位元組小數
BHD0: ADD A,ACC ;按十進制倍增
DA A
XCH A,R3
RLC A ;將進位標志移入結果中
XCH A,R3
DJNZ R2,BHD0 ;共計算8bit小數
ADD A,#0B0H ;剩餘部分達到0.50否?
JNC BHD1 ;四舍
INC R3 ;五入
BHD1:
MOV A,R3 ;取結果
RET
; 標號: HBD功能:單位元組十六進制小數轉換成單位元組BCD碼小數
;入口條件:待轉換的單位元組十六進制小數在累加器A中。
;出口信息:CY=0時轉換後的BCD碼小數仍在A中。CY=1時原小數接近整數1。
;影響資源:PSW、A、B 堆棧需求: 2位元組
HBD:
MOV B,#100 ;原小數擴大一百倍
MUL AB
RLC A ;余數部分四捨五入
CLR A
ADDC A,B
MOV B,#10 ;分離出十分位和百分位
DIV AB
SWAP A
ADD A,B ;拼裝成單位元組BCD碼小數
DA A ;調整後若有進位,原小數接近整數1
RET
jmp $
end
『肆』 利用51單片機實現2位元組16進制數乘法
;雙位元組無符號數乘法程序(R3R4*R6R7)=(R5R2R3R4)
NMUL22:MOVA,R4
MOVB,R7
MULAB
XCHA,R4
MOVR5,B
MOVB,R6
MULAB
ADDA,R5
MOVR5,A
CLRA
ADDCA,B
MOVR2,A
MOVA,R3
MOVB,R7
MULAB
ADDA,R5
MOVR5,A
MOVA,B
ADDCA,R2
MOVR2,A
CLRA
ADDCA,#00H
XCHA,R3
MOVB,R6
MULAB
ADDA,R2
MOVR2,A
MOVA,B
ADDCA,R3
XCHA,R5
MOVR3,A
CLROV
RET
『伍』 求一MCS-51系列單片機指令表
傳送指令是指令系統中最基本,使用最多的一類指令,主要用於數據的傳送、保存以及交換等場合。
1.以累加器A為目的操作數的指令(4條)
這組指令的功能是把源操作數指定的內容送入累加器A中。
有寄存器、直接、寄存器間接和立即4種定址方式。
MOV A, Rn MOV A, data
MOV A,@Rn MOV A,#data
2.以寄存器Rn為目的的操作數的指令(3條)
這組指令的功能是把源操作數指定的內容送到所選定的工作寄存器Rn中。
有寄存器、直接和立即3種定址方式。
MOV Rn, A MOV Rn,data
MOV Rn,#data
3.以直接地址為目的操作數的指令(5條)
這組指令的功能是把源操作數指定的內容送到由直接地址data所指定的片內RAM中。
有寄存器、直接、寄存器間接和立即4種定址方式。
MOV data,A MOV data,Rn
MOV data1,data2 MOV data,@Ri
MOV data,#data
4.以間接地址為目的操作數的指令(3條)
這組指令的功能是把源操作數指定的內容送到以Ri中的內容為地址的片內RAM中。
有寄存器、直接和立即3種定址方式。
MOV @Ri,A MOV @Ri,data
MOV @Ri,#data
5.查表指令(2條)
這組指令的功能是對存放於程序存儲器中的數據表格進行查找傳送。使用變址定址方式。
MOVC A,@A+DPTR MOVC A, @A+PC
6.累加器A與片外AM傳送指令(4條)
這組指令的功能為累加器A與片RAM間的相互傳送。由於MCS-51指令系統中沒有專門的輸入/輸出指令,且片外擴展的I/O口與片外RAM是統一編址的,故以下4條指令也可作為輸入/輸出指令。使用寄存器間接定址方式。
MOVX A,@DPAR MOVX @DPTR,A
MOVX A,@Ri MOVX @Ri,A
7.堆棧操作類指令(2條)
該類指令的功能是把直接定址單元的內容傳送到堆棧指針SP所指的單元中,以及把SP所指單元的內容送到直接定址單元中。
PUSH data POP data
前一條指令稱為入棧操作指令,後一條指令稱為出棧指令。由於開機復位後,(SP)=07H,故一般需重新設置SP的初值。由於壓入堆棧的第一個數必須存放在SP+1所指存儲單元,故實際的棧底為SP+1所指存儲單元。
8.交換指令(4條)
該類指令的功能是把累加器A中的內容與源操作數所指出的數據相互交換。
有寄存器、直接和寄存器間接3種定址方式。
XCH A,Rn XCH A,data
XCH A,@Ri XCHD A,@Ri
9.16位數據傳送類指令(1條)
MOV DPTR,#data
該指令的功能是把16位常數送入數據指針寄存器,使用立即定址方式。譯成機器碼時,是高位位元組在前,低位位元組在後。
MCS-51具有強大的加、減、乘、除四則算術運算指令。
1.程序狀態字PSW
MCS-51有一個程序狀態字寄存器PSW,用來保存指令執行結果的標志,供程序查訊和判別。PSW是特殊功能寄存器中的一個,其格式如下:
PSW7--既是布爾處理機的累加器C,又是進位標志CY,如果操作結果在最高位有進位輸出(加法時)或借位輸入(減法時),置位CY,否則清「0」CY。
AC--輔助進位(半進位)標志。如果操作結果的低4位有進位(加法時)或向高4位借位時(減法),置AC,否則清「0」AC,AC主要用於二-十進制數加法調整。
OV--溢出標志。如果操作結果有進位進入最高位,但最高位沒有產生進位,或者最高位產生進位而低位沒有向最高位進位,這時置位溢出標志位,否則OV清「0」。溢出標志位用於補碼運算,當有符號的數運算結果不能用8位二進制數表示時,OV將置位。
P--累加器A的奇偶標志位,如果累加器A的8位的模2和為1(奇),則P=1;否則P=0。由於P總是表示A的奇偶性,隨著A的內容變化的,所以一個值寫入PSW的P位的值不變。
RS1、RS0--指示當前使用的工作寄存器區。
F0--用戶標志位。可作為軟體標志,它的作用和內部RAM位定址區的各位相似。
PSW1--保留位,對它的操作無效。
2.加法指令
1、不帶進位加法指令
ADD A,#data ADD A,data
ADD A,@Ri ADD A,Rn
工作寄存器、內部RAM單元內容或立即數的8位無符號二進制數和累加器A中數相加,所得和存放於累加器A中,當和的第3、7位有進位時,分別將AC,CY標志位置1;否則為0。
上述指令的執行將影響標志位AC、CY、OV、P。
對於無符號數,進位標志位CY=1,表示溢出;CY=0表示無溢出。帶符號數運算的溢出取決於第6、7位中有一位產生進位,而另一位不產生進位,溢出標志位OV置「1」否則被清「0」。OV=1表示兩個正數相加,和變為負數,或兩個負數相加,和變為正數的錯誤結果。
源操作數有四種定址方式:寄存器、直接、間接和立即數。
2、帶進位加法指令:
ADDC A,#data ADDC A,data
ADDC A,@Ri ADDC A,Rn
這是四條帶進位的加法指令。將累加器A內容加當前CY標志位內容,再加無符號單位元組的數,和存於累加器A中。當運算結果第3、7位產生進位溢出時,則分別置位AC、CY和OV標志位。本指令執行將影響標志位AC、CY、OV、P。
本指令常用於多位元組加法。
3、加1指令:
INC A INC data
INC @Ri INC Rn
INC DPTR
INC指令將指定的內容加1,結果仍存放於原A或原單元中。如原值為0FFH,加1運算後將變成00H,運算結果不影響標志位。
本指令可對累加器A、工作寄存器RN、RI間址和直接定址的單元內容進行加1運算。可見MCS-51加1指令是較豐富的。
注意:當用本指令使輸出並行I/O內容加1時,用作輸出口原始值,將從輸出口的數據鎖存器中讀入,而不是從輸出口的引腳上讀入。
4、二-十進制調正指令:
DA A
若[(A0-3)>9]或[(AC)=1),則(A0-3)(A0-3)+06H
本指令是對A的BCD碼加法結果進行調正。兩個壓縮型BCD碼按二進制數相加之後,必須經本指令調正,才能得到壓縮型BCD碼的和數。
本指令的操作為:若累加器A的低4位數值大於9或者第3位向第4位產生進位,即AC輔助進位位為1,則需將A的低4位內容加6調正,以產生低4位正確的BCD碼值。如果加0調正後,低4位產生進位,且高4位均為1時,則內部加法將置位CY,反之,它並不清「0」CY標志位。
若累加器A的高4位值大於9或最高進位位CY=1,則高位4位需加6調正,以產生高4位的正確BCD碼值。同樣,在加6調正後產生最高進位,則置位CY,反之,不清「0」CY這時CY的置位,表示和數BCD碼值大於等於100。這對多位元組十進制加法有用。不影響OV標志。
由此可見,本指令是根據累加器A的原始數值和PSW的狀態,對累加器A進行加O6H、60H或66H的操作。
必須注意:本指令不能簡單地把累加器A中的16進制數交換成BCD碼,也不能用於十進制減法的調正。
3.減法指令
MCS-51在MCS-48的基礎上增加了帶借位減法指令,加強了計算機的運算功能。
1、帶借位減法指令:
SUBB A,#data SUBB A,data
SUBB A,@Ri SUBB A,Rn
帶借位減法指令SUBB,從累加器A中減去進位標志位CY和指定的變數,結果在累加器A中,若第七位有借位,則置位位CY,否則CY清0。若第3位有錯位,則置位輔助進位標志AC,否則清0 AC。若第7和第6位中有一位需借位,而另一位不借位,則置位溢出標志OV。溢出位OV用於帶符號的整數減法,它表示(OV=1)一個正數減負數結果為負數;或一個負數減正數結果為正數的錯誤結果。
源操作數允許有四種定址方式:寄存器RN,直接地址direct,間址Ri或立即數。
當在進行單位元組或多位元組減法前,不知道進位標志位CY的值,則應在減法指令前先將CY清「0」。
4.乘法指令
MUL AB
乘法指令是MCS-51新增加的,運算速度只需4個機器周期。它大大增加了MCS-51單片機的運算功能,克服了MCS-48系列單片機的不足。
本指令將累加器A和寄存器B中二個8位無符號整數進行相乘,16位乘積的低8位存於A中,高8位存於B中,如果乘積大於255(0FFH),即B的內容不為0時,則置位溢出標志位OV,否則清「0」OV。進位標志位CY總是清「0」。
5.除法指令
DIV AB
MCS-51系列單片機增加的除法指令,運算時間亦只需4個機器周期,同樣也增強了MCS-51的運算功能,使它能適用於復雜的且要求運算功能較強的控制系統。除法指令格式:
本指令將累加器A中8位無符號整數除以B寄存器中8位無符號整數,所得結果商的整數部分存於A中,整數作數部分存於寄存器B中。清「0」CY和OV標志位。當除數(B中內容)為00H時,則執行結果將為不定值,即執行結果送往A和B中的為不定值,且置位溢出標志位OV。在任何情況下,均清「0」CY。
6.減一指令
DEC A DEC data
DEC @Ri DEC Rn
DEC指令把所指的寄存器內容減1,結果仍送回原寄存器,若原來寄存器的內容為00H,則減1後將為FFH,運算結果不影響任何標志位,該組指令使用了直接、寄存器和寄存器間定址。同加1指令一樣,在第二條指令中,若直接地址是I/O口,則進行「讀-改-寫」操作。
邏輯操作類指令共有效25條,有與、或、異或、求反、左右移位、清0等邏輯操作,對應的定址方式有直接、寄存器和間接定址,該類指令的執行一般不影響PSW。
1.循環移位指令(4條)
RL A; RR A;
RLC A; RRC A;
前兩條指令的功能分別是將累加器A的內容循環左移一位,後兩條指令的功能分別是將累加器A的內容連同進位位CY一起循環左移或右移一位。
2.累加器半位元組交換指令(1條)
SWAP A;
這條指令的功能是將累加器A的高低兩半位元組交換。如(A)=56H,執行指令SWAP A 後,結果(A)=65H。
3.求反指令(1條)
CPL A;
4.清0指令(1條)
CLR A;
5.邏輯與指令(6條)
ANL A,#data; ANL data,#data
ANL A,Rn ANL A,data
ANL data,A ANL A,@Ri
這組指令的第二條和第五條指令中,若直接地址正好是I/O口,則也是「讀-改-寫」操作。
6.邏輯或指令(6條)
ORL A,#data ORL data,#data
ORL A,Rn ORL A,data
ORL data,A ORL A,@Ri
這組指令的第二條和第五條也具有「讀-改-寫」功能。
7.邏輯異或指令(6條)
XRL A,#data XRL data,#data
XRL A,Rn XRL A,data
XRL data,A XRL A,@Ri
同樣,這組指令的第二條和第五條也具有「讀-寫-改」功能。
控制轉移類指令用於控製程序的走向,故其作用區間是程序存儲器空間。利用具有16位地址的長調用、長轉移指令可對64K程序存儲器的任一地址單元進行訪問,也可用具有11位地址的絕對調用和絕對轉移指令,訪問2K位元組的空間。另外,還有在一頁范圍的短相對轉移以及許多條件轉移指令,這類指令一般不影響標志位,不面分別給予介紹。
1.無條件轉移語句(4條)
LJMP addr16 AJMP addr11 SJMP rel JMP @(A)+DPTR
上述指令的功能是當程序執行完該指令時,程序就無條件地轉移到指令所提供的地址上去。
第一條指令稱為長轉移指令,指令提供16位目標地址,將指令中第二位元組和第三位元組地址碼分別裝入PC的高8位中,所以無條件轉移的目標地址范圍是64K位元組空間。
第二條指令稱為絕對轉移指令,指令提供11位目標地址,所以,無條件轉移的目標地址范圍是從下條指令開始的2K位元組空間。
第三條指令稱為相對短轉移指令,指令控製程序無條件的轉向指定地址。該指令的rel是一個帶符號的相對偏移量,范圍為-128~+127。負數表示向後轉移,正數表示向前轉移。這條指令的優點是指令給出的是相對轉移地址,不具體指出地址值,這樣當程序地址發生變化時,只要相對地址不發生變化,該指令就不需作任何改動。在用匯編語言寫程序時,rel是一個標號,由匯編程序在匯編過程中自動計算偏移地址。在手工匯編時,可用下式計算偏移地址:
向後轉移時:rel=FEH-(源、目的地址的絕對值)
向前轉移時:rel=(源、目的地址差的絕對值)-2
第四條指令稱為散轉指令(又稱為間接轉移指令),該指令把累加器A中的8位無符號數與作為基址寄存器DPTR中的16位數據相加,所得的值送入PC作為轉移的目的地址。該指令執行後不影響累加器A和數據指針DPTR中的原內容,也不影響任何標志位。這條指令的特點是其轉移地址不是編程時確定的,而是在程序運行時動態決定的。因此,可以在DPTR中裝入多條轉移程序的首地址,而由累加器A中的內容來動態選擇該時刻應轉向那一條分支程序。
2.條件轉移指令(8條)
1.JZ rel 2.JNZ rel
3.CJNEA,data,rel 4.CJNE A,#data,rel
5. CJNE Rn,#data,rel
6.CJNE @Ri,data,rel
7.DJNZ Rn,rel
8.DJNZ data,rel
上述指令執行滿足某種特定條件的轉移,其目標在以下一條指令的起始地址為中心的256個位元組范圍內(-128~+127)。
第一條和第二條指令是判別累加器A中的內容是否為0來確定是順序執行還是轉移。
第三條至第六條是比較轉移指令,該指令通過比較前面兩個操作數的大小,如果它們的值不相等則轉移,相等則繼續執行。指令執行後要影響進位位CY,若操作數1小於操作數2,則CY=1;若操作數1大於操作數2,則CY=0。
3.調用指程序及返回指令(4條)
1.LCALL addr16 2.ACALL addr11 3.RET 4.RETI
在程序設計中,經常需要對某段程序反復執行,為了減少程序的編寫以及浪費不必要的地址空間,於是引入了主程序和子程序的概念,通常把某一段需要反復調用的程序稱為子程序,子程序的最後一條指令為返回主程序指令(RET),而對具有調用子程序功能的指令稱為調用指令。
第一條指令稱為長調用指令,其與LJMP一樣提供16位地址,可調用64K位元組范圍內的子程序。由於其為三位元組指令,所以執行時首先(PC)+3,以獲得下一條指令地址,並把此時的PC內容壓入堆棧,作為返回地址,然後把地址addr16裝入PC,轉去執行子程序。
第二條指令稱為絕對調用指令,該指令提供11位目標地址,限制在2K位元組范圍內調用,由於是雙位元組指令,所以執行時(PC)+2以獲得下一條指令的地址,然後把該地址壓入堆棧作為返回地址。其操作碼的形成與AJMP指令相同。
第三條指令稱為子程序返回指令,表示子程序結束需返回主程序,所以執行該指令時,分別從堆棧中彈出調用子程序時壓入的返回地址。
第四條指令稱為中斷返回指令,該指令的執行過程類似指令RET,但其還能恢復中斷邏輯,RETI和RET決不能互換使用。
4.空操作指令(1條)
NOP;
空操作指令除了PC加1外,CPC不作任何操作,而轉向下一條指令去執行。這條指令常用於產生一個機器周期的延時。
位操作類指令共有17條,均以位為操作對象,分別完成位傳送、位狀態控制、位邏輯運算、位條件轉移等功能,在匯編語言中,位地址的表示方式有以下4種:
直接用位地址表示:如91H。
位元組地址位數方式:如P1.0(90H)。
位名稱方式:如RS0。
用戶使用偽指令事先定義過的符號地址。
1.位數據傳送指令(2條)
MOV C,bit MOV bit,C
上述指令把源操作數指定的變數傳送到目的操作數指定的單元中。第二條指令若是對I/O口的位進行操作,則也是「讀-改-寫」操作。
2.位狀態控制指令(6條)
CLR C CLR bit CPL C
CPL bit SETB C SETB bit
上述指令的功能是分別對進位標志和直接定址進行清0、求反以及直接位地址是I/O口的某一位時,也具有「讀-改-寫」功能。
3.位邏輯運算指令(4條)
ANL C,bit ANL C,/bit
ORL C,bit ORL C/bit
上述指令的功能是將位累加器C的內容與直接位地址的內容或直接位地址內容的反進行邏輯與、邏輯或,結果仍送回C中。
4.位條件轉移指令(5)
JC rel JNC rel
JB bit,rel JNB bit,rel
JBC bit,rel
上述指令的功能分別是判別進位位C和直接位地址的內容是「1」還是「0」,以此來決定程序的走向。最後一條指令的功能是:若直接位址的內容為「1」則轉移,並且同時將該位清0,否則順序執行。這條指令若是對I/O口某一位操作,也具有「讀-改-寫」功能。
『陸』 MCS_51單片機的字長是多少
1、51系列單片機的字長是 8 位的;8031與8051的主要區別是:8051具有_程序存儲器_
2、單片機引腳中的 /RD引腳的功能是__讀片外數據存儲器__,信號方向是由51系列向_外_的,T1引腳的功能是__定時器1的外部計數輸入端__,方向是由51系列向_內_的。
3、程序狀態字寄存器PSW中的CY位是__進位__標志位,可以被_SETB C__或 _CLR C_置位或清除。
4、MSC-51單片機中,唯一一個用戶能使用的16位寄存器是_DPTR_ 。
5、訪問程序存儲器的兩條命令是:_MOVC A,@A+PC;__、MOVC A,@A+DPTR ;_。
『柒』 用51單片機程序顯示3位7段數碼管,求具體程序
假設為共陰極數碼管,驅動輸入端接單片機P1口,共陰極接P2口的0.1.2.腳。我的程序如下,當前顯示數字123
#include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef long int uint32;
code uint8 number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay_ms(uint16 x)//1ms延時
{
uint8 i = 121;
while(x > 0)
{
i = 121;
while(i > 0)
i --;
x --;
}
}
void xianshi(uint16 x)
{
uint8 i=0;
for(i=0;i<=2;i++)
{
P2=~(1<<i);
switch(i)
{
case 0:P1=number[(x/1)%10];break;
case 1:P1=number[(x/10)%10];break;
case 2:P1=number[(x/100)%10];break;
default:break;
}
delay_ms(10);
}
}
main()
{
while(1)
{
xianshi(123);
}
}
『捌』 51單片機P0M0 |=(1<<3)什麼意思
P0M0是STC單片機用來設置IO狀態的寄存器之一 具體看STC的手冊 P0M0|=(1<<3) 中 1對應16進制是0x01 向左移動3位 變成0x40 語句簡化成 P0M0|=0X40 再簡化 P0M0=P0M0|0X40 意思就是 把0x40 和p0m0 按位或 如果P0M0寄存器中原先的數值為0x20的話 執行 P0M0|=(1<<3) P0M0寄存器變成0x24
『玖』 51單片機的串口接收一幀數據有幾位
發送的位數跟工作方式有關。51單片機的發送和接受,只有10位和11位兩種。
先說單片機串口的工作方式:
單片機串口的工作方式共4種,方式0--方式3.
方式0:用移位脈沖。RXD做輸入/輸出,TXD進行移位。收發的數據為八位。
方式1:傳送一幀信息為10位,即1位起始位(0),8位數據位(低位在先)和1位停止位(1)。數據位由TXD發送,由RXD接收
方式1:一幀信息也是10位;即 1位起始位,8位數據位(先低位),1位停止位。在起始位到達移位寄存器的最左位時,它使控制電路進行最後一次移位。
方式2和方式3:發送(通過TXD)和接收(通過RXD)一幀信息都是 11位: 1位起始位(0), 8位數據位(低位在先),1位可編程位(即第9位數據)和1位停止位(1)。
可見:不論單片機串口接收還是發送一幀數據是多少位,實際有效位數據位都是8位,其餘位是為了奇偶校驗、做起始位或終止位用的。
以前所述有誤,特修正。
『拾』 在單片機中,一個三位數,怎樣才能達到個位十位百位上的數的程序
unsigned int num,ge,shi,; //先定義4個變數用於存放這四個數
ge=num%10; //'%'運算是取余數,比如7%4=3
shi=(num%100)/10; //也可以shi=(num/10)%10
=num/100;