Porta Serial RS-232C:
Software e Hardware
Prof. Eduardo Augusto Bezerra
<eduardob@inf.pucrs.br>
Faculdade de Informática e
Faculdade de Engenharia, PUCRS
Porto Alegre, Agosto de 2004
http://www.inf.pucrs.br/~eduardob/
Prof. Eduardo Augusto Bezerra <Eduardo.Bezerra@ufsc.br>
Departamento de Engenharia Elétrica e Eletrônica, UFSC
Florianópolis, Março de 2021
·
Nessa
seção é utilizada a abordagem botton-up
na apresentação dos exemplos de programa nas linguagens C e C++
para acesso
às portas serial (RS-
Porta Serial RS-
acesso
direto ao hardware – inportb, outportb
linguagem
C – MS-DOS/Windows 9x
·
O
primeiro exemplo, listado a seguir, usa a
porta serial via acesso direto ao hardware do computador, e os exemplos
seguintes utilizam recursos de mais alto nível como, por exemplo,
interrupções
e chamadas de sistema (function call). O sistema operacional e
compilador utilizados estão identificados nos comentários no início do
programa.
Obs. Uma
chamada de sistema é uma rotina
implementada em software, fazendo parte do sistema operacional ou como
um
driver, que é utilizada pelo sistema operacional ou pela aplicação para
acesso
ao hardware. Uma chamada de sistema pode solicitar uma interrupção, que
por sua
vez é originada no firmware do computador pessoal, ou fornecida pelo
driver
/*
serial_io.c
Programa em C para gerencia da porta
serial RS-
ao hardware pelas
instrucoes in e out.
Eduardo Augusto Bezerra, Maio de 2003
compilador Turbo C++ versao 1.0 (Borland)
*/
#include
<stdio.h>
#include
<dos.h>
#include
<process.h>
#include
<conio.h>
#define end_ctrl_50 0x03FD
/* Enderecos da UART 8250 */
#define end_dado_50 0x03F8
#define LRC
0x03FB
#define MSB
0x03F9
#define LSB
0x03F8
#define MCR
0x03FC
#define
LSR
0x03FD
#define
MSR
0x03FE
#define
IOR
0x03F8
#define
IIR
0x03FA
#define
IER
0x03F9
void
inic8250(){
/*
inicializacao da 8250 */
outportb(LRC, 0x80);
/* DLAB = 1, programa velocidade em MSB e
LSB */
outportb(MSB, 0x00);
outportb(LSB, 0x0C);
/* 00H 0CH == 9600 bps */
outportb(LRC, 0x07);
/* 8 bits de dados, 1 stop bit, sem
paridade */
}
void reseta8250(){
/*
reseta a 8250 */
inportb(LSR);
inportb(MSR);
inportb(IOR);
inportb(IIR);
}
void enable8250(){
/*
habilita a 8250 */
outportb(IER,
0x01);
}
void disable8250(){
/*
desabilita interrupcoes da 8250 */
outportb(IER,
0x00);
}
void
transm_dado(unsigned char caracter){
/*
transmite um caracter */
while (!(32 &
inportb(end_ctrl_50)) == 32);
outportb(end_dado_50,
caracter);
}
unsigned char
status(){
/* Le status da 8250 */
return
(inportb(end_ctrl_50) & 0x01);
}
int main(){
int opcao
= 0;
unsigned
char caracter = '';
unsigned
char aux = '';
inic8250();
reseta8250();
outportb(IER, 0x00);
/* sem interrupcoes */
while (opcao != 4){
clrscr();
printf("Entre com:\n");
printf("\t\t\t1 - Transmitir
um caracter pela serial\n");
printf("\t\t\t2 - Receber um
caracter pela serial\n");
printf("\t\t\t3 - Transmitir
arquivo pela serial\n");
printf("\t\t\t4 - Sair do
programa\n");
opcao = getch() -
'0';
caracter
= '';
/*
transmissao de um caracter */
if (opcao == 1)
while (caracter != 0x1B){
/* repete ate' pressionar ESC */
disable8250();
printf("\nEntre com
o carcter a ser transmitido ... ");
caracter
= getch();
printf("%c",
caracter);
transm_dado(caracter);
/*
envia um caracter */
}
/* recepcao de um caracter */
if (opcao == 2){
printf("\n\nAguardando
caracter na porta serial ... ");
for
(;;){
while(!status())
if (kbhit()) break;
if
(kbhit() && getch()) break;
aux
= inportb(end_dado_50); /* recebe um
caracter */
printf("\nRecebido
o caracter --> %c",
aux);
}
}
/* transmissao de arquivo */
if (opcao == 3){
FILE *fp;
char arq[20];
printf("\n\nNome do
arquivo: "); gets(arq);
if (!(fp =
fopen(arq, "r"))){
printf("\nArquivo
nao existe!");
exit(-1);
}
while(!feof(fp)){
/* transmite arquivo */
caracter = fgetc(fp);
disable8250();
transm_dado(caracter);
if
(status()) putch(inportb(end_dado_50));
}
fclose(fp);
printf("\nPressione
qualquer tecla para o menu.");
while(!kbhit());
}
}
return 0;
}
·
A
função outportb (int porta,
unsigned char valor); envia para o endereço especificado em porta
um
byte especificado
Porta Serial RS-
linguagem
C – MS-DOS/Windows 9x
·
Outra forma de acessar a UART 8250 é por
intermédio dos serviços da ROM-BIOS (interrupção 14H da BIOS), listados
na
tabela a seguir:
INT 14H |
Entrada |
Saida
|
|
1 |
Inicializa parametros da porta serial |
AL = parametro AH = 00 DX = nr. da porta. |
AX = status da porta |
2 |
Transmite um caracter |
AL = caracter AH = 01 DX = nr. da porta |
AH = status: passa/falha |
3 |
Recebe um caracter |
AH = 02 DX = nr. da porta |
AH = status: passa/falha AL = caracter |
4 |
Obtem status da porta serial |
AH = 03 DX = nr. da porta |
AH = codigo de status |
Inicialização – AL: |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Bits 0
.. 1 : tamanho da palavra
10 = 7 bits
11 = 8 bits
Bit 2 : stop bits
0 = 1 stop bit
1 = 2 stop bits
Bits 3
.. 4 : paridade
00, 10 =
sem paridade
01 = paridade impar
11 = paridade par
Bits 5
.. 7 : taxa de
transferencia
000
= 110 bps
001
= 150 bps
010
= 300 bps
011
= 600 bps
100
= 1200 bps
101
= 2400 bps
110 = 4800 bps
111
= 9600 bps
·
No
exemplo a seguir a 8250 é programada para
transferências a 9600 bps, 1 stop bit, 8 bits de dados e sem paridade.
/*
serial_bios.c
Programa em C para gerencia da porta
serial RS-
utilizando a INT 14H da BIOS.
Eduardo Augusto Bezerra
Maio de 2003
compilador Turbo C++ versao 1.0 (Borland)
*/
#include
<stdio.h>
#include
<dos.h>
#include
<conio.h>
#define SERIAL 0x14
#define ESC 0x1B
int main(){
union REGS
r;
unsigned
char caracter = '';
/* 7654321
*/
r.h.ah = 0x000;
/*
11100011 9600 bps, */
r.h.al = 0x0E3;
/* =
8 bits de dados, */
r.x.dx = 0x000;
/*
E3H 1 stop
bit, */
int86(SERIAL, &r, &r);
/*
sem paridade */
while (caracter != ESC) {
printf ("\nEntre com o
caracter: ");
caracter = getch();
printf("%c",
caracter);
r.h.ah
= 1;
/*
AH = 1, transmite caracter */
r.h.al = caracter;
r.x.dx = 0;
int86(SERIAL, &r, &r);
/* Transmite o caracter */
}
return 0;
}
·
A
função int int86(int nr. interrupção,
union REGS *inregs, union REGS *outregs); realiza um pedido de
interrupção
para a CPU. Essa segunda forma é bem mais simples do que o acesso
direto à 8250
mostrado anteriormente.
Porta Serial RS-
linguagem
C – Linux
·
A
listagem do programa para Linux a seguir
apresenta uma versao resumida do codigo listado anteriormente para
utilizacao
da porta serial, via acesso direto ao hardware.
/*
serial_io.c
Programa em C para gerencia da porta
serial RS-
utilizando acesso direto ao hardware
pelas instrucoes
in e out.
Eduardo Augusto Bezerra
Maio de 2003
compilador gcc
version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
*/
#include
<stdio.h>
#include
<stdlib.h>
#include
<sys/io.h>
#include
<unistd.h>
#include
<malloc.h>
#include
<string.h>
#define end_ctrl_50 0x03FD
/* Enderecos da UART 8250 */
#define end_dado_50 0x03F8
#define LRC 0x03FB
#define MSB 0x03F9
#define LSB 0x03F8
#define MCR 0x03FC
#define LSR 0x03FD
#define MSR 0x03FE
#define IOR 0x03F8
#define IIR 0x03FA
#define IER 0x03F9
int main(){
unsigned
char caracter = ' ';
int a;
a =
setuid(0);
printf("setuid
= %d\n", a);
if
(ioperm(end_dado_50, 2, 1)) {
perror("ioperm");
printf("Erro: Nao liberou a porta serial!");
}
/* inicializacao da 8250 */
outb(0x80, LRC);
/* 8 bits de dados */
outb(0x00, MSB); /*
1
stop bit */
outb(0x0C,
LSB);
/*
sem paridade */
outb(0x07, LRC);
/*
reseta a 8250 */
inb(LSR);
inb(MSR); inb(IOR); inb(IIR);
outb(0x00,
IER);
/*
sem interrupcoes */
caracter = ' ';
/* transmissao de um caracter */
while (caracter != 0x1B){
/* repete ate' pressionar ESC */
printf("\nEntre com o
caracter a ser transmitido ... ");
scanf("%c", &caracter);
printf("%c", caracter);
outb(caracter, end_dado_50);
/* envia um caracter */
}
return 0;
}
·
A
porta serial RS-
·
A
solucao utilizada para o exemplo listado
anteriormente, foi a criacao de um usuario especial pertencente ao
grupo uucp,
e a execucao do programa realizada por esse usuario.
·
Como
o programa utiliza acesso direto ao
hardware via instrucoes inb e outb, apenas usuarios
pertencentes
ao grupo root possuem permissao para executar esse programa.
Uma solucao
para possibilitar a execucao por usuarios comuns (no caso o usuario
pertencente
ao grupo uucp), foi a utilizacao da funcao setuid na
linha 35.
Essa funcao altera a identidade do processo atual (process ID) para o
valor
passado como argumento. No caso o valor 0 informa ao Linux que o
processo
pertence ao root. Nesse caso um usuario root tera que
compilar o
programa, e logo a seguir alterar as permissoes do arquivo para 4755 (chmod
4755 nome_do_arquivo_executavel). Isso possibilitara que um usuario
comum
execute o programa com funcoes para acesso direto ao hardware.
·
A
funcao ioperm na linha 37 e utilizada
para fornecer acesso a portas para usuarios que nao possui privilegios
de root
(ver man ioperm para maiores informacoes).
Porta Serial RS-
linguagem
C++ e Sistema Operacional Linux
·
A
listagem a seguir apresenta a implementacao
para as funcoes membro da classe RobotLinux, utilizada para controlar o
braco robo que e um dos exemplos utilizados na disciplina. O computador pessoal se comunica com o circuito de controle do braco robo via porta serial RS-
/************************************************************
*
File
RobotLinux.cpp - Implementation for the RobotLinux class
*
*
This class
has the implementation for virtual
*
methods from
Robot.h (and Robot.cpp)
*
*
Project:
Fischer Arm
*
*
Author:
Eduardo Augusto Bezerra
*
Date:
04/04/2003
*
*
Last change:
Eduardo Augusto Bezerra
*
Date:
26/04/2003
*
*
Methods for
controlling the robot in C++ under linux
*
This code has
been tested on linux Red Hat 8.0
*
*************************************************************/
#include
"RobotLinux.h"
/************************************************************
*
Constructor
*************************************************************/
RobotLinux::RobotLinux(void){
motorWord =
0;
fd = -1;
}
/************************************************************
*
Destructor
*************************************************************/
RobotLinux::~RobotLinux(void){
close(fd);
}
/************************************************************
*
void
RobotLinux::openSerial(int ser)
*
*
open the
serial connection;
*
sets the
serial parameters to 9600 Baud, no parity, 8, 1;
*
and turns all
motors off
*
*************************************************************/
void
RobotLinux::openSerial(int ser){
//
serial names
const char
*com1="/dev/ttyS0", *com2="/dev/ttyS1",
*com3="/dev/ttyS2", *com4="/dev/ttyS3";
struct termios
options;
switch(ser) {
case 1:
strcpy(serial,com1);
break;
case 2:
strcpy(serial,com2);
break;
case 3:
strcpy(serial,com3);
break;
case 4:
strcpy(serial,com4);
break;
default:
cout << "Error! valid ports are 1, 2, 3 and 4. "
<< "Will try to open port 1." << endl;
}
fd =
open(serial, O_RDWR|O_NOCTTY|O_NDELAY);
if (fd ==
-1) // ERROR!!
cout
<< "Error opening " << serial << endl;
else
fcntl(fd,
F_SETFL, 0);
cout <<
"Serial port in use: " << serial << endl << endl;
// Program
serial port to 9600, 8, 1, no parity
//
// Get the
current options for the port
tcgetattr(fd,
&options);
// Set the
baud rate to 9600
cfsetispeed(&options,
B9600);
cfsetospeed(&options, B9600);
// Enable the
receiver and set local mode
options.c_cflag |= (CLOCAL | CREAD);
// Setting
parity checking (no parity) 8N1
options.c_cflag &= ~PARENB;
/* no parity */
options.c_cflag
&= ~CSTOPB;
/* 1 stop bit */
options.c_cflag &= ~CSIZE;
/* Mask the character size bits */
options.c_cflag |= CS8;
/* Select 8 data bits */
// Setting
raw input
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// Setting
raw output
options.c_oflag &= ~OPOST;
// Set the
new options for the port
tcsetattr(fd,
TCSANOW, &options);
motorsOff();
//
motors off
}
/************************************************************
*
char sendCommand(char
motorWord)
*
*
gets a full
word representing all inputs (1..8)
*************************************************************/
char
RobotLinux::sendCommand(char motorWord){
char
commandWord[2];
commandWord[0] = '\xc1';
// 1st byte:
commandWord[1] = motorWord;
// 2nd byte: motorWord
int i;
if (fd == -1)
cout
<< "Erro: the serial port is closed. Please, "
<< "use the openSerial() method to open it. " <<
endl;
else{
int n =
write(fd, commandWord, 2); // send 2
bytes command & motors
if (n <
0)
cout
<< "Error! write() command and motor bytes failed." <<
endl;
else {
fcntl(fd, F_SETFL, FNDELAY);
i =
read(fd, commandWord, 1); // read 1 Byte interface status
fcntl(fd, F_SETFL, 0);
commandWord[1] = 0;
/* set
end of string, so we can printf */
}
}
return
commandWord[0];
}
·
De
forma semelhante ao exemplo de acesso direto
ao hardware, a solucao utilizada no caso da aplicacao para controle do
braco
robo foi a criacao de um usuario especial pertencente ao grupo uucp,
e a
execucao dos programas para acesso a serial (ao braco robo) realizada
por esse
usuario.
·
No
programa anterior, nas linhas 46 e 47 estao
listados os nomes dos arquivos que identificam as portas seriais com1 a
com 4
no Linux. Esses nomes substituem os antigos /dev/cua0 a /dev/cua3.
·
Uma
das portas (1, 2, 3 ou 4) e aberta na linha
64, de acordo com a selecao do usuario. O flag O_RDWR faz com
que a
porta seja aberta para entrada e saida. O flag O_NOCTTY garante
que o
programa nao sera o “terminal em controle” da porta. Se esse flag nao
for
utilizado, outras entradas de dados (ex. ^C enviado pelo teclado) pode
afetar o
programa. O flag O_NDELAY avisa ao Linux que o programa ira
ignorar o
sinal DCD da RS-
·
A
funcao fcntl na linha 68 e utilizada
para configurar a porta serial para possiveis operacoes de leitura. O
flag
F_SETFL e utilizado em conjunto com o terceiro argumento para ativar ou
desativar o modo de leitura da porta. Ao se utilizar 0 como terceiro
argumento
na funcao fcntl, uma operacao de leitura na porta serial (read)
ira bloquear a execucao do programa ate que um carcter seja recebido,
um
intervalo de tempo expire, ou um erro ocorra. Para realizar leituras
nao
bloqueantes na serial, utlizar o flag FNDELAY, no lugar do 0.
·
A
funcao tcgetattr na linha 75 e
utilizada para ler os parametros associados ao descritor de arquivo fd
(no caso
a porta serial aberta), e armazena-los na variavel options.
Esses dados
correspondem ao status atual da porta serial.
·
Logo
a seguir, na linha
·
Nas
linhas seguintes os demais parametros para
a comunicacao serial sao armazenados no registro options. A
porta serial
do braco robo esta configurada para comunicacao a 9600 bps, com 8 bits
de
dados, 1 stop bit e sem paridade.
·
A
funcao tcsetattr na linha 97 realiza a
escrita do registro options, programando assim a UART do
computador
pessoal de acordo com os dados do protocolo estabelecido pelo circuito
do braco
robo.
·
O
envio de comandos para o braco robo e
realizado na linha 118 por intermedio da funcao write que envia
o
comando a ser realizado, utilizando para isso o descritor do arquivo
aberto na
linha
·
Notar
o uso do flag FNDELAY na funcao fcntl (linha
122) para configurar a operacao de leitura nao-bloqueante do status da
serial.
Esse flag faz com que a funcao read retorne 0, caso nao existam
dados
disponiveis para serem lidos na porta serial.
·
A
seguir sao apresentados programas para acesso
a porta paralela. Caso os programas nao consigam escrever/ler o dado
desejado
na porta, verificar as possiveis causas:
o
Escrita
no endereco errado (378H equivale a 888
em decimal).
o
O
cabo/conectores podem estar ligados de forma
incorreta. Verificar!
o
O
dispositivo conectado a porta esta causando o
problema. Desconectar o dispositivo, e medir os bits da porta para ver
se eles
estao sendo alterados corretamente pelo programa no computador pessoal.
o
Os
bits 0, 1 e 3 no registrador de controle das
portas sao invertidos entre o registrador e o conector. Ao se escrever
no
registrador de controle, esses bits apareceram nos pinos do conector
com
valores invertidos em relacao aos escritos.
o
A
porta suporta modo PS/2 e foi escrito 1 no
bit 5 do registrador de controle. Isso desabilita a porta para saida de
dados.
Escrever 0 no bit 5 do registrador de controle para habilitar a saida.
o
Um
driver de baixo-nivel do Windows esta
proibindo o acesso a porta.
·
Caso
o valor lido da porta nao e o esperado
verificar, alem dos itens acima:
o
Os
bits 0, 1 e 3 no registrador de controle das
portas, e o bit 7 do registrador de status sao invertidos entre o
conector e os
respectivos registradores. Ao se ler desses registradores, os bits
mencionados
possuirao valores invertidos em relacao aos existentes nos pinos do
conector.
o
A
porta nao aceita o modo PS/2 e nao e possivel
desabilitar o modo de saida (unidirecional). O valor lido sera sempre o
ultimo
valor escrito.
o
A
porta suporta o modo PS/2, mas o bit 5 do
registrador de controle nao foi setado para 1 de forma a desabilitar o
modo de
saida da porta. Escrever 1 nesse bit de forma a habilitar a leitura nos
pinos
de dados da porta.
Porta Serial RS-
linguagem
Java – Win32 e Solaris
·
A commapi
e uma API que pode ser
utilizada por desenvolvedores em programas em Java para acesso as
portas de
entrada e saida (paralela e serial). Os arquivos dessa API podem ser
obtidos na
pagina do curso (ver Exercicio 3 da aula pratica), e tambem dicas de
instalacao
e utilizacao.
·
Para
instalar a commapi no Windows e
preciso ter permissao de escrita no diretorio onde o jdk esta
instalado. Para
realizar a instalacao executar os seguintes passos (<jdk> e o
caminho
onde o jdk esta instalado):
o
Copiar
o arquivo win32com.dll para o
diretorio <jdk>\jre\bin
o
Copiar
o arquivo comm.jar para o
diretorio <jdk>\jre\lib\ext
o
Copiar
o arquivo javax.comm.properties para
o diretorio <jdk>\jre\lib
·
Uma
dica extra e a execucao da aplicacao
utilizando a virtual machine (java) que se encontra no mesmo
diretorio
do arquivo win32com.dll (<jdk>\jre\bin). O ambiente pode
estar
configurado para ser utilizado outro java, e nesse caso o programa nao
funcionara corretamente.
·
A
melhor forma de entender o funcionamento
dessa API e por meio do estudo das aplicacoes exemplo que acompanham os
arquivos. Um bom ponto de partida e a aplicacao “Serial Demo”. O
arquivo README
que acompanha essa aplicacao contem dicas de compilacao e utilizacao.
·
Na
classe SerialConnection da
aplicacao SerialDemo, observar:
o
O
metodo openConnection(), na linha 90,
abre uma porta serial.
o
O
metodo closeConnection(), na linha
203, fecha uma porta serial liberando a mesma para uso por outra
aplicacao.
o
O
metodo setConnectionParameters(), na
linha 167, utilizado para configurar (programar) a porta serial com os
parametros fornecidos pelo usuario.
o
O
metodo serialEvent(), na linha 255,
utilizado para avisar a aplicacao sobre a chegada de dados na porta
serial, e
recepcao desses dados.
o
O
metodo keyTyped(), na linha 330,
utilizado para envio de dados para a porta serial. Cada caracter
digitado na
caixa de texto e enviado automaticamente para a porta serial aberta.
Porta Serial RS-
linguagens
Java, C++ – Win32 e Linux
Sockets
linguagem
Java – Win32, Linux
Internet
linguagens
HTML, Java, Servlet, C++ – J2EE, Win32 e Linux
·
As
tres formas de acesso acima sao demonstradas
com o auxilio da aplicacao WebRobot. Essa aplicacao utiliza esses tres
conceitos, conforme mostrado no diagrama a seguir.
·
Todos
os fontes que compoem essa aplicacao
estao disponiveis para download em:
http://www.inf.pucrs.br/~eduardob/disciplinas/extensao/Robot/WebRobot/
·
Os
seguintes diretorios contem os arquivos
dessa aplicacao:
Client/
Contem robot_client.html
que e o cliente
servlet/
Contem RoboServlet.java
que e o programa em Java (servlet) a ser executado no servidor J2EE.
Esse
programa utiliza a classe HttpServletRequest para se comunicar com o
cliente
HTML. Por exemplo, para obter o conteudo do campo Acao do formulario,
ou seja,
movimento a ser realizado pelo braco robo, o programa utiliza: String
userAcao
= (String)request.getParameter("Acao");
O servlet tambem realiza a
conexao via sockets a maquina onde o robo esta conectado. Para isso e
preciso
informar o endereco IP da maquina remota e a porta a ser utilizada
(linhas 64 e
65):
String serverURL =
"200.17.91.157";
int porta = 5001;
Apos isso basta criar a nova
conexao socket (linha 73) e o stream de saida (linha 74):
try{
mySocket
= new Socket(serverURL,porta);
out
= new DataOutputStream(mySocket.getOutputStream());
in
= new DataInputStream(mySocket.getInputStream());
O envio da string via
sockets e realizado na linha 77:
out.writeUTF(userName + "#" + userAcao);
Caso a maquina remota esteja
desligada ou caso o servidor socket nao esteja em execucao naquela
maquina,
entao mensagens de erro sao fornecidas ao usuario (cliente HTML):
}catch (UnknownHostException e) {
outClient.println("<center><h2> ERRO: Nao
encontrou host: ... </h2></center>");
}catch (IOException e)
{
outClient.println("<center><h2>ERRO: Sem
conexao de I/O para: </h2></center>");
}
O arquivo HOW-TO-COMPILE-JAVAX.SERVLET.TXT
contem dicas de como compilar o programa
RobotSocketJNI/
Esse diretorio contem os
programas em C++ utilizados para acesso a porta serial no Linux (vide
descricao
de um dos modulos desse programa fornecida anteriormente): Robot.h,
Robot.cpp, RobotLinux.h, e RobotLinux.cpp. No programa em C++ RoboProxy.cpp,
sao informadas as funcoes (metodos) a serem utilizados poelo programa
em Java
(JNI), que no caso sao openSerial e sendCommand. Notar
a sintaxe
JNI utilizada nesse programa para a definicao das funcoes. O arquivo RobotProxy.h
e automaticamente gerado pelo compilador javah
a partir do RobotProxy.class
(gerado a partir do Robot Proxy.java).
O principal programa desse
diretorio e o RobotLinuxSocketserver.java. Essa classe
implementa o
servidor sockets, e possui tambem chamadas aos metodos nativos (JNI)
para envio
de comandos para o robo via porta serial. Notar o uso de robot do tipo RobotProxy para acesso as
funcoes em C++.
No main desse
programa e instanciado o objeto socket:
RobotLinuxSocketserver
socketServer = new RobotLinuxSocketserver();
O programa entra entao em um
laco infinito aguardando por mensagem na porta 5001 utilizada pelo
socket para
comunicacao com o socket no servidor J2EE. Ao receber uma string do
pela porta
5001, o programa extrai a acao a ser executada pelo braco robo, e envia
o
comando via chamada JNI para o programa em C++:
char resp =
socketServer.sendCommand(cmd);
O programa em C++ por sua
vez envia os comandos para o braco robo, utilizando o protocolo
definido pelo
programa em execucao no microcontrolador no modulo de controle do braco
robo:
envio de dois bytes. O primeiro byte sempre devera ser 0xc1, seguido
pelo byte
contendo o comando a ser realizado.
Para compilar o programa,
utilizar o usuario serial (do grupo uucp) e executar o Makefile:
make clean
make
Para executrar o servidor
socket na maquina onde se encontra o braco robo, sempre como usuario serial,
executar o Makefile:
make runServer
·
No
mesmo endereco estao tambem arquivos com
dicas de como realizar o deploy da aplicacao no servidor J2EE (deploytool_HOWTO.html),
e tambem o codigo fonte em perl (perl_cgi) para processamento do
formulario, caso nao tenha acesso a um servidor J2EE:
http://www.inf.pucrs.br/~eduardob/disciplinas/extensao/Robot/WebRobot/
·
Uma
alternativa ao J2EE seria a utilizacao do
Jboss (http://www.jboss.org), totalmente gratuito, que pode ser
executado
diretamente na maquina onde o braco robo se encontra. Nesse caso nao
seria
necessaria a comunicacao via sockets.
·
Nesta
placa temos a utilização de um módulo
transmissor e um receptor.
·
Componentes da placa:
o
Conector
DB9 (fêmea) utilizado para conectar na
porta serial do computador, no caso na porta COM0, nota-se que são
utilizador
apenas os pinos necessários ficando os outros pinos soltos.
o
MAX232
Circuito Integrado utilizado para
compatibilizar os níveis de tensão apresentados pela porta serial
(-12V/+12V)
com os níveis aceitos pelo transmissor e pelo receptor (+5 volts), a
alimentação do MAX232 deve ser de +5V;
o
Capacitores
são utilizados para permitirem o
funcionamento correto do MAX232 conforme é apresentado em seu manual,
existem
dispositivos com a mesma função e que possuem estas capacitores
internamente,
tornando o circuito mais compacto;
o
Power
é um conector que permite ligar as
tensões necessárias ao funcionamento do receptor, transmissor e do
MAX232;
o
Transmissor
é o dispositivo que recebe as
informações da serial de forma digital e envia para que os receptores
possam
utilizar os dados, o transmissor utilizado aqui é o TWS-433 que
trabalha com
tensões de 1,5 até 12V;
o
Receptor
é o dispositivo que recebe as
informações do transmissor e converte em sinais digitais os quais são
enviados
para a porta serial, o receptor utilizado é o RWS-433 que deve ter uma
tensão
de alimentação de +5V;
·
Para
realizar uma comunicação com envio e
recepção de dados cada um dos pontos deve ter um transmissor e um
receptor;
·
Para
adquirir um par transmissor e receptor são
necessários em torno de US$7.00 (Brasil/SP).
·
As
figuras a seguir mostram o diagrama de
blocos do circuito e o layout da placa.
·
Outra
opcao (alem da commapi) para comunicacao
serial em Java:
http://www.frii.com/~jarvi/rxtx/download.html
·
Dicas
para o desenvolvimento de aplicacoes para
USB, bem como classes gratuitas para Java e C++:
http://jusb.sourceforge.net/
·
Muita
informacao interessante:
http://www.beyondlogic.org/
·
Mais
informacao:
http://www.cera2.com/WebID/software/index.htm
RS-232
Interfacing
Referencias
Bibliograficas Utilizadas
·
“PC Intern – The
Encyclopedia of System Programming”.
Michael Tisher and Bruno Jennrich. Ed. Abacus, 1996, 985 pp.
Partes
dessas notas de aula foram traduzidas diretamente desse livro.
·
“The Hardware Bible”. (Electronic Edition) Winn L.
Rosch. SAMs Publishing,
1997.
Partes
dessas notas de aula foram traduzidas diretamente desse livro.
·
Muito
material da internet!