11-30-2015 08:19 AM
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.
11-30-2015 09:57 AM
Is this something that is custom?
NI sells hardware that does I2C and SPI.
11-30-2015 10:00 AM
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.
12-01-2015 06:09 PM
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!