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

📄 modbus.asm

📁 modbus单片机开发源码,对一些初学者很有帮助
💻 ASM
字号:
; This files contains function that decodes and assemble modbus

; data patterns, over TCP or the OnChip USART.

; This is ugliest code i have ever written :-(



.incld proj.inc



.extrn ne_w_b, ne_d_w_B, ne_d_r_B, ne_d_r_X_crc, ne_d_w_X, ne_d_rs

.extrn USART_tx_byte_fromX, USART_rx_byte_toX, USART_rx_byte_toXinc, USART_rx_byte_toXdec

.extrn usart_flags

.extrn usart_chgbaud

.extrn curr_tpsr, tcp_data_len, tcp_ip_mk_hdr, tcp_mk_hdr_app_crc, tcp_crc_add, tcp_code, crc_add_alt

.extrn rx_finish, ne_d_ab, tx_transmit_packet

.extrn sleep



.sect modbus_ram, RAM

xact_id:	.dsb	0x02

proto_id:	.dsb	0x02

mb_pkt_len:	.dsb 0x02



	; Macros for Modbus.



	; Read ROM table macro. Returns value into "ISPRD".

	.macro readrom, addrhi, addrlo

	ld	ISPADHI, addrhi

	ld	A, addrlo

	x	A, ISPADLO

	ld	ISPKEY, #KEY

	jsrb	#0x11	; READ BYTE

	.endm





	.sect modbus_rom, ROM

	.public mb_tcp_forward, usart_mb_forward

mb_tcp_forward:

	; Read transaction ID.

	ld	B, #xact_id

	jsr	ne_d_r_B

	; Read protocol ID. Usually 0x00 0x00.

	ld	B, #proto_id

	jsr	ne_d_r_B

	; Read length field.

	ld	B, #T0

	jsr	ne_d_r_B

	; Convert to word count.

	ld	A, T1

	push	A		; Store byte count for later use.

	rrc	A

	x	A, T1

	; Initialize Checksum holder.

	ld	crc_l, #0xFF

	ld	crc_h, #0xFF

	; Loop until we have forwarded all to the USART.

mb_tcp_forward_toUsart:

	ld	X, #a_l

	jsr	ne_d_r_X_crc

	jsr	mb_crc_add

	jsr	USART_tx_byte_fromX

	jsr	mb_crc_add

	jsr	USART_tx_byte_fromX

	drsz	T1

	jmp	mb_tcp_forward_toUsart

	pop	A		; Now we check if byte count was odd.

	andsz A, #0x01

	jp	mb_tcp_forward_toUsart_extra

	jp	mb_tcp_forward_toUsart_exit

mb_tcp_forward_toUsart_extra:

	ld	X, #a_l

	jsr	ne_d_r_X_crc

	jsr	mb_crc_add

	jsr	USART_tx_byte_fromX

mb_tcp_forward_toUsart_exit:

	;ne_d_rd_stop

	jsr	rx_finish

	; Append Checksum.

	ld	X, #crc_h

	jsr	USART_tx_byte_fromX

	ld	X, #crc_l

	jsr	USART_tx_byte_fromX

	; Dummy read to reset RBFL bit of ENU. Init usart data pointer.

	rbit	ERI, ENUI

	ld	usart_data_ptr, #0x00

	ld	A, RBUF

	sbit	ERI, ENUI

	sbit	USART_FLG_RXPNG, usart_flags

	; Enable Timeout timer.

	;rbit	T2C0, T2CNTRL

	;rbit	T2PNDA, T2CNTRL

	;ld	TMR2LO, #0xff

	;ld	TMR2HI, #0xff

	;sbit	T2ENA, T2CNTRL

	;sbit	T2C0, T2CNTRL

	; ModbusTCP Packet forwarded to USART. Lets go back to business

	ret





	; Forward ModBus RTU to NIC.

usart_mb_forward:

	; Reinitialize CRC holder.

	ld	crc_h, #0xFF

	ld	crc_l, #0xFF

	; Set TCP CODE (header field).

	ld	tcp_code, #(TCP_ACK+TCP_PSH)

	; Obtain mb_pkt_len.

	; Wait until ModBus header is read into USART buffer or timeout.

mb_tcp_forward_toN_read3:

	; Check if we are ready (3 bytes have arrived).

	ld	A, usart_data_ptr

	ifgt	A, #0x02

	jmp	mb_tcp_forward_toN_read3done

	; Loop until timeout

	ifeq	usart_data_ptr, #0x00

	jmp	mb_tcp_forward_toN_timeout

	jmp	mb_tcp_forward_toN_read3

mb_tcp_forward_toN_read3done:

	ld	S, #SEG_USART

	; Copy Data length field into T0. mb_pkt_len isn't accesable here.

	ld	A, 0x02

	x	A, T0

	; Copy function byte to check for exception status flag.

	ld	A, 0x01

	x	A, T1

	ld	S, #0x00

	; Check function byte for Exception status and fixed length packet situations.

	ifbit	7, T1

	ld	T0, #0x00

	ifeq	T1, #0x05

	ld	T0, #0x03

	ifeq	T1, #0x06

	ld	T0, #0x03

	ifeq	T1, #0x07

	ld	T0, #0x03

	ifeq	T1, #0x0F

	ld	T0, #0x03

	ifeq	T1, #0x10

	ld	T0, #0x03

	ifeq	T1, #0x16

	ld	T0, #0x05

	; Copy ModBus packet length (T0) into mb_pkt_len.

	ld	B, #(mb_pkt_len+1)

	ld	A, T0

	x	A, [B-]

	clr	A

	x	A, [B+]

	; Add Modbus header.

	;ld	B, #(mb_pkt_len+1)

	ld	A, [B]

	rc

	ADC	A, #0x03	; ModBus header length = 0x03.

	x	A, [B-]

	ld	A, [B]

	IFC

	inc	A

	x	A, [B]

	; Make tcp_data_len.

	ld	A, #0x06	; 0x06 = MB/TCP header.

	rc

	ADC	A, (mb_pkt_len+1)

	x	A, tcp_data_len

	ld	A, mb_pkt_len

	IFC

	inc	A

	x	A, (tcp_data_len+1)

; START TCP/IP PACKET ASSEMBLY.

	; Make TCP/IP header.

	jsr	tcp_ip_mk_hdr

	; Write xact ID.

	ld	X, #xact_id

	jsr	tcp_crc_add

	jsr	ne_d_w_X

	; Write Protocol ID

	ld	X, #proto_id

	jsr	tcp_crc_add

	jsr	ne_d_w_X

	; Write data length.

	ld	X, #mb_pkt_len

	jsr	tcp_crc_add

	jsr	ne_d_w_X

	; Wait for complete serial packet to arrive on usart data buffer.

mb_tcp_forward_toN_wait_usart_data:

	ld	A, usart_data_ptr

	dec	A

	ifgt	A, (mb_pkt_len+1)

	jp	mb_tcp_forward_toN_wait_usart_data_done

	; Check timeout.

	ifeq	usart_data_ptr, #0x00

	jp	mb_tcp_forward_toN_dump_timeout

	jp	mb_tcp_forward_toN_wait_usart_data

mb_tcp_forward_toN_wait_usart_data_done:

	; Disable further USART activity and timeout counter

	;rbit	T2ENB, T2CNTRL

	rbit	T2C0, T2CNTRL

	rbit	T2PNDA, T2CNTRL

	rbit	T2ENA, T2CNTRL

	rbit	7, X

	rbit	ERI, ENUI

	ld	usart_data_ptr, #0x00

	; Dump the packet from SEG_USART into the NIC buffer.

 	ld	A, (mb_pkt_len+1)

 	x	A, T2

 	; mb_pkt_len MSB is ingored, because of ModBus/TCP specification: Byte count MSB is always cero.

 	ld	X, #0x00

 	ld	S, #SEG_USART

mb_tcp_forward_toN_dump:

	; Check if we are done.

	ld	A, T2

	dec	A

	ifgt	A, X

	jp	mb_tcp_forward_toN_dump_write_next

	; Align data if total byte count is odd for final byte write.

	ifbit	0, T2

	jp	mb_tcp_forward_toN_dump_aligndata

	jp	mb_tcp_forward_toN_dump_done

mb_tcp_forward_toN_dump_aligndata:

	rbit	7, X

	ld	A, [X]

	x	A, a_l

	ld	a_h, #0x00

	ld	X, #a_l

	jsr	mb_crc_add

	jsr	tcp_crc_add

	jsr	ne_d_w_X

	ld	A, T2

	x	A, X

	jp	mb_tcp_forward_toN_dump_done

mb_tcp_forward_toN_dump_write_next:

	; Transfer another word to nic buffer.

	rbit	7, X

	jsr	mb_crc_add_word

	jsr	tcp_crc_add

	jsr	ne_d_w_X

	ifbit	7, X

	ld	S, #(SEG_USART+1)

	ifeq	S, #(SEG_USART+1)

	sbit	7, X

	jp	mb_tcp_forward_toN_dump

mb_tcp_forward_toN_dump_done:

	; Verify Checksum. If checksum fail, abort anything.

	ifbit	7, X

	ld	S, #(SEG_USART+1)

	rbit	7, X		; Maybe we are just on the segment boundary.

	ld	A, [X+]

	ifne	A, crc_h

	jp	mb_tcp_forward_toN_dump_badchksum

	ifbit	7, X

	ld	S, #(SEG_USART+1)

	rbit	7, X		; Maybe we are just on the segment boundary.

	ld	A, [X]

	ifne	A, crc_l

	jp	mb_tcp_forward_toN_dump_badchksum

	ld	S, #0x00

	; Append TCP CRC to NIC buffer.

	jsr	tcp_mk_hdr_app_crc

	jmp	tx_transmit_packet



mb_tcp_forward_toN_dump_timeout:

	ld	S, #0x00

	jsr	ne_d_ab

mb_tcp_forward_toN_timeout:

	.ifdef	__DEBUG__

	ld	A, PORTED

	xor	A, #0x20

	x	A, PORTED

	.endif

	ret



mb_tcp_forward_toN_dump_badchksum:

	ld	S, #0x00

	; Bad Checksum indicator

	.ifdef	__DEBUG__

	ld	A, PORTED

	xor	A, #0x40

	x	A, PORTED

	.endif

	ret



; Checksum generator (on the fly CRC generator).

; X points to data.

; a_l is const array index.

mb_crc_add:

	; Achtung baby! : Pointer B gets lost on "readrom". Thats why we use X instead.

	ld	A, [X]

	xor	A, crc_h

	x	A, T0	;T0 = [X] xor crc_h

	readrom #HIGH(auchCRCHi), T0

	ld	A, ISPRD	;A = auchCRCHi[T0]

	xor	A, crc_l

	x	A, crc_h	;crc_h = auchCRCHi[T0] xor crc_l

	readrom #HIGH(auchCRCLo), T0

	ld	A, ISPRD	;A = auchCRCLO[T0]

	x	A, crc_l	;crc_l = auchCRCLO[T0]

	ret



mb_crc_add_word:

	; Achtung baby! : Pointer B gets lost on "readrom". Thats why we use X instead.

	ld	A, [X+]

	xor	A, crc_h

	x	A, T0	;T0 = [X] xor crc_h

	readrom #HIGH(auchCRCHi), T0

	ld	A, ISPRD	;A = auchCRCHi[T0]

	xor	A, crc_l

	x	A, crc_h	;crc_h = auchCRCHi[T0] xor crc_l

	readrom #HIGH(auchCRCLo), T0

	ld	A, ISPRD	;A = auchCRCLO[T0]

	x	A, crc_l	;crc_l = auchCRCLO[T0]

	; Second byte

	ld	A, [X-]

	xor	A, crc_h

	x	A, T0	;T0 = [X] xor crc_h

	readrom #HIGH(auchCRCHi), T0

	ld	A, ISPRD	;A = auchCRCHi[T0]

	xor	A, crc_l

	x	A, crc_h	;crc_h = auchCRCHi[T0] xor crc_l

	readrom #HIGH(auchCRCLo), T0

	ld	A, ISPRD	;A = auchCRCLO[T0]

	x	A, crc_l	;crc_l = auchCRCLO[T0]

	ret





	; CRC tables.

.sect modbus_crc, ROM, ABS = 0x1D00

auchCRCHi:

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41

	.db	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0

	.db	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1

	.db	0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1

	.db	0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40

	.db	0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1

	.db	0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40

	.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0

	.db	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41

	.db	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41

	.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40

	.db	0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1

	.db	0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41

	.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0

	.db	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

auchCRCLo:

	.db	0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06

	.db	0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD

	.db	0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09

	.db	0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A

	.db	0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4

	.db	0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3

	.db	0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3

	.db	0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4

	.db	0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A

	.db	0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29

	.db	0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED

	.db	0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26

	.db	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60

	.db	0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67

	.db	0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F

	.db	0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68

	.db	0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E

	.db	0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5

	.db	0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71

	.db	0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92

	.db	0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C

	.db	0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B

	.db	0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B

	.db	0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C

	.db	0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42

	.db	0x43, 0x83, 0x41, 0x81, 0x80, 0x40



⌨️ 快捷键说明

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