Добрый день. Пишу программу на C# (WPF). Всё общение с LTR27 сделано в фоновом потоке. Настроил LTR27 на частоту измерений 4Гц (чтобы иметь точность измерений 16 бит), данные об измерениях должны приходить 4 раза в секунду. Вот укороченный вариант кода, который я использую:
private void RecieveData_LTR27()
{
while (!break_thread)
{
if (ltr27 == null || ltr27.IsOpened() != _LTRNative.LTRERROR.OK)
{
if (!OpenSlot()) return;//вероятно не установлены библиотеки для общения с LTR27
}
if (errSlot == _LTRNative.LTRERROR.OK)
{
/* установка частоты сбора АЦП (Гц). Метод сам заполняет поле делителя */
ltr27.FillAdcFreqParams(adcFreq, out adcFreq);
errSlot = ltr27.SetConfig();
}
if (errSlot == _LTRNative.LTRERROR.OK)
{
int recv_data_cnt = RECV_BLOCK_CH_SIZE * ltr27api.LTR27_CHANNELS_CNT;
uint[] rbuf = new uint[recv_data_cnt];
double[] data = null;
errSlot = ltr27.ADCStart();// запуск сбора данных
if (errSlot == _LTRNative.LTRERROR.OK)
while (!break_thread && errSlot == _LTRNative.LTRERROR.OK)
{
int rcv_cnt;//количество принятых данных
uint[] tstamp = new uint[recv_data_cnt];
/* в таймауте учитываем время выполнения самого преобразования*/
uint tout = 1200 + (uint)(1000 * RECV_BLOCK_CH_SIZE / adcFreq + 1);
/* прием необработанных слов. есть варинант с tmark и без него для удобства */
rcv_cnt = ltr27.Recv(rbuf, (uint)rbuf.Length, tstamp, tout);
if (rcv_cnt > 0)
{
uint proc_cnt = (uint)rcv_cnt;
data = new double[recv_data_cnt];
bool value_type = true;//тип данных в возвращаемом массиве. false - значения в виде АЦП, представленные как double. true - физические величины.
errSlot = ltr27.ProcessData(rbuf, data, ref proc_cnt, true, value_type);
if (errSlot == _LTRNative.LTRERROR.OK)
{
List<List<double>> channels = new List<List<double>>();//данные для четырех каналов (4 коллекции)
TimeSpan cur_time = MainTimer.TimeSpanFromStart_inUI;
for (int ch = 0; ch < 4; ch++)//считываем данные для каждого канала
{
int mezzanine_idx = ch / ltr27api.LTR27_MAZZANINE_CHANNELS_CNT;
//ltr27.Mezzanine[0] - 2 десятивольтовых канала
//ltr27.Mezzanine[1] - 2 одновольтовых канала
if (ltr27.Mezzanine[mezzanine_idx].Name != "EMPTY")
{
List<double> ListData = new List<double>();//данные для одного канала (RECV_BLOCK_CH_SIZE точек измерения)
if (data != null)
{
for (int j = 0; j < proc_cnt; j += 16) ListData.Add(data[ch + j]);
channels.Add(ListData);
}
}
}
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
{
Split_AO(channels);
});
}
}
}
}
}
}
private bool OpenSlot()
{
try { ltr27 = new ltr27api(); }//если на этом месте ошибка, то надо установить: ltrdll.exe, ltrd-setup.exe и ltrmanager_setup.exe
catch (Exception ex) {
return false;
}
errSlot = ltr27.Open(slot_Ltr27);
if (errSlot != _LTRNative.LTRERROR.OK)
{ }
else
{
/* Считываем информацию о конфигурации модуля и о мезанинах */
errSlot = ltr27.GetConfig();
if (errSlot != _LTRNative.LTRERROR.OK)
{ }
else
{
errSlot = ltr27.GetDescription(ltr27api.Descriptions.MODULE);
for (int i = 0; (i < ltr27api.LTR27_MEZZANINE_NUMBER) && (errSlot == _LTRNative.LTRERROR.OK); i++)
if (ltr27.Mezzanine[i].Name != "EMPTY")
errSlot = ltr27.GetDescription((ushort)(1 << i));
}
}
return true;
}
Проблема в том, что при циклическом считывании метод ltr27.Recv(...), как я понял, возвращает мне то, что имеется в буффере, даже если последние данные из него были считаны на предыдущей итерации. При этом время таймаута не выдерживается. Массив меток tstamp всегда содержит одни 0. Возвращаемое значение (ref) proc_cnt - всегда 16. В своей задаче мне необходимо хранить массив ранее измеренных значений с привязкой ко времени их получения. В качестве времени получения мне подойдет и системное время в Windows. Сейчас массив ранее измеренных значений у меня заполняется большим количеством дублированных данных. Как мне изменить код, чтобы добиться желаемого результата?