relatório braço mecânico programado por microncontrolador intel 8081

16
Introdução: Esse relatório tem objetivo de apresentar o programa BRACO2.ASM. O foco desse programa era acionar o experimento do professor Domingos que é um braço robótico que utiliza dois motores de passo (um na vertical e o outro na horizontal) ligados ao PAULMON2. O Braço Robótico Sobre o funcionamento do motor de passo: O motor de passo é um tipo de motor elétrico onde a rotação do balancete é controlado por uma série de campos eletromagnéticos que são ativados e desativados eletronicamente. Usado quando algo tem que ser posicionado muito precisamente ou rotacionado em um ângulo exato. O controle computadorizado de motores de passo é uma das formas mais versáteis de sistemas de posicionamento, particularmente quando digitalmente controlado como parte de um servo sistema. Tipo de motor de passo usado no experimento

Upload: marcel-sheeny

Post on 30-Oct-2014

51 views

Category:

Documents


1 download

DESCRIPTION

Relatório Braço Mecânico programado por microncontrolador intel 8081

TRANSCRIPT

Page 1: Relatório Braço Mecânico programado por microncontrolador intel 8081

Introdução:

Esse relatório tem objetivo de apresentar o programa BRACO2.ASM. O foco desse programa era acionar o experimento do professor Domingos que é um braço robótico que utiliza dois motores de passo (um na vertical e o outro na horizontal) ligados ao PAULMON2.

O Braço Robótico

Sobre o funcionamento do motor de passo:

O motor de passo é um tipo de motor elétrico onde a rotação do balancete é controlado por uma série de campos eletromagnéticos que são ativados e desativados eletronicamente. Usado quando algo tem que ser posicionado muito precisamente ou rotacionado em um ângulo exato.

O controle computadorizado de motores de passo é uma das formas mais versáteis de sistemas de posicionamento, particularmente quando digitalmente controlado como parte de um servo sistema. Tipo de motor de passo usado no

experimento

Page 2: Relatório Braço Mecânico programado por microncontrolador intel 8081

Veja na figura abaixo o esquema do braço robótico desenvolvido pelo professor Domingos:

O braço robótico foi desenvolvido usando dois motores de passo, o motor de passo n° 1 para fazer movimentos verticais e o motor de passo n° 2 para fazer movimentos horizontais

Desenho da parte física:

Page 3: Relatório Braço Mecânico programado por microncontrolador intel 8081

O programa:

O programa foi baseado no STEPPER.ASM. Um programa que acionava um motor de passo continuamente usando uma tabela. E tinha objetivo de movimentar um braço robótico de acordo com comandos fornecidos do teclado. O programa apresentou duas versões:

Versão 1 (BRACO.ASM):

A primeira versão foi proposta uma apenas uma movimentação usando o teclado com um diálogo de entrada simples com o usuário como descrito abaixo.

Use o teclado numerico (Com NUM LOCK):7:ESQ-CIMA 8:CIMA 9:DIR-CIMA

4:ESQ 6:DIR1:ESQ-BAIXO 2:BAIXO 3:DIR-BAIXO

Diferentemente do STEPPER.ASM, esse programa não acionava o braço robótico continuamente, ele apenas fazia passos discretos de acordo com a movimentação do usuário, ou seja, deixamos de usar nossa sub-rotina criada anteriormente, a cinn (capturava caractere do teclado sem interromper a execução do programa), e usamos a sub-rotina nativa do PAULMON2 cin (Interrompe a execução esperando um caractere ser pressionado).

Continuamos usando a pstri que é uma sub-rotina que imprime uma mensagem na tela, onde sua programação é de uma maneira mais legível do que a sub-rotina pstr nativa do PAULMON2.

Criamos uma sub-rotina chamada prstrack, que consiste em imprimir para qual endereço da pilha o stack pointer está apontando. Foi criado para verificação de erros. Segue o código da prstack:prstack: ;imprime a pilha mov a,#10 acall cout mov a,#13 acall cout ;pulando linha push 00h ;r0 mov a,SP ;pega o endereço do topo pilha dec a ;para desconsiderar r0 lcall phex mov r0,a ;poe no r0prs1: cjne r0,#07h,prs2 ;se é o ultimo, sai pop 00h ;r0 ret ;retorna para quem chamou prs2: mov a,@r0 ;pega o byte da pilha lcall phex ;e imprime dec r0 ;avança para o proximo sjmp prs1

Page 4: Relatório Braço Mecânico programado por microncontrolador intel 8081

