![]() |
|
|
#1
|
|||
|
|||
|
Всем здраствуйте!!! Ребята такая проблема: Делаю курсовую на тему Управление внешними устройствами ......... Задание такое нужно написать программу которая бы управляла при помощи СОМ- порта каким либо простейшим устройством!!! Знакомый мальчик спаял мне диод с ресистором
, мол говорит если получится зажеч этот диод значит программа заработает и сможешь дальше больше!!!! Кучу лит-ры перечитала научилась открывать порт,а вот как эту штуку заставить гореть не могу врубиться!!!Подскажите что мне делать, или как делать!!! Горю((((((((((((( От меня респектик и за ранее спасибо)))))))))) |
|
#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
|
|||
|
|||
|
На 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. |