|
#1
|
|||
|
|||
Com-порт
Всем здраствуйте!!! Ребята такая проблема: Делаю курсовую на тему Управление внешними устройствами ......... Задание такое нужно написать программу которая бы управляла при помощи СОМ- порта каким либо простейшим устройством!!! Знакомый мальчик спаял мне диод с ресистором , мол говорит если получится зажеч этот диод значит программа заработает и сможешь дальше больше!!!! Кучу лит-ры перечитала научилась открывать порт,а вот как эту штуку заставить гореть не могу врубиться!!!
Подскажите что мне делать, или как делать!!! Горю((((((((((((( От меня респектик и за ранее спасибо)))))))))) |
#2
|
||||
|
||||
Схему электрическую покажи приборчика который тебе друг спаял.
Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#3
|
|||
|
|||
Нет там не приборчик! Просто резистор припаяный к светодиоду потом в ком порт RS 232! сказал подключил правильно, дерзай,я у же два дня дерзаю не как не получается.
|
#4
|
|||
|
|||
Попродуй мой модуль для работы с ком-портом.
Работает в WinXP Но для таких задач часто используют Win98. Дело в том что она позволяет прямое обращение к портам ввода-вывода (чего не допускает WinXP) В этом случае все сильно упрощается. Код:
unit ComDrv32; {----------------------------------------------------------------------- Интерфейсный модуль работы с COM- портом барометра БРС-1М, термогигрометром FLUKE через COM по теме Метрология ------------------------------------------------------------------------} interface uses Windows, Messages, SysUtils, Dialogs ; {$H+} function OpenPort(comName:string):integer; //открыть COM-порт procedure ClosePort; //закрыть COM-порт function SendData( DataPtr: pointer; DataSize: integer ):dword; //запись данных в порт function ReadData( DataPtr: pointer; DataSize: integer ):dword; //читает порт в буфер implementation const dcb_Binary = $00000001; dcb_ParityCheck = $00000002; dcb_OutxCtsFlow = $00000004; dcb_OutxDsrFlow = $00000008; dcb_DtrControlMask = $00000030; dcb_DtrControlDisable = $00000000; dcb_DtrControlEnable = $00000010; dcb_DtrControlHandshake = $00000020; dcb_DsrSensivity = $00000040; dcb_TXContinueOnXoff = $00000080; dcb_OutX = $00000100; dcb_InX = $00000200; dcb_ErrorChar = $00000400; dcb_NullStrip = $00000800; dcb_RtsControlMask = $00003000; dcb_RtsControlDisable = $00000000; dcb_RtsControlEnable = $00001000; dcb_RtsControlHandshake = $00002000; dcb_RtsControlToggle = $00003000; dcb_AbortOnError = $00004000; dcb_Reserveds = $FFFF8000; ComPortHandle = 0; // Not connected ComPort :pchar= 'COM1'; // COM 2 ComPortBaudRate = cbr_1200; // 9600 bauds ComPortDataBits = 8; // 8 data bits ComPortStopBits = 1; // 0 stop bit ComPortParity = NOPARITY; // no parity ComPortHwHandshaking = 0; // no hardware handshaking ComPortSwHandshaking = 0; // no software handshaking ComPortInBufSize = 2048; // input buffer of 2048 bytes ComPortOutBufSize = 2048; // output buffer of 2048 bytes ComPortReceiveData = nil; // no data handler ComPortPollingDelay = 50; // poll COM port every 50ms OutputTimeout = 4000; // output timeout - 4000ms EnableDTROnOpen = true; // DTR high on connect var porthandle:THandle=0; lpDCB:TDCB; lpCommTimeouts:TCommTimeouts; Key:byte=13; {--------------закрыть COM-порт--------------------} procedure ClosePort; begin CloseHandle(PortHandle); PortHandle:=0; end; {--------------------------------------------------------- открыть порт возвращает код ошибки открытия ----------------------------------------------------------} function OpenPort(comName:string):integer; begin if PortHandle=0 then begin PortHandle:= CreateFile( pchar(comName), GENERIC_READ or GENERIC_WRITE, 0, // Not shared nil, // No security attributes OPEN_EXISTING, // 0, FILE_ATTRIBUTE_NORMAL, 0 // No template ) ; Result:= GetLastError; with lpCommTimeouts do begin ReadIntervalTimeout := 4; // Specifies the maximum time, in milliseconds, // allowed to elapse between the arrival of two // characters on the communications line ReadTotalTimeoutMultiplier := 8; // Specifies the multiplier, in milliseconds, // used to calculate the total time-out period // for read operations. ReadTotalTimeoutConstant := 1000; // Specifies the constant, in milliseconds, // used to calculate the total time-out period // for read operations. WriteTotalTimeoutMultiplier := 0; // Specifies the multiplier, in milliseconds, // used to calculate the total time-out period // for write operations. WriteTotalTimeoutConstant := 0; // Specifies the constant, in milliseconds, // used to calculate the total time-out period // for write operations. end; //with with lpDCB do begin fillchar( lpdcb, sizeof(Tdcb), 0 ); DCBLength := sizeof(Tdcb); // dcb structure size BaudRate:=ComPortBaudRate; Flags := dcb_Binary; XONLim := ComPortInBufSize div 4; XOFFLim := 1; ByteSize:=ComPortDataBits; Parity := ComPortParity; StopBits := ComPortStopbits; XONChar := #17; XOFFChar := #19; end; //with // if not SetCommState(porthandle,lpDCB) then ShowMessage('ошибка SetCommState'); PurgeComm(porthandle,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR); if not SetCommTimeouts(porthandle,lpCommTimeouts) then ShowMessage('ошибка SetCommTimeout'); SetupComm( ComPortHandle, ComPortInBufSize, ComPortOutBufSize ); end; end; {-------------------------------------------------------------------- функция записывает строку в порт возвращает колич записанных байт ----------------------------------------------------------------------} function SendData( DataPtr: pointer; DataSize: integer ):dword; var n:dword; begin PurgeComm(porthandle,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR); //PurgeComm(porthandle,PURGE_TXABORT or PURGE_TXCLEAR); WriteFile(porthandle,pchar(DataPtr^),DataSize,Result,nil); WriteFile(porthandle,Key,1,n,nil); if n <> 1 then Result:=0; FlushFileBuffers(porthandle); end; {-------------------------------------------------------------------- функция читает данные из порта возвращает колич принятых байт ----------------------------------------------------------------------} function ReadData( DataPtr: pointer; DataSize: integer ):dword; begin //PurgeComm(porthandle,PURGE_RXABORT or PURGE_RXCLEAR); ReadFile(porthandle,DataPtr^,DataSize,Result,nil); FlushFileBuffers(porthandle); end; end. |
#5
|
|||
|
|||
и еще в догонку.
Тебе Обязательно потребуется тестовая программа. С ее помощью ты сможешь отладить канал связи и вообще убедиться что он работает. Я ее откопал в Инете. Чрезвычайно полезная вещь! Не мучайся с исходником. Я откомпилировал. См ComTestExe Схема вызыает большие сомнения. Вряд ли ты что-то увидишь. Процесс передачи байта очень быстрый. Ты не увидишь вспышки светодиода. Или в твоей проге посылай TxD в цикле Нормальное решение проблемы- соединить 2 компа через ком-порт и на них экспериментировать Или возьми какой-нибудь прибор с интерфейсом COM Последний раз редактировалось chainik, 30.09.2011 в 12:59. |
#6
|
||||
|
||||
Цитата:
Компьютер тоже просто коробочка из нее проводки идут и телевозор... А программа почему-то не пишется... Какой светодиод, номинал резистора, как спаяны, на какие ноги разъемы COM порта? Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#7
|
|||
|
|||
Аж слеза прошибла.
Отдаю свой интерфейсный модуль с прибором БРС-1М. Объясняю суть. В лаборатории метрологии имеется прибор измеряющий давление воздуха. Требуется периодически снимать показания и отсылать в БД и накапливать их там. Это давление используется для введения поправок при калибровке авиационных барометрических высотомеров. Прибор имеет интарфейс СОМ. Работает он предельно просто. Ты отсылаешь в прибор запрос- 1 байт равный $81 В ответ прибор выдает последовательность 7 байт из них 1байт=$DA-это байт начала последовательности. Далее 6 байт, каждый- это 1 разряд на индикаторе, ст. разряд-первый. и это все. Далее все это превращается в число и укладывается в БД. (но нам это пока не надо) Полагаю, зачет будет!!!!!!!! |
#8
|
|||
|
|||
Я нашла компонент работы с ком портом BCPort называется ,а как его на форму выложить не могу понять!!!
|
#9
|
|||
|
|||
Код:
procedure TForm1.Button2Click(Sender: TObject); var TRBuf:PChar; //передача nToWrite:DWord; //запись nWrite:DWord; //число записанных байт begin TRBuf:=PChar(Edit1.Text); //заполнить буфер nToWrite:=length(TRBuf)+1; //число передаваемых байт WriteFile(port,TRBuf^,nToWrite,nWrite,nil); //отпавить end; |
#10
|
|||
|
|||
|
#11
|
|||
|
|||
Не поможет. Этот СОМ- не тот СОМ (однофамилец)
Component Object Model (COM) а нам нужен последовательный интерфейс. Если есть такое непреодолимое желание копаться в компьютерной требухе- почитай Юрий Магда. Программирование последовательных интерфейсов. Вызывает подозрение твой вопрос по поводу линии которую надо выбрать для передачи. Он говорит о том что ты все-таки не совсем поняла суть. Она в том что линия передачи- всего одна! (TxD) и линия приема тоже только одна (RxD) Но может ты путаешь термины и речь идет о параллельном порте (LPT)? Тогда проясняется эта идея со светодиодом. В своей минимальной конфигурации Com- порт пребует всего 3 линии Txd, Rxd и общий- итого 3 провода. Если не веришь- расковыряй свою мышку. И передача и прием ведутся последовательно. Есть правда вспомогательные шины (готовности к приему и пр) но они как-то не прижились хотя и позволяют контролировать процесс передачи-приема и избежать потери данных. А впрочем кто знает что потребует от тебя твой препод... Последний раз редактировалось chainik, 02.10.2011 в 18:01. |
#12
|
|||
|
|||
Тогда должно подойти это http://www.helloworld.ru/texts/comp/.../com/index.htm
|
#13
|
|||
|
|||
Если нужно просто светодиодом поморгать, компоненты не нужны - и через WinApi все очень просто выходит. Вот код:
Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); public COMHandle : cardinal; end; var Form1: TForm1; implementation {$R *.dfm} // Эта функция записывает в биты X, заданные в Mask значение Value. // т.е. если X = bxxxxxxxx; Mask = b00011100; Value = b00000010; // Значение X после выполнения функции станет bxxx010xx; procedure SetBits(var X:integer; Mask,Value:integer); var temp:integer; begin if Mask=0 then exit; temp:=1; while (Mask and temp)=0 do begin temp := temp shl 1; Value := Value shl 1; end; X := X and (not Mask); X := X or (Value and Mask); end; procedure ClosePort(var Handle : cardinal); begin if Handle = INVALID_HANDLE_VALUE then exit; CloseHandle(Handle); Handle := INVALID_HANDLE_VALUE; end; function OpenPort(const COMName:string) : cardinal; var DCB:_DCB; begin // Открытие порта Result := CreateFile( PChar(ComName), GENERIC_READ+GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0 ); // Если удалось открыть порт - конфигурируем его if Result=INVALID_HANDLE_VALUE then exit; try // Запрещаем автоматическое управление линией DTR -> будем управлять вручную GetCommState(Result,DCB); SetBits(DCB.Flags,(3 shl 4),DTR_CONTROL_DISABLE); SetCommState(Result,DCB); except ClosePort(Result); end; end; // Управление линией DTR (нога 4 на разъеме DB9 COM порта) function Set_DTR_Pin(Handle:cardinal; State:boolean):boolean; const States : array [False..True] of cardinal = (CLRDTR,SETDTR); begin Result := false; if Handle=INVALID_HANDLE_VALUE then exit; Result := EscapeCommFunction(Handle,States[State]); // Управление линией DTR end; procedure TForm1.Button1Click(Sender: TObject); begin Set_DTR_Pin(COMHandle,true); end; procedure TForm1.Button2Click(Sender: TObject); begin Set_DTR_Pin(COMHandle,false); end; procedure TForm1.FormCreate(Sender: TObject); begin COMHandle := OpenPort('COM1'); end; procedure TForm1.FormDestroy(Sender: TObject); begin ClosePort(COMHandle); end; end. |
#14
|
|||
|
|||
Немного общей информации по порту RS232
На 9-ти контактном разъеме COM-порта всего есть 8 сигнальных линий: 5 на вход и 3 на выход. Из этих 8 линий, две отвечают за прием/передачу данных (одна линия на передачу и одна на прием). Эти две линии - это, собственно и есть основа COM-порта. Остальные 6 линий - вспомогательные, они используются не для передачи данных, а для управления процессом передачи. За передачу/прием данных отвечают функции ReadFile/WriteFile. За чтение/установку состояний вспомогательных линий в ручном режиме отвечают функции GetCommModemStatus/EscapeCommFunction (еще эти линии могут управляться аппаратно - при соответствующих настройках COM-порта).
Очевидно что для управления устройством можно использовать только выходные линии. Их всего три - это TX, DTR, RTS. Линию TX нельзя установить в фиксированное состояние - она может лишь выдавать данные, бит за битом, с установленной скоростью. За выдачу данных по линии TX отвечает функция WriteFile. Линии DTR, RTS можно переключить в фиксированное состояние: лог. 0 или 1 (Если, разумеется, не активирован какой-нибудь автоматический режим. Если активирован - состояние линий будет устанавливаться аппаратно). Максимальная скорость, переключения линий DTR,RTS может достигать нескольких десятков килогерц, поэтому на них вполне можно реализовать какой-нибудь протокол. Вот перечень команд для установки состояния линий DTR/RTS: Код:
EscapeCommFunction(Handle,CLRDTR); // лог.0 на линии DTR (-12В на ноге 4) EscapeCommFunction(Handle,SETDTR); // лог.1 на линии DTR (+12В на ноге 4) EscapeCommFunction(Handle,CLRRTS); // лог.0 на линии RTS (-12В на ноге 7) EscapeCommFunction(Handle,SETRTS); // лог.1 на линии RTS (+12В на ноге 7) Вот функции для передачи данных по линии TX: Код:
var Buffer:AnsiString; BytesWritten:cardinal; ... Buffer := 'AT COMMAND'; // Строка Buffer := #$00#$01#$02#$03; // А так можно и бинарные данные передать. WriteFile(Handle,Buffer[1],length(Buffer),BytesWritten,nil); WriteFileEx(...); // Пример вызова этой функции намного сложнее. P.S. Если в вашей схеме только светодиод и резистор, светодиод вполне может быть пробит при обратной полярности. Лучше вместо одного светодиода включить встречно-параллельно два светодиода разного цвета - и надежно и смотрится хорошо. |
#15
|
|||
|
|||
Привожу драйвер ком- порта для Win95/Win98
Обрати внимание насколько здесь все проще. Чтобы отослать байт ты просто отправляешь его в порт (команды IN/OUT) К сожалению в WinXP этот трюк уже не работает. Система не допускает прямого обращения к портам ввода/вывода. Это элемент защиты. У меня на предприятии есть стенды с такой системой. Заменить уже не на что... Код:
unit Port95; {********************************************************************** * Description: Port95 - very simple unit, that lets you access port * * under Window 95,not under Windows NT. * * Status: Freeware * * You can freely use or distribute this unit * * Target: Delphi 2 and Windows 95 * * Version: 1.0 (April 27, 1997 * * Status: Freeware * * Author: Anatoly Podgoretsky * * Address: kvk@estpak.ee * * Tips: font Courier, tabs = 2 * * Problems: Word Read/Write utulities may problems on some * * computers or interface cards, that can't access whole * * word. To prevent it You can use slow equivalent of * * these procedures with suffix LS * * Copyright: Copyright (C) 1997, NPS * **********************************************************************} interface function PortReadByte(Addr:Word) : Byte; function PortReadWord(Addr:Word) : Word; function PortReadWordLS(Addr:Word) : Word; procedure PortWriteByte(Addr:Word; Value:Byte); procedure PortWriteWord(Addr:Word; Value:Word); procedure PortWriteWordLS(Addr:Word; Value:Word); implementation {**************************************************************** * Port Read byte function * * Parameter: port address * * Return: byte value from given port * ****************************************************************} function PortReadByte(Addr:Word) : Byte; assembler; register; asm MOV DX,AX IN AL,DX end; {**************************************************************** * HIGH SPEED Port Read Word function * * Parameter: port address * * Return: word value from given port * * Comment: may problem with some cards and computers * * that can't to access whole word, usualy it work. * ****************************************************************} function PortReadWord(Addr:Word) : Word; assembler; register; asm MOV DX,AX IN AX,DX end; {**************************************************************** * LOW SPEED Port Read Word function * * Parameter: port address * * Return: word value from given port * * Comment: work in all cases, only to adjust DELAY if need * ****************************************************************} function PortReadWordLS(Addr:Word) : Word; assembler; register; const Delay = 150; // depending of CPU speed and cards speed asm MOV DX,AX IN AL,DX // read LSB port MOV ECX,Delay @1: LOOP @1 // delay between two reads XCHG AH,AL INC DX // port+1 IN AL,DX // read MSB port XCHG AH,AL // restore bytes order end; {**************************************************************** * Port Write byte function * * Parameter: port address * ****************************************************************} procedure PortWriteByte(Addr:Word; Value:Byte); assembler; register; asm XCHG AX,DX OUT DX,AL end; {**************************************************************** * HIGH SPEED Port Write word procedure * * Comment: may problem with some cards and computers * * that can't to access whole word, usualy it work. * ****************************************************************} procedure PortWriteWord(Addr:word; Value:word); assembler; register; asm XCHG AX,DX OUT DX,AX end; {**************************************************************** * LOW SPEED Port Write Word procedure * * Parameter: port address * * Return: word value from given port * * Comment: work in all cases, only to adjust DELAY if need * ****************************************************************} procedure PortWriteWordLS(Addr:word; Value:word); assembler; register; const Delay = 150; // depending of CPU speed and cards speed asm XCHG AX,DX OUT DX,AL // port LSB MOV ECX,Delay @1: LOOP @1 // delay between two writes XCHG AH,AL INC DX // port+1 OUT DX,AL // port MSB end; end. |