Получение данных на Делфи
- Войдите на сайт для отправки комментариев
Пнд, 30/04/2012 - 00:45
Доброй ночи!
У меня возникла проблема при сравнении данных переданных с ардуино на делфи. вот собственно кусок кода:
procedure TMainForm.ReadDataClick(Sender: TObject);
Var
RCBuf:TBytes; //Буфер данных для приема
nToRead:Cardinal; //Число байт для чтения
nRead:Cardinal; //Число прочитанных байт
begin
nToRead:=6; //считываем число байт для чтения из структуры
nToReadLabel.Caption:=IntToStr(nToRead); //выводим на форму число байт для чтения
SetLength(RCBuf,nToRead+1);
RCBuf[nToRead+1]:=0;// конец строки PAnsiChar
ReadFile(Port,RCBuf[0],nToRead,nRead,nil); //считываем данные
nReadLabel.Caption:=IntToStr(nRead); //выводим на форму число прочитанных байт
if (nRead <> 0) then begin
if (PAnsiChar(RCBuf) = PAnsiChar('s')) then //вот это сравнение
SLabel.Caption:='S';
if (PAnsiChar(RCBuf) = PAnsiChar('a')) then //и это
ALabel.Caption:='A';
Finalize(RCBuf);
end;
end;
что я делаю не правильно?
>что я делаю не правильно?
Плохо задаете вопросы. Совершенно упускаете из виду, что остальные не в контексте вашей проблемы.
Это ардуино.ru, а не "шоу экстрасенсов" или клуб любителй "в угадайку".
Хотя может быть и найдутся любители поперебирать варианты "что и как вы шлете, что вы ожидаете увидеть, что вы видите, как подключили и т.п."
P.S. Еще можете поиском воспользоватся, Delphi иногда встречается на форуме, не уверен, но может и найдете чего полезного.
Если проблема в коде то выкладываю полностью.
unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TBytes=array of byte; TMainForm = class(TForm) OpenPort: TButton; ClosePort: TButton; SendData: TButton; Edit1: TEdit; ReadData: TButton; PortStateLabel: TLabel; Label1: TLabel; Label2: TLabel; nToReadLabel: TLabel; nReadLabel: TLabel; Label3: TLabel; RcDataLabel: TLabel; procedure OpenPortClick(Sender: TObject); procedure ClosePortClick(Sender: TObject); procedure ReadDataClick(Sender: TObject); end; var MainForm: TMainForm; Port:THandle; implementation {$R *.dfm} procedure TMainForm.OpenPortClick(Sender: TObject); Var DCB:TDCB; //структура, содержащая настройки порта CommTimeouts:TCommTimeouts; begin Port:=CreateFile( '\\.\COM8', //открываем первый порт GENERIC_READ or GENERIC_WRITE,//открываем порт для чтения и записи 0, //общий доступ к ресурсу запрещен, для портов всегда так nil, //атрибуты защиты, не используются и потому nil OPEN_EXISTING, //атрибуты открытия, для портов OPEN_EXISTING FILE_ATTRIBUTE_NORMAL, //для синхронной работы так 0 //хз что это, но должно быть так ); GetCommState(port, DCB); //что бы не заполнять всю структуру самим, сначал считываем ее, потом поменяем нужные поля DCB.BaudRate:=9600; // скорость обмена 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; //байты в приемном буфере SetCommTimeouts(Port, CommTimeouts); //записываем измененную структуру end; procedure TMainForm.ClosePortClick(Sender: TObject); begin if not CloseHandle(Port) //если порт не закрылся then showmessage('Не закрылось') //то пишем что он не закрылся else PortStateLabel.Caption:='Порт не открыт'; //если всетаки закрылся , то пишем, что закрылся :) Close(); end; procedure TMainForm.ReadDataClick(Sender: TObject); Var RCBuf:TBytes; //Буфер данных для приема nToRead:Cardinal; //Число байт для чтения nRead:Cardinal; //Число прочитанных байт begin nToRead:=6; //считываем число байт для чтения из структуры nToReadLabel.Caption:=IntToStr(nToRead); //выводим на форму число байт для чтения SetLength(RCBuf,nToRead+1); RCBuf[nToRead+1]:=0;// конец строки PAnsiChar ReadFile(Port,RCBuf[0],nToRead,nRead,nil); //считываем данные nReadLabel.Caption:=IntToStr(nRead); //выводим на форму число прочитанных байт if (nRead <> 0) then begin if (PAnsiChar(RCBuf) = PAnsiChar('s')) then //вот это сравнение SLabel.Caption:='S'; if (PAnsiChar(RCBuf) = PAnsiChar('a')) then //и это ALabel.Caption:='A'; Finalize(RCBuf); end; end; end.просто уже сломал голову почему они неравные
if (PAnsiChar(RCBuf) = PAnsiChar('s')) then
SLabel.Caption:='S';
просто уже сломал голову почему они неравные
if (PAnsiChar(RCBuf) = PAnsiChar('s')) then
SLabel.Caption:='S';
Есть бредовая идея, что операнды не совпадают:
a) по типам и
b) по кодировкам
Любой из этих причин достаточно для того, чтобы порушить условие, а уж двух-то...
Кроме того - расскажите нам о том, что возвращает функция (или преобразование типа?) PAnsiChar?
Есть бредовая идея...
Решили, таки, в угадайку поиграть?
>Кроме того - расскажите нам о том, что возвращает функция (или преобразование типа?) PAnsiChar?
Похоже что это, не функция, а преобразование типа. Если это так, то возможно товарищь пытается сравнить указатели, а не значения куда они указывают. Причем правый вообще указывает на какой-то случайную ячейку памяти (с адресом 's').
Я уже не говорю, что не видно что-бы он бежал по символам в цикле. То есть если попался случайный мусор (например при включении дуины она плюнула пару символов в порт), то - привет.
Да и, возможно, он должен обладать не дюженной реакцией, что-бы нажать на форме кнопку чтения из порта, ровно в тот момент когда дуина что-то послала (какого-нибудь while ожидания данных в порте - тоже не видно).
А может тупо скорости не совпадают, или вообще порт не тот (скопированный из какого-то примера).
Да еще кучу всего нафантазировать можно. Только смысл? Если сам топик-стартер не торопится сузить область поиска. Значит не шибко оно ему и нужно. Обычное "Товарищи ученые, у меня в подполье уже третий год происходит какой-то стук. Объясните отчего и почему?"
> Кроме того - расскажите нам о том, что возвращает функция (или преобразование типа?) PAnsiChar?
это не функция, я пытаюсь преобразовать тип. извиняюсь за не полноту инфрмации в этом деле я начинающий.
я попытаюсь объяснить в чем проблема.
у меня ардуино посылает сигнал о нажатии кнопки, то есть передает символ "s". и мне надо на делфи сделать действие которое бы реагировала бы на это нажатие. так что бы если пришел символ "s", то сделать одно. а если "а", тогда - другое действие. в дальнейшем планирую эту проверку сделать на таймере. в интернете нашел этот исходник который соединяется к ком-порту и выводит с нее информацию. с этим проблем нету, если сделать SLabel.Caption:=PAnsiChar(RCBuf), то выводится нормальный символ.
> Я уже не говорю, что не видно что-бы он бежал по символам в цикле.
это как? дайте направление?
> что-бы нажать на форме кнопку чтения из порта, ровно в тот момент когда дуина что-то послала
на счет этого думаю проблем нету. так как SLabel.Caption:=PAnsiChar(RCBuf) выводит все то что отправлялась в порт.
> А может тупо скорости не совпадают, или вообще порт не тот
это все настроено
если требуется могу выложить код ардуино
leshak вас таки опередил - вам необходимо сравнивать не указатели, а содержимое областей памяти, на которые указывают указатели.
Вам также необходимо быть пооисторожнее с кодировками - нен сравнивать ASCII-символ (именно такой вы скорее всего получите от микроконтроллера, c ANSI. Для латиницы это не слишком критично, а вот кириллица может доставить в этом отношении мноооого радости.
В общем - разберитесь с этими пунктами. Не поможет - будем покопаться дальше. Но на интенсивную помощь не надейтесь. Вот я, напрмер, морковкины семечки сегодня сажал, а завтра лук хоронить буду. Да и шашлык уже на шампуры просится...
спасибо! приятного вам времепровождения.
постараюсь разобраться
>у меня ардуино посылает сигнал о нажатии кнопки, то есть передает символ "s"
Может быть. А может и нет.
>если требуется могу выложить код ардуино
Ну а почему сразу этого не сделать? Тут же нет оплаты трафика. Зато сразу куча вариантов отпала бы.
Кстати, а обычным сериал монитором нормально видите посылки из ардуины?
>я попытаюсь объяснить в чем проблема.
Ну и где в стартовом посте описание проблемы? Есть указание строчек в которых вы подозреваете проблему, но описания - нет. Вообще не читаются символы, или читаются но не все, или читаются но не те... что показывает nReadLabel? И т.п. мы же не видим вашего монитора. Только то что вы написали. А причина может быть в том что вы посчитали "не важным". Поэтому чем точнее вы опишите картину - тем больше шансов на помощь (но не гарантия).
>> Я уже не говорю, что не видно что-бы он бежал по символам в цикле.
>это как? дайте направление?
Ну это вообще не ардуино вопрос, а вопрос программирования на дельфи. Я уже лет десять его не видел/трогал.
Просто вот вы вычитали 6 симвовлов, своим сравнением (PAnsiChar(RCBuf) = PAnsiChar('s') вы какой из них стравниваете с 's', первый, третий, последний?
Возможно вам нужно сделать цикл и сравнивать как-то так (PAnsiChar(RCBuf+i) = PAnsiChar('s'), где i - номер символа который хотите сравнить. Как именно точно сразвинвать - смотрите книги по дельфи. Разделы работы со строками и указателями.
Но я бы даже, не бегал по этим массивам. Зачем читать сразу все 6-ть байт? Не проще читать по одному символу вычитать из порта и сравнивать?
Еще возможные грабли: Я так понял что PAnsiChar - это указатель. То есть "адрес в памяти" где хранится значение. Возможно вы сравниваете именно адресс буффера RCBuf с адресом где хранится символ 's'. Естественно они будут разными всегда. Вам же нужно сравнивать значения, а не "где они лежат". Возможно нужно делать как-то так PAnsiChar(RCBuf+i)^='s'
Гугланите "дельфи строки сравнение символы". Не думаю что вы останетесь в неведении как это делать.
Отложите, вначле в сторону ардуину. Научитесь в строке на дельфи находить символ. Напишите функцию которая говорит если в строке символ 's' или нет.
Почитайте базовые функции работы со строками. Наверняка у них есть, какая нибуть готовая функция типа contains, которая говорит есть подстрока/символ в строке или нет.
Научитесь просто сравнивать символы, не пришедшие из ардуины, а веденные в поле формы. Сократите количество неизвестного. Раздробите задачу на части. Вначале "умею сравнивать", потом "умею принимать данные из ардуины", а уж потом "умею принять данные и сравнить их".
Следующие:
Вы уверены что кнопку на ардуине и кноку "читать даныне из порта" нажимаете обсолютно одновременно? Скорее всего вы "запустили прогу", она послушала порт - ничего не нашла. И вышла из функции ReadDataClick. Потом вы ее жмете кнопку ардуины, она что-то посылает... но ее никто уже не слушает. Или вы эту ReadDataClick вызываете по таймеру? Тогда почему click? (вообщем видите, опять гадать нужно, просто потмоу что вы не описали что-же именно вы видите на экране).
Обычно делают пустой цикл, ожидающий "пока что-нибудь не прийдет".
Примерно так:
while(!port.avaliable()){} // ждем пока в порту не появятся какие-то данные
Хотя, возможно это (ожидание) уже сделанно внутри функции ReadFile.
Но опять, таки сработает она только один раз. И выйдет. Больше не будет слушать дуину.
Значить опять-таки нужно все это обернуть в какой-то цикл бесконечный (и прерывать его какой-нибудь кнопкой типа "прекратить слушать порт").
Общий подход такой (псевдокодом).
спасибо за ответ!
попробую разобраться с вашими советами.
за не информативность прошу прощения. первый раз пишу на форуме)))) в последующем постараюсь писать по конкретней.
выкладываю код для ардуино. на обычном сериал монитре вижу все нормально.
int led1 = 13, bPin1 = 5, led2 = 12, bPin2 = 4; boolean b1 = false, b2 = false; void setup() { Serial.begin(9600); pinMode(led1, OUTPUT); pinMode(bPin1, INPUT); pinMode(led2, OUTPUT); pinMode(bPin2, INPUT); } void loop() { if (digitalRead(bPin1) == HIGH) digitalWrite(led1, HIGH); else digitalWrite(led1, LOW); if (digitalRead(bPin2) == HIGH) digitalWrite(led2, HIGH); else digitalWrite(led2, LOW); if ((digitalRead(bPin1)==1)&&(b1==false)) {Serial.println("s");b1=true;}// нажали b1 if ((digitalRead(bPin1)==0)&&(b1==true)) {Serial.println("a");b1=false;}// отпустили b1 if ((digitalRead(bPin2)==1)&&(b2==false)) {Serial.println("q");b2=true;}// нажали b2 if ((digitalRead(bPin2)==0)&&(b2==true)) {Serial.println("w");b2=false;}// отпустили b2 }