LINUX.ORG.RU

serial port in raw mode & bad performance


0

0

Здравствуйте.

Здесь нужно обмениваться с неким железом (микроконтроллер) по последовательному порту. При этом информацию нужно осылать побайтно. Почему-то получается что не зависимо от скорости порта задержка между посылкой байт составляет 1/100 сек. Как этого можно избежать ?


Смотри прогу на контроллере или компе может чегото ждет с MCS51 такого не видел да и какая разница обмен то идет побитно

anonymous
()

Как раз с контроллером все в порядке. Существует программа под дос, которая великолепно с ним работает. Да и контроллер здесь не при чем. У меня есть тестовая программка, которая показывает этот эффект. Oна просто пишет данные в порт не ожидая никакого ответа. При этом к порту не нужно ничего подключать.

********** in file test-sline.cc ************

/* serial communication tester */ /* (C) Andrey A. Kolesnik */

#include <termios.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <stdio.h> #include <time.h> #include <string.h> #include <iostream>

#define DEV "/dev/ttyS1" #define BAUD B38400

int main() { int fd; termios old_options, options; fd = open(DEV, O_RDWR | O_NOCTTY | O_NDELAY ); if (-1 == fd) { cerr << "Unable to open " << DEV << endl; exit(1); } // init device fcntl(fd, F_SETFL, 0); // we'll wait for data tcgetattr(fd, &old_options); //store old options bzero(&options, sizeof(options)); //cfmakeraw(&options); options.c_cflag |= CS8 | CLOCAL | CREAD; // options.c_cflag |= CRTSCTS; options.c_iflag = IGNPAR ; options.c_oflag = 0; options.c_lflag = 0; options.c_cflag |= CSTOPB; // two stop bits

options.c_cc[VMIN]=0; options.c_cc[VTIME]=10; cfsetispeed(&options, BAUD); cfsetospeed(&options, BAUD); tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &options); // apply them immediately // end of init // sending bunch of data cout << "Sending [" ; int tm = time(NULL); int pcounter = 0; for (int idx = 0; idx < 1000 ; idx++) { int result; result = write(fd, &idx, 1); if (-1 == result) perror("write failed"); tcdrain(fd); if (!(++pcounter%10)) cout << '.' << flush ; // print point at each tenth byte } cout << "] sent at " << 11*1000/(time(NULL)-tm) << " bps." << endl;

tcsetattr(fd, TCSANOW, &old_options);

} ******** eof test-sline.cc ***************

Подчеркиваю, что обмен побайтный, после посылки байта нужно дождаться результата от контроллера. Отсюда tcdrain().

surfer
() автор топика

Ой. С форматированием проблема. Sorry.

/* serial communication tester */
/* (C) Andrey A. Kolesnik */

#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <iostream>

#define DEV "/dev/ttyS1"
#define BAUD B38400

int main()
{
        int fd;
        termios old_options, options;
        
        fd = open(DEV, O_RDWR | O_NOCTTY | O_NDELAY );
        if (-1 == fd)
        {
                cerr << "Unable to open " << DEV << endl;
                exit(1);
        } 
        // init device
        
        fcntl(fd, F_SETFL, 0);          // we'll wait for data          
        tcgetattr(fd, &old_options);    //store old options
        bzero(&options, sizeof(options));
        //cfmakeraw(&options);
        options.c_cflag |= CS8 | CLOCAL | CREAD;
//              options.c_cflag |= CRTSCTS; 
        options.c_iflag = IGNPAR ;
        options.c_oflag = 0;
        options.c_lflag = 0;
        options.c_cflag |= CSTOPB;              // two stop bits

        options.c_cc[VMIN]=0;
        options.c_cc[VTIME]=10;
        
        cfsetispeed(&options, BAUD);
        cfsetospeed(&options, BAUD);
        tcflush(fd, TCIFLUSH);  
        tcsetattr(fd, TCSANOW, &options); // apply them immediately
        // end of init 
        // sending bunch of data
        cout << "Sending [" ;
        int tm = time(NULL);
        int pcounter = 0;
        for (int idx = 0; idx < 1000 ; idx++)
        {
                int result;
                result = write(fd, &idx, 1);
                if (-1 == result) perror("write failed");
                tcdrain(fd);
                if (!(++pcounter%10)) cout << '.' << flush ; 
         // print point at each tenth byte
        }
        cout << "] sent at " << 11*1000/(time(NULL)-tm) << " bps." << endl;

        tcsetattr(fd, TCSANOW, &old_options);

}

surfer
() автор топика

Проверь setserial(на порту) и снизь для скорость до 28800.

saper ★★★★★
()

saper: Ты хочешь сказать, что у тебя тест показывает bps близкий к 38400 ?

surfer
() автор топика

Может статься, что система так и должна работать: сам посуди -- вывод в сом-порт происходит по прерыванию, а если нет данных на передачу, прерывание снимается. А однако ты передавая байт не отдаешь его непосредственно в аппаратный порт, а система забирает у тебя этот байт, и складывает его в буфер, а драйвер тоже не может проверять буфер с бесконечной скоростью (а прерывания-то он не получает оно ведь уже снято), а проверяет его по таймеру. Если бы ты передавал данные килобайтами, проблем с перфомансом бы не было. Выход -- работать с СОМ-портом непосредственно, как в дос.

ansky ★★★★★
()

У меня скорость 1100 (в программке). Как же так работает модем? Внешний ... у него 56K бывает.

saper ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.