⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prg3.asm

📁 单片机对FLASH芯片的烧写,源程序,原理图,PCB图
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;下位机--program the flash HY29LV1620 //89C52

;通讯传输的数据格式为:88H(通讯起始标识)+ LEN (数据长度)+ CMD + (LEN-2个数据)+ 校验和;LEN<=60
;接收数据存放在80H和C0H开始的位置,发送数据放在40H开始的位置,在读FLASH时,发送数据放在40H和C0H开始的位置,由RD_FLAG标志决定
;;;;;;;;;;;;;;B--BACKUP 接收数据的存放地址
;C_RX_ADDR0	EQU	80h	;串行接收数据的存放地址0
;C_RX_ADDR1	EQU	C0h	;串行接收数据的存放地址1
;REG BANK0: 
;R2--读FLASH数据时:实际读取的长度(字节数)
;R3--读FLASH数据时:累加和
;R4--读FLASH数据时:读取的最大字节数;/编程时:存储接收到的字节数
;R5--ERASE: DELAY REG
;R6,R7--DELAY REG; 
;REG BANK1: 
;R0(08H),R1(09H)--COMM-ADDRESSING; 
;R2-R3-R4(0AH-0BH-0CH)---FLASH START-ADDR FOR READ/PROGRAM(H---L),
;R5-R6-R7(0DH-0EH-0FH)---NUMBERS OF BYTES TO BE PROGRAMED/READ(H---L)
;REG BANK2:
;R0-R1-R2(10H-11H-12H, CB0-CB1-CB2)---TMP REG FOR COUNTING; 
;13H-14H-15H-16H-17H---TMP REG USED IN COUNTING ROUTING;???????????????????
;REG BANK3: 
;18H-19H -- ID_MC(MANUFACTURER CODE), 
;1AH-1BH -- ID_DC(DEVICE CODE), 
;1CH--BACK A; 
;1DH--RTMP

;REG DEF 寄存器定义
PCON	EQU	87H		;SMOD ADDR
SPX	EQU	2DH		;设置栈指针(2EH~3FH)

RX_COUNT	EQU	20H		;串行接收字节的个数(计数)
RX_LEN		EQU	21H		;串行接收字节的总数
RX_ADDRC	EQU	22H		;串行接收首字节的存放地址(地址为: 80H或C0H, 由BIT16H确定)
TX_COUNT	EQU	23H		;串行发送字节的个数(计数)
TX_LEN		EQU	24H		;串行发送字节的总数
TX_ADDRC	EQU	25H		;串行发送首字节的存放地址(首字节地址:40H)
ERR_CODE0	EQU	26H		;保存错误代码(30H~37H)
ERR_CODE1	EQU	27H		;保存错误代码(38H~3FH)

PRC_LEN	EQU	28H		;正在处理的数据的长度
PRC_ADDR	EQU	29H		;正在处理的数据的地址
PRC_COUNT	EQU	2AH		;正在处理的数据的计数
PRC_ADDRX	EQU	2BH		;下一组要处理的数据的起始地址(当串行通讯程序收到完整的数据时,将串行接收首字节的存放地址存入该寄存器,同时置RXEND标志)

TX_INDEX	EQU	09H	;发送间址寄存器BANK1--R1
ADDR2		EQU	0AH	;THE HIGHT BYTE OF THE ADDR
ADDR1		EQU	0BH	;
ADDR0		EQU	0CH	;THE LOWER BYTE OF THE ADDR
LEN2		EQU	0DH	;THE HIGHT BYTE OF THE LEN
LEN1		EQU	0EH	;
LEN0		EQU	0FH	;THE LOWER BYTE OF THE LEN

CB2		EQU	10H	;THE HIGHT BYTE OF THE NUMBER FOR COUNTING DOWN
CB1		EQU	11H	;
CB0		EQU	12H	;THE LOWERST BYTE OF THE NUMBER FOR COUNTING DOWN
ID_MCL		EQU	18H	;LOWERE BYTE OF THE ID_MC
ID_MCH		EQU	19H	;HIGHER BYTE OF THE ID_MC
ID_DCL		EQU	1AH	;LOWERE BYTE OF THE ID_DC
ID_DCH		EQU	1BH	;HIGHER BYTE OF THE ID_DC
ABAK		EQU	1CH		;BACKUP A
RTMP		EQU	1DH
;ERR_NUM	EQU	1EH	;保存错误代码

