Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » .NET - C# Программирование АЦП

Ответить
Настройки темы
.NET - C# Программирование АЦП

Старожил


Сообщения: 230
Благодарности: 2

Профиль | Отправить PM | Цитировать


Изменения
Автор: tumanovalex
Дата: 15-05-2021
АЦП Zet 220 (USB), есть библиотека zadc.dll на C. Функций в dll много, поэтому хотел бы в одном файле разместить обращение к dll. Начал с функций ZOpen и ZClose:
Код: Выделить весь код
namespace CsZet220cons
{
  class ZetFun
  {
    [DllImport("Zadc.dll", ExactSpelling = true)]
    static extern int ZOpen(int typeDevice, int numberDSP);
 
    [DllImport("Zadc.dll", ExactSpelling = true)]
    static extern int ZClose(int typeDevice, int numberDSP);
  }
}
В другом файле хотел бы разместить программу считывания данных из АЦП. Но уже при попытке вызвать ZOpen в Main возникли проблемы: ZetFun не видится в файле программы и после точки не показываются функции dll (если описание функций разместить в классе Program, то все работает). Пробовал сделать public ZOpen и ZClose - результат тот же. Если разместить методы в одном файле с программой - все работает. Подскажите, пожалуйста, что нужно изменить в файле (классе) ZetFun c функциями dll и файле (классе) Program, чтобы можно было обращаться к функциям dll из файла (класса) Program. Проект прикрепил.

Отправлено: 11:22, 01-02-2021

 

Забанен


Сообщения: 793
Благодарности: 260

Профиль | Цитировать


Какбэ... есть такая штука, модфикаторы называется: public, protect, internal. В C# объявление класса без явных модификаторов подразумевает private класс, то есть если вы разбиваете проект на сборки, данный аспект особенно чувствителен.
Код: Выделить весь код
using System;
using System.Runtime.InteropServices;

