[C++]Seriele Port communicatie lukt niet

Pagina: 1
Acties:

  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
Hoi,

Ik ben hier bezig met ene proggie die data over de seriele poort kan lezen en schrijven. Nu heb ik voor deze communicatie een mooie rs232 classe opgezet. Het probleem is dat het zenden helemaal goed gaat alleen het ontvangen gata totaal mis. Ik heb al heel wat serial howto's en manuals gelezen maar nergens staat iets wat mij kan helpen of wat ik nog niet geprobeerd heb.

Als eerste mijn code.

code:
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
bool RS232::initCommunication(void)
{
    termios oldtio;
    termios newtio;
    m_connection = open(this->m_iodevice, O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if (m_connection < 0)
    {
        printf("Port open failed\n");
        return false;
    }   
    else
    {
        //See man termios
        
        tcgetattr(m_connection, &oldtio);
        bzero(&newtio, sizeof(newtio));
        
        newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
        newtio.c_lflag = 0;
        
        //Delay for read
        newtio.c_cc[VTIME]=10;
        
        //Minimal characters to read
        newtio.c_cc[VMIN]=1;
        
        tcflush(m_connection, TCIFLUSH);
        tcsetattr(m_connection, TCSANOW, &newtio);
        printf("Port opened sucsesful\n");  
        return true;    
    }   
}

char* RS232::readData(int bytes)
{
    char *input = "";
    int res;
    
    if (m_connection < 1)
    {
        initCommunication();    
    }
    while(1){
        res = read(m_connection, input, bytes);
        if (res == -1)
        {
            //Error no data
            if (errno==EAGAIN)
            {
                printf("%s\n", "No data at this moment");
                usleep(500000);
            }
            else
            {
                printf("%s\n", "Cannot read");
            }
            res =0;
        }
    }
        
    //closeCommunication();
    return  input;
}

int RS232::putData(char * data)
{
    int bytes_send = 0;

        if (m_connection < 1)
        {
         initCommunication();
        }
    while(1)
    {
        bytes_send = write(m_connection, data, strlen(data));
        if (bytes_send != strlen(data))
        {
            printf("%s\n", "Error sending data");
        }
        else
        {
            printf("%s\n", "data send");
            usleep(5000000);    
        }
        //closeCommunication();
    }
    return bytes_send;
}


Nu heb ik twee test pc's aan elkaar verbonden. Op de 1 loopt een proggie die putdata() aanroept en op de ander loop readData(). als ik eerst de lezer start komt er (zoals verwacht) te staan " no data" . Start ik nu op de andere pc de schrijver dan krijg ik die " Cannot read" melding. Of te wel er gaat ergens is mis met de communicatie. Volgens mij staat de seriele verbinding goed ingesteld.

Btw het draait onder Linux. Op de ene machine /dev/ttys0 en op de andere /dev/tttS1.
Iemand een idee wat ik fout doe met het opzetten?.

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 21-05 14:59

pjvandesande

GC.Collect(head);

Gaaf, Questa mag debuggen. Ik denk dat je dat zelf eerst even moet doen en localizeer waar hij precies de mist in gaat. Mocht je er dan nog niet uit komen hoor ik het graag van je.

Verwijderd

Print samen met "Cannot read" de errorcode en zoek op wat deze betekend in de documentatie?

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

GAEvakYD schreef op 22 maart 2004 @ 11:32:
Hoi,

Ik ben hier bezig met ene proggie die data over de seriele poort kan lezen en schrijven. Nu heb ik voor deze communicatie een mooie rs232 classe opgezet. Het probleem is dat het zenden helemaal goed gaat alleen het ontvangen gata totaal mis. Ik heb al heel wat serial howto's en manuals gelezen maar nergens staat iets wat mij kan helpen of wat ik nog niet geprobeerd heb.

Als eerste mijn code.

code:
1
                printf("%s\n", "Cannot read");
Misschien een idee om de errorcodes die read() teruggeeft eens op het scherm te zetten ? Zie strerror(), perror() en de rest van de familie.

  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
Verwijderd schreef op 22 maart 2004 @ 12:14:
Print samen met "Cannot read" de errorcode en zoek op wat deze betekend in de documentatie?
Sja de errorcode is zoals ik hem ook al afvang in de code -1. dit is dus een lekkere algemene errorcode.

Verwijderd

GAEvakYD schreef op 22 maart 2004 @ 12:57:
[...]


Sja de errorcode is zoals ik hem ook al afvang in de code -1. dit is dus een lekkere algemene errorcode.
Nee dit is aantal bytes dat je ontvangen hebt. Als je -1 terug krijgt betekend het dus dat er een error is opgetreden. De daadwerkelijke errorcode kan je opvragen met functies als perror e.d.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

GAEvakYD schreef op 22 maart 2004 @ 12:57:
Sja de errorcode is zoals ik hem ook al afvang in de code -1. dit is dus een lekkere algemene errorcode.
Dat is niet de errorcode, maar de returncode. De errorcode staat in errno.

  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
igmar schreef op 22 maart 2004 @ 13:11:
[...]


Dat is niet de errorcode, maar de returncode. De errorcode staat in errno.
Ah kijk aan. Nu ben ik weer een stap verder bij de fout. Ik krijg errorcode 14 wat overeenkomt met EFAULT. of te wel "Bad adress".

Nu eens kijken wat ik daar aan ga doen. Bedankt voor de hint.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

GAEvakYD schreef op 22 maart 2004 @ 14:15:
Nu eens kijken wat ik daar aan ga doen. Bedankt voor de hint.
read() een goeie pointer geven, en geen een die zoals in jouw geval bestaat uit read-only data.

  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
igmar schreef op 22 maart 2004 @ 14:16:
[...]


read() een goeie pointer geven, en geen een die zoals in jouw geval bestaat uit read-only data.
Maar wat is er mis met mijn FD die ik meegeef dan?. Die staat 100% naar het juiste device te wijzen.

Dit is de output van strace.

voor ik de zender aan zet
code:
1
2
3
4
nanosleep({0, 100000000}, NULL)         = 0
read(3, 0x80a2d57, 23)                  = -1 EAGAIN (Resource temporarily unavailable)
write(1, "No data at this moment\n", 23No data at this moment
) = 23


nadat ik de zender aangezet heb
code:
1
2
3
nanosleep({0, 100000000}, NULL)         = 0
read(3, 0x80a2d57, 23)                  = -1 EFAULT (Bad address)
write(1, "Bad address\n", 12Bad address

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

GAEvakYD schreef op 22 maart 2004 @ 14:54:
Maar wat is er mis met mijn FD die ik meegeef dan?. Die staat 100% naar het juiste device te wijzen.
Niks, dan krijg je een anderen error EBADFD oid.
code:
1
2
3
nanosleep({0, 100000000}, NULL)         = 0
read(3, 0x80a2d57, 23)                  = -1 EFAULT (Bad address)
write(1, "Bad address\n", 12Bad address
Het gaat om de *buf parameter. Jij geeft daar een pointer aan mee naar read-only data ( = "" is een constante). Zorg ook dat de buffer groot genoeg is ok het gewenste aantal bytes in te zetten, hetgeen je aangeeft met de count parameter.

[ Voor 13% gewijzigd door igmar op 22-03-2004 15:21 ]


  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
igmar schreef op 22 maart 2004 @ 15:19:
[...]


Niks, dan krijg je een anderen error EBADFD oid.


[...]


Het gaat om de *buf parameter. Jij geeft daar een pointer aan mee naar read-only data ( = "" is een constante). Zorg ook dat de buffer groot genoeg is ok het gewenste aantal bytes in te zetten, hetgeen je aangeeft met de count parameter.
Kijk aan nu komt er eindelijk wat aan. Moet ik alleen even de communicatie goed zetten. Er komt nu maar 10% van de ingegeven data aan. En de waardes kloppen ook niet helemaal. Ik heb nu twee proggies. 1 wacht op input de ander wacht op input via stdin en stuurt dat dan over de seriele poort. Het is alleen zo dat van de 10 keer dat ik iets ingeef er ongeveer 1 keer iets aankomt. Tevens kloppen de characters die ingeef ook niet helemaal Maar dat zal wel ergens een timing instelling zijn.

Harstikke bedankt igmar

Ik heb er dit van gemaakt nu
code:
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
bool RS232::initCommunication(void)
{
    termios oldtio;
    termios newtio;
    m_connection = open(this->m_iodevice, O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if (m_connection < 0)
    {
        printf("Port open failed\n");
        return false;
    }   
    else
    {
        //See man termios
        
        tcgetattr(m_connection, &oldtio);
        bzero(&newtio, sizeof(newtio));
        
        newtio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
        newtio.c_lflag = 0;
        
        //Delay for read
        newtio.c_cc[VTIME]=10;
        
        //Minimal characters to read
        newtio.c_cc[VMIN]=1;
        
        tcflush(m_connection, TCIFLUSH);
        tcsetattr(m_connection, TCSANOW, &newtio);
        printf("Port opened sucsesful\n");  
        return true;    
    }   
}

bool RS232::closeCommunication(void)
{
    if (m_connection >  0)
    {
        if (close(m_connection)==0)
        {
            m_connection = 0;
            printf("Closing port sucsesful\n");
            return true;
        }   
        else
        {
            m_connection = 0;
            printf("Closing port failed\n");
            return false;
        }
    }
    else
    {
        m_connection = 0;
        printf("Port was already closed\n");
        return true;
    }   
}

char* RS232::readData(int bytes)
{
    char input[255];
    int res;
    
    if (m_connection < 1)
    {
        initCommunication();    
    }
    printf("%s\n", "Read some data");
    while(1){
        res = read(m_connection, input, bytes);
        if (res == -1)
        {
            //Error no data
            if (errno==EAGAIN)
            {
                //No data in buffer
                usleep(30000);
            }
            else if (errno ==EFAULT)
            {
                printf("%s\n", "Bad address");
                usleep(30000);
            }
            else
            {
                printf("%s\n", "Cannot read");  
                usleep(30000);
            }
            res =0;
        }
        else
        {
            input[res]=0;
            printf(":%s:%d\n", input, res);
        }
    }
    return  input;
}

int RS232::putData(char * data)
{
    int bytes_send = 0;
    char tmp[80] = "";
        if (m_connection < 1)
        {
         initCommunication();
        }
    printf("%s", "Give some data");
    while(1)
    {
        scanf("%s", tmp);
        bytes_send = write(m_connection, tmp, strlen(tmp));
        if (bytes_send != strlen(tmp))
        {
            printf("%s\n", "Error sending data");
        }
        else
        {
            usleep(300000); 
        }
    }
    return bytes_send;
}

[ Voor 65% gewijzigd door GAEvakYD op 22-03-2004 16:35 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Ik zou nog wel ff het aantal karakters beperken tot de grootte van je buffer, anders ga je weer segv'en. :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
Ik ben de afgelopen dagen bezig geweest met een bepaald data pakket dat ik ga doorsturen. Dat staat nu helemaal goed opgezet. Er gaat alleen nog ergens iets fout met het wegschrijven/uitlezen van de seriele poort. Daarom heb ik even getest om het woord hallo over de lijn te sturen. Aan de andere kant w8t ik continue op data, als er wat binnen komt laat ik dat zien op het scherm. De hele volgorde etc klopt totaal niet meer als ik het binnen krijg. Ik wete nu alleen niet waar ik de fout moet zoeken. Is het moment van schrijven/lezen wel goed?. Schrijf of lees ik niet te snel/langzaam?. of is er misschien wat anders aan de hand.

De klasse om te versturen ziet er zo uit:
code:
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
bool RS232::initCommunication(void)
{
    termios oldtio;
    termios newtio;
    this->connection = open(this->iodevice, O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if (this->connection < 0)
    {
        printf("Port open failed\n");
        return false;
    }   
    else
    {
        //See man termios
        
        tcgetattr(this->connection, &oldtio);
        bzero(&newtio, sizeof(newtio));
        
        newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
        newtio.c_lflag = 0;
        
        //Delay for read
        newtio.c_cc[VTIME]=10;
        
        //Minimal characters to read
        newtio.c_cc[VMIN]=1;
        
        tcflush(this->connection, TCIFLUSH);
        tcsetattr(this->connection, TCSANOW, &newtio);
        printf("Port opened sucsesful\n");  
        return true;    
    }   
}

bool RS232::closeCommunication(void)
{
    if (this->connection >  0)
    {
        if (close(this->connection)==0)
        {
            this->connection = 0;
            printf("Closing port sucsesful\n");
            return true;
        }   
        else
        {
            this->connection = 0;
            printf("Closing port failed\n");
            return false;
        }
    }
    else
    {
        this->connection = 0;
        printf("Port was already closed\n");
        return true;
    }   
}

int RS232::readFrame(void)
{
    char input[5];
    int res;
    std::string inputstring = "";

    if (this->connection < 1)
    {
        initCommunication();    
    }
    res = read(this->connection, input, 5);
    if (res == -1)
    {
        //Error no data
        if (errno==EAGAIN)
        {
            //No data in buffer
        }
        else if (errno ==EFAULT)
        {
            printf("%s\n", "Bad address");
        }
        else
        {
            printf("%s\n", "Cannot read");  

        }
        res =0;
    }
    else
    {
        inputstring=input;
        printf("%s\n", "----------------------------------------------------------------------------------");
        for(int i=0;i<=5;i++)
        {
            printf("data[%2d]   = %2c\n",i,inputstring.c_str()[i]);
        }
        printf("%s%s%d\n" ,inputstring.c_str()," heeft een lengte van ", inputstring.length() );
        printf("%s\n", "----------------------------------------------------------------------------------");
    }
    return  0;
}

int RS232::sendFrame(void)
{
    int bytes_send = 0;
    std::string outputstring = "";
    int lengte =0;
        if (this->connection < 1)
        {
         initCommunication();
        }
    
    //outputstring = toSendString();
    outputstring = "hallo";
    lengte = outputstring.length();
  
    printf("%s%s%d\n" ,outputstring.c_str()," heeft een lengte van ", lengte );
    
    if (lengte>0 && lengte<MAXDATAFRAMESIZE)
    {
        bytes_send = write(this->connection, outputstring, lengte);
        if (bytes_send != lengte)
        {
            printf("%s\n", "Error sending data");
            return 1;
        }
        else
        {
            printf("%s\n", "Data send.");
            return 0;
        }
    }
    else
    {
        printf("%s%d\n", "No data in frame, was ", lengte );
        return 1;
    }
}


De zendende kant doet dit.
code:
1
2
3
4
5
6
7
//READING FRAME 
    printf("%s\n", "Receiving frames"); 
    while(1){
        
        this->serialio->readFrame();
        usleep(10000);
    }


De ontvangende kant dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//SENDING FRAME;    
    printf("%s\n", "Sending frames");
    while(1){
//          setProcessDataVar(HH, 0+packets);
//          setProcessDataVar(LL, 15);
//          this->serialio->setType(001);   
//          this->serialio->setSender(node);
//          this->serialio->setDestination(128);
//          this->serialio->setData(LL,getProcessDataVar(LL));
//          this->serialio->setData(HH,getProcessDataVar(HH));
        this->serialio->sendFrame();    
//      packets++;
//      usleep(5000000);
//  }


Ik schrijf dus 5 bytes weg en lees 5 bytes uit. Er staat nog wat tussen commentaar in de code, dat is voor het testen van mijn datapakket. Omdat dat dus niet werkte ben ik eerst even aan het testen met "hallo".

Een voorbeeld output van de zender
code:
1
2
3
4
5
6
7
8
hallo heeft een lengte van 5
Data send.
hallo heeft een lengte van 5
Data send.
hallo heeft een lengte van 5
Data send.
hallo heeft een lengte van 5
Data send.


Een voorbeeld output van de ontvanger
code:
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
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
data[ 0]   =  l
data[ 1]   =  l
data[ 2]   =  o
data[ 3]   =
data[ 4]   =
data[ 5]   =  û
ll heeft een lengte van 4
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
data[ 0]   =  l
data[ 1]   =  l
data[ 2]   =  o
data[ 3]   =
data[ 4]   =
data[ 5]   =  û
ll heeft een lengte van 4
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
data[ 0]   =  l
data[ 1]   =  l
data[ 2]   =  o
data[ 3]   =
data[ 4]   =
data[ 5]   =  û
ll heeft een lengte van 4
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
data[ 0]   =  a
data[ 1]   =  l
data[ 2]   =  l
data[ 3]   =  o
data[ 4]   =
data[ 5]   =  û
allo heeft een lengte van 4
----------------------------------------------------------------------------------

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Je hebt een receivebuffer van vijf karakters, je leest er vijf in en zet em dan om in een std::string( waarom is me een raadsel, het is namelijk helemaal niet nodig in dit voorbeeld )

Anywayz, waar is de plek voor de afsluitende '\0', en waar is de afsluitende '\0' ?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • GAEvakYD
  • Registratie: Juni 2001
  • Laatst online: 10:10
Ja zeker wel, \0 doet het hem. Altijd leuk zoiets vergeten.

Hartstikke bedankt

[ Voor 77% gewijzigd door GAEvakYD op 24-03-2004 15:38 ]

Pagina: 1