Текст программы Test_DAC на Delphi 2007 |
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Math, Zadc_int;
type
TForm1 = class(TForm)
Timer1: TTimer;
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
procedure Form1OnCreate(Sender: TObject);
procedure Form1OnCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure OpenDevice;
procedure CloseDevice;
procedure ProcessDevice;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
MAX_TYPE_DSP = 30; // Максимальное поддерживаемое кол-во типов устройств
var
// Глобальные переменные
typeDevice: Longint; // Тип устройства
numberDSP: Longint; // Порядковый номер устройства
deviceOpened: Boolean = False; // Устройство открыто
deviceError: Boolean = False; // Ошибка устройства
deviceStarted: Boolean = False; // Устройство проинициализировано и запущено
numChannelsDAC: Longint; // Кол-во включенных каналов ЦАП
numWordsDAC: Longint; // Кол-во слов (по два байта) в одном отсчете ЦАП
pBufferDAC: Pointer; // Указатель на начало буфера драйвера
pBuffer16DAC: ^Smallint; // Указатель на начало буфера драйвера для ЦАП с разрядностью не более 16 бит
pBuffer32DAC: ^Longint; // Указатель на начало буфера драйвера для ЦАП с разрядностью более 16 бит
sizeBufferDAC: Longint; // Размер буфера драйвера в словах
sizeInterruptBufferDAC: Longint; // Размер буфера прерывания в словах
sizePacketDAC: Longint; // Кол-во отсчетов обрабатываемых за один раз
sleepTime: Longint; // Время ожидания в цикле (мс)
responseTime: Longint; // Время реакции в цикле (мс). Должно быть больше времени ожидания
pointerDriverDAC: Longint; // Указатель драйвера на текущий элемент заполнения буфера драйвера
pointerDriverDAC_old: Longint; // Предыдущее значение указателя драйвера на буфер драйвера
pointerCycleDAC: Longint; // Указатель цикла обработки на текущий элемент заполнения буфера драйвера
freqDAC: Double; // Частота дискретизации ЦАП
attenDAC0: Double; // Коэф. затухания по первому каналу ЦАП
resolutionDAC: Double; // Вес младшего разряда ЦАП
currentSinusTime: Double; // Аргумент функции синус
deltaSinusTime: Double; // Значение инкремента аргумента функции синус
amplitudeSin: Double; // Коэф. преобразования амплитуды синуса
freqSin: Double; // Частота синуса (Гц)
volt0: Double; // Мгновенное текущее значение, записываемое в ЦАП
volt0_int: Longint; // Мгновенное текущее значение, записываемое в ЦАП (код)
procedure TForm1.Form1OnCreate(Sender: TObject);
begin
//MessageDlg('OnCreate!', mtInformation, [mbOK], 0);
OpenDevice();
end;
procedure TForm1.Form1OnCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
// MessageDlg('OnCloseQuery!', mtInformation, [mbOK], 0);
CloseDevice();
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if deviceError <> FALSE then
begin
Form1.Close();
end
else
begin
ProcessDevice();
end;
end;
procedure TForm1.OpenDevice();
var
Err: Longint; // Код ошибки
enable: Longint; // Поддерживается / не поддерживается
i, size: Longint; // Счетчик цикла
begin
sleepTime := 50; // Время ожидания в цикле генерации синуса (мс)
responseTime := 250; // Время опережения (время реакции) (мс)
amplitudeSin := 0.1; // Амплитуда синуса 100 мВ (СКЗ = 70.71 мВ)
freqSin := 10; // Частота синуса 10 Гц
attenDAC0 := 0.1; // Значение аттенюатора зададим 0.1 (для лучшего соотношения сигнал/шум)
numberDSP := 0; // Здесь задан первый порядковый номер устройства
deviceOpened := FALSE;
deviceError := FALSE;
deviceStarted := FALSE;
pBufferDAC := nil;
pBuffer16DAC := nil;
pBuffer32DAC := nil;
pointerDriverDAC := 0;
pointerDriverDAC_old := 0;
pointerCycleDAC := 0;
// Цикл подключения к первому поддерживаемому устройству
for i := 0 to MAX_TYPE_DSP - 1 do
begin
// подключиться к драйверу (обязательно)
Err := ZOpen(i, numberDSP);
if Err = 0 then
begin
// Проверить поддерживается ли АЦП
Err := ZGetEnableADC(i, numberDSP, enable);
if (Err = 0) and (enable <> 0) then
break
else
ZClose(i, numberDSP);
end;
end;
typeDevice := i;
if typeDevice >= MAX_TYPE_DSP then
begin
MessageDlg('Поддерживаемое устройство не найдено!',
mtInformation, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
deviceOpened := TRUE;
// включить первый канал ЦАП
Err := ZSetOutputDAC(typeDevice, numberDSP, 0, 1);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZSetOutputDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// опросить кол-во включенных каналов ЦАП
// Если включено каналов больше одного, то пример правильно работать не будет
// (синус будет выдаваться на все каналы, причем его реальная частота разделится
// на кол-во включенных каналов)
Err := ZGetNumberOutputDAC(typeDevice, numberDSP, &numChannelsDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZGetNumberOutputDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// опросить вес младшего разряда ЦАП
Err := ZGetDigitalResolChanDAC(typeDevice, numberDSP, 0, resolutionDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZGetDigitalResolChanDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// опросить кол-во слов в одном отсчете ЦАП
Err := ZGetWordsDAC(typeDevice, numberDSP, numWordsDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZGetWordsDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// опросить частоту дискретизации ЦАП
Err := ZGetFreqDAC(typeDevice, numberDSP, freqDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZGetFreqDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// опросить размер буфера прерывания ЦАП
Err := ZGetInterruptDAC(typeDevice, numberDSP, sizeInterruptBufferDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZGetInterruptDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// Установить (опросить) коэф. затухания аттенюатора по первому каналу ЦАП
Err := ZSetAttenDAC(typeDevice, numberDSP, 0, attenDAC0, attenDAC0);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZSetAttenDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// Проверка переменных, чтобы избежать деления на 0
if (numWordsDAC < 1) or (numWordsDAC > 2) or (freqDAC < 1) or
(attenDAC0 = 0) or (resolutionDAC = 0) then
begin
MessageDlg('Ошибочные значения параметров ЦАП!',
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
// Запросить буфер ЦАП
Err := ZGetBufferDAC(typeDevice, numberDSP, pBufferDAC, sizeBufferDAC);
if Err <> 0 then
begin
MessageDlg('Ошибка в ZSetOutputDAC(), Error = ' + IntToHex(Err, 2),
mtError, [mbOK], 0);
deviceError := TRUE;
Exit;
end;
pBuffer16DAC := pBufferDAC;
pBuffer32DAC := pBufferDAC;
// Вычислим размер пакета согласно заданному времени реакции (опережения)
sizePacketDAC := Round(freqDAC * responseTime / 1000.0);
sizePacketDAC := numWordsDAC*sizePacketDAC;
// Размер пакета должен быть не меньше двух размеров буфера прерывания и не больше половины буфера драйвера
if sizePacketDAC < 2*sizeInterruptBufferDAC then
sizePacketDAC := 2*sizeInterruptBufferDAC;
if sizePacketDAC > sizeBufferDAC div 2 then
sizePacketDAC := sizeBufferDAC div 2;
// Рассчитаем параметры для генерации синуса
amplitudeSin := amplitudeSin / (resolutionDAC * attenDAC0);
deltaSinusTime := 2.0 * (4.0 * ArcTan2(1.0, 1.0)) * freqSin / freqDAC; // Число Пи = 4.*atan(1.)
currentSinusTime := 0.0;
// Запись в буфер драйвера первых двух пакетов
size := 2*(sizePacketDAC div numWordsDAC);
if numWordsDAC = 1 then
begin
pBuffer16DAC := pBufferDAC;
for i := 0 to size - 1 do
begin
volt0 := amplitudeSin * sin(currentSinusTime);
volt0_int := Round(volt0);
CopyMemory(pBuffer16DAC, @volt0_int, 2);
Inc(pBuffer16DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end
else
begin
pBuffer32DAC := pBufferDAC;
for i := 0 to size - 1 do
begin
volt0 := amplitudeSin * sin(currentSinusTime);
volt0_int := Round(volt0);
CopyMemory(pBuffer32DAC, @volt0_int, 4);
Inc(pBuffer32DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end;
pointerCycleDAC := 2*sizePacketDAC;
ZStopDAC(typeDevice, numberDSP); // Останов ЦАП
ZStopADC(typeDevice, numberDSP); // Останов АЦП
ZStartDAC(typeDevice, numberDSP); // Запуск ЦАП
ZStartADC(typeDevice, numberDSP); // Запуск АЦП
// Задать время ожидания таймера
Form1.Timer1.Interval := sleepTime;
deviceStarted := TRUE;
end;
procedure TForm1.CloseDevice();
begin
deviceStarted := FALSE;
if deviceOpened = FALSE then
Exit;
// Останов ЦАП
ZStopDAC(typeDevice, numberDSP);
// Останов АЦП
ZStopADC(typeDevice, numberDSP);
// Освободить буфер ЦАП
if pBufferDAC <> nil then
ZRemBufferDAC(typeDevice, numberDSP, pBufferDAC);
// Отключиться от драйвера (обязательно)
ZClose(typeDevice, numberDSP);
pBufferDAC := nil;
end;
procedure TForm1.ProcessDevice();
var
Err: Longint; // Код ошибки
i, size: Longint; // Счетчик цикла
begin
// Если устройство еще не стартовали и переменные не проинициализированны, то выйти
if deviceStarted = FALSE then
Exit;
Err := ZGetPointerDAC(typeDevice, numberDSP, pointerDriverDAC);
if Err <> 0 then
begin
deviceError := TRUE;
Exit;
end;
// Отобразить указатель цикла обработки на текущий элемент заполнения буфера драйвера
Form1.Edit1.Text := IntToStr(pointerCycleDAC);
// Отобразить указатель драйвера на текущий элемент заполнения буфера драйвера
Form1.Edit2.Text := IntToStr(pointerDriverDAC);
// Если опережение записи данных больше чем на один пакет, то перейти в начало цикла и подождать
if (pointerCycleDAC - pointerDriverDAC) > sizePacketDAC then
Exit;
if (pointerDriverDAC > pointerCycleDAC) and
(sizeBufferDAC - pointerDriverDAC + pointerCycleDAC > sizePacketDAC) then
Exit;
// Обновить предыдущее значение указателя драйвера
pointerDriverDAC_old := pointerDriverDAC;
// Запись в буфер драйвера очередного пакета данных
size := sizePacketDAC;
// Если пакет выходит за границы буфера драйвера, то его нужно разделить на две части
if (pointerCycleDAC + sizePacketDAC) > sizeBufferDAC then
size := sizeBufferDAC - pointerCycleDAC;
size := size div numWordsDAC;
if numWordsDAC = 1 then
begin
pBuffer16DAC := pBufferDAC;
Inc(pBuffer16DAC, pointerCycleDAC);
for i := 0 to size - 1 do
begin
volt0 := amplitudeSin * sin(currentSinusTime);
volt0_int := Round(volt0);
CopyMemory(pBuffer16DAC, @volt0_int, 2);
Inc(pBuffer16DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end
else
begin
pBuffer32DAC := pBufferDAC;
Inc(pBuffer32DAC, (pointerCycleDAC div numWordsDAC));
for i := 0 to size - 1 do
begin
volt0 := amplitudeSin * sin(currentSinusTime);
volt0_int := Round(volt0);
CopyMemory(pBuffer32DAC, @volt0_int, 4);
Inc(pBuffer32DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end;
// Передвинуть указатель на отсчет для следующей записи
pointerCycleDAC := pointerCycleDAC + numWordsDAC * size;
// Если подошли к концу буфера, то перейти в начало
if pointerCycleDAC >= sizeBufferDAC then
pointerCycleDAC := 0;
if size < (sizePacketDAC div numWordsDAC) then
begin
// Запись в буфер драйвера второй части пакета данных, если пакет пришлось разорвать
size := (sizePacketDAC div numWordsDAC) - size;
if numWordsDAC = 1 then
begin
pBuffer16DAC := pBufferDAC;
Inc(pBuffer16DAC, pointerCycleDAC);
for i := 0 to size - 1 do
begin
volt0 := amplitudeSin * sin(currentSinusTime);
volt0_int := Round(volt0);
CopyMemory(pBuffer16DAC, @volt0_int, 2);
Inc(pBuffer16DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end
else
begin
pBuffer32DAC := pBufferDAC;
Inc(pBuffer32DAC, (pointerCycleDAC div numWordsDAC));
for i := 0 to size -1 do
begin
volt0 := Round(amplitudeSin * sin(currentSinusTime));
volt0_int := Round(volt0);
CopyMemory(pBuffer32DAC, @volt0_int, 4);
Inc(pBuffer32DAC);
currentSinusTime := currentSinusTime + deltaSinusTime;
end;
end;
// Передвинуть указатель на отсчет для следующей записи
pointerCycleDAC := pointerCycleDAC + numWordsDAC * size;
end;
end;
end.
В любой части настоящего сайта могут иметься неточности и технические ошибки. В содержание могут периодически вноситься изменения и/или поправки.
Россия, Москва, Зеленоград, проезд 4922 (Озерная аллея), дом 4 стр. 5. Схема проезда.
Тел./Факс: +7(495)739-39-19 (многоканальный); E-mail: info@zetlab.ru, sale@zetlab.ru.
GPS координаты: долгота 37°13′14.57″E (37.220713) широта 55°59′1.3″N (55.983695)
|