2010-08-10 9 views
0

J'écris un programme C qui va lire et écrire depuis/vers un port série. Chaque écriture sera suivie d'une lecture qui contiendra des données basées sur l'écriture. J'aurai environ 16 écritures différentes à effectuer, chacune suivie d'une lecture.Lecture et écriture de port série avec C

Je suis encore novice en programmation série et j'essaie de déterminer comment l'aborder. Est-ce que le programme devrait bloquer pendant chaque écriture/lecture (ayant essentiellement une grande boucle (1) d'écriture et de lecture)?

Est-il possible d'avoir un thread qui envoie des écritures tandis qu'un autre thread effectue les lectures? Un rappel peut-il être créé pour permettre à un thread de savoir quand les données peuvent être lues à partir du port série?

Merci pour l'aide.

Edit:

OS: Linux

+1

quoi? Windows/Linux? – obelix

+0

Votre interface série est-elle recto-verso? – NickHalden

+1

Vous devez spécifier l'environnement d'exploitation. Les ports série ne sont pas normalisés en C, et les capacités qui affectent la bonne réponse varient d'un système à l'autre. – Darron

Répondre

1

Cela ressemble à une simple boucle avec une lecture et une écriture sera suffisant. Si vous voulez plus de contrôle (comme écrire un keep-alive après X secondes sans entrée), utilisez select ou poll; ils vous permettent de "détecter" si des données sont disponibles, ainsi un read ne bloquera pas (cependant, vous devriez toujours lire non-bloquant au cas où quelque chose se produirait entre le select et le read). Le multithreading n'a pas de sens dans ce cas. Vous pouvez également tester si l'écriture va bloquer;

select et poll encore une fois, écrivez non-bloquant juste pour être sûr. En général, vous ne voulez pas que votre processus soit bloqué dans un appel système bloquant, à l'exception de select ou poll. (au moins, je ne le fais pas)

Utilisez ioctl pour définir divers paramètres sur la ligne série. Utilisez

$ strace -o /tmp/strace.minicom -f minicom 

pour lancer minicom (ou tout autre programme de terminal) et de voir ce qu'ils font pour faire avancer les choses à travailler, si vous êtes coincé. Et comme toujours, voir man select/poll/read/ioctl pour plus d'informations.

0

Il existe plusieurs façons de procéder en général. Le meilleur choix dépend probablement du type de données que vous recherchez lorsque vous lisez le port série et de la manière dont vous souhaitez traiter les erreurs dans ces données.

La façon de poing serait d'ouvrir le fichier série pour bloquer IO et faire:

while (question) { 
    write(ser_fd, question.data, question.len); 
    sleep(1); 
    ioctl(ser_fd, FIONREAD, &answer.len); 
    answer.data = realloc(answer.data, answer.len); 
    read(ser_fd, question.answer, question.answer_len); 
    question = next(question); 
    answer = next(answer); 
} 

Bien que je ne fais pas de gestion des erreurs dans ce domaine.

Si vous voulez être en mesure d'attendre l'attente d'une réponse pour entrer dans le port série, cela change beaucoup de choses. Vous devriez utiliser soit select, pselect, poll, ppoll, soit la famille d'appels système epoll. Ceux-ci permettent à votre programme de bloquer (sommeil) jusqu'à ce que des données soient prêtes à être lues. Ensuite, vous pouvez boucler un sondage et lire jusqu'à ce que vous ayez terminé votre réponse ou que vous ayez manqué de temps.

Une autre option consiste à essayer d'utiliser SIGIO, mais je ne le recommande pas. Ce n'est pas facile de faire les choses correctement et difficile à déboguer. De plus, vous pouvez utiliser SIGALRM pour vous exclure de votre appel de lecture et agir comme un délai d'attente pour cela.

Si vous essayez d'utiliser les routines d'entrée et de sortie stdio, c'est beaucoup plus difficile. Vous serez bloqué avec quelque chose comme la première méthode sans être en mesure de demander combien de données sont prêtes.