IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème de configuration du port série sous linux !


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    508
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Vienne (Limousin)

    Informations forums :
    Inscription : Avril 2008
    Messages : 508
    Par défaut Problème de configuration du port série sous linux !
    Bonjour,

    J'ai créé une application sous linux (distribution "voyage linux") qui ouvre le port série "/dev/ttyUSB0", qui lit les données arrivant sur ce port (peut aussi en écrire) et qui traitent ces données pour les sauvegarder dans un fichier.

    Le matériel connecté en USB au système envoie toujours le même nombre d'octets (30). Lorsque j'utilise ce matériel sous windows et que je "sniffe" les trames du port USB, la configuration est comme ceci : 8 data, 1 stop, parité paire, vitesse 38400, aucun contrôle de flux.

    Dans mon application linux, j'utilise la fonction "open", et pour la config j'utilise la structure "termios".
    Lorsque le matériel doit m'envoyer une trame toutes les 32s par ex, il y a quelques fois des trames qui ne sont pas vues donc pas traitées !!!

    Je pense que ce problème vient des paramètres que je passe à la fonction "open" ou alors des paramètres de "termios".
    J'ai fait pas mal de recherches sur ces paramètres et j'avoue que je suis un peu perdu !


    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    int fd = open ("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
     
    	if (fd < 0)
    	{
    		printf ("Erreur ouverture port\n");
    		exit (EXIT_FAILURE);		
    	}
    	else
    	{
    		printf ("Ouverture COM reussie\n");
    	}
     
    	tcgetattr(fd,&oldtio); // sauvegarde les configurations actuelles du port
     
    	newtio.c_cflag = B38400 | CS8 | CREAD | PARENB;
    	newtio.c_lflag = ECHO;
    	newtio.c_oflag = OFDEL;
    	newtio.c_lflag = CSTOPB ;
     
    	newtio.c_iflag = IGNPAR | ICRNL;
     
    	newtio.c_oflag = 0;
     
    	tcflush(fd, TCIFLUSH);
    	tcsetattr(fd,TCSANOW,&newtio);
     
    	SignalRecu=0;
     
    	printf("Attente reception ...\n\n");
    	while (1)
    	{
     
    		int taille = read (fd,buf,sizeof (buf));
     
    		if ( taille == 30 )
    		{
     
                    }
            }
    Merci d'avance pour votre aide et à bientôt !

  2. #2
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    En C++, utilisons des solutions C++ !
    Avec Boost.Asio, on peut réaliser un manager de liaison série qui se réutilise quand on veut, sous presque n'importe quel OS courant. Pourquoi s'en priver ?
    Pour exemple, voici la classe que j'utilise personnellement.

    minicom_client.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #ifndef MINICOM_CLIENT_H
    #define MINICOM_CLIENT_H
     
    #include <deque>
    #include <iostream>
    #include <boost/bind.hpp>
    #include <boost/asio.hpp>
    #include <boost/asio/serial_port.hpp>
    #include <boost/thread.hpp>
    #include <boost/lexical_cast.hpp>
    #include <boost/date_time/posix_time/posix_time_types.hpp>
    #include <boost/signals2.hpp>
     
    #ifdef POSIX
    #include <termios.h>
    #endif
     
    using boost::asio::serial_port;
     
    /**
    * \class CMinicomClient
    * \brief Serial communication (RS232)
    */
    class CMinicomClient
    {
    public:
    	typedef boost::signals2::signal<void(char*, unsigned int)> msg_signal;
    	/**
            * \brief Constructor
            * \param io_service The io_service (event loop)
            * \param baud the speed of the connection
            * \param device Mostly "COM1" on Windows, and "/dev/ttyS0" on Linux
            * \param parity parity
            * \param stop_bits number of stop bits.
            */
    	CMinicomClient(boost::asio::io_service& io_service, unsigned int baud_rate, const std::string& device,
    					serial_port::parity::type parity = serial_port::parity::none,
    					serial_port::stop_bits::type stop_bits = serial_port::stop_bits::one);
     
    	~CMinicomClient();
     
    	/**
            * \brief Write vector to the serial port
            * \param vect a vector of char data
            * This is a mainly a convenience function. If you only use the WritePacet function to send data
            * on the serial port, then WritePacket ensures you make one call at a time.
            */
    	void WritePacket(const std::vector<char>& vect);
     
    	/**
            * \brief Write data to the serial port
            * \param msg a char data
            */
    	void Write(const char msg);
     
    	/**
            * \brief Close the connection
            */
    	void Close();
     
    	/**
            * \brief Asks for active connection
            * \return true if the socket is still active
            */
    	bool Active();
     
    	/**
            * \brief Register to response from the RS232 channel
            * \param slot function to call
            */
    	boost::signals2::connection OnNewData(const msg_signal::slot_type& slot);
     
    private:
     
    	static const int max_read_length = 512; // maximum amount of data to read in one operation
     
    	void read_start(void);
     
    	void read_complete(const boost::system::error_code& error, size_t bytes_transferred);
     
    	void do_write(const char msg);
     
    	void write_start(void);
     
    	void write_complete(const boost::system::error_code& error);
     
    	void do_close(const boost::system::error_code& error);
     
    private:
    	bool 						m_active; // remains true while this object is still operating
    	bool						m_operation_in_progress;
    	boost::asio::io_service& 	m_io_service; // the main IO service that runs this connection
    	boost::asio::serial_port 	m_serial_port; // the serial port this instance is connected to
    	char 						m_read_msg[max_read_length]; // data read from the socket
    	std::deque<char> 			m_write_msgs; // buffered write data
    	msg_signal					m_new_message_signal;
    };
     
    #endif
    minicom_client.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #include "minicom_client.h"
     
    CMinicomClient::CMinicomClient(boost::asio::io_service& io_service, unsigned int baud, const std::string& device, 
    								serial_port::parity::type parity, serial_port::stop_bits::type stop_bits)
    : m_active(true),
    m_io_service(io_service),
    m_serial_port(io_service, device),
    m_operation_in_progress(false)
    {
    	if (!m_serial_port.is_open() )
    	{
    		std::cerr << "Failed to open serial port\n";
    		return;
    	}
     
    	m_serial_port.set_option( boost::asio::serial_port::baud_rate(baud ) );
    	m_serial_port.set_option( boost::asio::serial_port::flow_control	(boost::asio::serial_port::flow_control::none ) );
    	m_serial_port.set_option( boost::asio::serial_port::parity			(parity) );
    	m_serial_port.set_option( boost::asio::serial_port::stop_bits		(stop_bits) );
    	m_serial_port.set_option( boost::asio::serial_port::character_size	( 8 ) );
     
    	read_start();
    }
     
    CMinicomClient::~CMinicomClient()
    {
    }
     
    void CMinicomClient::Write(const char msg)
    {
    	m_io_service.post(boost::bind(&CMinicomClient::do_write, this, msg));
    }
     
    void CMinicomClient::Close()
    {
    	m_io_service.post(boost::bind(&CMinicomClient::do_close, this, boost::system::error_code()));
    }
     
    bool CMinicomClient::Active()
    {
    	return m_active;
    }
     
    void CMinicomClient::read_start(void)
    { 
    	// Start an asynchronous read and call read_complete when it completes or fails
    	m_serial_port.async_read_some(boost::asio::buffer(m_read_msg, max_read_length),
    		boost::bind(&CMinicomClient::read_complete,
    		this,
    		boost::asio::placeholders::error,
    		boost::asio::placeholders::bytes_transferred));
    }
     
    void CMinicomClient::read_complete(const boost::system::error_code& error, size_t bytes_transferred)
    { 
    	// the asynchronous read operation has now completed or failed and returned an error
    	m_operation_in_progress = false;
    	if (!error)
    	{ // read completed, so process the data
    		m_new_message_signal(m_read_msg, bytes_transferred);
    		read_start(); // start waiting for another asynchronous read again
    	}
    	else
    		do_close(error);
    }
     
    void CMinicomClient::do_write(const char msg)
    { 
    	// callback to handle write call from outside this class
    	bool write_in_progress = !m_write_msgs.empty(); // is there anything currently being written?
    	m_write_msgs.push_back(msg); // store in write buffer
    	if (!write_in_progress) // if nothing is currently being written, then start
    		write_start();
    }
     
    void CMinicomClient::write_start(void)
    { 
    	// Start an asynchronous write and call write_complete when it completes or fails
    	m_operation_in_progress = true;
    	boost::asio::async_write(m_serial_port,
    		boost::asio::buffer(&m_write_msgs.front(), 1),
    		boost::bind(&CMinicomClient::write_complete,
    		this,
    		boost::asio::placeholders::error));
    }
     
    void CMinicomClient::write_complete(const boost::system::error_code& error)
    { 
    	// the asynchronous read operation has now completed or failed and returned an error
    	if (!error)
    	{ // write completed, so send next write data
    		m_write_msgs.pop_front(); // remove the completed data
    		if (!m_write_msgs.empty()) // if there is anthing left to be written
    			write_start(); // then start sending the next item in the buffer
    	}
    	else
    	{
    		do_close(error);
    	}
    }
     
    void CMinicomClient::do_close(const boost::system::error_code& error)
    { 
    	// something has gone wrong, so close the socket & make this object inactive
    	if (error == boost::asio::error::operation_aborted) // if this call is the result of a timer cancel()
    		return; // ignore it because the connection cancelled the timer
    	if (error)
    		std::cerr << "Error: " << error.message() << std::endl; // show the error message
    	else
    		std::cout << "Error: Connection did not succeed.\n";
    	std::cout << "Press Enter to exit\n";
    	m_serial_port.close();
    	m_active = false;
    } 
     
    void CMinicomClient::WritePacket(const std::vector<char>& vect)
    {
    	// Lock writing
    	m_operation_in_progress = true;
     
    	// Write packet
    	for (auto iter = vect.begin(); iter != vect.end(); ++iter)
    	{
    		Write(*iter);
    	}
    }
     
    boost::signals2::connection CMinicomClient::OnNewData(const msg_signal::slot_type& slot)
    {
    	return m_new_message_signal.connect(slot);
    }
    Poukill.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    508
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Vienne (Limousin)

    Informations forums :
    Inscription : Avril 2008
    Messages : 508
    Par défaut
    Bonjour,

    merci poukill pour ton aide, je vais tester ta solution.

    Par contre, quelqu'un pourrait quand même m'expliquer pourquoi le bout de code que j'ai posté ne fonctionne pas correctement dans mon cas ?

    A bientôt !

Discussions similaires

  1. Problème de ports série sous linux
    Par Imaging dans le forum Matériel
    Réponses: 0
    Dernier message: 15/05/2009, 19h24
  2. Lecture sur port série sous Linux
    Par DangerousBowlOfJelly dans le forum C
    Réponses: 6
    Dernier message: 28/03/2008, 17h00
  3. [Série] Accès au port série sous linux
    Par ghost dans le forum Entrée/Sortie
    Réponses: 10
    Dernier message: 10/10/2007, 10h43
  4. Port série sous Linux
    Par naoned dans le forum Bibliothèques tierces
    Réponses: 2
    Dernier message: 21/11/2005, 16h45
  5. Problème avec le port série sous Windows XP
    Par didou2dek dans le forum Composants VCL
    Réponses: 6
    Dernier message: 02/09/2003, 19h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo