таймер за nS
19 отговора
0 прегледа
таймер за nS
Възможно ли е да се реализира таймер примерно за 20 наносекунди.
Предварително благодаря
Предварително благодаря
Re: таймер за nS
Таймер в смисъла, който според мен влагаш в питането си - не. Имай предвид, че все пак програмата ти работи в една много задачна среда, процесорът не е само твой и твоят код от периодично спира да се изпълнява, за да може да се изпълнява друг код през това време. Тези периоди, през които твоят код не се изпълнява определено са по-продължителни от наносекунди, така че ще пропускаш тикове на един такъв хипотетичен таймер. И изобщо замисли се над това какво точно искаш да постигнеш, защото нещо не е в ред щом търсиш такъв таймер
Иначе можеш да засичаш времена от такъв порядък използвайки функциите QueryPerformanceCounter и QueryPerformanceFrequency (ако това ти върши работа...)
Linux isn't free, it's worthless.
Иначе можеш да засичаш времена от такъв порядък използвайки функциите QueryPerformanceCounter и QueryPerformanceFrequency (ако това ти върши работа...)
Linux isn't free, it's worthless.
Re: таймер за nS
Задачата е следната, имам АЦП което е 12 битово с 25милиона замера за секунда и тези данни трябва да влязат в компютъра.
Започнах да работя с RS232 но трябва да използвам много голяма памет за буфер. За съжаление с USB нямам никакъв опит макар че хардуерно мога да го синтезирам. Та сега ми се ще да пробвам да вкарам данните през LPT. Но и там излизат ред питанки -
-как да синхронизирам замерите към време
- възможно ли да се използва DMA
имам някакави стари спомени как порта ставаше двупосочен ECP EPP , но при опит да подам напрежение на данните порта ги чете но консумацията е огромна 60 mA, а контролните и входните битове са само 9
та се балтая и не знам от къде да почна
Търсих тръпка но определено се нахендрих.
Започнах да работя с RS232 но трябва да използвам много голяма памет за буфер. За съжаление с USB нямам никакъв опит макар че хардуерно мога да го синтезирам. Та сега ми се ще да пробвам да вкарам данните през LPT. Но и там излизат ред питанки -
-как да синхронизирам замерите към време
- възможно ли да се използва DMA
имам някакави стари спомени как порта ставаше двупосочен ECP EPP , но при опит да подам напрежение на данните порта ги чете но консумацията е огромна 60 mA, а контролните и входните битове са само 9
та се балтая и не знам от къде да почна
Търсих тръпка но определено се нахендрих.
Re: таймер за nS
Нямам голяма практика с такъв тип хардуер. Обаче като гледам с каква скорост ти пристигат данните - най-добре е да се ползва USB интерфейса, и то в bulk режим на трансфер. И ще ти трябват големи буфери - няма как да избягаш от това
За USB най-лесно става и доста масово ползвано е с FTDI чипа (сигурно го знаеш). Има много примери из нета за ползването му от страната на PC-то, включително и на Делфи. Освен това можеш да го ползваш и като виртуален COM порт.
Ако можем да ти помогнем нещо с делфийската част - казвай. Иначе - успех
Linux isn't free, it's worthless.
За USB най-лесно става и доста масово ползвано е с FTDI чипа (сигурно го знаеш). Има много примери из нета за ползването му от страната на PC-то, включително и на Делфи. Освен това можеш да го ползваш и като виртуален COM порт.
Ако можем да ти помогнем нещо с делфийската част - казвай. Иначе - успех
Linux isn't free, it's worthless.
Re: таймер за nS
благодаря за съвета,
прегледах описавието на FTDI чиповете но ги оставям за последен вариант.
- схемотехника на чипа
- синтезиране на кода на VHDL /голям набор функции на интерфейса
- външен буфер на данните
- и отново примането в реално време
- най вече МЪРЗЕЛ ако може по лесно защо да е сложно
За сега съм се спрял на LPT защото
- директно приема 12 битови данни -тествано
- безкрайно упростява а и поефтинява периферията
- не е необходим външен буфер/или ако се наложи ще е мнго малък/
функцията QueryPerformanceCounter е чудесна и
- ми дава маркер за време така че и липсващите замери могат да се
екстраполират
- стойността коята ми връща зависи основно от машината и има много малка девиация около 100 Hz което за това измерване е пренебрежимо.
- не се влияе от приоритета на процеса и от натоварването на машината
Не бях уточнил че замерът ще бъде само 1 секунда и даните ще се записват в масив , който след това ще се обработва, така че за това време компютъра дори и да "зависне" не е проблем.
Та след цялата хвалба ще дойде и мрънкането
не знам как QueryPerformanceCounter да ми инициира събитие в което да прочета LPT
Черпенето ще е от мен /а се сещам в коя кръчма в Пловдив ще отидем с танциорки певачки и едни блюда 1метър/
Благодаря ти предварително
прегледах описавието на FTDI чиповете но ги оставям за последен вариант.
- схемотехника на чипа
- синтезиране на кода на VHDL /голям набор функции на интерфейса
- външен буфер на данните
- и отново примането в реално време
- най вече МЪРЗЕЛ ако може по лесно защо да е сложно
За сега съм се спрял на LPT защото
- директно приема 12 битови данни -тествано
- безкрайно упростява а и поефтинява периферията
- не е необходим външен буфер/или ако се наложи ще е мнго малък/
функцията QueryPerformanceCounter е чудесна и
- ми дава маркер за време така че и липсващите замери могат да се
екстраполират
- стойността коята ми връща зависи основно от машината и има много малка девиация около 100 Hz което за това измерване е пренебрежимо.
- не се влияе от приоритета на процеса и от натоварването на машината
Не бях уточнил че замерът ще бъде само 1 секунда и даните ще се записват в масив , който след това ще се обработва, така че за това време компютъра дори и да "зависне" не е проблем.
Та след цялата хвалба ще дойде и мрънкането
не знам как QueryPerformanceCounter да ми инициира събитие в което да прочета LPT
Черпенето ще е от мен /а се сещам в коя кръчма в Пловдив ще отидем с танциорки певачки и едни блюда 1метър/
Благодаря ти предварително
Re: таймер за nS
Няма как " QueryPerformanceCounter да ти инициира събитие". Ако мога да направя следната аналогия - това е чаовник, а не будилник. Ти го питаш кажи ми колко е часа, а не му казваш събуди ме в 8:10.
Не виждам друг начин да го направиш през паралелния порт, освен да се въртиш в цикъл и да четеш постоянно данните от него, но няма да можеш да гарантираш непрекъснатостта на това четене. Трябва ти хардуер, който да буферира получените данни, докато твоята програма не е активна (т.е. COM или USB).
Linux isn't free, it's worthless.
Не виждам друг начин да го направиш през паралелния порт, освен да се въртиш в цикъл и да четеш постоянно данните от него, но няма да можеш да гарантираш непрекъснатостта на това четене. Трябва ти хардуер, който да буферира получените данни, докато твоята програма не е активна (т.е. COM или USB).
Linux isn't free, it's worthless.
Re: таймер за nS
прав си
пробвах го в цикъл, но пропуските на приетите даннни са огромни.
Явно ще се върна към матрицата, там ацп,rs са готови трябва само да буферирам данните
RS от матрицата ми е на 115200 и работи добре, евентуално мога да го променя на 256000bps
не ми ясно дали как ще го обслужа в PS До сега го бях направил тъпичко-в един таймер 50 мс чета порта
пробвах го в цикъл, но пропуските на приетите даннни са огромни.
Явно ще се върна към матрицата, там ацп,rs са готови трябва само да буферирам данните
RS от матрицата ми е на 115200 и работи добре, евентуално мога да го променя на 256000bps
не ми ясно дали как ще го обслужа в PS До сега го бях направил тъпичко-в един таймер 50 мс чета порта
Остави COM порта да те вика
Ами остави COM порта да си те вика, когато има данни. Ако работиш директно с CreateFile използвай overlapped I/O. Ако ползваш някакъв компонент за четене от порта, то той трябва да си има събитие OnReadData или нещо подобно. Така няма да изпускаш данни предадени на порта.
Linux isn't free, it's worthless.
Linux isn't free, it's worthless.
Re: Остави COM порта да те вика
Cid := CreateFile(ComTemp,GENERIC_WRITE OR GENERIC_READ,0,nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
чета го с
ReadFile(Cid,Input,2,Result,@Overlapped)
чета го с
ReadFile(Cid,Input,2,Result,@Overlapped)
Re: Остави COM порта да те вика
В такъв случай можеш да си изчакаш резултата от четенето с GetOverlappedResult или с някоя от wait функциите или да използваш ReadFileEx, която приема параметър callback, който да ти бъде викнат директно след приключване на четенето.
Linux isn't free, it's worthless.
Linux isn't free, it's worthless.
беше лесно да се каже
НЯМА ДА СЕ СПРАВЯ.
помогни
0886608575
помогни
0886608575
Редактирано от svetlin на
Re: беше лесно да се каже
Ето ти един пример, как да стане:
[линк]
В твоя случай, когато трябва да четеш всъщност трябва да викнеш Read_ComPort_UIButtonClick, както и да си вдигнеш таймаутите на нещо повече от секунда (например 2 секунди).
Linux isn't free, it's worthless.
[линк]
В твоя случай, когато трябва да четеш всъщност трябва да викнеш Read_ComPort_UIButtonClick, както и да си вдигнеш таймаутите на нещо повече от секунда (например 2 секунди).
Linux isn't free, it's worthless.
Re: беше лесно да се каже
нещо такова ли трябва да стане
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, shellapi, Spin;
type
TForm1 = class(TForm)
Label1: TLabel;
Read_ComPort_UIButton: TButton;
ReadToString_UIButton: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Read_ComPort_UIButtonClick(Sender: TObject);
procedure ReadToString_UIButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var //hCommFile : THandle; // Global variable set elsewhere
Form1: TForm1;
TimeoutBuffer: PCOMMTIMEOUTS;
hCommFile: Integer;
ComTemp : PChar;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
GetMem(TimeoutBuffer, sizeof(COMMTIMEOUTS));
GetCommTimeouts (hCommFile, TimeoutBuffer^);
TimeoutBuffer.ReadIntervalTimeout := 2000;
TimeoutBuffer.ReadTotalTimeoutMultiplier := 2000;
TimeoutBuffer.ReadTotalTimeoutConstant := 2000;
SetCommTimeouts (hCommFile, TimeoutBuffer^);
FreeMem(TimeoutBuffer, sizeof(COMMTIMEOUTS));
ComTemp := 'COM1';
// 115200
hCommFile := CreateFile(ComTemp,GENERIC_WRITE OR GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
end;
procedure TForm1.Read_ComPort_UIButtonClick(Sender: TObject);
var
InputBuffer : byte;
NumberOfBytesRead : dword;
Buffer : array[0..255] of byte;
i: Integer;
begin
if hCommFile=INVALID_HANDLE_VALUE then exit;
if ReadFile(hCommFile, Buffer, sizeof(Buffer),
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
InputBuffer := 0;
for i := 0 to NumberOfBytesRead - 1 do
begin
InputBuffer := InputBuffer + Buffer;
memo1.Lines.Add(inttostr(i)+' '+inttostr(InputBuffer)); //label1.caption := inttostr(InputBuffer);
end;
end;
procedure TForm1.ReadToString_UIButtonClick(Sender: TObject);
var
InputBuffer : string;
NumberOfBytesRead : dword;
MaxBytesToRead : dword;
begin
if hCommFile=INVALID_HANDLE_VALUE then exit;
InputBuffer := '11111111111111'; // the string must be longer than
// the number of bytes you expect to read
//InputBuffer :=''; // This fails, the string must have a length
MaxBytesToRead := 14; // could use sizeof(InputBuffer) instead
if ReadFile(hCommFile, PChar(InputBuffer)^, MaxBytesToRead,
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
InputBuffer := copy(InputBuffer, 1, NumberOfBytesRead);
// label1.caption := InputBuffer;
end;
end.
0886608575
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls, shellapi, Spin;
type
TForm1 = class(TForm)
Label1: TLabel;
Read_ComPort_UIButton: TButton;
ReadToString_UIButton: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Read_ComPort_UIButtonClick(Sender: TObject);
procedure ReadToString_UIButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var //hCommFile : THandle; // Global variable set elsewhere
Form1: TForm1;
TimeoutBuffer: PCOMMTIMEOUTS;
hCommFile: Integer;
ComTemp : PChar;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
GetMem(TimeoutBuffer, sizeof(COMMTIMEOUTS));
GetCommTimeouts (hCommFile, TimeoutBuffer^);
TimeoutBuffer.ReadIntervalTimeout := 2000;
TimeoutBuffer.ReadTotalTimeoutMultiplier := 2000;
TimeoutBuffer.ReadTotalTimeoutConstant := 2000;
SetCommTimeouts (hCommFile, TimeoutBuffer^);
FreeMem(TimeoutBuffer, sizeof(COMMTIMEOUTS));
ComTemp := 'COM1';
// 115200
hCommFile := CreateFile(ComTemp,GENERIC_WRITE OR GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
end;
procedure TForm1.Read_ComPort_UIButtonClick(Sender: TObject);
var
InputBuffer : byte;
NumberOfBytesRead : dword;
Buffer : array[0..255] of byte;
i: Integer;
begin
if hCommFile=INVALID_HANDLE_VALUE then exit;
if ReadFile(hCommFile, Buffer, sizeof(Buffer),
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
InputBuffer := 0;
for i := 0 to NumberOfBytesRead - 1 do
begin
InputBuffer := InputBuffer + Buffer;
memo1.Lines.Add(inttostr(i)+' '+inttostr(InputBuffer)); //label1.caption := inttostr(InputBuffer);
end;
end;
procedure TForm1.ReadToString_UIButtonClick(Sender: TObject);
var
InputBuffer : string;
NumberOfBytesRead : dword;
MaxBytesToRead : dword;
begin
if hCommFile=INVALID_HANDLE_VALUE then exit;
InputBuffer := '11111111111111'; // the string must be longer than
// the number of bytes you expect to read
//InputBuffer :=''; // This fails, the string must have a length
MaxBytesToRead := 14; // could use sizeof(InputBuffer) instead
if ReadFile(hCommFile, PChar(InputBuffer)^, MaxBytesToRead,
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
InputBuffer := copy(InputBuffer, 1, NumberOfBytesRead);
// label1.caption := InputBuffer;
end;
end.
0886608575
Горе-долу
Горе-долу, но...
Четенето от порта ще трябва да е повече от веднъж. Така четеш до 256 байта, а твоите данни би трябвало да са повече. Може да сложиш четенето в цикъл. Ти само си знаеш кога трябва да свърши той (имаш ли някакъв протокол за предаването на данните?).
Това, дето си го написал в цикъла в момента е грешно. InputBuffer ти е byte, а Buffer - масив от байтове. Не можеш да напишеш InputBuffer := InputBuffer + Buffer; Вероятно си искал InputBuffer да е голям масив от байтове, в който да натрупваш малкия Buffer? За да го направиш това можеш да ползваш например Move или да си въртиш цикъл и да си копираш байт по байт.
Втората процедура (ReadToString_UIButtonClick) не ти трябва.
Linux isn't free, it's worthless.
Четенето от порта ще трябва да е повече от веднъж. Така четеш до 256 байта, а твоите данни би трябвало да са повече. Може да сложиш четенето в цикъл. Ти само си знаеш кога трябва да свърши той (имаш ли някакъв протокол за предаването на данните?).
Това, дето си го написал в цикъла в момента е грешно. InputBuffer ти е byte, а Buffer - масив от байтове. Не можеш да напишеш InputBuffer := InputBuffer + Buffer; Вероятно си искал InputBuffer да е голям масив от байтове, в който да натрупваш малкия Buffer? За да го направиш това можеш да ползваш например Move или да си въртиш цикъл и да си копираш байт по байт.
Втората процедура (ReadToString_UIButtonClick) не ти трябва.
Linux isn't free, it's worthless.
май става
не бях го усмислил добре
ето го променения
Buffer : array[0..2000] of byte;
i: Integer;
begin
NumberOfBytesRead:=8;
if hCommFile=INVALID_HANDLE_VALUE then exit;
if ReadFile(hCommFile, Buffer, sizeof(Buffer),
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
for i := 0 to NumberOfBytesRead - 1 do
begin
memo1.Lines.Add(inttostr(i)+' '+inttostr(Buffer)); //label1.caption := inttostr(InputBuffer);
Buffer:=0;
end;
на този етап искаках само да го визуализирам после лесно ще го вкарам в масив.
матрицата ми праща 16 битово число и като измерената стойност е в младшите 8 бита съответно старшите 8 бита са 0 и MEMO1 започнаха да ми се появява 0 и измерената стойност
Протокол за приемането няма. Идеята е всяко приемане да да влиза в масив като индекса му е номера на приемането /примерно buffer/този индекс ми е и маркер за време
Не ми харесва че насила чета буфера а не ми извиква той
как може да се промени кода че да приемам 16 битово число
0886608575
ето го променения
Buffer : array[0..2000] of byte;
i: Integer;
begin
NumberOfBytesRead:=8;
if hCommFile=INVALID_HANDLE_VALUE then exit;
if ReadFile(hCommFile, Buffer, sizeof(Buffer),
NumberOfBytesRead, nil) = false then
begin
ShowMessage('Unable to read from comport');
exit;
end;
for i := 0 to NumberOfBytesRead - 1 do
begin
memo1.Lines.Add(inttostr(i)+' '+inttostr(Buffer)); //label1.caption := inttostr(InputBuffer);
Buffer:=0;
end;
на този етап искаках само да го визуализирам после лесно ще го вкарам в масив.
матрицата ми праща 16 битово число и като измерената стойност е в младшите 8 бита съответно старшите 8 бита са 0 и MEMO1 започнаха да ми се появява 0 и измерената стойност
Протокол за приемането няма. Идеята е всяко приемане да да влиза в масив като индекса му е номера на приемането /примерно buffer/този индекс ми е и маркер за време
Не ми харесва че насила чета буфера а не ми извиква той
как може да се промени кода че да приемам 16 битово число
0886608575
Редактирано от svetlin на
Re: май става
16 битовото число са две 8 битови едно след друго
За да те вика той можеш да ползваш ReadFileEx (виж последния параметър - процедура, която да бъде извикана след приключване на четенето) или да си изнесеш комуникацията в отделна нишка.
Linux isn't free, it's worthless.
За да те вика той можеш да ползваш ReadFileEx (виж последния параметър - процедура, която да бъде извикана след приключване на четенето) или да си изнесеш комуникацията в отделна нишка.
Linux isn't free, it's worthless.
Re: таймер за nS
Ако наистина ще четеш само една секунда, можеш да си сложиш REALTIME_PRIORITY_CLASS на процеса за това време със SetPriorityClass - това ти гарантира 100% процесорното време, като дори спира критичните задачи на операционната система. Но ако забравиш да върнеш нормалния приоритет или приложението ти забие, цялата система зависва - дори и мишката не можеш да мръднеш :)
Виж също и SetThreadPriority в MSDN.
Mixy
Виж също и SetThreadPriority в MSDN.
Mixy
Re: таймер за nS
и аз имах някяква подобна идея каго се борих с LPT но така и увисна
0886608575
0886608575
Re: таймер за nS
пробвах го с LPT чете без загуба на данни през 1 микро секунда
0886608575
0886608575