|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » .NET - C# Программирование АЦП |
|
.NET - C# Программирование АЦП
|
Старожил Сообщения: 230 |
Профиль | Отправить PM | Цитировать
АЦП Zet 220 (USB), есть библиотека zadc.dll на C. Функций в dll много, поэтому хотел бы в одном файле разместить обращение к dll. Начал с функций ZOpen и ZClose:
В другом файле хотел бы разместить программу считывания данных из АЦП. Но уже при попытке вызвать ZOpen в Main возникли проблемы: ZetFun не видится в файле программы и после точки не показываются функции dll (если описание функций разместить в классе Program, то все работает). Пробовал сделать public ZOpen и ZClose - результат тот же. Если разместить методы в одном файле с программой - все работает. Подскажите, пожалуйста, что нужно изменить в файле (классе) ZetFun c функциями dll и файле (классе) Program, чтобы можно было обращаться к функциям dll из файла (класса) Program. Проект прикрепил.
|
|
Отправлено: 11:22, 01-02-2021 |
Забанен Сообщения: 793
|
Какбэ... есть такая штука, модфикаторы называется: 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
|
Профиль | Отправить 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); 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!"); |
Отправлено: 14:59, 04-02-2021 | #3 |
Забанен Сообщения: 793
|
В C# указатели реализуются через unsafe code.
|
Отправлено: 16:34, 04-02-2021 | #4 |
Старожил Сообщения: 230
|
Профиль | Отправить PM | Цитировать Это я знаю. Только никак не могу понять, как при получении указателя с помощью функции
получить из pBuffer16 указатель pBuffer32 и правильно записать формулу
Я выделял кусок кода с помощью unsafe{...}, но возникали ошибки. Особенно мне не ясно, что значит выражение (pBuffer32[pointer / numWords]), которое похоже на указание элемента указателя и записывается как массив. В квадратных скобках получается число типа int, поделенное в моем случае на двойку.
|
|
Отправлено: 22:00, 04-02-2021 | #5 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Звук - Выяснить параметры ЦАП и АЦП? | 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 |
|