DXL		EQU	90H		;P1: 16位数据的低8位
DXH		EQU	0A0H		;P2--16位数据的高8位

;
;错误码	: BIT REG -- 26H,27H (30H~3FH)
ERR_IC_READY	EQU	30H	;FLASH NOT READY
ERR_LEN	EQU	31H	;读写字节长度(个数)错误(=0)
ERR_ID		EQU	32H	;读芯片ID错误
ERR_PERITY	EQU	33H	;接收过程中奇偶校验错
ERR_SUM	EQU	34H	;累加和错
ERR_ADDR	EQU	35H	;地址错:超出范围(0--0FFFFF)
ERR_STATE	EQU	36H	;状态错误:如--在执行读FLASH指令过程中收到擦除指令
ERR_TIMEOUT	EQU	37H	;编程时超时
ERR_ERASE	EQU	38H	;芯片擦除时校验错(!=0FFH)
ERR_CMD	EQU	39H	;指令错误
ERR_PRG_DATALEN	EQU	3AH	;编程时数据长度=0

;BIT REG DEFINE(2CH~2DH: 60H~6FH)
RET_ERR		EQU	60H		;需要向PC回答:接收错误(校验和/奇偶校验)
RD_FLAG		EQU	61H		;读FLASH过程中,发送缓冲区地址标志: 0--TRANSMITTING ADDR=40H; 1--TRANSMITTING ADDR=C0H;
CALL_RET	EQU	62H	;函数调用返回值:1--error, 0-- normal
FLAG0		EQU	63H	;通用标志
FLAG1		EQU	64H	;通用标志
;IC-NORDY		EQU	62H		;1--FLASH READY FOR OPERATING
;ERR_CODE	EQU	63H		;1--操作过程中发生错误
;ERR_RD_ID	EQU	64H		;1--读芯片ID错误
;ERR_LEN	EQU	65H		;1--读写字节长度(个数)错误(=0)
CBAK		EQU	69H		;BACKUP C
RX_END		EQU	6AH		;1--RECEIVED ALL DATA
RX_FLAG		EQU	6BH		;1--COMM_START RECEIVED(通讯起始标识)
IN_RX		EQU	6CH		;1--IN RECEIVING
TX_FLAG		EQU	6DH		;1--IN TRANSMITTING
IN_PROG		EQU	6EH		;1--IN PROGRAM
IN_READ		EQU	6FH		;1--IN READING FLASH

RX_ADDR_X	EQU	16H	;0--RX_ADDRC=80H, 1--RX_ADDRC=C0H

_DX_EN		EQU	0B3H	;P3.3		;DXL/DXH数据线使能: 低有效
_DX_RD		EQU	0B4H	;P3.4		;从数据线读数据DXL/DXH: 低有效; 1--向数据线写数据
_ADDR_INC	EQU	0B5H	;P3.5		;地址增1时钟: 下降沿有效
ADDR_CLR	EQU	0B6H	;P3.6		;地址清零:  高有效
IC_READY	EQU	0B7H	;P3.7		;FLASH 芯片准备好
_FLASH_BYTE	EQU	80H	;P0.0		;FLASH操作为字节方式(不是WORD字方式): 低有效(字节方式), 高为字方式
_FLASH_OE	EQU	81H	;P0.1		;FLASH数据线输出有效, 即: 从FLASH读数据
_FLASH_CE	EQU	82H	;P0.2		;FLASH 芯片片选: 低有效
_FLASH_RST	EQU	83H	;P0.3		;FLASH 芯片复位: 低有效, 复位后FLASH 芯片为读状态
_FLASH_WE	EQU	84H	;P0.4		;FLASH 芯片写控制: 低有效
_FLASH_BUSY	EQU	85H	;P0.5		;FLASH 忙(正在执行操作): 低有效
_FLASH_PWR	EQU	87H	;P0.7		;为FLASH 供电: 低有效

