??? 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 |