SCI problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SCI problem

5,151 Views
mylim
Contributor IV
Hi, i wrote my code as below; but somehow when i single step thru i can't see my the data i sending out loaded in the data register.
I' using the SCI to drive a sipex SP485.
I inititalise the SCI as ;
4807baud
SCI2BDH = $00
SCI2BDL = $1A
SCI2C1    = $40
SCI2C1    = $2C
SCI2C3    = $00
 
Code:
;--------------------;TX485 Routine;--------------------tx485       bset   RS485EN2,PTCD            bset   SCI2C2_TE,SCI2C2            jsr    idelay            jsr    idelay            clr    TXCHK            lda    TXADRtx485a      brclr  SCI2S1_TDRE,SCI2S1,tx485a            sta    SCI2D            add    TXCHK            sta    TXCHK            rts  ;--------------------;TX Data;--------------------txdata      lda    CARDADR            sta    TXADR                         jsr    tx485            lda    #$3C            jsr    tx485a            lda    #$07            jsr    tx485a            lda    #$07            jsr    tx485a            lda    #$07            jsr    tx485a            lda    #$07            jsr    tx485a            lda    TXCHK            and    #$7F            jsr    tx485atxdata2     brclr  SCI2S1_TC,SCI2S1,txdata2            jsr    idelayh            bclr   RS485EN2,PTCD

 
When i try to read SCI2D, it doesnt tally with the data i loaded.
Are there something wrong at my 'tx485a'?
Please advise.
Thanks.


Message Edited by mingyee on 2007-07-09 06:17 PM
Labels (1)
0 Kudos
Reply
22 Replies

1,699 Views
bigmac
Specialist III
Hello,
 
Yes, it is correct that you won't read the byte you just sent to SCI2D.  This is because the read of this register returns the last byte received by the SCI2 module, not the send byte.  For RS485 it is usual that, when send is enabled for the transceiver, receive will be disabled, so there would be no receive data.
 
Do you actually receive the sent data at the remote end?
 
Regards,
Mac
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi bigmac, Thanks for the response.
From my understanding, when we sending data out we will move the data to SCIxD.
Does that mean when i read SCIxD right after
Code:
    sta   SCI2D

 I will be able to see what i write into SCIxD?
At the other receiving end which is my laptop, I only receive 0 0 0 0 0 0
 

 
Please advise.
 
PEG is right that I have typo (second C1 should be C2) at the initialize portion.
 
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
The SCID is actually two hardware registers located at the same address.
If you read that address you get the recieve buffer, if you write to it, you write into the transmit buffer.
It is impossible to read from the transmit buffer or write to the recieve buffer!
This is spoken about in the SCI section of the manual.
The best way to use buffers is a bit protocol specific so I did not go into more detail straight away. If you tell me how it works maybe I can assist you implement it using buffers.
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi Peg,
Thanks.
To store the data into a buffer I'll have to declare a buffer & use the stack pointer to move the data 1 by 1 into the buffer. Am i right?
 
regards,
mingyee
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
Here is a quick go at a buffer based background transmit. Notice that the code never waits around doing nothing while the transmission occurs. Also if you are sending from many places in your code the buffer load bit is minimal.
 
