51单片机:汇编改C语言(一)

之前答应给同学帮忙做毕设,想着应该很简单。结果老师给了他一份汇编程序,由于自己之前做过汇编编程的工作,就胆(no)大(zuo)妄(no)为(dai)的说是给他翻译成C语言的。
当我仔细瞅了那份程序之后。额,好吧,我只能说我尽力而为吧!

东西只有一篇近2000行的汇编程序和一份原理图,程序中无任何变量,需要变量或者是标志位时,直接操作一个RAM地址,子程序起名也是相当佛系。目前我只注释了一小部分的程序,大概三四百行吧,贴出来,作为一个笔记,以供后面学习。
由于不是本人程序,所以会在程序中做删减,但不会影响汇编语言的学习。注释为?的,意思是我也没看懂到底什么意思……同样的内容,在前面注释过的,后面不再注释。最后,向那个年代用汇编写单片机程序的老师们致敬。嘻嘻!_!

	ORG 0000H	;程序起始地址
	LJMP MAIN
	ORG 0003H	;外部中断0	
	LJMP I0000
	ORG 000BH	;定时器0
	LJMP T0000
	ORG 0023H	;串行中断
	LJMP ES000
	ORG 0030H	;程序存储区(用户RAM)
MAIN:
	MOV R0,#7FH		;将数据7FH存入R0寄存器
MAIN1:
	MOV @R0,#00H	;将0存入7FH地址
	DJNZ R0,MAIN1	;给R0-1,若不为0,则跳转到MAIN1,上面这两条语句是一个小循环,意思是将00-7FH地址清0,以便后续使用。
	MOV SP,#60H		;将60H存入堆栈指针,即栈顶指针地址为60H	
	LCALL WR100		;转到WR100,写数据到外部器件,应该是初始化外部器件
	MOV TMOD,#21H	;配置定时器控制寄存器,T1为8位自动加载计数器模式,T2为,16位定时器模式
	MOV TH0,#0FAH
	MOV TL0,#00H	;T0
	MOV TH1,#0FBH
	MOV TL1,#0FBH	;T1
	ANL PCON,#7FH	;配置电源控制寄存器,默认值
	SETB SM0		;以下6行配置SCON串行通信控制寄存器
	SETB SM1		;配置串行通信波特率为11:由定时器T1或T2的溢出率和SMOD所定:2SMOD ×(T1溢出率)/32
	CLR SM2			;多机通信控制位
	CLR RI			;接收中断标志位
	CLR TI			;发送终端标志位
	CLR REN			;禁止接收
	SETB P1.4		
	SETB TR0		;允许T0计数
	SETB TR1		;允许T1计数
	SETB ET0		;定时器0中断充许
	SETB ES			;打开串行中断
	SETB PT0		;定时器0中断优先
	SETB EX0		;打开外部中断INT0
	SETB EA			;打开总中断
	CLR P1.0		;根据原理图,P1.0接在外部看门狗上,应该是喂狗信号,后面同理		
	SETB P1.0
	MOV DPTR,#0E000H	;将0E00H写入DPTR(数据指针寄存器),片外RAM首地址?
MAIN2:
	MOV A,#00H		
	MOVX @DPTR,A
	INC DPTR
	MOV A,DPH
	CJNE A,#0E4H,MAIN2	;清零0E000H-0E4000H地址区间
	CLR P1.0
	SETB P1.0
	MOV DPTR,#0F000H	
MAIN3:
	MOV A,#00H
	MOVX @DPTR,A
	INC DPTR
	MOV A,DPH
	CJNE A,#0F5H,MAIN3	;清零0F000H-0F5000H地址区间
	CLR P1.0
	SETB P1.0	
	MOV DPTR,#0E000H
	MOV A,#00H
	MOVX @DPTR,A	
	INC DPTR
	MOVX @DPTR,A	
	INC DPTR
	MOVX @DPTR,A	
	INC DPTR
	MOVX @DPTR,A		;清零0E000H-0E0003H地址区间	
	INC DPTR
	MOV A,#0F1H
	MOVX @DPTR,A	
	INC DPTR
	DEC A
	MOVX @DPTR,A		;将0F1H写入0E0004H,将0F0H写入0E0005H
	INC DPTR		
	MOV A,#0C0H
	MOVX @DPTR,A		;将0C0H写入0E0006H
	INC DPTR
	MOV A,#05H			
	MOVX @DPTR,A		;将05H写入0E0007H
	MOV DPTR,#7FFFH		
	CPL A
	CJNE A,#03H,MAIN4	;?
MAIN4:
	JNC MAIN5
	MOV A,#03H			;以下赋值原理同上,不再解释			
MAIN5:
	;此处有删减
	SETB 00H		;标志位0		
	MOV 12H,#01H	;R2第2组通用寄存器
	MOV 2FH,#00H	;位寻址区
	MOV 32H,#03H	;用户RAM区,以上三句,应该是设置了三个变量
	MOV C,P1.5			
	CPL C
	MOV 78H,C
	MOV C,P1.6
	CPL C
	MOV 79H,C
	MOV C,P1.7
	CPL C
	MOV 7AH,C		;读取P1.5、P1.6、P1.7的值,并取反后存到78H、79H、7AH
XDY00:
	CLR P1.0
	SETB P1.0
	JNB 01H,M0000	;若标志位1,为0,跳转到M0000
	LJMP M0100		;否则跳转到M0100
	;程序由此转向两个分支,后续。。。

子程序(有删减)

WR100:
	MOV A,#06H		;将06H存入累加器A	
    CLR P1.0		;清零P1.0
	LCALL WR200		;转到WR200,写8位数据到外部器件
	SETB P1.0		;置位P1.0
    MOV A,#01H		;同上,将01H写入外部器件
	CLR P1.0
	LCALL WR200		
	MOV A,#20H		;同上,将20H写入外部器件
	LCALL WR200
	SETB P1.0
	LCALL DEL20		;转到DEL20,延时
    RET
WR200:
	MOV R3,#08H		;将08H存入R3寄存器
WR201:
	RLC A			;将A带进位左移一位
	MOV P1.2,C		;上一次左移无进位,因此P1.2为0
	CLR P1.3		;清零P1.3
	SETB P1.3		;置位P1.3
	DJNZ R3,WR201	;将R3-1,若不为0,转到WR201
	RET				;返回。综上,此函数是将A通过左移写入外部器件,类似于I2C,SPI通信的写寄存器操作,A是所要写入的内容
DEL20:
	MOV R2,#0FH
DEL21:
	MOV R3,#0BAH
DEL22:
	NOP
    NOP
    NOP
    DJNZ R3,DEL22
	CPL P1.0		;对P1.0每隔(3个指令周期*0BAH)这么长时间取反
	DJNZ R2,DEL21	;取反0FH次
    RET				;返回,综上,此函数可以实现将P1.0取反0FH次,每次保持0BAH*3T,T为1指令周期,类似于让LED闪烁的函数

你可能感兴趣的:(C51)