| ??? 03/02/08 23:46 Read: times |
#151767 - So where is the problem? Responding to: ???'s previous message |
You tell us 'it doesn't work' - what doesn't work? Is it the receive? Transmit? Do you really expect us to debug your complete code for you? I'd suggest you use tools like Modscan and Modsim (www.win-tech.com/html/modbus1.htm)to debug your code. I would expect once you start to localise the problem, the solution will be obvious.
Here are some routines to implement the core modbus features.
;
;
; this module implements the Modbus rx/tx code and the register
; structure.
; In order to save ram, certain modbus registers are only implemented in EEprom, the read/write_modbus_reg
; routines take care of any shenanigans.
;
public read_modbus_reg ; reads a modbus reg into R7:R6
public write_modbus_reg ; writes a modbus reg into R7:R6
public cold_init ; loads defaults into ram based regs & eeprom base regs(if required)
public serial_isr ; int vector for the serial port
public MODBUS_READ_HOLDING_REGS
public modbus_buff
public process_modbus ; task to process modbus messages
public stack
public NUM_MODBUS_REGS
public our_addr
extern MODBUS_TYPE
extern RX_PKT
;
; kernel externals
;
extern TASK0_RUN
extern dispatch
;
;
;
extern _R0
extern _R1
extern _R2
extern _R3
extern _R4
extern _R5
extern _R6
extern _R7
extern bank1_R0
extern bank1_R1
extern bank1_R2
extern bank1_R3
extern bank1_R4
extern bank1_R5
extern bank1_R6
extern bank1_R7
;
; Dallas 1 wire memory read/write routines
;
extern read_one_wire_serialno
extern read_one_wire_eeprom
extern write_one_wire_eeprom
;
; MODBUS command values
;
MODBUS_PRESET_REGS equ 16
MODBUS_READ_HOLDING_REGS equ 3
;
SIZEOF_MODBUS_BUFF equ 40 ;modbus rx/tx buffer
MAX_RW_REGS equ 16+1 ;maximum number of registers than can be read/written at one time
INIT_TAG equ 0aa55h ;tag stored in eeprom to see if we're initialised yet
CR equ 13
LF equ 10
;
; special Modbus register addresses to read/write the 1 wire memory device
;
MBREG_1WIRE_READ equ 200
MBREG_1WIRE_WRITE equ 220
CODE
;----------------------------------------------------------------------------
;
;
; process modbus. decodes the modbus packet in modbus_buff
; and performs the required command
; ** assumes the rx code has checked the modbus address **
; zaps:most regs!
;
;----------------------------------------------------------------------------
process_modbus
jb MODBUS_TYPE,pm_c ;if modbus_type is ascii then we don't need to check the CRC
;
; modbus transport is RTU, check the CRC before continuing
;
mov r0,#modbus_buff
mov a,bank1_R7 ;get the rx packet size
mov bank1_R7,#0 ;reset the packet size
cjne a,#7,pm_1
pm_1 jc pm_z ;ignore packet if it is too small
clr c
subb a,#2 ;-2 for CRC bytes
mov r6,a
lcall calculate_crc
jz pm_c ; if CRC was ok - process the packet
pm_z
ljmp L72 ;bad crc-skip the packet
pm_c
setb RX_PKT ;flash asterisk on the lcd for good rx pkts
mov r0,#modbus_buff+1
mov a,@r0 ;get the modbus command
cjne a,#MODBUS_READ_HOLDING_REGS,L59
;
; read holding regs command
;
mov r0,#modbus_buff+3 ;get the starting reg#
mov a,@r0
mov r2,a
mov r0,#modbus_buff+5 ;get # of regs
mov a,@r0
mov r5,a
clr c
subb a,#MAX_RW_REGS
jc pm_11
ljmp L62 ;if too many registers requested
pm_11
mov a,r5
add a,r5 ;register count times 2
mov r0,#modbus_buff+2
mov @r0,a ;set the reply byte count
inc r0
;
; copy mregs[] into the transmit buffer
;
pm_2
mov a,r2 ;get modbus reg#
anl a,#0fch ;mask off the lower two bits
cjne a,#MBREG_1WIRE_READ,pm2_1
;
; magic register number for Dallas 1 wire rom read!
;
mov a,r2
anl a,#3 ;get lower two bits for 1wire port address
; mov r4,a
push _R4
push _R2
mov r4,a
lcall read_one_wire_serialno
pop _R2
pop _R4
jc L51 ;the read failed - return an error
sjmp pm_3 ;things worked! send reply
;
pm2_1
mov a,r2
anl a,#0fch ;mask off the lower two bits
cjne a,#MBREG_1WIRE_WRITE,pm2_2
;
; magic register number for Dallas 1 wire eeprom read!
;
mov a,r2
anl a,#3 ;get lower two bits for 1wire port address
mov r4,a
push _R2
mov r2,#31
lcall read_one_wire_eeprom
pop _R2
jc L51 ;the read failed - return an error
sjmp pm_3 ;things worked! send reply
;
pm2_2
mov a,r2
lcall read_modbus_reg ;A has the modbus register#
jnz L51 ;if register error
mov a,r7
mov @r0,a ;store high
inc r0
mov a,r6
mov @r0,a ;store low
inc r0
inc r2 ;next register#
djnz r5,pm2_2 ;loop until regs copied
pm_3:
clr c
mov a,r0
subb a,#modbus_buff ;calc message length
inc a ;+1 for msg length
sjmp send_modbus ;& send it
L51:
;
; register request exceeded the # of registers
;
mov r0,#modbus_buff+1
mov a,@r0 ;get modbus cmd
orl a,#80h ;set error flag
mov @r0,a
mov r0,#modbus_buff+2
mov a,#2 ;bad address
mov @r0,a
mov a,#4 ;length =4 including the LRC
sjmp send_modbus
L59
cjne a,#MODBUS_PRESET_REGS,L44
;
; Modbus preset registers command
;
mov r0,#modbus_buff+3
mov a,@r0 ;get the starting reg#
mov r2,a ;into R2
anl a,#0fch ;clear lower 2 bits
cjne a,#MBREG_1WIRE_WRITE,prc_4 ;test for 'magic' modbus register for dallas 1 wire write
;
; write the dallas DS2430 1 wire eeprom
;
mov a,r2
anl a,#3 ;get lower two bits for 1wire port address
mov r4,a
mov r0,#modbus_buff+7 ;r0 ->modbus_buff[7] point to the data to write
push _R2
mov r2,#31 ;# of bytesto write
lcall write_one_wire_eeprom
pop _R2
jc L62 ;return error packet if fail
sjmp prc_3 ;else return ack packet
;-
prc_4
mov r0,#modbus_buff+5
mov a,@r0 ;get # of regs
mov r5,a ;into R5
clr c
subb a,#MAX_RW_REGS
jnc L62 ;if too many registers requested
mov a,r5
add a,r2 ;add + count
clr c
subb a,#NUM_MODBUS_REGS+1
jnc L62
prc_1
mov a,r5 ;test reg count
jz prc_3 ;if all done
prc_2
mov r0,#modbus_buff+7 ;r0 ->modbus_buff[7]
;
; get the register from the rx buffer into R7:R6
;
mov a,@r0
mov r7,a ;reg high
inc r0
mov a,@r0
mov r6,a ;reg low
inc r0
mov a,r2 ;get modbus reg#
lcall write_modbus_reg
;
; next!!
;
inc r2
djnz r5,prc_1 ;count--
prc_3
mov a,#4 ;set reply pkt length
sjmp send_modbus
;
; bad register passed
;
L62
mov r0,#modbus_buff+1
mov a,@r0
orl a,#080h ;set error flag
mov @r0,a
inc r0
mov a,#2 ;bad address
mov @r0,a
mov a,#4 ;pkt length =4 inc LRC
sjmp send_modbus
;
; catch all for command not supported
;
L44
mov r0,#modbus_buff+1
mov a,@r0
orl a,#080h ;set error flag
mov @r0,a
inc r0
mov a,#1 ;bad command
mov @r0,a
mov a,#4 ;pkt length =4 inc LRC
;
; send the modbus data out
; A has the packet length
; modbus data is assumed to be in modbus_buff
;
send_modbus
orl a,a
jz L72 ;if length ==0, skip transmit
jb MODBUS_TYPE,send_ascii
push a
mov r6,a ;packet length
mov r0,#modbus_buff
call calculate_crc
pop a
add a,#2 ;+crc bytes
;
; use MODBUS RTU as the packet transport
;
clr ea ;no interrupts
mov bank1_R6,a
mov bank1_R0,#modbus_buff
mov bank1_R2,#1 ;set tx state
setb ea
sjmp L72
;
; use MODBUS ascii as the packet transport
;
send_ascii
clr EN_485 ;set 485 buffer to tx
mov bank1_R6,a ;set the packet length
mov bank1_R0,#modbus_buff
mov bank1_R2,#0 ;clear tx state
mov bank1_R4,#0 ;clear LRC
mov SBUF,#':' ;send the start token (fires the tx interrupt)
clr TI
L72
L42
L41
clr TASK0_RUN ;reset task request
mov bank1_R3,#0 ;reset the rx state
ljmp dispatch
;----------------------------------------------------------------------------
;
; write MODBUS register
; entry:
; R7:R6 has the modbus register value to write
; A has the MODBUS register#
; returns: A == 0 if ok, A ==1 if bad register#
; zaps: A,PSW,DPTR
;
;----------------------------------------------------------------------------
write_modbus_reg
push _R0
push b
cjne a,#NUM_MODBUS_REGS,wmr_1 ;test for max reg#
wmr_1
jnc wmr_bad ;if reg# >=NUM_MODBUS_REGS
;
; dptr->modbus_options_table
;
mov b,#SIZEOF_MB
mul ab ;calc table offset
mov dptr,#modbus_options_table
add a,dpl
mov dpl,a
mov a,b
addc a,dph
mov dph,a ;dptr->modbus_options_table[reg#]
;
; check the register options
;
mov a,#MB_FLAGS
movc a,@a+dptr ;get the options byte
jnb a.MB_EEPROM,wmr_2
;
; EEprom option is set, write the register to eeprom
;
mov a,#MB_OFFSET
movc a,@a+dptr ; get the eeprom addr
clr c
rrc a ; calc the page addr
clr c
rrc a
mov EADRL,a ;set the page address
mov ECON,#01h ;read page -'cos we do a read_modify_write
jc wmr_11 ; if we're writing the hi two bytes in the page
;
; write the two low bytes in the page
;
mov a,R7
mov EDATA1,a
mov a,R6
mov EDATA2,a
sjmp wmr_12
;
; write the two low bytes in the page
;
wmr_11
mov a,R7
mov EDATA3,a
mov a,R6
mov EDATA4,a
;
; erase the eeprom page, then write it
;
wmr_12
mov ECON,#05h ;erase page (we sleep for 2mS)
mov ECON,#02h ;write the page (we sleep for 250uS)
sjmp wmr_3
;
; modbus register is in ram
;
wmr_2
mov a,#MB_OFFSET
movc a,@a+dptr
mov r0,a ;r0-> modbus register in ram
mov a,r7
mov @r0,a ;store hi byte
inc r0
mov a,r6
mov @r0,a ;store low byte
wmr_3
clr a
wmr_x
pop b
pop _R0
ret
wmr_bad
mov a,1 ;return a bad status
sjmp wmr_x
;----------------------------------------------------------------------------
;
; read MODBUS register
; entry:
; A has the MODBUS register#
; returns: A == 0 if ok, A ==1 if bad register#, R7:R6 with the modbus reg value
; zaps: A,PSW,DPTR
;
;----------------------------------------------------------------------------
read_modbus_reg
push _R0
push b
cjne a,#NUM_MODBUS_REGS,rmr_1 ;test for max reg#
rmr_1
jnc rmr_bad ;if reg# >=NUM_MODBUS_REGS
;
; check the register options
;
mov b,#SIZEOF_MB
mul ab ;calc table offset
mov dptr,#modbus_options_table
add a,dpl
mov dpl,a
mov a,b
addc a,dph
mov dph,a ;dptr->modbus_options_table[reg#]
mov a,#MB_FLAGS
movc a,@a+dptr ;get the options byte
jnb a.MB_EEPROM,rmr_2
;
; EEprom option is set, read the register from eeprom
;
mov a,#MB_OFFSET
movc a,@a+dptr ; get the eeprom addr
clr c
rrc a ; calc the page addr
clr c
rrc a
mov EADRL,a ;set the page address
mov ECON,#01h ;read page
jc rmr_11 ;if we're reading the hi two bytes in the page
;
; read the low two bytes from the eeprom page
;
mov r7,EDATA1
mov r6,EDATA2
sjmp rmr_3
;
; read the hi two bytes from the eeprom page
;
rmr_11
mov r7,EDATA3
mov r6,EDATA4
sjmp rmr_3
;
; modbus register is in ram
;
rmr_2
mov a,#MB_OFFSET
movc a,@a+dptr
mov r0,a ;r0-> modbus register in ram
mov a,@r0
mov r7,a ;read hi byte
inc r0
mov a,@r0
mov r6,a ;read low byte
rmr_3
clr a
rmr_x
pop b
pop _R0
ret
rmr_bad
mov a,1 ;return a bad status
sjmp rmr_x
;----------------------------------------------------------------------------
;
;
; called on power-up to initialise the modbus registers
; reads all the values from the modbus_options_table default values
; into the eeprom if the INIT_TOKEN is not set and reads the defaults
; into the ram based registers
;
;----------------------------------------------------------------------------
cold_init
mov r5,#NUM_MODBUS_REGS
mov dptr,#modbus_options_table
ci_loop
mov a,#MB_FLAGS
movc a,@a+dptr ;get the options var
jb a.MB_EEPROM,ci_2 ;if an eeprom based register, skip as no init required
;
;
;
mov a,#MB_OFFSET
movc a,@a+dptr
mov r0,a ;r0->ram modbus register
mov a,#MB_DEFAULT
movc a,@a+dptr
mov @r0,a ;store the hi default value
inc r0
mov a,#MB_DEFAULT+1
movc a,@a+dptr
mov @r0,a ;store the low default value
ci_2
mov a,#SIZEOF_MB
add a,dpl
mov dpl,a
mov a,#0
addc a,dph
mov dph,a ;->next record
djnz r5,ci_loop
;
; test INIT_TOKEN for the correct value. If not, load the eeprom with the default values from the modbus_options_table
;
mov EADRL,#<INIT_TOKEN
mov ECON,#1
mov a,EDATA1
cjne a,#>INIT_TAG,ci_do
mov a,EDATA2
cjne a,#<INIT_TAG,ci_do
ret
;if init tag was valid
ci_do
mov r5,#NUM_MODBUS_REGS
mov dptr,#modbus_options_table
mov r2,#0 ;modbus register #1
ci_1
mov a,#MB_FLAGS
movc a,@a+dptr
jnb a.MB_EEPROM,ci_3 ;skip init if a ram based register
;
; eeprom based register...init it.
;
mov a,#MB_DEFAULT
movc a,@a+dptr
mov r7,a
mov a,#MB_DEFAULT+1
movc a,@a+dptr
mov r6,a
push dph
push dpl
mov a,r2 ;get modbus reg#
lcall write_modbus_reg
pop dpl
pop dph
;
; next register..
;
ci_3
inc r2
mov a,#<SIZEOF_MB
add a,dpl
mov dpl,a
mov a,#>SIZEOF_MB
addc a,dph
mov dph,a ;next entry
djnz r5,ci_1
mov EADRL,#<INIT_TOKEN
mov EDATA1,#>INIT_TAG
mov EDATA2,#<INIT_TAG
mov ECON,#05h ;erase page (we sleep for 2mS)
nop ;I'm suspicious!!!
mov ECON,#02h ;write the page (we sleep for 250uS)
nop
ret
;
;
; calculates and appends the CRC for a MODBUS RTU message
; R0->modbus msg
; R6 has the msg length
; return value ==0 if crc on a rx packet was ok else 1 = crc error
; zaps:A,B,R0,R2,R4,R5,R6
;
; crc_lo R4
; crc_hi R5
;
;
;
calculate_crc
mov r4,#0ffh
mov r5,#0ffh ;preload the crc accumulator
cc_lp
mov a,@r0 ;get a byte from the buffer
inc r0
xrl a,r4
mov r4,a ;CRC ^= *buff
mov r2,#8 ;for x=1 to 8
cc_1
clr c
mov a,r5
rrc a
mov r5,a
mov a,r4
rrc a
mov r4,a ;CRC >>=1
jnc cc_2
mov a,#0a0h
xrl a,r5
mov r5,a
mov a,#01h
xrl a,r4
mov r4,a ;if (carry) CRC ^= 0xa001
cc_2
djnz r2,cc_1 ;next x
djnz r6,cc_lp
mov b,#0 ;B has the error status
mov a,@r0
xrl a,r4 ;if crc_lo != *buff then err = 1
jz cc_3
mov b,#1 ;flag error
cc_3
mov a,r4
mov @r0,a
inc r0 ; *buff++ = crc_lo
mov a,@r0
xrl a,r5
jz cc_4
mov b,#1 ;flag error
cc_4
mov a,r5
mov @r0,a
inc r0 ;*buff++ = crc_hi
mov a,b ;get the return result
ret
;----------------------------------------------------------------------------
;
;
; outputs the modbus ascii data. converts the buffer data to ascii and
; appends the modbus LRC and cr/lf
;
; we use register bank 1 exclusively
;
; R0 is tx_ptr
; R1 is rx_ptr
; R2 is tx_state
; R3 is rx_state
; R4 is tx_lrc
; R5 is rx_lrc
; R6 is tx_length
; R7 is rx_length
;
serial_isr
jb MODBUS_TYPE,ascii
jb TI,txrtu
jb RI,rxrtu
sjmp serial_exit
ascii
jb TI,txascii
jnb RI,serial_exit
ljmp rxascii
serial_exit
reti
;
;
; modbus RTU rx code
; we use register bank 1 exclusively
;
; R0 is tx_ptr
; R1 is rx_ptr
; R2 is tx_state
; R3 is rx_state
; R4 is tx_lrc
; R5 is rx_lrc
; R6 is tx_length
; R7 is rx_length
;
;
;
rxrtu
push psw
push a
mov psw,#00001000b ;select register bank#1
mov a,r3 ;get the rx state
cjne a,#0,rxrtu_1
;
; RTU rx state 0, grab the rx data & store into the buffer
;
mov r5,#3 ;load the timeout with 2 character times
mov a,r7 ;test the rx length
clr c
subb a,#SIZEOF_MODBUS_BUFF-2
jnc rxrtu0_1 ;rx count too large! exit
mov a,SBUF ;rx buff ok, grab the rx char
clr RI
mov @r1,a ;store it
inc r1 ;rx->++
inc r7 ;rx length++
sjmp rxrtu_x
rxrtu_1
;
; RTU rx state1, ignore any more rx chars for the moment
;
rxrtu0_1
mov a,SBUF ;junk the rx character
clr RI
rxrtu_x
pop a
pop psw
reti
;
;
; the tx code is a little trickier since we use the tx as a timer for the
; rx packet timeout when we're not actually transmitting a packet
;
;
txrtu
push psw
push a
mov psw,#00001000b ;select register bank#1
mov a,r2 ;get the tx state
cjne a,#0,txrtu_1
;
; RTU tx state 0. we keep the tx alive so the rx code can use it as a timer
; in this instance we send a NULL char. The real world (RS485) doesn't see these
; characters as the rs485 tx is disabled.
;
setb EN_485 ;don't send anything to the outside!
mov SBUF,#0 ;send a null char
clr TI
mov a,r5 ;get the rx timer
jz txrtu_x ;already 0, don't do anything!
djnz r5,txrtu_x ;dec the timer
;
; timer just hit 0, activate the rx process code
;
mov r1,#modbus_buff
mov a,@r1 ;get the first byte (modbus addr)
xrl a,our_addr ;test with our address
jnz txrtu0_2 ;if not us
setb TASK0_RUN ;if a good packet, activate the rx task
mov r3,#1 ;set state for rx idle, when packet is processed, we are reset
sjmp txrtu_x
;
; restart the RTU rx code
;
txrtu0_2
mov r1,#modbus_buff ;reset the rx->
mov r7,#0 ;reset the byte count
mov r3,#0 ;reset the rx state
sjmp txrtu_x
txrtu_1
cjne a,#1,txrtu_x
;
; RTU tx state 1. here we send tx data to the outside world
;
;
clr EN_485
mov a,@r0
mov SBUF,a
clr TI
inc r0
djnz r6,txrtu_x
;
; last character of the packet, next state is 0
;
mov r2,#0
txrtu_x
pop a
pop psw
reti
;
;
; implements the MODBUS ASCII protocol.
; user routine must set tx_ptr (R0), tx_length (R6) and send the ':' start token
; to fire the tx interupt
;
;
txascii
push psw
push a
mov psw,#00001000b ;select register bank#1
mov a,r2 ;get the state into A
cjne a,#0,tx_st1
;
; state = 0
;
mov a,@r0
add a,r4
mov r4,a ;accumulate the checksum
mov a,@r0
swap a ;get hi nibble
anl a,#0fh
cjne a,#10,mti_1
mti_1
jnc L96
add a,#'0' ;ascii offset 0..9
sjmp L97
L96
add a,#'0' + 7 ;ascii offset A..F
L97
mov SBUF,a
clr TI
mov r2,#1 ;next state = 1
sjmp L95_X
tx_st1
cjne a,#1,tx_st2
;
; state = 1. send ascii low nibble
;
mov a,@r0
inc r0
anl a,#0fh ;get low nibble
cjne a,#10,mti_2
mti_2 jnc L96_1
add a,#'0' ;ascii offset 0..9
sjmp L97_1
L96_1
add a,#'0' + 7 ;ascii offset A..F
L97_1
mov SBUF,a
clr TI
dec r6
mov a,r6
cjne a,#1,mti_3 ;length == 1?
sjmp L102 ;yep! calc the lrc
mti_3
jnz L103 ;if the last byte
mov r2,#2 ;next state =2,send CR
sjmp L95_X
L103
mov r2,#0 ;next state = 0,send next byte
sjmp L95_X
L102
mov a,r4 ;get the lrc
cpl a ;ones complement
inc a ;plus 1
mov @r0,a ;store the lrc
mov r2,#0 ;next state =send hi nibble
sjmp L95_X
tx_st2
cjne a,#2,tx_st3
;
; state = 2. send CR
;
mov SBUF,#CR ;send CR
clr TI
mov r2,#3 ;next state = 3 send line feed
sjmp L95_X
tx_st3
cjne a,#3,tx_st4
;
; state = 3. send line feed
;
mov SBUF,#LF ;send LF
clr TI
mov r2,#4 ;next state = 4
sjmp L95_X
tx_st4
cjne a,#4,L95_X
;
; state = 4. end of transmit, set 485 buffer to receive and sit
; here until the tx code re-activates us
;
clr TI
setb EN_485
L95_X
pop a
pop psw
reti
;
;
; implements the MODBUS ASCII receive protocol
;
;
rxascii
push psw
push a
push b
mov psw,#00001000b ;select register bank#1
mov b,SBUF ;get the rx char into B
clr RI
;
; always test for the start token
;
mov a,b
cjne a,#':',L129 ;start token?
mov r5,#0 ;rx_lrc = 0
mov r7,#0 ;rx_length = 0
mov r1,#modbus_buff ;->start of rx buffer
mov r3,#1 ;next state = 1
sjmp L116_X
L129
rx_st1
mov a,r3 ; get the rx state
cjne a,#1,rx_st2
;
; rx_state = 1. expect a hex ascii char or a carriage return
; for end of packet
;
clr c
mov a,b
subb a,#'0' ;minus ascii offset
jc L127 ;if number < '0'
cjne a,#9+1,rx_st1_2
rx_st1_2
jnc L125 ;if rx char > 9
sjmp L126
L125
clr c
subb a,#7
cjne a,#0ah,rx_st1_3
rx_st1_3
jc L127 ;if rx char is < 'A'
cjne a,#0fh+1,rx_st1_4
rx_st1_4
jnc L127 ;if rx char > 'F'
L126
anl a,#0fh
swap a
mov @r1,a
mov r3,#2 ;next state = 2
sjmp L116_X
L127
mov a,b
cjne a,#CR,L124 ;carriage return? (end of packet?)
;
; end of packet
;
mov a,r5 ;get our rx_lrc
jnz L124 ;if lrc was bad!
mov r1,#modbus_buff
mov a,@r1 ;get the first byte (modbus addr)
xrl a,our_addr ;test with our address
jnz L124 ;if not us
setb TASK0_RUN ;if a good packet, activate the rx task
mov r3,#4 ;idle in an illegal state, when packet is processed, we are reset
sjmp L116_X
L124
mov r3,#0 ;next state = 0
sjmp L116_X
rx_st2
cjne a,#2,L116_X
;
; state = 2. expect hex ascii for low byte nibble
;
clr c
mov a,b
subb a,#'0' ;minus ascii offset
jc L137 ;if number < '0'
cjne a,#9+1,rx_st2_2
rx_st2_2
jnc L135 ;if rx char > 9
sjmp L133
L135
clr c
subb a,#7
cjne a,#0ah,rx_st2_3
rx_st2_3
jc L127 ;if rx char is < 'A'
cjne a,#0fh+1,rx_st2_4
rx_st2_4
jnc L127 ;if rx char > 'F'
L133
anl a,#0fh
orl a,@r1 ;'or' in the hi nibble
mov @r1,a
add a,r5 ;get rx_lrc
mov r5,a ;accumulate the lrc
inc r1 ;rx_ptr++
inc r7 ;rx_length++
cjne r7,#SIZEOF_MODBUS_BUFF,rx_st2_5
rx_st2_5
jnc L137 ;if rx packet is too large!
mov r3,#1 ;otherwise next state = 1
sjmp L116_X
L137
mov r3,#0 ;next state = 0
L116_X
pop b
pop a
pop psw
reti
|
| Topic | Author | Date |
| MODBUS RTU for 8051/DS89C450 | 01/01/70 00:00 | |
| How to post source code | 01/01/70 00:00 | |
| Formatted Source Code | 01/01/70 00:00 | |
| Looks like translated PIC code! | 01/01/70 00:00 | |
| So where is the problem? | 01/01/70 00:00 | |
| More details... | 01/01/70 00:00 | |
| How did you test your VC++ app...? | 01/01/70 00:00 | |
| uC -> RTU Slave (OK) ; RTU Slave -> uC (FAIL) | 01/01/70 00:00 | |
| RE:8 bit buffer | 01/01/70 00:00 | |
| Problem? | 01/01/70 00:00 | |
RE:8 bit buffer | 01/01/70 00:00 | |
| RTU Communication is working! | 01/01/70 00:00 |