Code:
TXBUF       rmb    8              ;transmit bufferTXSTAT      rmb    1              ;transmit status bitsTXCHK       rmb    1              ;checksumTXCNT       rmb    1              ;transmit buffer index*somewhere in your code...            mov    #$3C,TXBUF            mov    #$07,TXBUF+1            mov    #$07,TXBUF+2            mov    #$07,TXBUF+3            mov    #$07,TXBUF+4            mov    #$00,TXBUF+5     ;mark end of string            bset   0,TXSTAT         ;mark to send            STARTMAIN   BLAH,BLAH            BLAHTXNEED      BRCLR  0,TXSTAT,MAINEND     ;bail if don't need to transmit            BRCLR  TDRE,SCI2S1,MAINEND  ;bail if Tx reg not MT            BRSET  1,TXSTAT,SENTADR     ;check if address sent            BSET   1,TXSTAT            BSET   RS485EN2,PTCD        ;enable transmitter            MOV    CARDADR,SCI2D        ;send address            BRA    CHK1SENTADR     BRSET  2,TXSTAT,SCITC       ;check if TXCHK sent            LDX    TXCNT                ;GET TX'D CHAR COUNT            INC    TXCNT            LDA    TXBUF,X              ;GET NEXT CHAR FROM TX1BUF            BEQ    CHKSM            STA    SCI2D                ;SEND CHAR            ADD    TXCHKCHK1        STA    TXCHK            BRA    MAINEND              ;KEEP GOING IF NOT ENDCHKSM       LDA    TXCHK            AND    #$7F            STA    SCI2D                ;SEND TXCHK            BSET   2,TXSTAT             ;set TXCHK sent            BRA    MAINENDSCITC       BRCLR  TC,SCI2S1,MAINEND    ;WAIT FOR TRANSMISSION COMPLETE            CLR    TXSTAT               ;clear status bits            BCLR   RS485EN2,PTCD        ;disable transmitter (enable recieve)            CLR    TXCNT                ;RESET TX COUNTERMAINEND     JMP    STARTMAIN

 
Of course you may need some other code to mark the end of the string, or, if you can't afford one use a "number of bytes to send" variable.
 
Did you get your comms to work?
I would not substitute this in until you get it working.
This is not going to fix any problems there.
Your original method is more basic and so a bit easier to debug.
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi Peg,
The old routine is working now.
I will be trying out your methods. It sounds more effecient compare to mine.
However, am i able to do the same for my RECEIVING?
Anything which I've to aware of?
Thanks.
 
Regards,
mingyee
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi again mingyee,
 
I normally use something very similar to that shown for transmit although I normally use a unique header character which would then add another stage (and flag) to the transmit routine. You continually check for the header char and reset the index if you get one. This recovers from dropped/mangled chars faster.
 
For recieve I always use an ISR and put it in a buffer checking for header and "my address" in the isr. Roughly the same technique is used but in reverse.
 
Why don't you give it a go yourself and post it back here for perusal.
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV

 

Hi Peg,

I've tried my buffering rx routine as follow.

it seems to work.

Any comment to make it more efficient?

Thanks.

 

Code:
Code:;--------------------;RX485 rxirq routine;--------------------XDEF    isrVsci2rxisrVsci2rx:        pshh        clr     RXCHK        jsr     rx485        sta     RXDEV        bne     rxirq        jmp     rxirqz          rxirq   lda     RXDEV        cmp     #DEVICE         beq     rxirq1        jmp     rxirqzrxirq1  jsr     rx485        sta     RXADR        cmp     CARDADR        beq     rxirq2        jmp     rxirqzrxirq2  jsr     rx485        sta     RXCMD         rx0     cmp     #$55          ;poll status        bne     rx1        jmp     rxpoll     rx1                                 rxirqy  bclr    LBUSYF,SR2  rxirqz  pulh        rti;--------------------;RX485 Routine;--------------------rx485       clr    RXCTR            clr    RXLEN            mov    #$04,RXDEL            bset   LBUSYF,SR2rx485a      lda    #$00            feed_watchdog            ldx    RXLEN            brset  SCI2S1_RDRF,SCI2S1,rx485b              dec    RXCTR            bne    rx485a            dec    RXDEL            bne    rx485a                        rx485b      lda    SCI2D            sta    RXDATA            sta    RXBUF,X            add    RXCHK            sta    RXCHK            lda    RXDATA            inc    RXLENrx485z      rts       


 
Regards,

mingyee