A versão 1 do programa não teve maiores dificuldades em sua programação, pois era bastante parecido com o STEPPER.ASM. A principal mudança foi na hora de construir as tabelas. Foi preciso construir uma tabela para cada tipo de movimento.

Cada tecla acionada no teclado gerava 8 bits e analisamos que os 4 primeiros bits estavam relacionados ao movimento vertical, e os próximos 4 bits relacionados ao movimento horizontal. Assim foi possível construir a tabela de acordo com o que foi proposto no menu e usava-se ESC para interromper a execução do programa.. Veja a tabela montada abaixo:

DIR_CIMA: ;Tecla 9 DB 00010001b DB 00100010b DB 01000100b DB 10001000b

CIMA: ;Tecla 8 DB 00010000b DB 00100000b DB 01000000b DB 10000000b

ESQ_CIMA: ;Tecla 7 DB 00011000b DB 00100100b DB 01000010b DB 10000001b

DIR: ;Tecla 6 DB 00000001b DB 00000010b DB 00000100b DB 00001000b

ESQ: ;Tecla 4 DB 00001000b DB 00000100b DB 00000010b DB 00000001b

DIR_BAIXO: ;Tecla 3 DB 10000001b DB 01000010b DB 00100100b DB 00011000b

BAIXO: ;Tecla 2 DB 10000000b DB 01000000b DB 00100000b DB 00010000b

ESQ_BAIXO: ;Tecla 1 DB 10001000b DB 01000100b DB 00100010b DB 00010001b

O programa funcionou sem maiores problemas.

Versão 2 (BRACO2.ASM):

A nova versão do programa vinha com bastantes incrementos, pois agora o braço robótico era capaz de aprender, repetir e voltar os movimentos.

Inicialmente fizemos um novo diálogo com o usuário perguntando se ele queria movimentar(pressionando a tecla M) ou aprender (pressionando a tecla A). Caso o usuário pressionasse a tecla M ele iria apenas executar a versão 1 do programa.

Caso contrário criamos um algoritmo para Aprender que consistia em pegar todos os caracteres pressionados e armazenamos em um buffer.O algoritmo do buffer foi trazido do programa previamente feito, o BANNER.ASM. Nesse buffer era possível guardar até 255 movimentos, pois no final do buffer gravamos uma tecla ESC interromper e evitar que alguns caracteres do buffer fossem perdidos.

Page 5: Relatório Braço Mecânico programado por microncontrolador intel 8081

Após o buffer está preenchido é perguntado ao usuário se ele deseja repetir ou voltar o movimento. Como mostrada na interface a seguir:

Programa para acionamento do Experimento do Professor Domingos(Mover, Aprender, Repetir e Voltar)

Escolha: (M)over (A)prender (R)epetir (V)oltar

No movimento repetir percorria-se o buffer continuamente sem interrupções e no movimento voltar o braço faz-se o movimento oposto e percorrendo o buffer de trás pra frente. Nesse movimento de volta onde usamos os movimentos opostos, usamos o seguinte procedimento: Como a soma do movimento com o oposto é sempre 10 (exemplo: 2 é oposto de 8), então basta diminuir o movimento atual por 10 que se descobre o movimento oposto. Para podermos implementar isso no PAULMON2 tivemos que recorrer a tabela ASCII para achar a real constante que no caso foi 106. Então bastava diminuir o valor do movimento por 106 que se descobria o movimento oposto.

Tivemos algumas dificuldades na implementação do código da versão 2. Um dos erros foi que após apertar o ESC o programa não estava retornando diretamente ao PAULMON2, criamos a sub-rotina prstack para descobrir o erro, mas depois descobrimos que depois de digitar o ESC era necessário apertar o ENTER para retornar. Outra dificuldade foi armazenar o ESC no buffer para que ele possa interromper automaticamente após executado, que depois de um tempo foi solucionado. Outro problema ocorreu no cjne que usa um sjmp embutido no comando sendo necessário criar pontes para onde deveria ir o código.

Um fato que era necessário ter atenção, estava na hora de movimentar ou mandar repetir os movimentos, pois o braço estava ligado por fios, poderia ocorrer de enrolar os fios durantes os movimentos, outro problema físico ocorria porque o braço poderia bater na base e não conseguir fazer o movimento completo desejado. O que também estava ocorrendo era que alguns movimentos não estavam sendo executados, provavelmente a placa de potência não estava alimentando o braço com toda potência necessária para o movimento. Infelizmente os problemas físicos não foram solucionados.