;通讯命令(常数)定义
COMM_START	EQU	88H		;通讯起始标识
CMD_CHIP_ERASE	EQU	11H		;指令: 擦除
CMD_SECT_ERASE	EQU	22H		;指令: 擦除
CMD_PROG	EQU	33H		;编程指令: 传送编程地址、长度
CMD_PROGX	EQU	044H		;编程指令: 传送编程数据
CMD_READ	EQU	55H		;指令: 读FLASH
CMD_RSTFLASH	EQU	66H		;FLASH复位
CMD_ERR	EQU	77H		;错误返回:由错误码确定
CMD_OK		EQU	99H		;接收正确:错误码=0
CMD_CHIP_ID	EQU	0AAH		;指令: FLASH ID
CMD_ERR_PRG	EQU	0BBH		;编程错误:CMD+ADDR(3 byteS)+SOURCE DATA+REAL DATA+SUM
CMD_END	EQU	0CCH		;编程、读FLASH指令执行完毕
;CMD_SHKHND	EQU	0DDH		;通讯握手:返回CMD_OK

T_RESET		EQU	20		;FLASH复位延迟时间:20us
RD_BYTES	EQU	60		;每次读60字节


	ORG	0000H
	AJMP	INIT		;复位后转初始化程序

	ORG	000BH		;定时器T0中断
	LJMP	TIMER		;转定时程序

	ORG	0023H		;串口中断
	LJMP	TX_RX

	ORG	0050H
INIT:	MOV	SP,#SPX		;设置栈指针
	LCALL	INITX

LOOP:
;	MOV	C,IC_READY	;********************
;	CPL	C		;********************
;	MOV	_FLASH_PWR,C
	JB	IC_READY,LOOP0
	LCALL	CLR_INTERFACE
	AJMP	LOOP01
LOOP0:	JB	IN_READ,LOOP01
	JB	IN_PROG,LOOP01
	LCALL	SET_INTERFACE
LOOP01:
	JB	RET_ERR,L0
LOOP1:	JNB	IN_READ,LOOP2	;在读FLASH过程中:如果上一组数据发送完毕(TX_FLAG=0),则调用READTX读取下一组数据
	JB	TX_FLAG,LOOP2
	LCALL	READTX			;将FLASH数据读入发送缓冲区,
	AJMP	LOOP
LOOP2:	JNB	RX_END,LOOP		;检查是否收到数据
	LCALL	TRXPRO
	AJMP	LOOP
L0:	JB	TX_FLAG,LOOP1
	LCALL	RETERR
	AJMP	LOOP


CLR_INTERFACE:
	SETB	_FLASH_PWR
	MOV	DXL,#0
	MOV	DXH,#0
	CLR	_DX_RD		;数据线方向:FLASH --> HOST
	CLR	_DX_EN		;数据线使能
	CLR	ADDR_CLR	;CLR THE ADDR TO ZERO
	CLR	_ADDR_INC	;
	RET

SET_INTERFACE:
	MOV	DXL,#0FFH
	MOV	DXH,#0FFH
	SETB	_DX_EN		;数据线X使能
	SETB	ADDR_CLR	;CLR THE ADDR TO ZERO
	CLR	_FLASH_PWR
	RET


;初始化程序
INITX:
;	CLR	RX_FLAG
;	CLR	TX_FLAG
;	CLR	RX_END
;	CLR	IN_RX
;	CLR	IN_PROG
;	CLR	IN_READ
;	CLR	RET_ERR
;	CLR	RD_FLAG

	MOV	2CH,#0
	MOV	2DH,#0
	MOV	ERR_CODE0,#0		;CLEAR THE REG OF ERR_CODE
	MOV	ERR_CODE1,#0		;CLEAR THE REG OF ERR_CODE

	MOV	RX_ADDRC,#80H		;串行接收首字节的存放地址:80h
	MOV	TX_ADDRC,#40H		;串行发送首字节的存放地址:40h

	MOV	TH1,#0FFH		;设置波特率: #0FDH: BDR=9600,SMODE=0; FOSC=11.0592M; #0FFH: BDR=57.6K,SMODE=1
	MOV	PCON,#80H		;SMODE=1
	MOV	TMOD,#20H		;定时器T1设为方式2, 定时器T0设为模式0(13BIT)
	SETB	TR1			;启动定时器T1
	MOV	SCON,#0D0H		;串行口工作方式: 方式3,允许接收
	SETB	ES			;开串行口中断

;	MOV	TMOD,#0H		;定时器T0设为模式0
	MOV	TL0,#0H		;T0置初值(12M,8191ms)
	MOV	TH0,#0H		;
;	SETB	TR0			;启动T0
;	SETB	ET0			;允许T0中断
	SETB	EA			;CPU开中断
	RET

;接收正确, 回答PC: 在编程状态时,请求PC发送下一组数据
RETOK:	MOV	A,#CMD_OK
	MOV	ERR_CODE0,#0		;CLEAR THE REG OF ERR_CODE
	MOV	ERR_CODE1,#0		;CLEAR THE REG OF ERR_CODE
	AJMP	RETX1
;接收到的数据有错误-->回复PC
RETERR:
	CLR	IN_READ	;发生错误后,停止正在进行的操作
	CLR	IN_PROG	;发生错误后,停止正在进行的操作
	MOV	RX_ADDRC,#80H		;发生错误后,恢复初始设置:串行接收首字节的存放地址:80h
	MOV	A,#CMD_ERR	;指令字
RETX1:	MOV	TX_LEN,#04H	;共发送4个字节: CMD_XXX,ERR_CODE1,ERR_CODE0, 校验和
	MOV	TX_COUNT,#05H	;发送时,计数器先减1然后再判断是否发送完毕,所以,计数器初值比TXLEN多1
	MOV	R0,TX_ADDRC
	MOV	@R0,A		;############指令字########################
	INC	R0
	MOV	@R0,ERR_CODE1	;取错误代码: 0--NO ERROR
	ADD	A,ERR_CODE1
	MOV	ERR_CODE1,#0		;CLEAR THE REG OF ERR_CODE
	INC	R0
	MOV	@R0,ERR_CODE0	;取错误代码: 0--NO ERROR
	ADD	A,ERR_CODE0
	MOV	ERR_CODE0,#0		;CLEAR THE REG OF ERR_CODE
	INC	R0
	MOV	@R0,A		;校验和
	MOV	TX_INDEX,TX_ADDRC	;
	LCALL	TX_COMM_START	;发送通讯起始标识
	CLR	RET_ERR
	RET

;处理接收到的数据
TRXPRO:
	MOV	R0,RX_ADDRC	;取串行接收首字节的存放地址
	CLR	A		;校验数据累加和
TRXP0:	DJNZ	RX_COUNT,TRXP1
	XRL	A,@R0
	JZ	TRXP2		;累加和正确->TRXP2
	SETB	ERR_SUM
	CLR	RX_END		;允许接收下一组数据
TRXPE:	JB	TX_FLAG,TRXPE	;等待发送完毕
	LCALL	RETERR		;ERROR	;	AJMP	INIT		;######################################
	RET			;
TRXP1:	ADD	A,@R0		;计算数据累加和
	INC	R0
	AJMP	TRXP0
TRXP2:
;	MOV	B,RX_ADDRC	;指令字节存放地址
	LCALL	RETOK		;回答(TO PC): CMDOK
	MOV	R0,RX_ADDRC	;指令字节存放地址
TRXPW0:	JNB	TX_FLAG,TRXPW0	;等待发送
	CPL	RX_ADDR_X	;设置下一次接收的地址:串行接收首字节的存放地址(地址为: 80H或C0H, 由BIT16H确定)
	MOV	A,RX_LEN	;保存接收到的字节数
	CLR	RX_END		;允许接收下一组数据
	DEC	A
	CLR	C
	RRC	A
	MOV	R4,A		;
;	MOV	R0,B		;指令字节存放地址
	MOV	A,@R0		;取指令
	INC	R0
;	INC	B
TRXPW1:	JB	TX_FLAG,TRXPW1	;等待发送完毕

	CJNE	A,#CMD_OK,TRXP20	;通讯联络命令
	RET
TRXP20:	CJNE	A,#CMD_RSTFLASH,TRXP3	;FLASH 芯片复位:CMD+SUM, 复位后FLASH 芯片为读状态
	LCALL	RST_RDID_RST
	JB	CALL_RET,TRXPE
	LCALL	RET_ID				;将ID送给PC
	RET
TRXP3:	CJNE	A,#CMD_READ,TRXP4		;读FLASH数据: CMD+START_ADDR(3 BYTES: H---L)+READ_LEN(3 BYTES: H---L)+SUM
	JNB	IN_PROG,TRXP31
TRXP30:	SETB	ERR_STATE
	AJMP	TRXPE
TRXP31:	LCALL	RD_PREPARE
	RET
TRXP4:	CJNE	A,#CMD_PROG,TRXP40		;FLASH编程: CMD+START_ADDR(3 BYTES: H---L)+PRG_LEN(3 BYTES: H---L)+SUM
	JB	IN_READ,TRXP30
	LCALL	PRG_PREPARE			;接收编程数据:CMD+数据+SUM
	RET
TRXP40:	CJNE	A,#CMD_PROGX,TRXP5	;接收编程数据:CMD+数据+SUM
	JNB	IN_PROG,TRXP41
	LCALL	PROGM	;
TRXP41:	RET
TRXP5:	CJNE	A,#CMD_CHIP_ERASE,TRXP6	;FLASH擦除
	LCALL	CHIP_ERASE			;芯片擦除
	JB	CALL_RET,TRXPE
	MOV	A,#CMD_CHIP_ERASE
TRXP50:	JB	TX_FLAG,TRXP50	;等待发送完毕
	LCALL	RET_ID1
	RET
TRXP6:	CJNE	A,#CMD_SECT_ERASE,TRXPEND	;FLASH擦除
	LCALL	SECT_ERASE			;扇区擦除
	JB	CALL_RET,TRXPE
	MOV	A,#CMD_SECT_ERASE
	AJMP	TRXP50
;TRXP7:	CJNE	A,#CMD_SHKHND,TRXPE	;通讯握手
;	LCALL	RETOK
	RET
TRXPEND:	SETB	ERR_CMD
	AJMP	TRXPE

;收到FLASH编程命令后:先读取ID,发送给PC,然后再设置有关标志,等待接收编程数据
PRG_PREPARE:
	MOV	ADDR2,@R0	;SAVE THE ADDR
	INC	R0
	MOV	ADDR1,@R0	;SAVE THE ADDR
	INC	R0
	MOV	ADDR0,@R0	;SAVE THE ADDR
	INC	R0
	MOV	LEN2,@R0	;SAVE THE LEN
	INC	R0
	MOV	LEN1,@R0	;SAVE THE LEN
	INC	R0
	MOV	LEN0,@R0	;SAVE THE LEN
;	INC	R0

	LCALL	CHK_ADD_LEN		;检查地址、长度
	JB	CALL_RET,P_PE	;ERROR
	LCALL	RST_RDID_RST		;芯片复位、读取ID
	JB	CALL_RET,P_PE
	LCALL	RET_ID			;将ID送给PC

	LCALL	WRITE_CMD_HEAD	;UNLOCK CMD SEQUENCE
	SETB	_DX_RD		;数据线方向:FLASH <-- HOST
	CLR	_DX_EN		;数据线使能
	MOV	DXL,#20H	;unlock bypass CMD
	MOV	DXH,#0		;SET THE DATA: 20
	CLR	_FLASH_WE
	CLR	_FLASH_CE	;LATCH THE ADDR
	SETB	_FLASH_CE	;LATCH THE DATA
	SETB	_FLASH_WE	;
	SETB	_DX_EN		;关闭数据线

	MOV	CB2,ADDR2		;设置起始地址
	MOV	CB1,ADDR1
	MOV	CB0,ADDR0
	LCALL	SETADDR
	MOV	CB2,LEN2		;设置字节计数
	MOV	CB1,LEN1
	MOV	CB0,LEN0
	SETB	IN_PROG		;置编程标志
	RET
P_PE:	LCALL	RETERR
P_PX:	RET


;接收到编程数据:CMD+数据+SUM,R4--数据字数
PROGM:
	JB	IC_READY,PRG0	;$$$$$$$$$$$$$$$$$$$$$????????????
	LCALL	CLR_INTERFACE
	SETB	ERR_IC_READY
PRGX:	SETB	RET_ERR
PRGX1:	SETB	_FLASH_PWR
	CLR	IN_PROG		;结束PROGRAM
	SETB	_DX_EN		;YES: 关闭数据线
	SETB	_FLASH_OE
	SETB	_FLASH_CE	;
	RET
PRG0:	LCALL	ISZERO			;检查要编程的字节数是否为零
	SETB	ERR_PRG_DATALEN
	JZ	PRGX
	CLR	ERR_PRG_DATALEN
	SETB	_DX_RD		;数据线方向:FLASH <-- HOST
	CLR	_DX_EN		;数据线使能
	CLR	_FLASH_CE	;
PRG1:	MOV	DXL,#0A0H	;unlock bypass PROGRAM CMD
	MOV	DXH,#0		;SET THE DATA: 20
	CLR	_FLASH_WE	;LATCH THE ADDR
	SETB	_FLASH_WE	;
	MOV	A,@R0		;PROGRAM DATA
	MOV	DXH,A		;PROGRAM DATA
	MOV	DPH,A		;STORE THE DATA: FOR VERIFY THE PROGRAMED DATA
	INC	R0
	MOV	A,@R0		;SET THE DATA
	MOV	DXL,A		;SET THE DATA
	MOV	DPL,A
	INC	R0
	CLR	_FLASH_WE
	SETB	_FLASH_WE	;
	MOV	A,#0FFH
	MOV	DXL,A
	MOV	DXH,A

	LCALL	COUNT_DOWN		;字节数-1
	SETB	FLAG0
	JZ	PRG4
	LCALL	COUNT_DOWN		;字节数-1
	CLR	FLAG0
	JZ	PRG4
	MOV	R6,#20		;DELAY 20*3us
PRGDLY:	JB	_FLASH_BUSY,PRG3
	DJNZ	R6,PRGDLY
	SETB	ERR_TIMEOUT	;超时
	AJMP	PRGX
PRG3:
	CLR	_DX_RD		;数据线方向:FLASH --> HOST: 校验数据
	CLR	_FLASH_OE	;FOR READING THE PROGRAMED DATA
	MOV	A,DXL
	CJNE	A,DPL,PRG30
	MOV	A,DXH
	CJNE	A,DPH,PRG31
	SETB	_FLASH_OE	;FOR WRITING
	SETB	_DX_RD		;数据线方向:FLASH <-- HOST
	CLR	_ADDR_INC		;INC ADDR
	SETB	_ADDR_INC	
	DJNZ	R4,PRG1	;END? no --> PRG1
	SETB	_DX_EN		;YES: 关闭数据线
	SETB	_FLASH_CE	;
	RET
PRG30:	SETB	FLAG0
	LCALL	RET_PRG_ERR
	AJMP	PRGX1
PRG31:	CLR	FLAG0
	LCALL	RET_PRG_ERR
	AJMP	PRGX1
PRG4:
	MOV	R6,#20		;DELAY 20*3us
PRGDLYX:	JB	_FLASH_BUSY,PRG4X
	DJNZ	R6,PRGDLYX
	SETB	ERR_TIMEOUT	;超时
	AJMP	PRGX

PRG4X:	CLR	_DX_RD		;全部数据编程完毕,校验最后一组数据。数据线方向:FLASH --> HOST
	CLR	_FLASH_OE	;FOR READING THE PROGRAMED DATA
	MOV	A,DXL
	XRL	A,DPL
	JZ	PRG40
	LCALL	RET_PRG_ERR
	AJMP	PRGX1		;校验错:
PRG40:	JB	FLAG0,PRG41
	MOV	A,DXH
	XRL	A,DPH
	JZ	PRG41
	LCALL	RET_PRG_ERR
	AJMP	PRGX1
PRG41:	SETB	_FLASH_OE	;FOR WRITING
	SETB	_DX_EN		;关闭数据线
	SETB	_FLASH_CE	;
	MOV	A,#CMD_END	;回复PC:编程结束--指令字
	LCALL	RETX1
	LCALL	RST_FLASH
	SETB	_FLASH_PWR
	CLR	IN_PROG		;结束PROGRAM
	RET


;编程时校验数据出错:回复PC
RET_PRG_ERR:
	CLR	IN_PROG	;发生错误后,停止正在进行的操作
	MOV	A,#CMD_ERR_PRG	;指令字
	MOV	TX_LEN,#08H	;共发送8个字节: CMD_ERR_PRG,CB2,CB1,CB0,PNUM,W_DATA,R_DATA,校验和
	MOV	TX_COUNT,#09H	;发送时,计数器先减1然后再判断是否发送完毕,所以,计数器初值比TXLEN多1
	MOV	R0,TX_ADDRC
	MOV	@R0,A		;############指令字########################
	INC	R0
	MOV	@R0,CB2	;取错误位置
	ADD	A,CB2
	INC	R0
	MOV	@R0,CB1	;取错误位置
	ADD	A,CB1
	INC	R0
	MOV	@R0,CB0	;取错误位置
	ADD	A,CB0
	INC	R0
	JB	FLAG0,R_P_E0
	MOV	@R0,#1
	INC	R0
	INC	A
	MOV	@R0,DPH
	ADD	A,DPH
	INC	R0
	MOV	@R0,DXH
	ADD	A,DXH
	AJMP	R_P_E1
R_P_E0:
	MOV	@R0,#2
	INC	R0
	ADD	A,#2
	MOV	@R0,DPL
	ADD	A,DPL
	INC	R0
	MOV	@R0,DXL
	ADD	A,DXL
R_P_E1:	INC	R0
	MOV	@R0,A		;校验和
	MOV	TX_INDEX,TX_ADDRC	;
	LCALL	TX_COMM_START	;发送通讯起始标识
R_P_E2:
	JNB	TX_FLAG,R_P_E2
	RET


;将FLASH ID送给PC
RET_ID:
	MOV	A,#CMD_CHIP_ID	;指令字
RET_ID1:
	MOV	TX_LEN,#06H	;共发送6个字节: CMD_XXX,ID_MCH,ID_MCL,ID_DCH,ID_DCL, 校验和
	MOV	TX_COUNT,#07H	;发送时,计数器先减1然后再判断是否发送完毕,所以,计数器初值比TXLEN多1

	MOV	R0,TX_ADDRC
	MOV	@R0,A		;############指令字########################
	INC	R0

	MOV	@R0,ID_MCH
	ADD	A,ID_MCH
	INC	R0
	MOV	@R0,ID_MCL
	ADD	A,ID_MCL
	INC	R0
	MOV	@R0,ID_DCH
	ADD	A,ID_DCH
	INC	R0
	MOV	@R0,ID_DCL
	ADD	A,ID_DCL
	INC	R0

	MOV	@R0,A		;校验和
	MOV	TX_INDEX,TX_ADDRC	;
	LCALL	TX_COMM_START
RET_ID0:	JNB	TX_FLAG,RET_ID0	;等待发送
	RET

;发送通讯起始标识
TX_COMM_START:
	MOV	A,#COMM_START	;发送通讯起始标识
	MOV	C,P		;奇偶校验
	MOV	TB8,C
	MOV	SBUF,A
	CLR	TX_FLAG
	RET

;芯片复位(hardware)
RST_FLASH:
	CLR	CALL_RET
	JB	IC_READY,RST_F0		;33333333333333333333#############????/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -