Драйвер для ДК использует стандартную библиотеку Libmodbus v.2.0.3 от Stephane Raimbault. Первый вариант реализовывал на базе другой библиотеки libmodbus 0.0.1.
Однако, столкнулся с трудностями интеграции библиотеки с основным ядром ДК. С библиотекой от Стефана же проблем не возникло, все очень четко и продумано.
Немного опишу процедуру использования.
Шаг первый - конфигурация ["./configure" в директории пакета]
Шаг второй - компиляция ["make" там же]
Шаг третий - инсталляция ["make install"]
Библиотека устанавливается в "/usr/local/bin", заголовочные файлы в "/usr/local/include".
Линкуем библиотеку в make файле своего проекта -lmodbus.
В драйвере устройства (в нашем случае тепловычислителя Эльф),
прописываем неоходимые действия, например чтение данных:
//1. Установить в регистр Архив(40001 + 3) значение соответствующее требуемому архиву.
result = preset_single_register(&mb_param, this->adr, ADR_ARCHTYPE, rs);
// this->adr - адрес устройства, ADR_ARCHTYPE - адрес регистра типа читаемого архива,
rs - тип архива (9-текущие, 26-часовые, 27-дневные, 28-по месяцам)
//2. Заполните поля ГОД, МЕСЯЦ, ДЕНЬ, ЧАС(40001+0 - 40001+1) значениями,
соответствующими дате требуемой архивной записи.
rs=(10)*256+currenttime->tm_mon+1;
result = preset_single_register(&mb_param, this->adr, ADR_YEAR, rs);
if (type==DAY_ARCHIVE) rs=(currenttime->tm_mday-1)*256+currenttime->tm_hour;
else rs=currenttime->tm_mday*256+currenttime->tm_hour;
result = preset_single_register(&mb_param, this->adr, ADR_YEAR+1, rs);
//3. Установить биты AId, Id в регистре Статус(40001 + 6) в значение 0, а биты Dbd, AIc в 1.
if (type>9) rs=0x6A; else rs=0;
result = preset_single_register(&mb_param, this->adr, ADR_STATUS, rs);
// Читаем циклически нужное количество записей, метка времени при этом декрементируется.
//4. Считать таблицу измерительных параметров. Регистры имеют формат данных Тип1.
result = read_input_registers(&mb_param, this->adr, ADR_DATA, 20, (uint16_t *)data);
data_in[0]=data[16]; data_in[3]=data[15]; data_in[2]=data[14]; data_in[1]=data[13];
q=*(float*)(data_in);
Результат работы программы примерно следующий.
[elf] total 1 ELF add to list
Opening /dev/ttyS1 at 4800 bauds (none)
[elf] open com-port success
[01][04][03][42][00][04][51][99]
Waiting for a message (13 bytes)...
<01><04><08><03><02><00><04><03><03><09><00><40><0C>
[elf] ELF [23403309] software
[01][04][00][00][00][03][B0][0B]
Waiting for a message (11 bytes)...
<01><04><06><0A><03><11><0E><2D><1C><23>
[elf] ELF time [17-03-2010 14:45:00]
[01][06][00][03][00][09][B9][CC]
Waiting for a message (8 bytes)...
<01><06><00><03><00><09>
[01][06][00][06][00][00][69][CB]
Waiting for a message (8 bytes)...
<01><06><00><06><00><00><69>
[01][04][01][00][00][14][F1][F9]
Waiting for a message (45 bytes)...
<01><04><28><39><2D><0E><00><80><00><00><00><00><00><00><00><00><00><00><48><11><36><0A>
<00><00><00><00><4A><50><3C><1A><00><42><99><89><00><42><99><01><5C><38>
[elf] [14:45:57] q1=0.000000, q2=0.000002, t1=76.972656, t2=76.767586, v1=0.000000, v2=0.009417
// считанные текущие данные
[01][06][00][03][00][1B][39][C1]
Waiting for a message (8 bytes)...
<01><06><00><03><00><1B><39>
[01][06][00][00][0A][03][CF][6B]
Waiting for a message (8 bytes)...
<01><06><00><00><0A><03><6B>
[01][06][00][01][10][0D][14][0F]
Waiting for a message (8 bytes)...
<01><06><00><01><10><0D><14><0F>
[01][06][00][06][00][6A][E9][E4]
Waiting for a message (8 bytes)...
<01><06><00><06><00><6A>
[01][04][01][00][00][14][F1][F9]
Waiting for a message (45 bytes)...
<01><04><28><0A><03><10><00><80><00><00><00><00><41><00><00><00><00><00><00><00><00>
<00><00><00><00><00><00><00><00><47><42><99><87><61><42><99><00><00><00><00><6B>
[elf] [16-03-2010 00:00:00] q=0.000000, t1=76.965584, t2=76.763672, v1=0.000000, v2=0.000000
// считанные архивные данные
Вот и все. Удачного программирования.
Заметки:
Перспектива:
Драйвер будет сильно дорабатываться под новые задачи и пожелания, будет реализовано чтение всех параметров прибора.