Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux (Lazarus плюс Synaser и бит четности Space и Mark)
Модератор: Модераторы разделов
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Описание проблемы.
Есть сеть RS-485 со множеством приборов. Мастер - только компьютер. Адрес и конец обмена выдаются с нулевым битом четности (Space), а обмен ведется с единичным битом четности (Mark). Корректность данных и команд контролируется контрольной суммой в конце команды от мастера и в конце данных от прибора. Есть исходники программ на Delphi. Очень легко все перевел на Lazarus в Windows. Получиласть такая же графическая оболочка, как и на Delphi (немного с построеним графиков заморочки были, т.к. компонент TChart сильно от дельфийского отличается). Но в итоге - практически аналогичная программа под Windows. Затевалось это все для портирования в Linux. И тут .... ЗАСАДА!!! В стандартном варианте Synaser для Linux ПРОСТО НЕЛЬЗЯ сделать бит четности Space/Mark. Никак!!!
Решение.
Начал рыть интернет. Наткнулся на статью Томаса Лочматтера "Linux and MARK/SPACE Parity" http://www.lothosoft.ch/thomas/libmip/markspaceparity.php Хорошо, думаю, путь понятен. Теперь надо надыбать конкретные биты во флаге c_cflag. Ну, с #define CMSPAR 010000000000 - понятно, переводим восьмеричное в hex и все. А вот с битами PARENB PARODD опять была засада - поиск #define PARODD (#define PARENB) давал такое количество вариантов, что голова кругом шла. Пришлось все варианты перепробовать. И вот окончательный результат
uses
... SynaSer, SynaUtil, SynaFPC, ....
const
CMSPAR= $40000000; { mark or space (stick) parity }
PARENB= $00000100; { enable parity on output }
PARODD= $00000200; { use odd parity if set, else even }
type
...
procedure ParitySpace;
procedure ParityMark;
...
var
ser: TBlockSerial;
...
...
implementation
procedure TForm1.ParitySpace; {SPACE parity is selected by}
begin
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag or CMSPAR or PARENB;
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag and (Not PARODD);
ser.SetCommState;
end;
procedure TForm1.ParityMark; {MARK parity is selected by}
begin
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag or CMSPAR or PARENB or PARODD;
ser.SetCommState;
end;
...
По окончании работы с программой не забывайте в FormCloseQuery сбрасывать бит CMSPAR.
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag and (Not CMSPAR);
Проверено - работает замечательно!
Есть сеть RS-485 со множеством приборов. Мастер - только компьютер. Адрес и конец обмена выдаются с нулевым битом четности (Space), а обмен ведется с единичным битом четности (Mark). Корректность данных и команд контролируется контрольной суммой в конце команды от мастера и в конце данных от прибора. Есть исходники программ на Delphi. Очень легко все перевел на Lazarus в Windows. Получиласть такая же графическая оболочка, как и на Delphi (немного с построеним графиков заморочки были, т.к. компонент TChart сильно от дельфийского отличается). Но в итоге - практически аналогичная программа под Windows. Затевалось это все для портирования в Linux. И тут .... ЗАСАДА!!! В стандартном варианте Synaser для Linux ПРОСТО НЕЛЬЗЯ сделать бит четности Space/Mark. Никак!!!
Решение.
Начал рыть интернет. Наткнулся на статью Томаса Лочматтера "Linux and MARK/SPACE Parity" http://www.lothosoft.ch/thomas/libmip/markspaceparity.php Хорошо, думаю, путь понятен. Теперь надо надыбать конкретные биты во флаге c_cflag. Ну, с #define CMSPAR 010000000000 - понятно, переводим восьмеричное в hex и все. А вот с битами PARENB PARODD опять была засада - поиск #define PARODD (#define PARENB) давал такое количество вариантов, что голова кругом шла. Пришлось все варианты перепробовать. И вот окончательный результат
uses
... SynaSer, SynaUtil, SynaFPC, ....
const
CMSPAR= $40000000; { mark or space (stick) parity }
PARENB= $00000100; { enable parity on output }
PARODD= $00000200; { use odd parity if set, else even }
type
...
procedure ParitySpace;
procedure ParityMark;
...
var
ser: TBlockSerial;
...
...
implementation
procedure TForm1.ParitySpace; {SPACE parity is selected by}
begin
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag or CMSPAR or PARENB;
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag and (Not PARODD);
ser.SetCommState;
end;
procedure TForm1.ParityMark; {MARK parity is selected by}
begin
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag or CMSPAR or PARENB or PARODD;
ser.SetCommState;
end;
...
По окончании работы с программой не забывайте в FormCloseQuery сбрасывать бит CMSPAR.
ser.TermiosStruc.c_cflag:= ser.TermiosStruc.c_cflag and (Not CMSPAR);
Проверено - работает замечательно!
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
а чем termios не угодил ?
puts ("Working, please wait...");while(1);
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
SidorLuty, если бы вы пользовались С, а не какими-то нераспространенными ЯП, у вас бы проблем не было.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
А чем он лучше? Даже если его перевести на паскаль в нем изначально недокументированного бита CMSPAR нет, а без этого Space/Mark в Linux НЕ БУДЕТ! Т.е. если в Windows мы имеем dcb.parity = 0; /*No Parity*/, dcb.parity = 1; /*Odd Parity*/, dcb.parity = 2; /*Even Parity*/, dcb.parity = 3; /*Mark Parity*/, dcb.parity = 4; /*Space Parity*/, то в Linux мы однозначно имеем dcb.parity = 0; /*No Parity*/, dcb.parity = 1; /*Odd Parity*/, dcb.parity = 2; /*Even Parity*/, dcb.parity = 3; /*Even Parity*/, dcb.parity = 4; /*Even Parity*/. Эта же проблема существует и у Mac OS, как у UNIX-подобной системы.
Ключевая фраза была "Есть исходники программ на Delphi"!!! Возможно, есть аналоги Borland C++ Builder (опыт переноса проектов с Delphi на C++ Builder - самый положительный) для Linux, но мне они неизвестны. Qt Creator, согласитесь, совсем другая штука. И проблемы были бы самые, что ни наесть. А именно - разработка программы с нуля!!! А вот про паскаль первый раз слышу "какой-то нераспространенный ЯП". Да и вообще... Концепция IDE Borland (а Lazarus - аналог) с визуальными (и не очень) компонентами для создания GUI мне гораздо больше нравится, чем концепция Qt Creator.
А поделился я своим опытом для тех, кому это будет необходимо. Зря Вы считаете, что Free Pascal и Lazarus мало людей пользуют. Я лично, пользую тот ЯП, который мне на данный момент удобнее (очень сожалею, что для микроконтроллеров альтернативы C нет, не считая ассемблера, конечно). Кстати, на этой ссылочке, которую я изначально дал, http://www.lothosoft.ch/thomas/libmip/markspaceparity.php как раз приведен пример для C.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Код: Выделить всё
man termios
...
CMSPAR (not in POSIX) Use "stick" (mark/space) parity (supported on certain serial devices): if PARODD is set, the parity bit is always 1; if PARODD is not set,
then the parity bit is always 0). [requires _BSD_SOURCE or _SVID_SOURCE]
...В серьезных целях - никто.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Я видел бейсик для микроконтроллеров.
ЯП - это инструмент. У каждого инструмента есть свое назначние. Можно конечно и отверткой дырку ковырять, но лучше использовать шлямбур.
Я тоже когда-то с Паскаля-дельфи начинал, но потом его перерос. А QIP (виндовая аська) не на дельфи написана кстати?
puts ("Working, please wait...");while(1);
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Я, кстати, для МК только С использую
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Все кого ты не спроси программируют на Си
Встретишь ты кого едва ли тех кто пишет на паскале
puts ("Working, please wait...");while(1);
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Уж больно неуклюж язык,
И синтаксис его страдает.
Да и какой же ты мужик,
Коль что-то пишешь на Паскале?
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Давай не будем религиозные войны разводить! Я сам на Си и Си++ пишу для МК. И недостатки Си вижу, впрочем, как и достоинства. Так и в паскале (строгость языка, например). А на счет "В серьезных целях - никто." - так это что считать серьезной целью. Лично для меня серьезная цель - это стабильно работающее ПО любого назначения. А писать, лично мне, удобнее на IDE типа Borland. termios.h я смотрел несколько исходников, например - http://www.raspberryginger.com/jbailey/min..._8h-source.html и нигде про CMSPAR. Да и вообще, если паскаль не интересует, то в чем смысл ваших посланий? Мое послание - тем, кто столкнется с этой проблемой в FPC и Lazarus. Доказывать чего либо я не собираюсь, у каждого своя голова.
P.S. Шутки на счет бейсиков для МК хороши, только это не более, чем шутки. Есть и паскали шуточные, например - http://users.iafrica.com/r/ra/rainier/ Но ведь писал про серьезную альтернативу, как, например, Delphi и C++ Builder.
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
SidorLuty писал(а): ↑30.11.2010 20:06P.S. Шутки на счет бейсиков для МК хороши, только это не более, чем шутки. Есть и паскали шуточные, например - http://users.iafrica.com/r/ra/rainier/ Но ведь писал про серьезную альтернативу, как, например, Delphi и C++ Builder.
Ну расскажите про шутки этим ребятам: http://www.picbasic.ru/. И для АВРов тоже есть Бейсик.
Я тоже против религиозых войн, но так исторически сложилось, что системным ЯП стал Си.
puts ("Working, please wait...");while(1);
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
SidorLuty писал(а): ↑30.11.2010 20:06termios.h я смотрел несколько исходников, например - http://www.raspberryginger.com/jbailey/min..._8h-source.html и нигде про CMSPAR
Это потому, что termios.h сам включает несколько файлов. Погрепали бы получше:
Код: Выделить всё
grep -R CMSPAR /usr/include
/usr/include/asm/termbits.h:#define CMSPAR 010000000000 /* mark or space (stick) parity */
/usr/include/bits/termios.h:# define CMSPAR 010000000000 /* mark or space (stick) parity */
/usr/include/asm-generic/termbits.h:#define CMSPAR 010000000000 /* mark or space (stick) parity */RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
shotdownsystem писал(а): ↑01.12.2010 11:18Ну расскажите про шутки этим ребятам: http://www.picbasic.ru/. И для АВРов тоже есть Бейсик.
Я тоже против религиозых войн, но так исторически сложилось, что системным ЯП стал Си.
Эти ребята и так все прекрасно знают про шутки. Для начинающих возможно и имеет смысл, но я бы для начинающих именно ассемблер порекомендовал, а потом сразу Си. Холивар http://lurkmore.ru/%D0%A5%D0%BE%D0%BB%D0%B...%B2%D0%B0%D1%80 на тему ЯП не поддерживаю. Что сие означает "но так исторически сложилось, что системным ЯП стал Си. http://lurkmore.ru/C "? Что за системы? ОС? Я знаю ОС написанную полностью на ассемблере (MenuetOS http://lurkmore.ru/MenuetOS ). А мне вообще по-боку на чем пишется ОС. Или под системой имеется ввиду программирование железа (систем ПК)? Все современные реализации Паскаль http://lurkmore.ru/Pascal позволяют делать с системой все тоже, что и Си, только более строго, не допускают детских ошибок неявных преобразований типов, например. "но так исторически сложилось, что системным ЯП стал Си", а вот разработчик Total Commander, к примеру, историю не учил и все лепит его на Delphi! На курсы истории его отправить, что ли? Может хватит про ЯП? Достало еще в 90-е гг.
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
SidorLuty писал(а): ↑01.12.2010 11:55Я знаю ОС написанную полностью на ассемблере (MenuetOS http://lurkmore.ru/MenuetOS ). А мне вообще по-боку на чем пишется ОС. Или под системой имеется ввиду программирование железа (систем ПК)? Все современные реализации Паскаль http://lurkmore.ru/Pascal позволяют делать с системой все тоже, что и Си, только более строго, не допускают детских ошибок неявных преобразований типов, например. "но так исторически сложилось, что системным ЯП стал Си", а вот разработчик Total Commander, к примеру, историю не учил и все лепит его на Delphi! На курсы истории его отправить, что ли? Может хватит про ЯП? Достало еще в 90-е гг.
Си более системный язык, Паскаль более прикладной. Программирование УАРТ системная задача.
А задание констант для стандартных устройств снижает ценность ПО
puts ("Working, please wait...");while(1);
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
без знания архитектуры и сразу ассемблер - оригинальный подход
а ну ка напишите на паскале кроссплатформенное приложение.
puts ("Working, please wait...");while(1);
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
shotdownsystem писал(а): ↑01.12.2010 12:29без знания архитектуры и сразу ассемблер - оригинальный подход
Без знания архитектуры только олигофрен в МК полезет. Нормельный прог. хотя бы одним глазом в даташит посмотрит.
Я с этого начал, если Вы внимательно читали первый пост. Lazarus - IDE для Free Pascal.
"А задание констант для стандартных устройств снижает ценность ПО" - проняло! Я по-наивности считал, что ценность ПО определяется надежностью и удобством пользования!
-
shotdownsystem
- Сообщения: 423
- ОС: Basic command interpreter
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
если поймет там что-то
Windows, linux - скучно. Давайте по взрослому - os-9, например.
ценность ПО определяется множеством факторов:надежность, удобство, читабельность кода, маштабируемость - понятия субъективные; есть еще и численные характеристики.
puts ("Working, please wait...");while(1);
-
SidorLuty
- Сообщения: 99
- ОС: Debian 5.0 Lenny
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
shotdownsystem писал(а): ↑01.12.2010 12:44Windows, linux - скучно. Давайте по взрослому - os-9, например.
А зачем? Мне-то это зачем? Я даже не знаю какой там GUI. Вот LynxOS это уже интереснее! Но такая задача у меня не стояла. А встанет, может на Си буду ее решать. Сколько раз повторять - мне все равно на чем писать - на Си, на Паскале - главное максимально полная и быстрая реализация поставленной задачи. Увижу, что Модула лучше подходит или ассемблер, буду на них писать, или другой язык какой выучу. Для той задачи, которую я описал выше по срокам и функциональности альтернативы Lazarus не было.
shotdownsystem писал(а): ↑01.12.2010 12:44ценность ПО определяется множеством факторов:надежность, удобство, читабельность кода, маштабируемость - понятия субъективные; есть еще и численные характеристики.
Для пользователей сетей наших приборов - только два фактора: 1 - возможность работать месяцами без сбоев и создавать базу данных для каждого прибора (минимальный интервал опроса - 6 с); 2 - возможность выбора даты и времени работы прибора и просмотр в виде графиков с возможностью вывода на печать. Все! Ну и, конечно, графики должны масштабироваться с выбором конкретной точки.
Давайте и мы поставим точку!
-
Doublespace
- Сообщения: 275
- ОС: Debian Lenny,Squeeze,Centos
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
Понимаю, что вы привязаны к уже имеющемуся коду, но lazarus- это тихий ужас. Там даже examples нормально не компилируются, в свое время поглядел на него, что ни шаг- то граблями в морду.
-
xorader
- Сообщения: 1030
- Статус: собирающий миры
- ОС: Debian
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
-Жуткий кошмар! Нули и единицы повсюду. Кажется, я видел двойку. Настоящую двойку!
- Это просто сон, Бендер. Двоек не бывает.
Molchanov Alexander (aka Xor)
*offtopic* - ololo!
*offtopic* - ololo!
-
artemst
- Сообщения: 1
- ОС: linux
Re: Личный опыт: Как я решил проблему бита четности Space и Mark в последовательном порте Linux
SidorLuty писал(а): ↑29.11.2010 12:43Описание проблемы.
Есть сеть RS-485 со множеством приборов. Мастер - только компьютер. Адрес и конец обмена выдаются с нулевым битом четности (Space), а обмен ведется с единичным битом четности (Mark). Корректность данных и команд контролируется контрольной суммой в конце команды от мастера и в конце данных от прибора. Есть исходники программ на Delphi. Очень легко все перевел на Lazarus в Windows. Получиласть такая же графическая оболочка, как и на Delphi (немного с построеним графиков заморочки были, т.к. компонент TChart сильно от дельфийского отличается). Но в итоге - практически аналогичная программа под Windows. Затевалось это все для портирования в Linux. И тут .... ЗАСАДА!!! В стандартном варианте Synaser для Linux ПРОСТО НЕЛЬЗЯ сделать бит четности Space/Mark. Никак!!!
Решение.
Начал рыть интернет. Наткнулся на статью Томаса Лочматтера "Linux and MARK/SPACE Parity" http://www.lothosoft.ch/thomas/libmip/markspaceparity.php Хорошо, думаю, путь понятен. Теперь надо надыбать конкретные биты во флаге c_cflag. Ну, с #define CMSPAR 010000000000 - понятно, переводим восьмеричное в hex и все. А вот с битами PARENB PARODD опять была засада - поиск #define PARODD (#define PARENB) давал такое количество вариантов, что голова кругом шла. Пришлось все варианты перепробовать. И вот окончательный результат
....
Всем привет.
Тоже реализую 9-битный протокол передачи. Изучил и первоисточник http://www.lothosoft.ch/thomas/libmip/markspaceparity.php В теории всё понятно. Вот часть кода:
Код:
int main(void)
{
int FileHandle;
unsigned char LedOn[] = {0x01,0x05,0x00,0x07,0xB4};
FileHandle = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
if ( FileHandle<0 )
{
puts ("error ");
FileHandle=-1;
return EXIT_FAILURE;
}
puts(" serial device opened" );
// Set port Settings
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | IGNBRK;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush(FileHandle, TCIOFLUSH);
tcsetattr(FileHandle, TCSANOW, &newtio);
// Set non-blocking mode
fcntl(FileHandle, F_SETFL, O_NONBLOCK);
SendPacket_9bit(FileHandle,LedOn,5);
close( FileHandle );
return EXIT_SUCCESS;
}
void SendPacket_9bit(int mFileHandle, unsigned char *packet, int len)
{
int err;
struct termios tio;
bzero(&tio, sizeof(tio));
tcgetattr(mFileHandle, &tio);
// Send first byte with mark parity
tio.c_cflag |= PARENB;
tio.c_cflag |= CMSPAR;
tio.c_cflag |= PARODD;
err = tcsetattr(mFileHandle, TCSADRAIN, &tio);
if(err) puts(" tcsetattr error ");
write(mFileHandle, packet, 1);
// Send the rest with space parity
tio.c_cflag &= ~PARODD;
err = tcsetattr(mFileHandle, TCSADRAIN, &tio);
if(err) puts(" tcsetattr error ");
write(mFileHandle, packet+1, len-1);
}
Но опыт показывает что, второе применение функции tcsetattr() после write() почему то безрезультатный. Т.е передаётся первый байт после первого write() в функции SendPacket_9bit, а остальные где то теряются. Всю голову уже поломал, не знаю куда копать
(так же тема продублирована на http://www.linux.org.ru/forum/development/7127056)