Comunicacao serial no Linux

Muitas vezes voce precisa de um exemplo simples de como fazer um programa de comunicacao serial no Linux, mas todos os exemplos que voce acha sao muito complexos e dificeis de entender.

Hoje precisei fazer um programa simples de comunicacao serial e passei por este mesmo problema, finalmente consegui encontrar um programa de exemplo (mais complexo do que eu queria) e modifiquei para que sei ficasse simples de entender e usar.


#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/types.h>
#define BAUDRATE B19200
#define FALSE 0
#define TRUE 1
//
volatile int STOP=FALSE;
void signal_handler_IO (int status);
int wait_flag=TRUE;
char devicename[80] = "/dev/ttyUSB0", ch;
int status;
//
int main(int argc, char *argv[])
{
int fd, res, i;
struct termios newtio;
struct sigaction saio;
char buf[255];
//
//open the device in non-blocking way (read will return immediately)
fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0)
{
perror(devicename);
exit(1);
}
//
//install the serial handler before making the device asynchronous
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);   //saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
//
// allow the process to receive SIGIO
fcntl(fd, F_SETOWN, getpid());
//
// make the file descriptor asynchronous
fcntl(fd, F_SETFL, FASYNC);
//
// set new port settings for canonical input processing
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
//
// loop while waiting for input. normally we would do something useful here
while (STOP == FALSE)
{
//
// read characters typed by user in non-blocking way
ch = getchar_unlocked();
if(ch > 0)
write(fd,&ch,1);
//
// after receiving SIGIO, wait_flag = FALSE, input is available and can be read */
if (wait_flag == FALSE)  //if input is available
{
res = read(fd,buf,255);
if (res > 0)
{
for (i=0; i < res; i++)  //for all chars in string
{
printf("%c", buf[i]);
}
}
wait_flag = TRUE;      /* wait for new input */
}
}
close(fd);
}
//
/***************************************************************************
* signal handler. sets wait_flag to FALSE, to indicate above loop that     *
* characters have been received.                                           *
***************************************************************************/
//
void signal_handler_IO (int status)
{
//printf("received SIGIO signal.\n");
wait_flag = FALSE;
}

Compile da forma usual:

gcc serial.c -o serial

Com este programa é possível fazer comunicacao serial bidirecional entre dois dispositivos. Inicialmente eu testei comunicando com o bootloader de uma placa embarcada configurada para 19200 8N1. Basta alterar o baudrate para o valor desejado (ex. 115200) e recompilar.

Advertisements

10 thoughts on “Comunicacao serial no Linux

  1. Bom dia João,

    Na verdade esta primeira implementacao está rodando no PC com Linux usando um conversor USB/Serial.

    Em seguida compilei ele para rodar no uClinux no microcontrolador Coldire MCF5282. A versão deste programa que roda no microcontrolador comunica com uma placa MBED (LPC1768) rodando o RTOS NuttX.

    Gostei da sua implementacao em Python, porém preferi fazer em Linguagem C para poder usar no uClinux e no NuttX.

  2. Opa show de bola, porem não consigo enviar caractere com o programa mais consigo receber de boa 🙂 alguma dica?

  3. Olá Rafael,

    Verifique se o baudrate e paridade usados estão corretos, talvez no seu caso você terá que modificar o newtio.c_iflag para ficar paridade certa.

  4. Oi João,
    Preciso de um help: eu testei teu programa e ele funcionou; porém preciso que ele leia em hexadecimal. Alguma solução?
    Obrigada!

  5. Olá José,
    Para enviar um arquivo pela porta serial é necessário que os dois lados comuniquem num mesmo protocolo. Normalmente os protocolos seriais usados para isso são xmodem, ymodem ou zmodem.
    Você precisaria implementar (ou usar uma biblioteca que implemente) este protocolo no seu programa. []’s

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s