Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Write a "clock" signal out while reading data synchronized on the written clock.

I'm trying to implement a programming protocol for a microcontroller.  It's a 2 line hardware serial interface.  One line is the clock, the other line is data.  The PXI system plays the role of the master, and the microcontroller is the slave.  The master always generates the clock.  Each device (slave or master) reads and writes data as specified by the protocol.  I understand the protocol, but I'm struggling with getting the bit-banging right.

 

I'm working with a PXIe-6535 digital IO module mounted in slot 6 in a PXIe-1085 backplane.  

 

I have the writing portion down, but I'm struggling with reading data.  I start by creating a sequence of DigitalStates to create the clock.

 

    //Creates a list of alternating DigitalStates
private List<DigitalState> GenerateClock(int dataSampleCount) { List<DigitalState> clock = new List<DigitalState>(); for (int i = 0; i < dataSampleCount; i++) { if (i % 2 == 0) clock.Add(DigitalState.ForceDown); else clock.Add(DigitalState.ForceUp); } return clock; }

That list of DigitalStates is then used to create a DigitalWaveform...

 

    private DigitalWaveform CopyStatesIntoWaveform(List<DigitalState> writeMe)
    {
      DigitalWaveform waveform = new DigitalWaveform(writeMe.Count, 1);
      for (int i = 0; i < writeMe.Count; i++)
      {
        waveform.Signals[0].States[i] = writeMe[i];
      }
      return waveform;
    }

I'm going to need 2 tasks in order to read and write simultaneously; one for the clock out, the other for data in.  And here's where I get stuck.  I can't seem to figure out how to make the "data in task" sample on the falling edge (specified by the programming protocol) of the "clock out task".  Here's the full code for reading X numbers of bytes back.  The code's not perfect yet.  I'm just trying to get something that works...

 

clockLine is "PXI1Slot6/Port3/Line5".

dataLine is "PXI1Slot6/Port3/Line3". 

 

 

    NationalInstruments.DAQmx.Task readDataTask;
    DigitalSingleChannelReader dataReader;

    public List<byte> ReadData(int bytesToRead)
    {
      int digitalSampleCount = CalculateNumberOfSamplesNeededFromByteCount(bytesToRead);
      List<DigitalState> clockStates = GenerateClock(digitalSampleCount);
      DigitalWaveform clock = CopyStatesIntoWaveform(clockStates);

      List<byte> dataRead = new List<byte>();
      List<DigitalState> readStates = new List<DigitalState>();

      using (NationalInstruments.DAQmx.Task writeClockTask = new NationalInstruments.DAQmx.Task("Write Clock Task"))
      {
        writeClockTask.DOChannels.CreateChannel(clockLine, "Clock", ChannelLineGrouping.OneChannelForEachLine);
        writeClockTask.Timing.ConfigureSampleClock("", 20000, SampleClockActiveEdge.Rising,
          SampleQuantityMode.FiniteSamples, digitalSampleCount);

        DigitalSingleChannelWriter clockWriter = new DigitalSingleChannelWriter(writeClockTask.Stream);
        clockWriter.SynchronizeCallbacks = true;

        readDataTask = new NationalInstruments.DAQmx.Task("Read Data Task");
        readDataTask.DIChannels.CreateChannel(dataLine, "Data", ChannelLineGrouping.OneChannelForEachLine);

/******* NOTE: I'm trying to use the clockLine as the clock output as the sampling clock for the read data task ****/ readDataTask.Timing.ConfigureSampleClock(clockLine, 20000, SampleClockActiveEdge.Falling, SampleQuantityMode.FiniteSamples, digitalSampleCount); dataReader = new DigitalSingleChannelReader(readDataTask.Stream); dataReader.SynchronizeCallbacks = true; dataReader.BeginReadWaveform(digitalSampleCount, new AsyncCallback(CallBack), readDataTask); clockWriter.WriteWaveform(true, clock); writeClockTask.WaitUntilDone(); } return new List<byte>(); } private void CallBack(IAsyncResult state) { if (readDataTask != null && readDataTask == state.AsyncState) { DigitalWaveform readData = dataReader.EndReadWaveform(state); Console.WriteLine("Number of samples read: {0}", readData.Signals[0].States.Count); for (int i = 0; i < readData.Signals[0].States.Count; i++) { Console.WriteLine("State at {0}: {1}", i, readData.Signals[0].States[i].ToString()); } } readDataTask.Dispose(); }

but this codes fails with:

An exception of type 'NationalInstruments.DAQmx.DaqException' occurred in NationalInstruments.DAQmx.dll but was not handled in user code

Additional information: Specified route cannot be satisfied, because the hardware does not support it.



Property: NationalInstruments.DAQmx.Timing.SampleClockSource

Requested Value: PXI1Slot6/Port3/Line5

Suggested Values: PFI5, RTSI7, PXI_Star, PXIe_DSTARA



Task Name: Read Data Task



Status Code: -89136

 

I'm clearly missing something on PXI clock configuration.

 

How can I synchronize the write clock task and the read data task?  The read data task needs to sample the data line on the falling edge of the output clock line.

0 Kudos
Message 1 of 4
(4,421 Views)

Is this something that is custom?

 

NI sells hardware that does I2C and SPI.

0 Kudos
Message 2 of 4
(4,415 Views)

It's an SPI-like interface, but it's different enough that I need to be able to bit-bang it.  Basically, I need to implement a custom, 2 line (clock and data) communication protocol.  I have the writing part down.

 

The root problem is that I cannot seem to be able to configure the read data task to use the clock line (output) as the sampling trigger to read data in.

0 Kudos
Message 3 of 4
(4,412 Views)

Hi,

 

You could try using the Export Signal Method to route your sample clock to one of the suggested values in that error code.

 

Probably also worth checking the "Device Routes" tab in MAX for your particular card to see if it's a valid route.

 

Hope this helps!

https://www.linkedin.com/in/trentweaver
0 Kudos
Message 4 of 4
(4,383 Views)