namespace KakayaToZhopa {
  inetrnal static class ExternalCall {
     // импорты
     [DllImport("tugoybolt.dll", SetLastError = true]
     internal static extern Int32 ZhOpen(Int32 DeviceType, Int32 DSPNumber);
  }

  internal sealed class Program {
    static void Main() {
       // ... точка входа
    }
  }
}
Это сообщение посчитали полезным следующие участники:

Отправлено: 17:53, 03-02-2021 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Старожил


Сообщения: 230
Благодарности: 2

Профиль | Отправить PM | Цитировать


Спасибо за ответ. Я попробовал internal и public сразу же после того, как задал вопрос - не получилось. Оказалось, что я случайно исключил файл с функциями из DLL из компилирования. Прошу прощения за свою невнимательность.

Возникла более серьезная проблема. Есть пример программы на C++ (Test_Zadc.cpp), который я поместил в архив. Код на С++ работает, я проверял на АЦП с подключенными к первому (0) и второму (1) входам АЦП батарейками на 1.5 и 3 V. Все функции из zadc.dll работают нормально в программе на C#, ошибок не выдают. Но у меня не получается правильно перевести строки с указателями. В коде на C++ (проверку на ошибки убрал):
Код: Выделить весь код
short *pBuffer16ADC = NULL; // Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
long *pBuffer32ADC = NULL;  // Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит 
long sizeBufferADC;  // Размер буфера драйвера в словах
long pointerADC = 0; // Указатель на текущий элемент заполнения буфера драйвера (кратен 2)
long pointerADC_old = 0; // Предыдущее значение указателя на буфер драйвера
// Запрос буфера АЦП
Err = ZGetBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC, &sizeBufferADC);
pBuffer32ADC = (long*) pBuffer16ADC;
// Запрос на останов АЦП
Err = ZStopADC(typeDevice, numberDSP);
// Запрос на запуск АЦП
Err = ZStartADC(typeDevice, numberDSP);
// Цикл чтения данных АЦП
while(!kbhit())
{
    // Задержка обновления данных АЦП для отображения
    Sleep(500);
    // Запрос указателя на текущий элемент буфера
    Err = ZGetPointerADC(typeDevice, numberDSP, &pointerADC);
    // Если новые данные в буфер от АЦП не поступили, то перейти в начало цикла и подождать
    if(pointerADC == pointerADC_old)
        continue;
    // Обновление предыдущего значения указателя
    pointerADC_old = pointerADC;
    // Переход на отсчет первого включенного канала последнего кадра АЦП
    if(pointerADC - numWordsADC * numChannelsADC < 0)
        pointerADC = sizeBufferADC + pointerADC - numWordsADC * numChannelsADC;
    else 
        pointerADC = pointerADC - numWordsADC * numChannelsADC; 
    // Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для первого канала
    if(numWordsADC == 1)
        volt0 = resolutionADC0 * (pBuffer16ADC[pointerADC]) / amplifyADC0;
    else
        volt0 = resolutionADC0 * (pBuffer32ADC[pointerADC / numWordsADC]) / amplifyADC0;
    // Вывод мгновенного значения напряжения для первого канала
    printf("%+8.4f", volt0);
    // Если количество каналов устройства больше одного
    if(numChannelsADC > 1)
    {
        // Переход на следующий отсчет АЦП
        pointerADC += numWordsADC;
        // При выходе за границу буфера, осуществляется переход в начало
        if(pointerADC >= sizeBufferADC)
            pointerADC = pointerADC - sizeBufferADC;
        // Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для второго канала
        if(numWordsADC == 1)
            volt1 = resolutionADC1 * (pBuffer16ADC[pointerADC]) / amplifyADC1;
        else
            volt1 = resolutionADC1 * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC1;
        // Вывод мгновенного значения напряжения для второго канала
        printf("\t%+8.4f", volt1);
Я попытался переписать код на C#:
Код: Выделить весь код
IntPtr pBuffer16;
 int sizeBuffer;
 if (ZetFun.ZGetBufferADC(typeDevice, numberDSP, out pBuffer16, out sizeBuffer) != 0)
   ShowMes("Не удалось получить указатель на буфер АЦП!");
 IntPtr pBuffer32 = pBuffer16; //НАВЕРНОЕ, НУЖНО КАКОЕ-ТО ПРЕОБРАЗОВАНИЕ
 if (ZetFun.ZStartADC(typeDevice, numberDSP) != 0) // инициализация АЦП
   ShowMes("Не удалось запустить АЦП!");
 var watch = new Stopwatch();
 double[] volt = new double[nChan];
 int pointer; int pointer_old;
 watch.Start();
 while (true)
 {
   Thread.Sleep(500);
   if (watch.ElapsedMilliseconds >= 6000) 
     break;
   if (ZetFun.ZGetPointerADC(typeDevice, numberDSP, out pointer) != 0)
     ShowMes("Не удалось получить указатель на текущий элемент буфера!");
   if (pointer == pointer_old)
     continue;
   pointer_old = pointer;
   for (int i = 0; i < ariNumberChannel.Length; i++)
   {
     if (pointer - numWords * ariNumberChannel[i] < 0)
       pointer = sizeBuffer + pointer - numWords * ariNumberChannel[i];
     else
       pointer = pointer - numWords * ariNumberChannel[i];
     volt[i] = ardResol[i] * (pBuffer32[pointer / numWords]) / ardAmplify[i]; // ТУТ ОШИБКА
     // (pBuffer32[pointer / numWords]) подчеркнут красным, я не знаю, как правильно записать эту строку
     Console.WriteLine(volt[i]);
     pointer += numWords;
     if (pointer >= sizeBuffer)
       pointer = pointer - sizeBuffer;
   } // for
 } // while
 watch.Stop();
 // Запрос на останов АЦП
 if(ZetFun.ZStopADC(typeDevice, numberDSP) != 0)
     ShowMes("Не удалось остановить АЦП!");
 // Запрос на освобождение буфера АЦП
 if (pBuffer16 != null)
 {
     if(ZetFun.ZRemBufferADC(typeDevice, numberDSP, ref pBuffer16) != 0)
      ShowMes("Не удалось освободить буфер!");
 }
 if (ZetFun.ZClose(typeDevice, numberDSP) != 0)
   ShowMes("Ошибка ZClose!");
Помогите, пожалуйста, разобраться, как нужно переписать строки с указателями в коде на C# так, чтобы получался правильный результат измерения входного сигнала АЦП. Проект прикрепить не смог, максимальная сумма всех вложений достигнута. Подскажите, пожалуйста, как обнулить свои сложения или размещать код по URL.

Отправлено: 14:59, 04-02-2021 | #3


Забанен


Сообщения: 793
Благодарности: 260

Профиль | Цитировать


В C# указатели реализуются через unsafe code.

Отправлено: 16:34, 04-02-2021 | #4


Старожил


Сообщения: 230
Благодарности: 2

Профиль | Отправить PM | Цитировать


Это я знаю. Только никак не могу понять, как при получении указателя с помощью функции
Код: Выделить весь код
ZetFun.ZRemBufferADC(typeDevice, numberDSP, ref pBuffer16
получить из pBuffer16 указатель pBuffer32 и правильно записать формулу
Код: Выделить весь код
volt[i] = ardResol[i] * (pBuffer32[pointer / numWords]) / ardAmplify[i];
Я выделял кусок кода с помощью unsafe{...}, но возникали ошибки. Особенно мне не ясно, что значит выражение (pBuffer32[pointer / numWords]), которое похоже на указание элемента указателя и записывается как массив. В квадратных скобках получается число типа int, поделенное в моем случае на двойку.

Отправлено: 22:00, 04-02-2021 | #5



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » .NET - C# Программирование АЦП

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Звук - Выяснить параметры ЦАП и АЦП? Firm_Head Прочее железо 2 23-08-2010 21:53
Программирование andy666 Программирование и базы данных 3 24-10-2003 22:17
Программирование andy666 Программирование и базы данных 1 10-10-2003 19:52
Программирование LeXo Программирование и базы данных 10 11-10-2002 12:23




 
Переход