powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
7 сообщений из 7, страница 1 из 1
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39713831
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Отлаживал программу, долго и упорно. Данные передаются через раз. И передаются когда использую снифер ком порта. Во всех других случаях программа валится, потому что не получает ответы от устройства.
Решил проверить, а какие же настройки у меня падают в СОМ порт. Завёл для этого ещё одну переменную структуры термиос и:


Код: plaintext
1.
2.
    int ii = tcsetattr(m_hPort, TCSANOW, &Options); //применяю структуру к ком порту
    tcgetattr(m_hPort, &Options1); // получаю, но уже в другую переменную



Локальные переменные Options @0xbfd5e2c4 termios c_cc @0xbfd5e2d5 cc_t[32] c_cflag 7607 tcflag_t c_iflag 260 tcflag_t c_ispeed 4098 speed_t c_lflag 0 tcflag_t c_line 0 cc_t c_oflag 0 tcflag_t c_ospeed 4098 speed_t Options1 @0xbfd5e300 termios c_cc @0xbfd5e311 cc_t[32] c_cflag 7607 tcflag_t c_iflag 260 tcflag_t c_ispeed 4103 speed_t c_lflag 0 tcflag_t c_line 0 cc_t c_oflag 0 tcflag_t c_ospeed 4103 speed_t PortName "/dev/ttyUSB0" char*

вопрос: было ли у кого-нибудь такое и как с этим бороться?
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39713957
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Оказывается таких тем в интернете очень много, и ни одной нету ответа. Нашёл решение - костыльное, но решение.
Сначала в структуру termios записываю флаги и применяю её (структуру) к дескриптору, а затем прописываю скорости, чётности и остальное. Решил вопрос с нестабильностью получения из serial порта данных. В итоге инициализация порта у меня выглядит так:

Код: plaintext
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.
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE    -1
#endif

#ifndef FALSE
#define FALSE                   0
#endif

#ifndef TRUE
#define TRUE                    1
#endif
//дефайны на всякий случай.

BOOL CComPort::rawOpen(const char* PortName, long lBaudRate, long lDataBits, long lParity, long lStopBits)
{
    struct termios Options;

    m_hPort = open(PortName, O_RDWR | O_NOCTTY | O_SYNC | O_NOCTTY);
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    };

    tcgetattr(m_hPort, &Options);

    Options.c_cflag &= ~CRTSCTS;
    Options.c_cflag |= CREAD;

    Options.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO);
    Options.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON | BRKINT);
    Options.c_oflag &= ~OPOST;

    Options.c_cc[VTIME] = 0;
    Options.c_cc[VMIN] = 1;

    tcsetattr(m_hPort, TCSAFLUSH, &Options);
    tcgetattr(m_hPort, &Options);
    this->SetBaudRate(lBaudRate, Options);
    this->SetDataBits(lDataBits, Options);
    this->SetParity(lParity, Options);
    this->SetStopBits(lStopBits, Options);
    cfmakeraw(&Options);
    tcsetattr(m_hPort, TCSAFLUSH, &Options);

    return TRUE;
}
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39719473
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Диалог с самим собой.

В этом коде метод
"cfmakeraw(&Options);"
перезатирает все предыдущие настройки, поэтому его неверно использовать здесь. Как показала практика, ещё необходимо обнулять все флаги, перед тем как в них устанавливать новые значения.
Код: plaintext
1.
2.
3.
4.
    Options.c_cflag = 0;
    Options.c_lflag = 0;
    Options.c_iflag = 0;
    Options.c_oflag = 0;



Возник другой вопрос.
Очень медленно передаются данные в последовательный порт. Именно запись медленная. Программа под Windows отрабатывает примерно за 2 минуты, эта "закачивает" данные уже за 15+ минут.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
BOOL CComPort::SendByte(const byte b)
{
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    tcdrain(m_hPort);
    if (write(m_hPort, &b, 1) != 1)
    {
        return FALSE;
    }
    return TRUE;

}



Если убрать вызов очистки выходного буфера
" tcdrain(m_hPort);"
тогда вообще всё плохо.

Есть предложения в чём затык со скоростью может быть?
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39719499
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShevgeniyЕсть предложения в чём затык со скоростью может быть?

В передаче по одному байту.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39719559
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не моя придумка передавать по одному байту.
Эта программа для прошивки оборудования.
Точно такая же реализация работает прекрасно под Windows. А вот под Linux'ом не хочет работать быстро.
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39720244
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И всё же, что может тормозить процесс передачи данных в COM? При отладке переход на следующий оператор замирает именно в момент записи в порт и заметно долго находится в таком состоянии.
...
Рейтинг: 0 / 0
Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
    #39722312
Shevgeniy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Продолжаю свой диалог с собой:
Вопрос с медленной записью решился.

Я передавал данные в порт так:
Код: plaintext
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.
BOOL CComPort::SendByte(const byte b)
{
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    tcdrain(m_hPort);
    if (write(m_hPort, &b, 1) != 1)
    {
        return FALSE;
    }
    return TRUE;

}

BOOL CComPort::SendPacket( IN  const vector<byte> vbData )
{
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    for(size_t i = 0; i < vbData.size(); i++)
    {
        if(!SendByte(vbData[i]))
            return FALSE;
    }
    return TRUE;
}



Ключевой момент.
Код: plaintext
1.
    tcdrain(m_hPort);


переделал
Код: plaintext
1.
    tcflush(m_hPort, TCIFLUSH);



Я считал, что после записи в порт, необходимо отчистить исходящий буфер, а надо было чистить входящий буфер.
И оказалось из-за этого были некоторые тормоза. (Плюс из-за выбора синхронного режима в настройках COM порта).


Сделал вот так:
открытие порта
Код: plaintext
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.
BOOL CComPort::rawOpen(const char* PortName, long lBaudRate, long lDataBits, long lParity, long lStopBits)
{
    struct termios Options;

    m_hPort = open(PortName, O_RDWR | O_NOCTTY | O_NDELAY);
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    };

    tcgetattr(m_hPort, &Options);

    Options.c_cflag = 0;
    Options.c_lflag = 0;
    Options.c_iflag = 0;
    Options.c_oflag = 0;

    Options.c_cflag |= CRTSCTS;
    Options.c_iflag &= ~(IXON | IXOFF | IXANY);
    Options.c_cflag |= CREAD;

    Options.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO);
    Options.c_iflag &= ~(ICRNL | ISTRIP | BRKINT);
    Options.c_oflag &= ~OPOST;

    Options.c_cc[VTIME] = 0;
    Options.c_cc[VMIN] = 0;

    tcsetattr(m_hPort, TCSANOW, &Options);
    tcgetattr(m_hPort, &Options);
    this->SetBaudRate(lBaudRate, Options);
    this->SetDataBits(lDataBits, Options);
    this->SetParity(lParity, Options);
    this->SetStopBits(lStopBits, Options);
    tcsetattr(m_hPort, TCSANOW, &Options);

    return TRUE;
}


и передача в порт
Код: plaintext
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.
BOOL CComPort::SendByte(const byte b)
{
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    tcflush(m_hPort, TCIFLUSH);
    if (write(m_hPort, &b, 1) != 1)
    {
        return FALSE;
    }
    return TRUE;

}

BOOL CComPort::SendPacket( IN  const vector<byte> vbData )
{
    if(m_hPort == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
    for(size_t i = 0; i < vbData.size(); i++)
    {
        if(!SendByte(vbData[i]))
            return FALSE;
    }
    return TRUE;
}



теперь работает быстро.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Некорректная запись скорости передачи данных в настройки Serial порта в Linux.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]