0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
You seem to have failed to grasp the basic concept of using an interrupt to do this.
Firstly without worrying too much about what the code is achieving, let me point out a few
inefficiencies in how you are going about it.
We will call the pshh at the top line 1.
1. At line 5,6 you are handling this as if a jmp is required. This can be handled directly by a branch and so both lines should be replaced by beq  rxirqz.
 
2. Line 7, you are loading the accumulator with a value that it already has, drop this line.
 
3. Line 9,10 and 14,15 and 19,20 same as point 1.
 
4. where is rxpoll?
 
5. at rx485a, probably no need to clra before feed_watchdog.
 
6. You should not feed the watchdog from within an isr!
 
7. Doing a jsr out of an ISR is usually not a good idea it should be simple enough to not require this much overhead.
 
That will do for that.
 
Now, the idea of an SCI recieve ISR is simply this. Every time a character comes in the ISR fires then within the isr you simply get the char, do a quick analysis of it and set a bit or store it in a buffer then get out back to background tasks waiting for the next character to trundle in.
 
If you want to do a time out, do it in the background.
In the ISR you set a bit or something to indicate that you have the entire message and then further processing is done by code in the background.
 
If you tell me what you are expecting to recieve maybe I can help with a routine.
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi Peg,
Thanks.
My rxpoll routine is as below.
After checking what the RXCMD is then I'll jmp to respective RXPOLL for its dedicated action.
 
Code:
rxpoll  jsr     rxchksum  ;chksum        bne     rxirqzrxpoll1 lda     CARDADR   ;slave adr for master to identify        sta     TXADR         jsr     tx485        lda     #$3C      ;command        jsr     tx485a        lda     #$07      ;txdta        jsr     tx485a        lda     #$07      ;txdta1        jsr     tx485a        lda     #$07      ;txdta2        jsr     tx485a        lda     #$07      ;txdta3        jsr     tx485a        lda     TXCHK     ;txchksum        and     #$7F        jsr     tx485a          rxpoll2 brclr   SCI2S1_TC,SCI2S1,rxpoll2        jsr     idelayh        bclr    RS485EN2,PTCD                         pulh        rti

 
what I'm expecting to receive is
1. "RXDEV, RXADR, RXCMD,RXDTA(1-n), RXCHK" for MASTER to SLAVE
2. "RXADR, RXCMD,RXDTA(1-n), RXCHK" for SLAVE to MASTER
RXDEV = different for different slave system or device
RXADR = for MASTER to SLAVE reflects to slave adr / for SLAVE to MASTER reflects to slave adr itself for master to identify 
RXCMD = command
RXDTA = data for each command
RXCHK = chksum by adding all the bytes in front
 
I would like to chk if it is possible to do something like:
1. i chk for the RXDEV if valid then i buffer everything into RXBUF
2. then chk RXADR if valid
3. then chk RXCHK if valid
4. then cmp command & process the data?
 
I see that what I'm currently doing is while i receive i chk & compare the data receive.
Please advise.
Thanks.
 
Regards,
mingyee


Message Edited by mingyee on 2007-07-15 05:21 AM
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
I am still unclear on a couple of things to do with the protocol, like:
 
How do you identify the start of a new transmission?
What do you do if, say, the checksum is wrong?
What is a valid RXDEV?
 
What I will do is give you my version of a rx ISR for the slave in psuedo code
 
load SCI status reg
check for errors and ???
load SCI data reg
if have not got valid RXDEV
  check for valid RXDEV
  if OK reset buffer index
  store it in RXCHKS
  and set gat valid RXDEV
if got valid rxdev but not my address bit
  check for my address
  if not, clear got valid RXDEV
  if is mw address set bit to say so
       add to RXCHKS
if got valid rxdev and my address
  buffer the rest
  add to RXCHKS
  if this is RXCHK
     cmp to calculated RXCHKS
     if OK set bit to say got a valid string and clear all other bits
 
......
in your background code now you can detect the "got valid string bit"
now you can intepret it.
In the buffer is only the command and its data.
 
