Проблема со скоростью COM-порта
От: XaSSeR  
Дата: 05.06.10 12:15
Оценка:
Два компа связаны через com-порт. Написал программу обмена данными, но что то очень долго передается небольшой файл. Написал две тестовые программы:
1 программа просто открывает com-порт на одном компе и заворачивает все принятые байты назад.
Вот код программы.

main.cpp
//    Этот файл является частью проекта ПС "Конструктор".
//    Время создания: Втр Май 11 18:32:38 2010

#include <iostream.h>
#include <stdio.h>
#include <hrs232.h>

#define COM1    "/dev/ttyS0"
#define COM2    "/dev/ttyS1"

int main( int argc, char ** argv )
{
    char mmcc=0;
    printf("1 - COM1\n2 - COM2\n3 - Exit\n");
    cin >> mmcc;
    RS232 *mrs232;
    if (mmcc=='1') mrs232=new RS232((unsigned char*)COM1,0x3f8);
    else
    if (mmcc=='2') mrs232=new RS232((unsigned char*)COM2,0x2f8);
    else return 0;
    unsigned char rch=0;
    while (1==1)
    {
    mrs232->readdev();
    rch = mrs232->getreadchar();
    mrs232->writeprd(rch);
    }
    return 0;
}


prs232.cpp
#include <errno.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <linux/serial.h>
#include "hrs232.h"


RS232::RS232(unsigned char* buf,int sadr)
{    
    dev=new unsigned char[strlen((const char*)buf)+1];
    memcpy(dev,buf,strlen((const char*)buf)+1);
    strtadr=sadr;
    SIOperm();
    fd = open((const char*)buf, O_RDWR| O_NOCTTY); //| O_NDELAY
    if(fd<0)
    printf("\nErr open %s\n",buf);
    else
    printf("\nGood Open %s\n",buf);
    setttySmode();    
}

RS232::~RS232()
{
    close(fd);
}


void RS232::setttySmode()
{
//    tcflag_t FlSp=getspeed();
    struct termios newtio;
    memset(&newtio, 0,sizeof(newtio));
    newtio.c_cflag = B38400 | CS8 | CREAD|CSTOPB |PARENB|CLOCAL;
    //cкор|8 бит|доступный прием|2 стоп|дост паритет PARENB(если |PARODD-нечетно иначе четно)| игнорировать сгналы
    //newtio.c_cflag = FlSp | CS8 | CREAD|CSTOPB |PARENB;
    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME]    = 0;   // inter-character timer unused
    newtio.c_cc[VMIN]     = 1;//5;   // blocking read until 5 chars received
    tcflush(fd, TCIFLUSH);
    if(tcsetattr(fd,TCSANOW,&newtio)==-1)
    cerr << "err set ttyS";
}

int RS232::reinit()
{
    close(fd);
    SIOperm();
    fd = open((const char*) dev, O_RDWR| O_NDELAY| O_NOCTTY);// | O_NDELAY |
    setttySmode();
    return 0;
}

int RS232::SIOperm()
{
    int res=ioperm(strtadr,7,1);
    return res;
}

int RS232::writeprd(unsigned char chfout)/*запись в порт*/
{
    int res;//,i;
    res=write(fd,&chfout,1);
    return res;
}

int RS232::readdev()//читаем порт
{
    unsigned char chfr=0;
    int i=read(fd,&chfr,1);
    mreadch=chfr;
    return i;
}


hrs232.h

#if !defined( __HRS232_H)
#define __HRS232_H

#include <pthread.h>



class RS232
{
    public:
    RS232(unsigned char*,int);
    ~RS232();
    
    int  readdev();    
    void setttySmode();
    int  reinit();
    unsigned char getreadchar(){return mreadch;}
    int  SIOperm();
    int  writeprd(unsigned char);
    int get_fd(){return fd;}
    
    private:
    unsigned char mreadch;
    int fd;
    unsigned char* dev;
    int strtadr;
    
};


#endif


2 программа отсылает байт, потом принимает его, считает скорость и выводит ее.
Вот код второй программы

main.cpp
//    Этот файл является частью проекта ПС "Конструктор".
//    Время создания: Втр Май 11 18:32:38 2010

#include <iostream.h>
#include <stdio.h>
#include <time.h>
#include <hrs232.h>

#define COM1    "/dev/ttyS0"
#define COM2    "/dev/ttyS1"

void clrcr(void)
/*Очистка консоли.*/
{
    printf("\033[2J");
    printf("\033[0;0f");
    return;
}

int main( int argc, char ** argv )
{
    char mmcc=0;
    while (1==1)
    {
    printf("\n1 - COM1\n2 - COM2\n3 - Exit\n");
    cin >> mmcc;
    RS232 *mrs232;
    if (mmcc=='1') mrs232=new RS232((unsigned char*)COM1,0x3f8);
    else
        if (mmcc=='2') mrs232=new RS232((unsigned char*)COM2,0x2f8);
    else return 0;
    printf("1 - Speed test\n2 - Read-Write test\n3 - Exit\n");
    cin >> mmcc;
    if (mmcc=='2')
    {
        unsigned char rch=0;
        unsigned char i=0;
        int mb=0;
        int ke=0;
        while (mb==0)
        {
        mrs232->writeprd(i);
        mrs232->readdev();
        rch=mrs232->getreadchar();
        if (rch!=i) {printf("\nError!!! Output - %02x. Input - %02x\n",i,rch);ke++;}
        else printf("%02x ",i);
        if (i==0xff) mb++;
        i++;
        }
        printf("\nRead/Write - 256 byte. Error - %d.\n",ke);
    }
    else if (mmcc=='1')
    {
        clrcr();
        time_t first_now,second_now;            //время 1 и 2
        first_now = time((time_t*)NULL);        //получаем текущее время            //получаем текущее время
        unsigned long tout=0;                //разница времен
        unsigned long prb=0;
        unsigned char mskret=0x55;            //для считывания символа    
        mrs232->writeprd(mskret);
        int kolpop=0;
        
        while (kolpop<10)
        {
        if (mrs232->readdev()==1) 
        {
            mskret=mrs232->getreadchar();
            if (mskret!=0x55) printf("Error I/O!\n");
            mskret=0x55;
            mrs232->writeprd(mskret);
            prb++;
        }
        second_now = time((time_t*)NULL);    //получаем текущее время
        tout=difftime(second_now, first_now);    //узнаем разницу времен в секундах;
        if (tout>=3) 
        {
            printf("%d byte/s\n", prb*2/3);
            prb=0;
            first_now=second_now;
            kolpop++;
        }
        }
        prb=0;
        printf("Next Test Begin NOW!\n");
        first_now = time((time_t*)NULL);        //получаем текущее время    
        while (prb<=500);
        {
        if (mrs232->readdev()==1) 
        {
            mskret=mrs232->getreadchar();
            if (mskret!=0x55) printf("Error I/O!\n");
            mskret=0x55;
            mrs232->writeprd(mskret);
            prb++;
        }
        }
        second_now = time((time_t*)NULL);    //получаем текущее время
        tout=difftime(second_now, first_now);    //узнаем разницу времен в секундах
        printf("Read/Write 4000 byte from %d sec.\n",tout);
    }
    else return 0;
    }
    return 0;
}


prs232.cpp
#include <errno.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <linux/serial.h>
#include "hrs232.h"


RS232::RS232(unsigned char* buf,int sadr)
{    
    dev=new unsigned char[strlen((const char*)buf)+1];
    memcpy(dev,buf,strlen((const char*)buf)+1);
    strtadr=sadr;
    SIOperm();
    fd = open((const char*)buf, O_RDWR| O_NOCTTY); //| O_NDELAY
    if(fd<0)
    printf("\nErr open %s\n",buf);
    else
    printf("\nGood Open %s\n",buf);
    setttySmode();       
}

RS232::~RS232()
{
    close(fd);
}


void RS232::setttySmode()
{
    struct termios newtio;
    memset(&newtio, 0,sizeof(newtio));
    newtio.c_cflag = B38400 | CS8 | CREAD|CSTOPB |PARENB|CLOCAL;
    //cкор|8 бит|доступный прием|2 стоп|дост паритет PARENB(если |PARODD-нечетно иначе четно)| игнорировать сгналы
    //newtio.c_cflag = FlSp | CS8 | CREAD|CSTOPB |PARENB;
    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME]    = 0;   // inter-character timer unused
    newtio.c_cc[VMIN]     = 1;//5;   // blocking read until 5 chars received
    tcflush(fd, TCIFLUSH);
    if(tcsetattr(fd,TCSANOW,&newtio)==-1)
    cerr << "err set ttyS";
}

int RS232::reinit()
{
    close(fd);
    SIOperm();
    fd = open((const char*) dev, O_RDWR| O_NDELAY| O_NOCTTY);// | O_NDELAY |
    setttySmode();
    return 0;
}

int RS232::SIOperm()
{
    int res=ioperm(strtadr,7,1);
    return res;
}

int RS232::writeprd(unsigned char chfout)/*запись в порт*/
{
    int res=1;//,i;
    res=write(fd,&chfout,1);
    return res;
}

int RS232::readdev()//читаем порт
{
    unsigned char chfr=0;
    int i=read(fd,&chfr,1);
    readchar=chfr;
    return i;
}


hrs232.h

#if !defined( __HRS232_H)
#define __HRS232_H

#include <pthread.h>



class RS232
{
    public:
    
    RS232(unsigned char*,int);
    ~RS232();
    
    int  readdev();    
    void setttySmode();
    unsigned char getreadchar(){return readchar;}
    int  reinit();
    int  SIOperm();
    int  writeprd(unsigned char);
    int get_fd(){return fd;}
    
    private:
    int fd;
    unsigned char* dev;
    int strtadr;
    unsigned char readchar;
    
};


#endif


Запускаю одну программу на одном компьютере, другую на другом и получаю скорость обмена где-то 200 байт в секунду. Хотя скорость должна быть намного больше. Почему так происходит? И как бы это мне исправить.
Re: Проблема со скоростью COM-порта
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.06.10 20:14
Оценка: 3 (1)
Здравствуйте, XaSSeR, Вы писали:

XSS>Два компа связаны через com-порт. Написал программу обмена данными, но что то очень долго передается небольшой файл. Написал две тестовые программы:

XSS>1 программа просто открывает com-порт на одном компе и заворачивает все принятые байты назад.
XSS>Вот код программы.

1. Выбросьте воспоминания об адресах портов типа 0x3f8. Если работаете через драйвер, работайте через драйвер. Никакие I/O permissions тут нафиг не нужны, только мешают.

2. Нельзя плевать на ошибки. Например, если fd = open(...) выдало -1, то или вызывайте err() из <err.h> и завершайте программу, или — если уж приспичило такую тривиальщину делать на C++ — кидайте исключение.

3. Не понимаю смысла в комбинации 8 бит, чётности и двух стопов. Это чтобы сразу на лыжах и в гамаке?:) На локальном шнурке — уберите чётность и два стопа, будет легче проверять.

4. Рекомендуется не ставить поля termios напрямую и с нуля, а ставить скорости через cfsetspeed() и вводить сырой режим через cfmakeraw().

Это вчерне. А теперь смотрим вот на что. 200 байт в секунду, говорите? Наверняка машинки чем-то ещё подгружены. Типичный линукс не совсем недавних времён имеет таймерное прерывание 100 раз в секунду. Если данные пришли, а машинка занята другим, она может и 10 и 20 мс чего-то ждать. Не знаю, какой там у Вас шедулер и как он настроен. Но отвечать он может ой не сразу.

Я вот предполагаю, что если программы переделать на посылку не 1 байта за цикл, а N — скорость "внезапно" станет не 200 байт/сек, а чуть-чуть меньше чем 200*N байт/сек. Разумеется, это при N < 19, иначе таки будет затыкание по скорости линии.

Попробуйте.
The God is real, unless declared integer.
Re[2]: Проблема со скоростью COM-порта
От: XaSSeR  
Дата: 05.06.10 20:49
Оценка:
Здравствуйте, netch80, Вы писали:

N>Я вот предполагаю, что если программы переделать на посылку не 1 байта за цикл, а N — скорость "внезапно" станет не 200 байт/сек, а чуть-чуть меньше чем 200*N байт/сек. Разумеется, это при N < 19, иначе таки будет затыкание по скорости линии.


N>Попробуйте.


У меня реализовано 2 программы, которые обмениваются данными: одна шлет байт данных, а другая передает квитанцию на байт. Пробовал передавать данные без квитанции — идет потеря данных. Так что я не могу писать больше 1 байта.
Re[3]: Проблема со скоростью COM-порта
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.06.10 21:03
Оценка: 1 (1)
Здравствуйте, XaSSeR, Вы писали:

N>>Я вот предполагаю, что если программы переделать на посылку не 1 байта за цикл, а N — скорость "внезапно" станет не 200 байт/сек, а чуть-чуть меньше чем 200*N байт/сек. Разумеется, это при N < 19, иначе таки будет затыкание по скорости линии.


N>>Попробуйте.


XSS>У меня реализовано 2 программы, которые обмениваются данными: одна шлет байт данных, а другая передает квитанцию на байт. Пробовал передавать данные без квитанции — идет потеря данных. Так что я не могу писать больше 1 байта.


Муть какую-то пишете, чесслово. Причём тут "передавать без квитанции"? Попробуйте в обеих программах читать и писать не по 1 байту за раз, а сразу 4. Правка тривиальна, зато результат сразу будет виден.
The God is real, unless declared integer.
Re: Проблема со скоростью COM-порта
От: ДимДимыч Украина http://klug.org.ua
Дата: 06.06.10 15:50
Оценка:
Здравствуйте, XaSSeR, Вы писали:

XSS>Запускаю одну программу на одном компьютере, другую на другом и получаю скорость обмена где-то 200 байт в секунду. Хотя скорость должна быть намного больше.


Помимо вышесказанного, вот Вам способ для проверки. С принимающей стороны:
$ stty -F /dev/ttyS0 38400 cs8 -cstopb -parity
$ cat /dev/ttyS0 > destination_file

С передающей:
$ stty -F /dev/ttyS0 38400 cs8 -cstopb -parity
$ cat source_file > /dev/ttyS0


А насчет "квитанций", если в них есть необходимость — поднимайте SLIP.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.