Após corrigir todos os erros de implementação do código conseguimos rodar esse programa com todas as funcionalidades previstas com sucesso.

Próximas Etapas:

Uma das próximas etapas pra esse projeto seria a escolha de quantas vezes deseja ir e voltar o movimento, fazendo assim uma aplicação real de uma linha de montagem, por exemplo, onde braços robóticos ficam repetindo movimentos inúmeras vezes para acelerar o processo de montagem.

Outra idéia seria tenta expandir o movimento para braços mais complexos com mais tipos de movimentos se aproximando bastante de um braço robótico profissional.

Page 6: Relatório Braço Mecânico programado por microncontrolador intel 8081

Conclusão:

O programa BRACO2.ASM apresentou um nível mais elevado do que os programas feitos anteriormente, conseqüentemente apresentou bastante dificuldades na sua implementação, mostrando o quanto é necessário dar passos curtos para conseguir programar sem erros com menos dificuldades. Mas com ele foi possível desenvolver novos algoritmos que não se havia estudado anteriormente, , além de ajudar no aprendizado da linguagem assembly.

Abaixo o código do BRACO2.ASM:

;Programa para acionar o experimento do professor Domingos: Braço robótico com dois motores de;passo.;Baseado no EPD.asm, acionando dois motores de passo simultaneamente(um na vertical e o outro;na horizontal.;Novas funcionalidades: Mover, Aprender, Repetir e Voltar;Interface mais complexa;Movimento complementar#include <SFR51.inc>;CSEG AT 0000h ;necessário para a simulação;ljmp startupORG 0x2000; endereco inicial de montagem;Cabeçalho do Paulmon2DB 0xA5,0xE5,0xe0,0xA5 ;signiture bytesDB 35,255,0,0 ;id (35=prog)DB 0,0,0,0 ;prompt code vectorDB 0,0,0,0 ;reservedDB 0,0,0,0 ;reservedDB 0,0,0,0 ;reservedDB 0,0,0,0 ;user definedDB 255,255,255,255 ;length and checksum (255=unused)DB "Braco2",0

ORG 0x2040 ;endereço de montagem do código executável;rotinas do paulmon2cout EQU 0x0030 ;imprime o acumulador na serialcin EQU 0x0032 ;captura para o acumulador o que vem da serialphex EQU 0x0034 ;imprime o acumulador em hexadecimalupper EQU 0x0040 ;Converte o conteúdo do acumulador para maiuscula ;82C55 memory locations P0 -> PA, PB, PCport_b EQU 0x4001 ;82C55B: porta B motorport_c EQU 0x4002 ;82C55C: porta C LEDsport_abc_pgm EQU 0x4003 ;82C55pgm: registro de programação;nossas variáveisdphc EQU 0x7Fdplc EQU 0x7E ;variáveis para armazenar o dptr na pstrigravar EQU 0x7D ;Define se grava o movimento(gravar=1) ou não grava(gravar=0)mem EQU 0x7C ;Define se o movimento vem do teclado(mem=0) ou do Buffer(mem=1)

Page 7: Relatório Braço Mecânico programado por microncontrolador intel 8081

volta EQU 0x7B ;Define se vai(volta=0) ou se volta(volta=1)num EQU 0x7A ;Armazena o número de caracteres que tem no buffertemporizacao EQU 0x79 ;Guarda a temporizacao atualbuffer EQU 0x81 ;Endereço do buffer ESC -> 126 bytes -> ESC;nossas constantes;soma EQU 106 ;Usado para fazer o complemento;maxBuffer EQU 128 ;Numero máximo de caracteres que são guardados no bufferstartup: ljmp inicio ;salta as subrotinas;>>>>>>>>>>>>>>>>>>>>>>>>>>> Nossas subrotinaspstri: ;imprime mensagem imediata mov dphc,dph mov dplc,dpl ;salva dptr pop dph pop dpl ;recupera o endereço inicial da mensagem push acc ;salva o acumuladorpstr1: clr a movc a, @a+dptr ;pega um caracter inc dptr ;avança o ponteiro jz pstr2 ;testa se é o último; mov c, acc.7; anl a, #0x7F ;retiramos a terminação por bit 7 ligado lcall cout ;imprime o caracter; jc pstr2 sjmp pstr1 ;vai para o próximopstr2: pop acc ;recupera o acumulador push dpl push dph ;empilha o endereço de retorno mov dpl,dplc mov dph,dphc ;recupera o dptr original ret;--------------------------------prstack: ;imprime a pilha; acall pstri DB 10,13,0 ;pula uma linha mov a,#10 acall cout mov a,#13 acall cout ;pulando linha push 00h ;r0 mov a,SP ;pega o endereço do topo pilha dec a ;para desconsiderar r0 lcall phex mov r0,a ;poe no r0prs1: cjne r0,#07h,prs2 ;se é o ultimo, sai pop 00h ;r0 ret ;retorna para quem chamou prs2: mov a,@r0 ;pega o byte da pilha lcall phex ;e imprime dec r0 ;avança para o proximo sjmp prs1; ----------------- Fim das rotinas;incio do codigo: programa principal

Page 8: Relatório Braço Mecânico programado por microncontrolador intel 8081

inicio: ;Programa 8255, inicializações, desenergiza bobinas e apaga os leds mov dptr,#port_abc_pgm ;aponta para programação mov a,#128 ;prepara código de programação movx @dptr,a ;A:saida; B:saída; C:saída mov num,#0 ;Buffer começa vazio mov a,#00000000b ;Coloca 0 no acumulador mov dptr,#port_b ;aponta para porta dos motores movx @dptr,a ;Desenergiza as bobinas mov a,#11111111b ;Coloca 1 no acumulador mov dptr,#port_c ;aponta para porta dos LEDs movx @dptr,a ;Apaga os LEDs mov temporizacao, #70 ;temporizacao inicial de 70 mov r0,#buffer ;Endereco inicial do buffer mov @r0,#27 ;Pre insere um ESC; setb TI;<<<<<<<<<<<<<<<<<<<<<<<<< APENAS PARA SIMULAÇÃOMenuInicial:; mov a,sp ; lcall phex; acall prstack; acall pstri DB 13,10,"...............",0 acall pstri DB 13,10,"Programa para acionamento do Experimento do Professor Domingos",13,10,0 acall pstri DB "(Mover, Aprender, Repetir e Voltar)",13,10,10,0 acall pstri DB "Escolha: (M)over",10,13,0 acall pstri DB " (A)prender",10,13,0 mov a,num ;Acc recebe num (para jn) jz FimMenu ;Se buffer vazio, termina menu acall pstri DB " (R)epetir",10,13,0 acall pstri DB " (V)oltar",10,13,0FimMenu: acall pstri DB "(Tecla ESC sai do programa)",10,13,0; mov a,sp ; lcall phex; acall prstackLeTeclaInicial: lcall cin ;Pega resposta do usuário; lcall phex lcall upper ;Transforma caracter em maiusculo ; lcall phex cjne a,#'A',not_A ; <<<<<<<<<<<<<<<<<<<<<<<<<<<< Aprender;Aprender: acall pstri DB 10,13,"Aprendendo > ",10,13,0 mov mem,#0 ;Movimentos vem do teclado ;mem=0 mov gravar,#1 ;Grava movimentos ;gravar=1 mov volta,#0 ; mov num,#0 ;Zera contador de caracteres do buffer ljmp MenuNumerico ;Solicita os comandos a serem gravados not_A: cjne a,#'R',not_R ;Repetir: ;Prepara para repetir os movimentos gravados no buffer acall pstri DB 10,13,"Repetindo > ",10,13,0 mov mem,#1 ;Movimentos vem do buffer ;mem=1 mov gravar,#0 ;Não grava movimentos ;gravar=0 mov volta,#0 ;

Page 9: Relatório Braço Mecânico programado por microncontrolador intel 8081

mov r3,#0 ;Indice de leitura do buffer; mov r5,num ;num é copiado para r5(controle do loop) <<<<<<<<<<<<<<<<<<<<<<<<< ljmp PegaCmd ;Inicia captura de dados do buffer <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<not_R: cjne a,#'V',not_V ;Voltar: ;Implementa o o voltar no buffer; Usa complemento. acall pstri DB 10,13,"Voltando > ",10,13,0 mov mem,#1 ;Movimentos vem do buffer ;mem=1 mov gravar,#0 ;Não grava movimentos ;gravar=0 mov volta,#1 ;Buffer percorrido ao contrario, calculo do movimento complementar mov b,num ;num é copiado para r5(controle do loop) <<<<<<<<<<<<<<<<<<<<<<<<< inc b mov r3,b ;r3 começa no fim do buffer ljmp PegaCmd ;Inicia captura de dados do buffer <<<<<<<<<<<<<<<<<<<<ponte1: ljmp LeTeclaInicialnot_V: cjne a,#'M',not_M ;Mover: acall pstri DB 10,13,"Movendo > ",10,13,0 mov mem,#0 ;Movimentos vem do teclado ;mem=0 mov gravar,#0 ;Não grava movimentos ;gravar=0 mov volta,#0 ;Indica que o buffer vai ser lido no sentido original sjmp MenuNumerico ;E vai acionarnot_M:; lcall phex cjne a,#27,ponte1 ;Se nao for ESC, espera próximo caracter válido inc a; lcall phex; acall prstack ;Teste: impressao da pilha ret ;Retorna ao PaulMon2 mov a,#00000000b ;desenergiza as bobinas mov dptr,#port_b ;aponta para os motores movx @dptr,a ;manda para os motores: desliga cpl a ;inverte os bits mov dptr,#port_c ;aponta para os LEDs movx @dptr,a ;manda para os LEDs: desliga; ret ;Retorna ao PaulMon2MenuNumerico: acall pstri DB 13,10,"Use o teclado numerico (Com NUM LOCK):",13,10,0 acall pstri DB 13,10,"7:ESQ-CIMA 8:CIMA 9:DIR-CIMA",0 acall pstri DB 13,10,"4:ESQ 6:DIR",0 acall pstri DB 13,10,"1:ESQ-BAIXO 2:BAIXO 3:DIR-BAIXO",13,10,0

PegaCmd: mov a,mem ;Verifica flag de gravação jnz LeMem ;Se zero vai ler memoriaLeTec: lcall cin ;pega o input do usuário sjmp ExecutaBuffer ;vai pro caseLeMem: TestaOrdem:

Page 10: Relatório Braço Mecânico programado por microncontrolador intel 8081

mov a,volta ;Guarda o sentido da leitura (0: direto| 1: inverso) jnz LerInverso ;Sentido inversoLeDireto: inc r3 ;Pega proxima posicao do buffer mov a,#buffer ;Pega endereço do buffer add a,r3 ;Calcula posicao atual do buffer para ler; lcall phex mov r0,a ;r0 fica com endereco do caracter no buffer mov a,@r0 ;Acc recebe char do buffer sjmp ExecutaBuffer ;Executa proximo movimento do bufferPonte2: ljmp MenuInicialLerInverso: dec r3 ;Recua apontando para o próximo comando mov a,#buffer ;Pega endereço do buffer add a,r3 ;Calcula posicao atual do buffer para ler mov r0,a ;r0 fica com endereco do caracter no buffer mov a,@r0 ;Acc recebe char do buffer cjne a,#27,ContinuaLendo sjmp FimLeituraContinuaLendo: mov b,a ;Guarda um cópia mov a,#106 ;Prepara constante clr c ;Limpa o carry subb a,b ;Computa comando complementar: (106 - Cmd)FimLeitura: ljmp ExecutaBuffer ;Executa proximo movimento do bufferExecutaBuffer: cjne a,#'9',not_9 ;testa se o usuário digitou 9:DIR-CIMA mov dptr,#DIR_CIMA ;aponta para a tabela do 9 sjmp loop_tab ;Vai acionar not_9: cjne a,#'8',not_8 ;testa se o usuário digitou 8:CIMA mov dptr,#CIMA ;aponta para a tebela do 8 sjmp loop_tab ;Vai acionar not_8: cjne a,#'7',not_7 ;testa se o usuário digitou 7:ESQ-CIMA mov dptr,#ESQ_CIMA ;aponta para a tebela do 7 sjmp loop_tab ;Vai acionar not_7: cjne a,#'6',not_6 ;testa se o usuário digitou 6:DIR mov dptr,#DIR ;aponta para a tebela do 6 sjmp loop_tab ;Vai acionar not_6: cjne a,#'4',not_4 ;testa se o usuário digitou 4:ESQ mov dptr,#ESQ ;aponta para a tebela do 4 sjmp loop_tab ;Vai acionar Ponte3: sjmp LeTecPonte4: sjmp PegaCmdnot_4: cjne a,#'3',not_3 ;testa se o usuário digitou 3:DIR-BAIXO mov dptr,#DIR_BAIXO ;aponta para a tebela do 3 sjmp loop_tab ;Vai acionar not_3: cjne a,#'2',not_2 ;testa se o usuário digitou 2:BAIXO

Page 11: Relatório Braço Mecânico programado por microncontrolador intel 8081

mov dptr,#BAIXO ;aponta para a tebela do 2 sjmp loop_tab ;Vai acionar not_2: cjne a,#'1',not_1 ;testa se o usuário digitou 1:ESQ-BAIXO mov dptr,#ESQ_BAIXO ;aponta para a tebela do 1 sjmp loop_tab ;Vai acionar not_1: cjne a,#27,not_esc ;testa se o usuario digitou ESC mov a,#00000000b ;desenergiza as bobinas mov dptr,#port_b ;aponta para os motores movx @dptr,a ;manda para os motores: desliga cpl a ;inverte os bits mov dptr,#port_c ;aponta para os LEDs movx @dptr,a ;manda para os LEDs: desliga mov a,gravar ;Verifica flag de gravação jz Ponte2 ;Se !=1, nao grava mov a,num ; Coloca numero de caracteres atualizado add a,#buffer ;Calcula insercao no buffer mov r0,a ;Prepara endereço de insercao no buffer inc r0 ;ESC não será contado em num mov a,#27 ;Vai inserir um ESC mov @r0,a ;Insere caracter no buffer ;Endereçamento indireto ljmp MenuInicial ;retorna para o menu inicial not_esc: ljmp LeTec ;Espera uma tecla válida loop_tab: mov r5,a ;Salva caracter digitado em r5 lcall cout ;Valida a tecla, mostra para o usuario mov b,#4 ;tabela com 4 linhasloop_linha: clr a ;Zerar o acumulador movc a,@a+dptr ;Pega um byte da tabelaupdate: push dph ;Parte mais significativa do dptr push dpl ;Parte menos significativa do dptr mov dptr,#port_b ;Move o endereço da porta dos motores para o dptr movx @dptr,a ;Manda a configuraçao binaria para os motores cpl a ;Inverte os bits mov dptr,#port_c ;Move o endereço da porta dos LEDs movx @dptr,a ;Liga os LEDs pop dpl ; pop dph ;Reconstrói o dptr mov a,temporizacao ;Pega a temporizacao;temporizaçao: gasta tempo mov r0,a ;inicializa loop externodly2: mov r1,#250 ;inicializa loop internodly3: nop ;gasta tempo nop djnz r1,dly3 ;testa e repete djnz r0,dly2 ;testa e repete ;terminou a temporização inc dptr ;incrementa o dptr djnz b,loop_linha ;conta a linhafim_tab: mov a,mem ;Verifica flag de leitura de memória

Page 12: Relatório Braço Mecânico programado por microncontrolador intel 8081

jnz Ponte4 ;Se !=1, nao le mov a,gravar ;Verifica flag de gravação jz Ponte3 ;Se !=1, nao grava ;Gravaçãograva: inc num ;mais um caracter será gravado mov a,num ;Coloca numero de caracteres atualizado add a,#buffer ;Calcula insercao no buffer; lcall phex mov r0,a ;Prepara endereço de insercao no buffer mov a,r5 ;Restaura caracter digitado para Acc mov @r0,a ;Insere caracter no buffer ;Endereçamento indireto mov r0,num ;Coloca numero de caracteres para r0 cjne r0,#254,Ponte3 ;Testa fim de buffer inc r0 ;Buffer cheio: Avança no buffer mov a,#27 ;Prepara o ESC mov @r0,a ;Insere o ESC acall pstri DB 13,10,"Buffer cheio.",13,10,0 ljmp MenuInicial ;Aguarda o próximo modo

DIR_CIMA: ;Tecla 9 DB 00010001b DB 00100010b DB 01000100b DB 10001000b

CIMA: ;Tecla 8 DB 00010000b DB 00100000b DB 01000000b DB 10000000b

ESQ_CIMA: ;Tecla 7 DB 00011000b DB 00100100b DB 01000010b DB 10000001b

DIR: ;Tecla 6 DB 00000001b DB 00000010b DB 00000100b DB 00001000b

ESQ: ;Tecla 4 DB 00001000b DB 00000100b DB 00000010b DB 00000001b

DIR_BAIXO: ;Tecla 3 DB 10000001b DB 01000010b DB 00100100b DB 00011000b

Page 13: Relatório Braço Mecânico programado por microncontrolador intel 8081

BAIXO: ;Tecla 2 DB 10000000b DB 01000000b DB 00100000b DB 00010000b

ESQ_BAIXO: ;Tecla 1 DB 10001000b DB 01000100b DB 00100010b DB 00010001b

END