0 Kudos
Reply

1,699 Views
bigmac
Specialist III
Hello mingyee,
 
To elaborate on Peg's comments about your protocol . . .
 
For a slave to identify whether the value of RXDEV is valid, it first of all needs to identify which incoming byte represents RXDEV.  Bear in mind that, for a RS485 system, each slave will receive the transmissions from every other slave, as well as the master.  Therefore, the value of RXDEV itself must be unique, and must never appear elsewhere within any data packet.  Alternatively, the value of RXDEV must be preceeded by a single character, or sequence of characters, that will identify the start of a packet, and again this must not appear elswhere within a packet.
 
If the data within a packet consists of binary data that may have any value, one approach is for the SCI to use 9-bit data mode.  The start of a packet, and the value of RXDEV, can then be identified by the 9th bit being set for this character, and clear for all other characters.
 
If the data can be restricted to ASCII characters (7-bit), the normal 8-bit data mode could be used, and RXDEV identified with the eighth bit set.
 
If the data is further restricted to printable ASCII characters, it should be possible to use a control character to represent the start of a packet.  Of course, the checksum byte value would also need to be represented by two ASCII characters (non-control).
 
Another related issue, is to identify when the end of a packet is reached, especially if the length of a packet may vary.  One choice would be to allocate a byte, perhaps immediately following RXDEV, to represent the length of the packet.  Alternatively, a control character to represent the end of the packet might be used.  The checksum byte(s) could follow this character.
 
When the master receives a response from the slave, and a checksum error is detected, in many cases the master should request that the slave resend its previous packet.  One method I have used is for the master to respond to the received packet by sending an ACK control character if OK, and a NAK character if a resend is required.
 
Regards,
Mac
 
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
Mac's comments have now prompted me to ask you:
Are you making up this protocol yourself or are you following some pre-defined protocol?
I had thought you were following an already defined one and is why I have been asking rather than suggesting/telling.
This was actually reinforced by Mac's comment that it was for some kind of sercurity/entry system although I am not sure how he came to that conclusion. (I presumed he recognised the byte sequence?)
 
Of course if you are making this protocol up for yourself then further consideration taking Mac's comments in would be advised. One point I would like to add is that not all ASCII protocols send the checksum as ASCII. Simple XOR types often send it as binary or like you have done earlier simply lop off the MSB.
 


Message Edited by peg on 2007-07-16 09:09 AM
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Thanks Peg & Mac,
I'm actually experimenting some audio control system adopting the distributed architecture of an security system. I'd say I'm seeking your advise to find out how to produce an efficient protocol.
 
I'll explain further my thoughts for the protocol I'm using currently.
Where there is an chksum error,
 
1. from master to slave
- slave will ignore & wait to be poll again
- when an command is received from master to slave, slave will reply with an ack command with its slave address in it.
 
2. from slave to master
-master will resend msg again up to 3 times b4 concluding the particular slave failed & will indicate error to user.
 
basically the slave only listen & respond to master.
This is not a critical system, so I wanted to make the protocol a simple one.
Yes i did notice about the ASCII part that's why I mask off  the MSB.
The RXDEV is unique & different master will have a different RXDEV. They are read from the dip-switch setting on the master.
Adding the length bytes is brilliant, I will add that portion in & will also be looking into both comments given by both of you & try to implement them & post it up for your comments.
 
Thank you very much.
 
 
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
I think you would be best to adopt a fixed header character, say ASCII <STX>.
Then you need either of the following:
1. fixed length messages, shorter ones are padded, like leading zeroes
2. a termination character, say ASCII <ETX>
3. a length byte, probably straight behind the header.
 
This not only improves the robustness of the protocol, but makes it easier to implement.
If the messages are very short fixed length can be best/more efficient.
 
Doing this also speeds recovery from a dropped or garbled byte. Generally without proper framing like this the following good message will be lost as well as it will be needed to re-sync. Having a header means every message re-syncs the comms.
 
There are so many ways to do this that you will get a different answer from all you ask. However I believe this is the minimum for a simple protocol.
 
header, address, command, data, checksum, terminator.
or
header, length, address, command, data, checksum.
 
Is this system single master?
If single will it have an address like a slave, say 0, or will the format be different for master messages.
This affects how the response is structured, but possibly:
 
header, master address, slave address, <ACK> or data, checksum, terminator
or
header, master address, slave address, length, <ACK> or data, checksum
 
your RXDEV could be added in front of the ack/data
 
Multi-master has many other issues not addressed here.
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi guys,
I'm back. I wasn't in town for a little while.
I've also figured out to change the protocol a bit.
I will add a #$FA at the end of the packet to identify as end of packet which it will not be used anywhere else.
In front of the packet will be #DEVICE.
 
 
Code:
isrVsci2rx:        pshh        jsr     rx485        psha        lda     RXPTR        bne     rxirq0        pula        cmp     #DEVICE        beq     rxirq1        jmp     rxirqz     rxirq0  pularxirq1  ldhx    #RXBUF        ldx     RXPTR              sta     ,X        incx        stx     RXPTR         cmp     #$FA         beq     rxirq1a    ;to routine to process the data received        jmp     rxirqz1    ;exit irq

Once i see #DEVICE next i will check for #$FA while having RXPTR as counter to count the length of the packet.
I will be storing the packet's data into RXBUF.
 
I tried it & it works.
Any comment?
Thanks.
 
p/s: some off the topic question, I'm planning to buy a new laptop. Previously I found that PEmicro developement tools doesnt have drivers for Vista & also codewarrior. Is it safe for me to get a vista laptop? any comments or experience to share? Thanks.
 
Regards,
mingyee

 


Message Edited by mingyee on 2007-07-26 06:41 AM
0 Kudos
Reply

1,699 Views
peg
Senior Contributor IV
Hi mingyee,
 
I offer the following comments about your posted code:
 
at rxirq1, you have:
 
ldhx #RXBUF
ldx RXPTR
sta ,X
 
I think you should have:
 
clrh
ldx RXPTR
sta RXBUF,X
 
as unless RXBUF is located at $xx00 your won't work.
 
Also you have no protection for missing the "end of string" byte. As you are only looking for the header at the beginning, if you miss the EOS you will get all of the next string tacked on to the broken first one.
 
0 Kudos
Reply

1,699 Views
bigmac
Specialist III
Hello Mingyee,
 
In addition to Peg's comments, it is still unclear whether the value represented by the parameter DEVICE can also occur within the body of the packet, including the checksum.  If so, the start of the packet would be ambiguous.
 
Regards,
Mac
 
0 Kudos
Reply

1,699 Views
bigmac
Specialist III
Hello mingyee,
 
From your initial post, I might surmise that you are trying to implement a security card entry arrangement, and that you are using the RS485 link for a "master" controller to communicate with multiple card reader units, the "slaves".  Is this assumption correct?
 
If so, I am unsure whether you are trying to implement the master end, the slave end, or both ends.  The approach to data buffering, and the use of interrupts, may differ somewhat depending of whether master or slave.
 
Does the master require to "poll" each slave in order to retrieve data from the particular slave, or is some other arrangement used?  After a slave sends data to the master, does the master then require to acknowledge the correct receipt, i.e. whether or not there is a checksum error?  If an error is detected, what course of action does the slave take?
 
It is difficult to make further useful suggestions without knowledge of the type of  communications protocol required.
 
Regards,
Mac
 
0 Kudos
Reply

1,699 Views
mylim
Contributor IV
Hi Bigmac,
My application is quite similiar as u mentioned.
I believe buffering my tx reoutine is only applicable to my master to poll for slave.
Because my slave only feedback their status when everthey are polled.
Thanks.
 
regards,
mingyee
0 Kudos
Reply