Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В подавляющем большинстве случаев для создания даже таких относительно «навороченных» программ, как СОМ2000, можно обойтись стандартным Турбо Паскалем под DOS. Это было бы целесообразно, однако пользование DOS-программами на современном ПК крайне неудобно и порождает множество проблем совместимости (не говоря уж о многозадачности — конечно, работать в режиме немедленной проверки в DOS далеко не так удобно, как в Windows). Потому мы остановимся на Delphi, как одном из самых популярных в нашей стране средств быстрого создания приложений (RAD, Rapid Application Development). Можно использовать и Visual Basic (в некоторых отношениях это даже более удобно, т. к. в силу происхождения он лучше интегрирован с Windows), однако мой личный опыт общения с этим продуктом отрицательный — значительную часть времени приходится тратить на то, чтобы бороться с внутренними проблемами самого VB. Язык Delphi (Object Pascal) проще и понятнее новичку. Для тех, кто привык к С, можно рекомендовать Borland C++ Builder — это почти то же самое, что и Delphi, даже с общей библиотекой компонентов, только язык другой.
Мы будем ориентироваться на Delphi 7 — последнюю версию для Win32. Программы работают без оговорок во всех версиях Windows (начиная с 98-й). Насколько программы для этой платформы работоспособны в Vista — на момент написания этих строк мне еще не удалось проверить, но, по слухам, все более-менее в порядке (правда, установление этого порядка все требует некоторых «плясок с бубном»), а на крайний случай там имеется режим совместимости с более ранними версиями, который работает, говорят, лучше, чем в Windows ХР. Потому, надеюсь, с изучением платформы. NET можно повременить.
В дальнейшем я буду предполагать, что читатель имеет некоторые навыки работы в Delphi, поскольку рассмотрение данного вопроса выходит за рамки этой книги. Остальным я рекомендую обратиться к [15] и [16], а также к моей книге [11].
Работа через функции Win32 API
Собственно передача и прием данных через COM-порт неоднократно описаны во множестве публикаций и теоретически в них ничего сложного нет. На практике, однако, могут возникнуть проблемы различного уровня сложности, особенно касающиеся непрерывного приема данных в реальном времени. Далее я описываю только проверенные способы работы (многие публикации в Интернете содержат ошибки, и к тому же не описывают ситуацию полностью).
Начнем мы с самого главного — с отдельной процедуры инициализации порта, которую назовем iniCOM. COM-порт представляется с точки зрения системы в виде файла, потому его сначала нужно открыть («создать файл»). Но этого недостаточно — необходимо проверить его работоспособность, и факт, не является ли запрошенный COM-порт модемом.
Объявим следующие переменные:
var
Form1:TForm1;
hCOM:hFile=0;
pDCB:TDCB;
comt ime:TCOMMTIMEOUTS;
xb:byte;
xn:dword;
ab:array[1..32768] of byte;
st,stcom:string;
ttime,told:TDateTime;
…
Размер буфера ab может быть произвольным в зависимости от количества ожидаемых данных (в данном случае он подогнан для чтения данных из используемой нами внешней flash-памяти). К началу выполнения процедуры iniCOMу нас в строке stcomдолжно содержаться название порта, например, «СОМ1». Задаваемые параметры: прием по схеме 8n1, скорость 9600. Текст процедуры приведен в листинге 18.1.
Листинг 18.1
procedure IniCOM;
var i:integer;
begin
{инициализация СОМ — номер в строке stcom}
hCOM:=CreateFile(Pchar(stcom),
GENERIC_READ+GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);
if (hCom = INVALID_HANDLE_VALUE) then
begin
st:=stcom+'не найден';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end ;
if GetCommState(hCOM,pDCB)
then st:=stcom+': baud=9600 parity=N data=8 stop=l';
if BuildCommDCB(Pchar(st), pDCB) the n SetCommState(hCOM,pDCB)
else
begin
st:=stcom+' занят или заданы неверные параметры';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end ;
GetCommTimeouts(hCom,comtime); {устанавливаем задержки:}
comtime.WriteTotalTimeoutMultiplier:=1;
comtime.WriteTotalTimeoutConstant:=10;
comtime.ReadlntervalTimeout:=10;
comtime.ReadTotalTimeoutMultiplier:=1;
comtime.ReadTotalTimeoutConstant:=2 000; {ждем чтения 2 с}
SetCommTimeouts(hCom,comtime);
ab[1]:=ord('A');{будем посылать инициализацию модема}
ab[2]:=ord('T');
ab[3]:=13 ;{CR}
ab[4]:=10 ;{LF}
WriteFile(hCOM,ab,4,xn,nil);
if ReadFile(hCOM,ab,10,xn,nil) then {ответ модема 10 знаков}
begin
st:=»;
for i:=1 to 10 do st:=st+chr(ab[i]);
if pos('OK',st)<>0 then
begin
st:=stcom+' занят модемом';
Application.MessageBox(Pchar(st),'Error',MB_OK);
CloseHandle(hCOM); hCOM:=0;
Forml.Label7.Caption:='COM?';
exit;
end;
end;
Form1.Labe17.Caption:=s tcom+' 9600 1;
end;
Сначала текст тут мало отличается от того, что описано во всех стандартных рекомендациях по программированию порта. Единственный момент, который несколько выходит за рамки стандарта: мы не устанавливаем поля структуры DCВнапрямую, а используем функцию BuildCommDCB. Я это делаю отчасти потому, что структура DCBв Delphi транслируется из API не полностью (сравните ее описание в Windows.pas и в Win32.hip), и хотя для данного случая, разумеется, все нужные поля имеются, но функция BuildCommDCBвсе равно удобнее.
После стандартных установок мы сразу выполняем два действия, о которых упоминают далеко не всегда. Во-первых, мы устанавливаем все возможные задержки (timeout) для разных вариантов приема и передачи. В параметрах, которые заканчиваются на «Multiplier» можно для простоты всегда ставить «1» (если больше, то процедуры чтения/записи будут отслеживать еще и скорость поступления байтов, что нам не требуется). А остальные из этих параметров делают следующее: если задержка посылки через порт больше, чем writeTotaiTimeoutConstant(в миллисекундах), то будет прервана передача, а при задержке между поступающими байтами больше, чем ReadIntervaiTimeout, и при задержке всей процедуры чтения (в данном случае — самый главный параметр) больше, чем ReadTotalTimeoutConstant, будет прерван прием. Последний параметр мы установили равным двум секундам. При выборе этих параметров следует иметь в виду, что один байт при скорости 9600 передается/принимается примерно за 1 мс. Если эти параметры вообще не устанавливать (оставить их в значении «0», как по умолчанию), то при отсутствии принимаемых байтов процедура чтения через ReadFileпросто зациклится и «повесит» всю программу.
Во-вторых, мы определяем, не является ли установленный нами порт модемом. Так как мы рассматриваем «чистый» RS-232, то для нас модемный порт все равно как бы занят. Определяем модем мы очень просто: посылаем в выбранный порт символьный код инициализации, который одинаков для всех модемов: «AT» (65 84 13 10). В ответ мы от модема должны получить строку «АТOK» (65 84 13 10 13 10 79 75 13 10), но все такие подробности нам не требуются, подозреваю, что строка для разных модемов может немного отличаться. Но в любом случае в ней должны содержаться символы «ОК», если модем, конечно, свободен (с занятым модемом я предоставляю читателю разобраться самостоятельно). В последнем операторе, если порт инициализировался нормально, выводим в Labelномер порта и скорость.
Читать дальшеИнтервал:
Закладка: