2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
1

Блок управления и rs 232

10.11.2016, 12:20. Показов 2417. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток, форумчане. Сразу перейду к делу, есть блок управления двумя фотоприемниками и затворами, нужно программно обеспечить проведение эксперимента с использованием этих устройств, есть код на c# нужно переписать на c++, либо написать подобный, чем я и занялся.

Вступление:
Удаленный компьютер (PC) всегда мастер (master) на линии, устройство (УС) всегда раб (slave).

Обмен данными происходит в пакетном режиме.
Начало пакета это байт 0x55.

Первый байт – байт статуса пакета, распределение битов в этом байте:
биты 0 – 4 это адрес устройства (0x00..0x01F; 0..31),
биты 5 и 6 длина данных (бит 0x20 и бит 0x40):
0b00 – один байт
0b01 – двухбайтовое число (целое)
0b10 – резервный параметр
0b11 – четырехбайтовое число (плавающее)
бит 7 (0x80) определяет тип операции
1- чтение из прибора,
0 - запись в прибор
Второй и Третий байт – 16 разрядный адрес данных в приборе.
Второй байт - старший байт адреса,
Третий байт – младший байт адреса.
Байты 4, 5, 6, 7 – байты данных.
Для байтовых операций данные – это байт 7.
Для двухбайтовых операций – байты 6-7.
Байт 8 это последний байт – контрольная сумма.
Контрольная сумма это сумма байтов с первого по 8. Для вычисления контрольной суммы байты складываются как беззнаковые 8 битные числа (unsigned char).

Если тип операции – запись, то устройство (SLAVE) игнорирует байты данных.
Если тип операции чтение, то устройство (SLAVE) отправляет тот же пакет, только данные другие.
Поскольку PC всегда мастер, то обмен данными происходит только по команде со стороны PC.
Прибор в ответ отправляет такой же пакет.

Суть проблемы:
1) Serial port не отвечает на пакеты, или отвечает на предыдущие спустя несколько пакетов.
Пример:
Чтобы ввести устройство в режим "измерение" (идет считывание с фотоприемников, моргают затворы) нужно записать задержки в мс (в пределах 1 секунды) на 3 стадии работы:
stad1 - задержка на стадию 1 (время когда оба затвора открыты) это 2 байта (unsigned int) по адресу 0xDF

stad2 - задержка на стадию 2 (затвор 2 - закрыт; затвор 1 - открыт) это 2 байта (unsigned int) по адресу 0xE1

stad3 - задержка на стадию 3 (оба затвора закрыты) это 2 байта (unsigned int) по адресу 0xE3
Как я это реализовал:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    //Delay 1 (байт для записи первой задержки)
    zad1.resize(9);
    zad1[0] = 0x55;
    zad1[1] = 0x21;
    zad1[2] = 0;
    zad1[3] = 0xDF;
    zad1[4] = 0;
    zad1[5] = 0;
    if (zad1in > 256) //условие если длительность задержки больше 256 (режим двух двухбайтовых числа)
    {
    zad1[6] = 1;
    zad1[7] = (zad1in - 256);
    }
    else //если длительность задержки меньше 256 (режим одного двухбайтового числа)
    {
    zad1[6] = 0;
    zad1[7] = zad1in;
    }
    zad1[8] = zad1[1];
    for (int i=2; i<8; i++)
        zad1[8]=zad1[8]+zad1[i];
 
 
    //Delay 2 (байт для записи второй задержки)
    zad2.resize(9);
    zad2[0] = 0x55;
    zad2[1] = 0x21;
    zad2[2] = 0;
    zad2[3] = 0xE1;
    zad2[4] = 0;
    zad2[5] = 0;
    if (zad2in > 256) //условие если длительность задержки больше 256 (режим двух двухбайтовых числа)
    {
    zad2[6] = 1;
    zad2[7] = (zad2in - 256);
    }
    else //если длительность задержки меньше 256 (режим одного двухбайтового числа)
    {
    zad2[6] = 0;
    zad2[7] = zad2in;
    }
    zad2[8] = zad2[1];
    for (int i=2; i<8; i++)
        zad2[8]=zad2[8]+zad2[i];
 
 
    //Delay 3 (байт для записи третьей задержки)
    zad3.resize(9);
    zad3[0] = 0x55;
    zad3[1] = 0x21;
    zad3[2] = 0;
    zad3[3] = 0xE3;
    zad3[4] = 0;
    zad3[5] = 0;
    if (zad3in > 256) //условие если длительность задержки больше 256 (режим двух двухбайтовых числа)
    {
    zad3[6] = 1;
    zad3[7] = (zad3in - 256);
    }
    else //если длительность задержки меньше 256 (режим одного двухбайтового числа)
    {
    zad3[6] = 0;
    zad3[7] = zad3in;
    }
    zad3[8] = zad3[1];
    for (int i=2; i<8; i++)
        zad3[8]=zad3[8]+zad3[i];
 
    //Запись
    com1->write(zad1);
    com1->write(zad2);
    com1->write(zad3);
В ответ устройство после каждый записи com1->write(...) должно отправлять такой же байт, но устройство отправляет ответ только на команду com1->write(zad1); (отслеживал в режиме HEX программой Advanced Serial Port Monitor)

Как исправить? (пробовал считывать командой com1->read(result, 9); толку нету, так же пробовал использовать функцию com1->waitForBytesWritten(100); после каждой записи, ситуация не поменялась)

Могу скинуть исходники на c# (там все работает как надо) и свои исходники если необходимо

Буду благодарен за любую помощь.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.11.2016, 12:20
Ответы с готовыми решениями:

Алгоритм или протокол управления эл.двигателем по RS-232
Всем привет! Подскажите плз как бы правильнее реализовать управление эл.двиг. подключенного к МК...

rusEfi - блок управления двигателем
Я допроектировал свой ЭБУ до состояния, что могу ездить вокруг дома. Ищу смелых добровольцев, кто...

Блок управления шаговым двигателем.
Доброго времени суток. Возникла у меня необходимость сделать непростое устройство с шаговым...

Блок управления микропрограммной структурой
Добрый вечер всем,не знаю правильную ли выбрал тему,но нужна помощь. Нам дали задание,а я делал...

13
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
10.11.2016, 14:32 2
Krounis, что скрывает строчка com1->write(zad1) и как вы собственно принимаете данные?
0
2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
10.11.2016, 15:04  [ТС] 3
vxg, com1->write(zad1) это запись в компорт байта первой задержки, принимать данные не обязательно, этими командами я даю понять устройству, что сейчас будет проходить запись/считывание данных с фотоприемников, при том что два затвора будут открываться и закрываться в определенные моменты. А вообще прием данных далее буду осуществлять:
C++ (Qt)
1
2
char Result[9];
com1->read(Result, 9);
Устройство должно мне ответить таким же пакетом, это будет означать что задержка записалась

P.S.
C++ (Qt)
1
2
3
4
5
6
7
8
9
//SerialPort
    com1 = new QSerialPort;
        com1->setPortName("COM1");
        com1->open(QIODevice::ReadWrite);
        com1->setFlowControl(QSerialPort::NoFlowControl);
        com1->setBaudRate(QSerialPort::Baud115200);
        com1->setStopBits(QSerialPort::OneStop);
        com1->setDataBits(QSerialPort::Data8);
        com1->setDataTerminalReady(false);
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
10.11.2016, 15:38 4
Krounis, попробуйте понизить скорость обмена. какие таймауты ставит QSerialPort не смотрели?
0
2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
10.11.2016, 16:10  [ТС] 5
vxg, а как их посмотреть/поменять?
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
10.11.2016, 18:48 6
Krounis, если бы речь шла о winapi я бы сказал а в qt не знаю в свойствах объекта смотреть надо очевидно
0
2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
10.11.2016, 19:29  [ТС] 7
vxg, хорошо, спасибо попробую, как я понимаю таймауты надо уменьшить?
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
11.11.2016, 06:22 8
Krounis, я думаю что они наоборот могут быть очень малыми
0
2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
12.11.2016, 08:48  [ТС] 9
vxg, не нашел как настроить тайм-ауты((
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
12.11.2016, 17:58 10
Krounis, попробуйте для пробы кинуть запрос через winapi
0
2 / 2 / 1
Регистрация: 10.11.2016
Сообщений: 94
13.11.2016, 18:51  [ТС] 11
vxg, а это как?)
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
14.11.2016, 11:18 12
Krounis, примерно так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
        HANDLE h;
        DCB dcb;
        COMMTIMEOUTS cto; 
 
        h = INVALID_HANDLE_VALUE;
 
        memset(&dcb, 0, sizeof(dcb));
        memset(&cto, 0, sizeof(cto));
    
        dcb.DCBlength = sizeof(dcb);
    
        dcb.BaudRate = CBR_9600;
        dcb.fBinary = true;
        dcb.fParity = false;
        dcb.fOutxCtsFlow = false;
        dcb.fOutxDsrFlow = false;
        dcb.fDtrControl = DTR_CONTROL_DISABLE;
        dcb.fDsrSensitivity = false;
        dcb.fTXContinueOnXoff = false;
        dcb.fOutX = false;
        dcb.fInX = false;
        dcb.fErrorChar = false;
        dcb.fNull = false;
        dcb.fRtsControl = RTS_CONTROL_DISABLE;
        dcb.fAbortOnError = false;
        dcb.ByteSize = 8;
        dcb.Parity = 0;
        dcb.StopBits = 0;
        dcb.XonChar = '\x11';
        dcb.XoffChar = '\x13';
        dcb.ErrorChar = '\x00';
        dcb.EofChar = '\x00';
        dcb.EvtChar = '\x00';
 
        cto.ReadIntervalTimeout = 0;
        cto.ReadTotalTimeoutMultiplier = 0;
        cto.ReadTotalTimeoutConstant = 1000;
        cto.WriteTotalTimeoutMultiplier = 0;
        cto.WriteTotalTimeoutConstant = 1000;
 
        h = CreateFile
        (
            "COM1", //lpFileName
            GENERIC_READ | GENERIC_WRITE, //dwDesiredAccess
            0, //dwShareMode
            0, //lpSecurityAttributes
            OPEN_EXISTING, //dwCreationDistribution
            FILE_ATTRIBUTE_NORMAL, //dwFlagsAndAttributes
            0 //hTemplateFile
        );
        PurgeComm
        (
            h,
            PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR
        );
        SetCommState(h, &dcb);
        SetCommTimeouts(h, &cto);
        GetCommState(h, &dcb);
        GetCommTimeouts(h, &cto);
...
        //------------------------------------------------------------------------------
        bool com_port::write(unsigned char *out, unsigned long sizeof_out)
        {
            unsigned long sizeof_out_real;
            return
            WriteFile(h, out, sizeof_out, &sizeof_out_real, 0) &&
            sizeof_out_real == sizeof_out;
        }
        //------------------------------------------------------------------------------
        bool com_port::read(unsigned char *in, unsigned long * const sizeof_in)
        {
            unsigned long sizeof_in_max = *sizeof_in;
            return
            ReadFile(h, in, sizeof_in_max, sizeof_in, 0);
        }
0
45 / 44 / 1
Регистрация: 11.07.2012
Сообщений: 1,024
18.11.2016, 13:16 13
Цитата Сообщение от vxg Посмотреть сообщение
Krounis, примерно так
я так понимаю, это код настройки регистров сом порта, в каком то типовом варианте?
0
Модератор
3382 / 2154 / 352
Регистрация: 13.01.2012
Сообщений: 8,371
18.11.2016, 13:48 14
седьмой, да
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.11.2016, 13:48
Помогаю со студенческими работами здесь

Блок управления ШД с тремя обмотками
Задача: сделать блок управления для ШД, который можно подцепить к МК. двигатель не один, их два....

Беспроводной блок управления нагрузками 220В
Приветствую. Ищу информацию о следующем девайсе. Требуется дистанционно (например, брелком) в...

Блок управления подкачивающего насоса котла
Доброго времени суток! Уважаемые форумчане обращаюсь к Вам, за помощью. Требуется составить...

Блок управления автоматическим открыванием ворот
Надумал создать свой блок управления открыванием ворот. Пока схемку только накидал, собираюсь плату...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru