Conexão serial baseada em software

Observação: Se deseja usar uma interface serial baseada em software, veja a biblioteca SoftwareSerial que está incluída no Arduino 0007 ou superior. Continue a leitura desta página caso queria entender como essa biblioteca funciona.

Neste tutorial, você aprenderá como implementar uma comunicação serial assíncrona no Arduino em software, para que ele se comunique com outros dispositivos seriais. Isso permitirá que você crie uma conexão serial em qualquer um dos pinos digitais de entrada/saída do Arduino, o que é muito útil para quando precisa-se de múltiplas conexões seriais. Se apenas uma porta serial for necessária, recomenda-se usar a que já está embutida no hardware. Este tutorial é para software de uso geral e não para um dispositivo em particular. Há aqui um tutorial de como é possível comunicar-se com um computador. Tutoriais específicos para certos dispositivos podem ser encontrados na página Aprenda. Para uma bom entendimento do funcionamento de uma comunicação serial, consulte a Wikipédia. A conexão serial baseada em software consegue rodar a 4800 ou 9600 bauds com segurança.

Funções disponíveis:

SWread(): retorna um byte proveniente da conexão serial baseada em software.

Exemplo:

byte RXval;
RXval = SWRead();

SWprint(): envia um byte à transmissão pela conexão serial baseada em software.

Exemplo:

byte TXval = 'h';
byte TXval2 = 126;
SWprint(TXval);
SWprint(TXval2);

Definições necessárias:

#define bit9600Delay 84  
#define halfBit9600Delay 42
#define bit4800Delay 188 
#define halfBit4800Delay 94

Essas definições servem para ajustar o sincronismo na operação da conexão serial baseada em software às velocidades de 4800 e 9600 bauds.

Materiais necessários

  • Dispositivo com o qual deseja comunicar-se
  • Protoboard
  • Fios
  • Placa Arduino
  • LED - opcional, para depuração de erros

Prepare a protoboard

Insira o dispositivo com o qual deseja comunicar-se. Conecte o terra (GND) do Arduino ao terra da protoboard. Se seu dispositivo usa 5V, conecte os 5V do Arduino a ele, ou então conecte a alimentação e o terra provenientes de uma fonte externa. Faça as outras conexões necessárias ao seu dispositivo. Adicionalmente, você pode conectar um LED no pino 13 do Arduino, para fins de depuração de erros.

Decida-se por quais pinos do Arduino haverá a transmissão/recepção. Neste exemplo, utiliza-se o pino 7 para transmissão e o 6 para recepção, mas qualquer outro pino digital servirá para a tarefa.

Programe o Arduino

Agora é necessário escrever o código que capacita a comunicação de dados seriais. Este programa simplesmente aguarda a chegada de um caracter via porta de recepção e então devolve-o em caixa alta (maiúscula) para a porta de transmissão. Este é um bom programa de depuração de erros na interface serial e você poderá extrapolá-lo a fim de atender a toda sua necessidade relacionada à porta serial. Acompanhe os comentários ao longo do código.


#include <ctype.h>

#define bit9600Delay 84  
#define halfBit9600Delay 42
#define bit4800Delay 188 
#define halfBit4800Delay 94 

Aqui declaramos as diretivas do pré-processador. Elas são processadas antes que comece mesmo a compilação. As diretivas iniciam-se com o caracter "#" e não terminam com ponto-e-vírgula.

Incluímos o arquivo ctype.h em nossa aplicação. Isso nos dá acesso à função toupper() da biblioteca C de operações com caracteres, que usaremos mais logo no laço principal. Essa biblioteca é parte da instalação do Arduino, portanto não é necessário mais nada além de incluir a linha do #include para que ela possa ser usada.

Em seguida, estabelecemos as definições relativas à taxa de transmissão de dados. As linhas a seguir são diretivas que definem os tempos de sincronismo para a transmissão serial. A linha "#define bit9600Delay 84" faz com que o compilador substitua pelo número 84 toda vez que encontrar o rótulo "bit9600Delay". As definições do pré-processador são muito usadas para constantes porque dessa forma elas não ocupam nenhum espaço de memória de programa.


byte rx = 6;
byte tx = 7;
byte SWval;

Aqui, ajustamos os pinos de transmissão (tx) e recepção (rx). Mude os valores à vontade, de acordo com a sua montagem. E também alocamos espaço para a variável que recebe dados, SWval.


void setup() {
  pinMode(rx,INPUT);
  pinMode(tx,OUTPUT);
  digitalWrite(tx,HIGH);
  digitalWrite(13,HIGH); //liga LED de depuração de erros
  SWprint('o');  //depurando "ola"
  SWprint('l');
  SWprint('a');
  SWprint(10); // retorno de carro
} 

Aqui, inicializamos as linhas, ligamos o LED de depuração de erros e imprimimos uma mensagem para confirmar que tudo está funcionando como planejado. Podemos passar caracteres individuais ou números à função SWprint.


void SWprint(int data)
{
  byte mask;
  // bit de início
  digitalWrite(tx,LOW);
  delayMicroseconds(bit9600Delay);
  for (mask = 0x01; mask>0; mask <<= 1) {
    if (data & mask){ // escolha bit
     digitalWrite(tx,HIGH); // envie 1
    }
    else{
     digitalWrite(tx,LOW); // envie 0
    }
    delayMicroseconds(bit9600Delay);
  }
  // bit de parada
  digitalWrite(tx, HIGH);
  delayMicroseconds(bit9600Delay);
} 

Esta é a função SWprint(). Primeiro, a linha de transmissão é posta em LOW para sinalizar um bit de início. Depois, iteramos ao longo de uma máscara de bits e enviamos oito pulsos no pino de saída, um para cada bit do valor a ser transmitido. No final, põe-se a linha em HIGH para sinalizar um bit de parada. Para cada bit transmitido, mantemos a linha em HIGH ou LOW durante um intervalo de tempo específico. Neste exemplo, usamos uma velocidade de transmissão de 9600 bauds. Para usar 4800 bauds, simplesmente substituímos "bit9600Delay" por "bit4800Delay".


int SWread()
{
  byte val = 0;
  while (digitalRead(rx));
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) {
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rx) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay); 
    delayMicroseconds(bit9600Delay);
    return val;
  }
} 

Esta é a função SWread(), que aguarda a chegada de um byte no pino de recepção e retorna-o à variável alocada. Primeiro, aguarda-se que a linha de recepção seja posta em LOW. Verifica-se após um período de meio bit para ter certeza de que a linha ainda permanece em LOW e que não se trata de ruído. A seguir, iteramos ao longo de uma máscara de bits e deslocamos "1"s ou "0"s para dentro do byte de saída, baseado no que chegar. Finalmente, faz-se uma pausa para o bit de parada e então retorna-se o byte.


void loop()
{
    SWval = SWread(); 
    SWprint(toupper(SWval));
} 

Finalmente, implementamos o laço principal do programa. Aqui, simplesmente esperamos a chegada dos caracteres, mudamo-nos para maiúsculas e devolvemo-nos. É sempre uma boa idéia utilizar este programa para certificar-se de que a conexão serial está funcionando direito.

Share