Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

TNT4882 bus readdressing problem

Hello all,

I've got a problem with the TNT4882 handling when getting unaddressed.

My interrupt routine works well in the following two cases:

(TNT has GPIB address 17, UNL = Unlisten, UNT = Untalk, END = End Or Identify)

1) UNT -> UNL -> LA17 -> TA0 -> "*IDN?" END ->  UNT -> UNL -> LA0 -> TA17 "TNT4882" END -> UNT -> UNL -> ...
  
2) UNT -> UNL -> LA17 -> TA0 -> "command1" END -> "command2" END -> "command3" END -> ...

But it failes in case 3, when the bus is readdressed after each write:

3) UNT -> UNL -> LA17 -> TA0 -> "command1" END -> UNT -> UNL -> LA17 -> TA0 -> "command2" -> ...
  
I found out, this problem occurs, because I start a new read after receiving a command.
But If I get the next command, I get ADSC & LA, so I also start a read (including reset FIFO).
In the meantime, the TNT already accepted new data (because it was configured to listen) and this
data is lost when I reset the FIFO.

Is there a better way for an interrupt routine to handle both cases 2 and 3?

Thanks in advance for any suggestions!

My interrupt service routine looks like this:

void tnt_isr(void)
{
    isr0 = tnt_in(R_ISR0);
    isr1 = tnt_in(R_ISR1);
    isr2 = tnt_in(R_ISR2); // to clear ADSC when SDC received
    isr3 = tnt_in(R_ISR3);
    adsr = tnt_in(R_ADSR);

    // clear buffers on request
    if (isr1 & B_DEC) {
        clearBuffers();
        tnt_out(R_CMDR, F_STOP); // Stop FIFOs
        return;
    } else if (isr1 & B_END) {
        tnt_out(R_CMDR, F_STOP); // END RX received: Stop FIFOs
    }

    // check for Talker/Listener addressing changes
    if (isr2 & B_ADSC) {

        if (adsr & B_LA) {
            tnt_mode = listen;
            startRead();
            tnt_out(R_IMR1, B_END);
            tnt_out(R_IMR3, B_TLCINT | B_NEF);

        } else if (adsr & B_TA) {
            tnt_mode = talk;
            startWrite();
            tnt_out(R_IMR1, B_ERR);
            tnt_out(R_IMR3, B_TLCINT | B_NFF);

        } else {
            tnt_mode = unaddr; // unaddressed
            tnt_out(R_CMDR, F_STOP);
            tnt_out(R_IMR2, B_ADSC);           // Interrupt on Address changes
            tnt_out(R_IMR3, B_TLCINT);
        }
    }

    if (tnt_mode == listen) {

        readFromFifo();

        // Receive complete, copy data to work buffer
        // and prepare interface for new receive
        if (isr3 & B_DONE) {

            parse_command();

            startRead();
        }
    }

    if (tnt_mode == talk) {

        writeToFifo();
    }
}

0 Kudos
Message 1 of 8
(3,658 Views)

Any ideas?

 

Thanks.

 

0 Kudos
Message 2 of 8
(3,631 Views)

Ahm,

 

Thank you for the well formatted code.  From your routine, I see that you first check ADSC to see if your addressing has changed.  This is where things go wrong.  If the SISB bit in AUXRI is not clear, reading ISR2 will not clear ADSC.  In the firmware of your instrument, read ISR2 again to verify that ADSC has cleared.  If it has not, please use the clearADSC command to clear it after you read the ISR.

 

Write 5B to AUXMR.

 

Since your controller is not readdressing during your problem test, there should be no changes in ADSC, so it should be clear.  That is why I suspect that you are not actually clearing that bit in your routine.

 

I hope this helps,

Steven T.

0 Kudos
Message 3 of 8
(3,625 Views)

Steven,

 

thanks for your reply.

 

I just checked, that ADSC bit in ISR2 is cleared after reading ISR2.

 

This is what I expected since I don't use static interrupt bits (AUXRI is never written by my code, and should be zero after PON, shouldn't it?)

 

In my opinion, I should always get an ADSC interrupt, when I'm no longer Talker or Listener. Is this right?

 

If I send some messages to the TNT, this code works for 50...100 messages and then fails (which makes it hard to debug).

In case it fails, some characters at the beginning of the message are missing.

I think this is the result of resetting the FIFOs while TNT is already listening.

 

Maybe I'm thinking to complicated? Is there an example for a really *simple* listen/talk interrupt routine?

 

 Thanks in advance!

 

0 Kudos
Message 4 of 8
(3,619 Views)

Ahm,

 

This may not be the easiest source code, but it has a clearly defined Interrupt service routine and you can see how data is read. 

 

http://joule.ni.com/nidu/cds/view/p/id/223/lang/en

 

This is the only real example that we have that shows how to communicate using the TNT4882.  It was compiled using Microsoft C 2.0. 

 

I hope this helps,
Steven T.

0 Kudos
Message 5 of 8
(3,593 Views)

Hi Steven,

 

thanks for your answer.

 

I already knew the ESP-488 code, but for my controller this seems oversized.

 

For testing, I put my ISR in an empty project with an empty main loop, and it works much better.

 

So it seems, that there a race condition that fails, if the CPU cannot handle the interrupt fast enough.

 

So I will have to search further for this problem.

 

But once again the question, the principle interrupt handling in my ISR looks OK?

 

Thanks.

 

0 Kudos
Message 6 of 8
(3,580 Views)
Hello all,

I still have two problems with the TNT4882.

1)
If the controller sends UNL (unlisten) after every write,
the ISR code above fails after 40...100 commands.
In case it fails, my receive buffer is empty (seems like nothing
was read from the FIFOs).

Adding a delay of 100 µs in the ISR before "if (tnt_mode == listen)"
improved things massive, but still fails after 1000...5000 commands.
And I don't think it is right to delay in an ISR!

I can't understand why adding a delay improves the receiving behavior.

2)
If the controller doesn't re-address the TNT as listener, I have to start a new read
after a successful read (reset FIFOs, setting count registers, write GO to CMDR), right?

But when the controller readdress the TNT (UNL -> TA0 -> LA17), I have to start a new read.
But as the TNT is already configured as listener, it accept bytes before I start the read,
and it is possible that I loose these bytes when starting a new read (because of reset FIFO).

I can't figure out how to be compatible to both addressing schemes (UNL after each command vs.
no UNL between commands).

Please help as I'm stucking in these problems and every try leads to new misery.
If you need more information, please ask.

Thanks!

0 Kudos
Message 7 of 8
(3,508 Views)

Hello,

 

I just finished testing the ESP code with all of the parameters that you explained and it performs correctly in all cases.  I know that it seems a bit bulky, but it should be used as a starting point so you can start with something that works.  The code can be compiled with Microsoft C 2.0.  If you replace the OS specific portions of the code, it can be compiled with anything (but they are embedded throughout).

 

I hope this helps,

Steven T.

0 Kudos
Message 8 of 8
(3,496 Views)