Pages : 1
#1 Le 20/06/2016, à 18:30
- axelou
programmation port serie C
Bonjour,
Je dois faire un programme dont l'un des objets à piloter est un ohmètre via le port serie et je suis dans la mouise parce que ça marche pas et que je comprends pas pourquoi. Tout me paraissait pourtant simple quand j'ai commencé. En plus le petit programme gtkterm fonctionne très bien, alors j'ai essayé de m'en inspirer. Mais même en lisant leur code j'ai pas réussi à trouver l'astuce qui fait que quand gtkterm utilise write le ohmètre réagit, quand c'est moi, ben aucune réaction. Les messages sont ignorés et j'en suis sûr parce que affichage du ohmètre.
Bref, voici le code:
#include <stdio.h> // standard input / output functions
#include <stdlib.h>//strtoul
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <termios.h> // POSIX terminal control definitionss
#include <fcntl.h> // File control definitions
#include <sys/ioctl.h>
#include <errno.h> // Error number definitions
#include "microhmetre.h"
#define SELF_TEST 1
int microhmetre_fd = -1;
struct termios tio_save;
int microhmetre_Init(void)
{
microhmeter_close();
char* portName = "/dev/ttyUSB0";
/** open serial ports**/
microhmetre_fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);
if(microhmetre_fd==-1) {
printf("openPort ERROR\n");
return 1;
}
/**Configuring serial port transmission type**/
struct termios newtio;
if(!isatty(microhmetre_fd)) {
printf("port %d is not a tty\n", microhmetre_fd);
close(microhmetre_fd);
microhmetre_fd = -1;
return 1;
}
//bzero(&newtio, sizeof(newtio)); // clear struct for new port settings
tcgetattr(microhmetre_fd, &newtio);
memcpy(&tio_save, &newtio, sizeof(struct termios));
//setting c_cflags
newtio.c_cflag = B9600;//baud rate
newtio.c_cflag |= CS8;//set 8 bits
newtio.c_cflag |= CSTOPB;//|= CSTOPB; 2 stop bits &=~CSTOPB; 1 stop bit
newtio.c_cflag |= (CREAD | CLOCAL); //enable receiver
//l_flags
newtio.c_lflag = 0;
//i_flags
newtio.c_iflag = IGNPAR | IGNBRK;
//o_flags
newtio.c_oflag = 0;
//other flags
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 1; //Inter-char timer 1s read timeout
//apply settings
if(tcsetattr(microhmetre_fd, TCSANOW, &newtio)<0) {
printf("Unable to apply given port settings\n");
close(microhmetre_fd);
microhmetre_fd = -1;
return 1;
}
tcflush(microhmetre_fd, TCOFLUSH);
tcflush(microhmetre_fd, TCIFLUSH);
return 0;
}
void microhmeter_close(void){
if( microhmetre_fd != -1){
tcsetattr(microhmetre_fd, TCSANOW, &tio_save);
tcflush(microhmetre_fd, TCOFLUSH);
tcflush(microhmetre_fd, TCIFLUSH);
close(microhmetre_fd);
microhmetre_fd = -1;
}
}
int microhmeter_write(char * buf, int length)
{
if (microhmetre_fd == -1) return 1;
if (length = 0) return 0;
int res, err;
/*Write data*/
res = write(microhmetre_fd, buf, length);
if( res < 0){
err = errno;
printf("write failed: error %d\n", err);
return 1;
}
else if (res != length){
printf("write not completed\n");
return 1;
}
else {
tcdrain(microhmetre_fd);//attendre la fin de l'envoie.
}
return 0;
}
int microhmeter_configure(void)
{
char * remote = "SYST:REM\n";
if(microhmeter_write(remote, 9)){
printf("configure remote failed\n");
return 1;
}
sleep(1);
char * trig_bus = "TRIG:SOURCE BUS\n";
if(microhmeter_write(trig_bus, 16)){
printf("configure trig bus failed\n");
return 1;
}
sleep(1);
return 0;
}
int microhmeter_read(int recvBytes, char * buf)
{
unsigned long time;
unsigned long mesure;
int res;
//select
fd_set rfds;
struct timeval tv;
int retval = 0;
FD_ZERO(&rfds);
FD_SET(microhmetre_fd, &rfds);
//Timeout 500ms
tv.tv_sec = 3;
tv.tv_usec = 500000;
while(retval == 0) {
retval = select(microhmetre_fd+1, &rfds, NULL, NULL, &tv);
if(retval == -1) {
printf("Select Error in read port\n");
return 1;
} else if (retval) {
res = read(microhmetre_fd, buf, recvBytes);
break;
} else {
printf("Read_port timeout\n");
return 1;
}
}
if(res==15){
buf[res] = 0;
//TODO enregistrer et renvoyer la mesure
} else {
printf("error in read microhmeter\n");
return 1; //something is wrong
}
return 0;
}
int microhmeter_getMes(long double* mes)
{
char * mes_cmd = "MEAS:FRES?\n";
if(microhmeter_write(mes_cmd, 11)){
printf("error microhmeter write\n");
return 1;
}
char buf[16];
if(microhmeter_read(16, buf)){
printf("error microhmeter read\n");
return 1;
}
char ** res;
*mes = strtold(buf, res);
return 0;
}
#if SELF_TEST
int main(void){
long double mes;
if(microhmetre_Init()) {
printf("error init\n");
return 1;
} else printf("init succes\n");
if(microhmeter_configure()) {
microhmeter_close();
return 1;
}
else printf("configure succes\n");
if(microhmeter_getMes(&mes)) {
microhmeter_close();
return 1;
}
else printf("mesure succès\n");
printf("mes = %Lf", mes);
microhmeter_close();
return 0;
}
#endif // SELF_TEST
J'ai l'impression de faire du code style années 70 avec termios, etc. Mais bon ça devrait marcher. C'est pour un prototype de code qui doit être fini cette semaine. Je suis dans la mouise...
L'appareil fonctionne en 8N2, 1 start bit, DTR/DSR handshake. Bref, normalement c'est ce que j'ai mis. Je compile avec gcc. Quelqu'un a une idée de bêtise que j'aurais faite?
Merci,
Hors ligne
#2 Le 04/07/2016, à 16:20
- pires57
Re : programmation port serie C
Salut,
Pas d'erreur à la compilation? à l’exécution?
Utilisateur d'Archlinux, Ubuntu et Kali Linux
Administrateur système et réseau spécialisé Linux.
LinkedIn
Hors ligne
Pages : 1