Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

9914 controller Intermittantly misses first character

I have a 9914 chip configured as a controller which intermittently fails to read the first character sent to it from an talker.
 
The 9914 is configured as follows:
 
1. Primary adressing only with controller address of 0.
2. LWC and ATPT set.
3. Holdoff on each byte and End enabled.
 
The operational sequence is.
 
1. Place controller in active mode, the mode is verified as correct.
2. Send command word to untalk and unlisten.
3. Send my listen address 0, then mytalk address 1 (Fluke 8840A DMM, slow sample rate)
4. Place controller back into standby mode, and wait until correct mode indicated in Address status register.
5. Wait until BI goes high.
6. Read Data in register.
7. repeat 5 & 6 until EOI detected.
 
To verify it is not an instrument issue I constructed a read routine using a HS488 usb - GPIB interface to read the instrument at the fastest rate possible using the standard GPIB read VI in labview 8.2.  This consistenly read the correct data from the bus.
 
Using the 9914 as a pure listener I modified the setup so that I could verify the reading of data.  Using the Labview setup to send data I correctly read all data transmitted to the device therefore the code for actually reading the data is stable and correct.  The transmissin of data was looped as fast as possible by simply looping the labview executable.
 
The 9914 clock frequency is 5MHz, is there any advantage to changing this to 20MHz.
 
Are their any intrinsic delays that should be implemented during the transmission of commands and then the receipt of data on to the bus.
 
I can send data from the controller at any rate without data loss so it is only the read function.
 

Message Edited by sma on 06-02-2007 10:31 PM

Message Edited by sma on 06-02-2007 10:31 PM

0 Kudos
Message 1 of 11
(4,763 Views)
Further to above,
 
I have found that if I add a 20mS delay following the setting of MLA which causes an interrupt as a result of accepting the MLA the input data is complete.
 
This tends to indicate that either the chip or instrument requires the delay to ensure that the MLA is processed correctly.
0 Kudos
Message 2 of 11
(4,751 Views)

Hello sma,

It sounds like you've taken some steps to uncover the problem.  It sounds like using another interface to communicate with both sides made things work.  But the two pieces have intermittent problems communicating with each other, correct?

It still seems like the problem could be residing in either device.  I would normally make sure that there are no operations between releasing the hold-off and checking the BI Bit and then reading, but you are using hold-off on all.  This causes a nrfd hold-off to occur after each byte.  Is it possible that you are releasing the hold-off twice in your firmware?

Make sure that your read routine is following the suggested guidelines from the NAT9914 Reference Manual.

Steven T.

0 Kudos
Message 3 of 11
(4,736 Views)

Message Edited by Steven T on 06-04-2007 09:56 AM

0 Kudos
Message 4 of 11
(4,744 Views)
The system I am developing uses one 9914 as a pure talker listener (input channel) which receives data from a controller.  The input data is converted from CIIL to SCPI and then using a second 9914 as a controller it is sent to the insrument in question.
 
The data sent and received from by the input channel is stable and has not failed during all testing.  The problem has been traced to the controller side of things.
 
When the controller is addressed as the talker all data is transferred correctly.  The system clock was increased from 5MHz to 20MHz and the initialization sequence changed to setup the 9914 chips for the new frequency.  This enabled the delay to be reduced to 10mSec.  However I have found that the timing of any writes to the AUXCR also affect the stability of the system.  The manual states that writes to this register must be separated by atleast 4 clock cycles yet reducing the delay to approx 500nS (10cycles) results in additional instability.  Below is my initialization code and the code used to perform the read.
 
short int Init_GPIB_OUT(void)
{
 short int Result = TRUE;
 int Test = 0x0;
 // Refer to section 5 of the 9914 Manual.
 // Step 1 ignored as we assume reset has been asserted and then removed by the input channel initalization.
 Write_AUXCR(GPIB_OUT, 0x1c);
 Write_AUXCR(GPIB_OUT, 0x80);
 
 // Set Clock to 20MHz
 Write_AUXCR(GPIB_OUT, 0x99);   // Place in 7210 Mode
 Write_TAUXMR(GPIB_OUT, 0x50);  // 7210 Page In Command, offset 5
 Write_AUXCR(GPIB_OUT, 0x81);   // Set ICR2[0] high,
 Write_TAUXMR(GPIB_OUT, 0x15);  // Return to 9914 Mode
 Write_ICR(GPIB_OUT, 0x2A);     // Set Frequency to 20MHz.
 Write_ADR(GPIB_OUT, 0x00);    // Step 4.a Write logical device address to ADR.
 
 // Step 4.c Configure initial parallel response
 Write_PPR(GPIB_OUT, 0x00);  // Disable Parallel Poll

 // Step 4.b Write Serial poll response to SPMR
 Write_SPMR(GPIB_OUT, 0x00);

 // Step 4.d Set GPIB Hand Shake Parameters
    Write_ACCRI(GPIB_OUT, 0xE1);  // Cleared Ultra Short Delay, Parallel Poll response w/o software &
         // DMA disabled.
 Write_AUXCR(GPIB_OUT, 0x97); // Set very short delay on T1
 Write_AUXCR(GPIB_OUT, 0x15); // Clears Short T1 delay should not be need as this is cleared by reset
 // Configure NEWLINE character (0x0a) to end incoming and outgoing gpib messages
 Write_EOSR(GPIB_OUT, 0x0A);
 // Configure ACCRA to use EOS and XEOS
 Write_ACCRA(GPIB_OUT, 0x08 | 0x04);
 // Configure ACCRB to force device to listen to cmds originated by itself
 Write_ACCRB(GPIB_OUT, 0x05);
 // Ensure hold off is set after recieving each data bit.
 Write_AUXCR(GPIB_OUT, 0x83);
 Write_AUXCR(GPIB_OUT, 0x84);
 Write_IMR0(GPIB_OUT, 0x3F);   // Step 5 Enable all interrupts except DMAO & DMAI
//         // Disable BI and BO interrupts.
 Write_IMR1(GPIB_OUT, 0xEF);  // ISR1[4] Must be set for extended addressing
 Write_IMR2(GPIB_OUT, 0xFF);  // ISR2[0] is not required as this channel always CIC
 Write_AUXCR(GPIB_OUT, 0x00); // Clear software reset
 // Ensure it is a controller
 Write_AUXCR(GPIB_OUT, 0x8F);  // Set Send Interface Clear
 wait(1);         // IFC Must be set for a minimum of 100uS.
 Write_AUXCR(GPIB_OUT, 0x0F);  // Clear Interface Clear
 Write_AUXCR(GPIB_OUT, 0x10);  // Deassert drive Enable
 wait(1);
 Write_AUXCR(GPIB_OUT, 0x90);  // Drive Remote Enable
 Write_AUXCR(GPIB_OUT, 0x0B);  // Goto controller standby state
 // Enable Output Channel as a controller all the time
 GETDR_PORTB(Test);
 Test = Test | 0x10;  // Set Port B4 high
 SETDR_PORTB(Test);
 
// RunTests2();
 return Result;
 
}
 
0 Kudos
Message 5 of 11
(4,732 Views)

As this code could not fit with my previous response here are the read functions.

unsigned short ControllerRead(short int ToAddress)
{
// This function configures the output channel as a controller and forces the
// all instruments on the bus to stop talking and to listen using the respective
// global commands.
// The function the sends the required command word to enable the reading of the data
// from the required instrument.
    unsigned char Continue = TRUE;  
    int Count = 0;
    unsigned char ISR0_Status = 0;
    unsigned char ISR1_Status = 0;
    unsigned char BSR_Status = 0;
    int DataLength = 0;
 unsigned char Data[20];
 unsigned short Result = TRUE;
 unsigned char Bus = 0;
 
 Start_GPIB_Timer(10000);
 
 if(Read_ISR2(GPIB_OUT) & 0x01) // Controller in charge
 {
  if(!(Read_ADSR(GPIB_OUT) & 0x20)) // Standby controller
  {
   // Make it active
   Write_AUXCR(GPIB_OUT, 0x0C); // Take control Asynchronously
   while(!(Read_ISR2(GPIB_OUT)& 0x01))
   {
    if(GPIB_IN_TIMEOUT)
    {
     Result = FALSE;
     break;
    }
   }
  }  
 }
 else
 {
  LCD_prints("Not CIC"); // Print a string
  Result = FALSE;
 }

 if(Result)
 {
  if((Result = SendUnTalkUnListen()))
  {
   if(ToAddress == 0)
    sprintf(Data, "_? A"); // @!UNT, UNL, MTA 1, MLA0 the space represents the MLA0
   else
   {
   sprintf(Data, "_? A%c", ToAddress + 0x20);
   }
  }
 
  DataLength = strlen(Data);
  Continue = TRUE;
  if(DataLength > 0)
  {
   Count = 0;
   Continue = TRUE;
 
   while(!((ISR0_Status = Read_ISR0(GPIB_OUT)) & 0x10))
   {
    if(GPIB_IN_TIMEOUT);
    {
     Continue = FALSE;
     break;
    }
   }
   if(Continue == TRUE)
    Write_CDOR(GPIB_OUT, Data[Count++]); 
   while(Continue == TRUE)
   {
    if(!GPIB_IN_TIMEOUT)
    {
     if((ISR1_Status = Read_ISR1(GPIB_OUT)) & 0x40)  
     {
      Write_AUXCR(GPIB_OUT, 0x05);
      Continue = FALSE;
     }
     if(ISR1_Status & 0x04) 
     {
      Write_AUXCR(GPIB_OUT, 0x01);  
      wait(10);
     }
     
     if((ISR0_Status = Read_ISR0(GPIB_OUT)) & 0x10)  
     {
          Write_CDOR(GPIB_OUT, Data[Count++]);
      if(Count == DataLength)
      {
       Continue = FALSE;
      }
     }
    }
    else
    {
     Continue = FALSE;
    }
   }
  }
  while(!((ISR0_Status = Read_ISR0(GPIB_OUT)) & 0x10)) 
  {
   if(GPIB_IN_TIMEOUT)
    break;
  }
  // Put Controller back into standby state
  Write_AUXCR(GPIB_OUT, 0x0B);
 
  // Wait until controller is in standby
  while(((Read_ADSR(GPIB_OUT) & 0x20)) & (!GPIB_IN_TIMEOUT));
  if(GPIB_IN_TIMEOUT == FALSE)
  {
   if(!GPIB_IN_TIMEOUT)
   {
    ISR0_Status = Read_ISR0(GPIB_OUT);
     ContReadDataFromBus(GPIB_OUT, ISR0_Status);
    if(Result & !GPIB_IN_TIMEOUT)
    {
     WriteDataToBus(GPIB_IN, ciilbuffer);
    }
   }
  }
 }
 if(GPIB_IN_TIMEOUT)
 {
  LCD_prints("GPIB Timed Out");   // Print a string
  Read_ISR2(GPIB_OUT);
  Result = FALSE;
 }
 return Result;
}
 

 
void ContReadDataFromBus(short int Bus, unsigned char ISR0_Status)
{
 unsigned char* CiilPos = ciilbuffer;
 unsigned char Read = 0;
    unsigned char Continue = TRUE;  
 int Count = 0;
    unsigned char ISR1_Status = 0;
    unsigned char BSR_Status = 0;
 unsigned char BIWait = FALSE;
 Count = 0;
 Continue = TRUE;
 Start_GPIB_Timer(12000); 
 *(CiilPos) = '\0';
 if(ISR0_Status & 0x20) // BI
 {
  Read = Read_DIR(Bus);
  *(CiilPos++) = Read;
 }
 while(Continue == TRUE)
 {
  if(GPIB_IN_TIMEOUT == TRUE)
  {
   Continue = FALSE;
  }
  else
  {
   Write_AUXCR(Bus, 0x02);
   ISR0_Status = Read_ISR0(Bus); 
   if(ISR0_Status & 0x20)  // BI Interrupt occured
   {
       Read = Read_DIR(Bus);
    *(CiilPos++) = Read;
    Count++;
    if(Count > 1022)
     Continue = FALSE;
   }
   if(ISR0_Status & 0x08)  // Check for END
    Continue = FALSE;
  }
 }
 if(GPIB_IN_TIMEOUT)
 {
  LCD_prints("GPIB Timed Out");   // Print a string
  *(ciilbuffer) = 0;  // clear any data already read
  Write_AUXCR(Bus, 0x05);  //Send new byte available false to prohibit
 }
 else
 {
  Stop_GPIB_Timer();
  *(CiilPos) = '\0';
 }
}
0 Kudos
Message 6 of 11
(4,731 Views)

Hello sma,

After looking at your code, I see that the ContReadData has exactly the condition I was describing.  Your code calls ContReadData with a copy of ISR0.  If the byte has not made it into the NAT9914 yet, then BI will not be set.  This will put the first read in ContReadData as never happening.  Then when you get to the while loop, the first thing that is done is a release rfd hold-off.

I would recommend restructuring your program so that you will not need to have the initial read that may not happen resulting in the loss of the first byte.

You can also do some debug prints in your code if you have doubts that this is the problem.  Perhaps you can save some statements in a buffer so that you can see the flow of the program.

Steven T.

0 Kudos
Message 7 of 11
(4,708 Views)

I restructured my code as you suggested by removing the read before entering the read routine.  This did not resolve the problem.

It is strage however that the slower the sample rate (talk cmds) the worse the error rate is.  Running the commands at app 2.5/Sec results in an error rate of about 1.4% whislt running it with a sample rate of 15/Sec results in an error rate of 0.00217%.

The error rate is also dependant on the delay before releasing the holdoff caused by the MA which occurs when the MLA is placed on the bus.

It appears that the NRFD line may be intermittently deasserting, as the NDAC line is high during the transition from active mode to standby mode.

Do you have any code examples for the implementation of a 9914 based controller?

Message Edited by sma on 06-05-2007 08:30 PM

0 Kudos
Message 8 of 11
(4,706 Views)
Hello sma,
 
We may be talking about two different reads.  My suggestion was to delete
 
if(ISR0_Status & 0x20) // BI
 {
  Read = Read_DIR(Bus);
  *(CiilPos++) = Read;
 }
 
because if it does not execute (if BI is not set), the next line of code for the chip is a release holdoff which will cause the first byte to be overwritten before reading.  All of your reading (reading the CDOR byte) should be done in the while loop. 
 
There is example code for the TNT4882 at [link removed].  There aren't any examples written directly for the 9914, but the basic structure of the program is the same.  You should be able to trace it to see how it works.
 
I hope this helps.
 
Steven T.
0 Kudos
Message 9 of 11
(4,694 Views)
I completed what you had suggested and removed the lines prior to my last reply and hence the problem still exists, I'll take a look at the mentioned example and see if I can determine the cause by comparing my code with it.
0 Kudos
Message 10 of 11
(4,683 Views)