|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Работа с COM-портом
Пишу программу, под определенное устройство, которое в ПЗУ хранит информацию в формата:
… $GPRMC,101072.00,A,5029.0728,N,03028.7404,E,000.0, 000.0,230111,02.2,E,A*0D … Для получения данных необходимо отправить команду «1». Полученное сохранить в *.txt файл. Добился того, что программа отправляет команду, считывает информацию и записывает в текстовый файл, проблема в том как она её считывает и записывает… В результате работы моей программы в файл записывается следующее: (это маленький кусочек из текстового файла, я предполагаю, что это одна запись в формате выше) Код:
???????????????????°?G?? ???????????????????°?G?? ??T Даже не знаю в чем проблема, такое впечатление, что где-то что-то нужно инвертировать… Код программы: Код:
unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry,ReadThread; type TMainForm = class(TForm) OpenPort: TButton; ClosePort: TButton; SendData: TButton; ReadData: TButton; PortStateLabel: TLabel; Label1: TLabel; Label2: TLabel; nToReadLabel: TLabel; nReadLabel: TLabel; Label3: TLabel; RcDataLabel: TLabel; Label4: TLabel; Label5: TLabel; bRefreshComPrt: TButton; cbCOMPrts: TComboBox; cbSpeed: TComboBox; procedure OpenPortClick(Sender: TObject); procedure ClosePortClick(Sender: TObject); procedure SendDataClick(Sender: TObject); procedure ReadDataClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure bRefreshComPrtClick(Sender: TObject); procedure RefreshComPrt; procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } Port:THandle; end; var MainForm: TMainForm; ReadThr:TReadThread; implementation {$R *.dfm} procedure TMainForm.OpenPortClick(Sender: TObject); Var DCB:TDCB; //структура, содержащая настройки порта CommTimeouts:TCommTimeouts; begin Port:=CreateFile( pWideChar(cbCOMPrts.Text), //открываем первый порт GENERIC_READ or GENERIC_WRITE,//открываем порт для чтения и записи 0, //общий доступ к ресурсу запрещен, для портов всегда так nil, //атрибуты защиты, не используются и потому nil OPEN_EXISTING, //атрибуты открытия, для портов OPEN_EXISTING FILE_ATTRIBUTE_NORMAL, //для синхронной работы так 0 //хз что это, но должно быть так ); if (port=INVALID_HANDLE_VALUE) //если порт не окрылся then showmessage('Ошибочка вышла!') //то выводим сообщение об ошибке else POrtStateLabel.Caption:='Порт открыт'; //Если порт открылся, то пишем что открылся GetCommState(port, DCB); //что бы не заполнять всю структуру самим, сначал считываем ее, потом поменяем нужные поля DCB.BaudRate:=StrToInt(cbSpeed.Text); // скорость обмена DCB.Parity:=NoParity; // нет контроля четности DCB.ByteSize:=8; //байт из восьми бит DCB.StopBits:=ONESTOPBIT; //один стоповый бит SetCommState(port, DCB); //записываем измененную структуру, для открытого порта GetCommTimeouts(Port, CommTimeouts); //получаем структуру CommTimeouts что бы не заполнять все вручную CommTimeouts.ReadIntervalTimeout :=MAXDWORD; //функция ReadFile возвращает CommTimeouts.ReadTotalTimeoutMultiplier := 0; //немедленно все имеющиеся CommTimeouts.ReadTotalTimeoutConstant := 0; //байты в приемном буфере CommTimeouts.WriteTotalTimeoutMultiplier := 0;//общий тайм-аут для CommTimeouts.WriteTotalTimeoutConstant := 0; //операции записи не используется. SetCommTimeouts(Port, CommTimeouts); //записываем измененную структуру end; procedure TMainForm.RefreshComPrt; var reg : TRegistry; ts : TStrings; i : integer; begin cbCOMPrts.Items.Clear; reg := TRegistry.Create; reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey('hardware\devicemap\serialcomm', false); ts := TStringList.Create; reg.GetValueNames(ts); for i := 0 to ts.Count -1 do begin cbCOMPrts.Items.Add(reg.ReadString(ts.Strings[i])); end; if cbCOMPrts.Items.Count>0 then cbCOMPrts.ItemIndex:=0; ts.Free; reg.CloseKey; reg.free; end; procedure TMainForm.bRefreshComPrtClick(Sender: TObject); begin RefreshComPrt; end; procedure TMainForm.ClosePortClick(Sender: TObject); begin if not CloseHandle(Port) //если порт не закрылся then showmessage('Не закрылось') //то пишем что он не закрылся else PortStateLabel.Caption:='Порт не открыт' //если всетаки закрылся , то пишем, что закрылся :) end; procedure TMainForm.SendDataClick(Sender: TObject); var TRBuf:PChar; //буфер данных для передачи nToWrite:DWord; //число байт для записи nWrite:DWord; //число записанных байт begin TRBuf:='1'; //заполняем буфер данными nToWrite:=length(TRBuf)+1; //число передаваемых байт WriteFile(port,TRBuf^,nToWrite,nWrite,nil); //собственно отпавляем данные // WriteFile(port,Edit1.Text[1],nToWrite,nWrite,nil); //собственно отпавляем данные // WriteFile(port,TRBuf[0],nToWrite,nWrite,nil); //собственно отпавляем данные end; procedure TMainForm.ReadDataClick(Sender: TObject); Var RCBuf:PChar; //Буфер данных для приема nToRead:Cardinal; //Число байт для чтения ReadedBytes:integer; //число всего прочитанных байт nRead:Cardinal; //Число прочитанных байт ComStat:TComStat; //состояние порта Errs:Dword; Data:TStringList; //прочитанные данные begin ReadedBytes:=0; Data:=TStringList.Create; ClearCommError(POrt,Errs,@ComStat); //считываем состояние порта nToRead:=ComStat.cbInQue; //считываем число байт для чтения из структуры nToReadLabel.Caption:=IntToStr(nToRead); //выводим на форму число байт для чтения while ReadedBytes<nToRead do begin ReadFile(Port,RCBuf^,nToRead,nRead,nil); //считываем данные nReadLabel.Caption:=IntToStr(nRead); //выводим на форму число прочитанных байт ReadedBytes:=ReadedBytes+nRead; RcDataLabel.Caption:=RCBuf; Data.Add(RCBuf); end; Data.SaveToFile(ExtractFilePath(ParamStr(0))+'Output.txt'); Data.Free; end; procedure TMainForm.FormCreate(Sender: TObject); begin nToreadLabel.Caption:=''; //Очищаем метки nReadLabel.Caption:=''; RcDataLabel.Caption:=''; ReadThr:=TReadThread.Create(True); ReadThr.Priority:=tpNormal; ReadThr.FreeOnTerminate:=True; ReadThr.Start; end; procedure TMainForm.FormShow(Sender: TObject); begin RefreshComPrt; end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin //CloseHandle(Port) //закрываем порт end; end. Надеюсь на вашу помощь, заранее спасибо. |