Você está na página 1de 63

Introduoparaoiniciante LinguagemAssemblydos MicroprocessadoresATMELAVR

por GerhardSchmidt http://www.avrasmtutorial.net Dezembrode2003


Verso corrigida em Julho de 2006 Correes adicionais e atualizaes em Janeiro de 2008 Traduzido por Guilherme Groke ggroke@gmail.com

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Contedo
PorqueaprenderAssembler?......................................................................................................................1 Curtaefcil...........................................................................................................................................1 Veloz.....................................................................................................................................................1 Assemblerdefcilaprendizado..........................................................................................................1 AVRssoideaisparaseaprenderassembler........................................................................................1 Teste!.....................................................................................................................................................2 HardwareparaprogramaoemAssemblerAVR.....................................................................................3 AinterfaceISPdafamliadeprocessadoresAVR................................................................................3 ProgramadorparaaportaparaleladoPC..............................................................................................3 Placasexperimentais.............................................................................................................................4 PlacaexperimentalcomATtiny13...................................................................................................4 PlacaexperimentalcomumAT90S2313/ATmega2313..................................................................5 PlacasdeprogramaocomerciaisparaafamliaAVR........................................................................6 STK200.............................................................................................................................................6 STK500.............................................................................................................................................6 AVRDragon.....................................................................................................................................7 FerramentasparaprogramaoassemblyAVR........................................................................................8 Deumarquivotextoapalavrasdeinstruoparaamemriaflash......................................................8 Oeditor.............................................................................................................................................8 Oassembler......................................................................................................................................9 Programandooschips.........................................................................................................................10 Simulaonostudio............................................................................................................................11 Registrador...............................................................................................................................................13 Oqueumregistrador?......................................................................................................................13 Registradoresdiferentes......................................................................................................................14 Registradoresponteiros.......................................................................................................................14 Recomendaoparausodosregistradores..........................................................................................15 Portas........................................................................................................................................................17 OqueumaPorta?..............................................................................................................................17 DeatlhesdeportasrelevantesdoAVR................................................................................................18 Oregistradordestatuscomoaportamaisutilizada............................................................................18 Detalhesdasportas..............................................................................................................................19 SRAM......................................................................................................................................................20 UsandoSRAMemlinguagemassemblerAVR.................................................................................20 OqueSRAM?..................................................................................................................................20 ParaquepropsitospossousaraSRAM?...........................................................................................20 ComousaraSRAM?...........................................................................................................................20 UseofSRAMasstack.........................................................................................................................21 DefinindoSRAMcomopilha.........................................................................................................21 Usodapilha....................................................................................................................................22 Bugscomaoperaodepilhas.......................................................................................................22 SaltoseDesvios.......................................................................................................................................24 Controlandoaexecuoseqencialdeumprograma.........................................................................24 Oqueaconteceduranteumreset?..................................................................................................24 Execuolineardoprogramaedesvios..............................................................................................25 Temporizaoduranteaexecuodoprograma.................................................................................25 Macroseexecuodoprograma.........................................................................................................26 Subrotinas............................................................................................................................................26 Interrupeseaexecuodoprograma..............................................................................................28 Clculos....................................................................................................................................................30 Sistemasnumricosemassembler......................................................................................................30 Nmerospositivosinteiros(bytes,palavras,etc.)..........................................................................30 Nmeroscomsinal(inteiros)..........................................................................................................30 DgitosCodificadosemBinrio,BCD(BinaryCodedDigits)......................................................30 BCDscompactados.........................................................................................................................31 NmerosemformatoASCII...........................................................................................................31 Manipulaodebits.............................................................................................................................31

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Deslocaerotaciona..............................................................................................................................32 Somando,subtraindoecomparando....................................................................................................33 Conversodeformatosnumricos......................................................................................................35 Multiplicao.......................................................................................................................................35 Multiplicaodecimal....................................................................................................................35 Multiplicaobinria......................................................................................................................36 ProgramaemAssemblerAVR.......................................................................................................36 Binaryrotation................................................................................................................................37 Multiplicaonostudio..................................................................................................................37 Diviso.................................................................................................................................................39 Divisodecimal..............................................................................................................................39 Binarydivision...............................................................................................................................39 Passosdoprogramaduranteadiviso............................................................................................40 Divisonosimulador......................................................................................................................40 Conversonumrica............................................................................................................................43 Fraesdecimais.................................................................................................................................43 Converseslineares........................................................................................................................43 Exempl01:ConversorAD8bitparasadadecimalcompontofixo.............................................44 Exemplo2:ConversorADde10bitscomsadadecimalfixa.......................................................45 Anexo.......................................................................................................................................................46 Instruesordenadasporfuno.........................................................................................................46 ListadeDiretivaseInstruesemordemalfabtica...........................................................................48 DiretivasdeAssembleremordemalfabtica.................................................................................48 Instruesemordemalfabtica......................................................................................................48 DetalhesdasPortas..............................................................................................................................50 RegistradordeStatus,FlagsdoAcumulador.................................................................................50 Ponteirodepilha.............................................................................................................................51 SRAMecontroleexternodeinterrupes......................................................................................51 ControledeInterrupoExterno.....................................................................................................52 ControledoTimerdeInterrupo..................................................................................................52 Timer/Contador0............................................................................................................................53 Timer/Contador1............................................................................................................................54 WatchdogTimer.............................................................................................................................55 EEPROM........................................................................................................................................56 InterfacedePerifricosSeriais(SPI)..............................................................................................56 UART.............................................................................................................................................57 AnalogComparator........................................................................................................................58 PortasE/S.......................................................................................................................................59 Portas,ordemalfabtica......................................................................................................................59 Listadeabreviaes............................................................................................................................60

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Porque aprender Assembler?


Assembler ou outras linguagens, esta a questo. Porque eu deveria aprender mais uma linguagem, se eu j conheo outras linguagens de programao? O melhor argumento: enquanto voc viver na Frana, poder sobreviver falando Ingls, mas voc nunca se sentir em casa, e a vida fica difcil. Voc pode apenas continuar desta forma, mas isto no apropriado. Se as coisas ficarem complicadas, voc dever usar a linguagem corrente do pas Muitas pessoas j experientes em programao de AVRs e que usam linguagens de alto nvel em seu trabalho normal, recomendam que os iniciantes comecem aprendendo linguagem assembly. A razo para isto que, algumas vezes, podem ocorrer certas situaes, como:

se bugs tm que ser analizados, se o programa faz coisas diferentes das que foram escritas e so esperadas, se linguagens de alto nvel no suportam o uso de certas caractersticas do hardware, se rotinas em que a temporizao crtica requerem pores de linguagem assembly,

necessrio entender a linguagem assembly, e.g., entender o que os compiladores de linguagens de alto nvel produzem. Sem compreender a linguagem assembly, voc no ter chance de ir adiante nestes casos.

Curta e fcil
Os comandos assembler so traduzidos um a um para serem comandos executados pela mquina. O processador necessita apenas executar o que voc quer fazer e o necessrio para executar a tarefa. Nenhum loop extra ou caractersticas desnecessrias poluem o cdigo. Se o espao para o seu programa curto e limitado e voc ter que otimizar seu programa para caber na memria, assembler a escolha nmero um. Programas mais curtos so mais fceis de depurar (debugar), cada passo faz sentido.

Veloz
Como apenas os passos necessrios so executados, os programas em assembly so to rpidos quanto possvel. Aplicaes onde o tempo crtico, como medies de tempo que devam ter boa performance, sem que haja um hardware de temporizao, devem ser escritas em assembler. Se voc tiver mais tempo e no se importar que seu chip permanea 99% em um estado de espera (wait state) de operao, voc pode escolher a linguagem que desejar.

Assembler de fcil aprendizado


No verdade que a linguagem assembly mais complicada ou no to fcil de compreender quanto outras linguagens. Aprender linguagem assembly para qualquer tipo de hardware facilita a compreenso de conceitos de qualquer outro dialeto da linguagem assembly. Aprender outros dialetos depois mais fcil. Algumas caractersticas so dependentes do hardware, e isto requer alguma familiaridade com os conceitos de hardware e seus dialetos. O que faz o assembler parecer complicado algumas vezes que ele requer uma compreenso das funes do controlador do hardware. Linguagens de alto nvel no permitem a utilizao de caractersticas especiais do hardware, e escondem estas funes. O primeiro cdigo assembly no parece muito interessante, mas depois de 100 linhas adicionais programadas, parecer melhor. Programas perfeitos requerem apenas alguns milhares de linhas de cdigo de exerccio, e otimizao requer bastante trabalho. Os primeiros passos so difceis em qualquer linguagem. Aps algumas semanas programando, voc dar risada se analisar seu primeiro cdigo. Alguns comandos em assembler requerem meses de experincia.

AVRs so ideais para se aprender assembler


Programas em assembler so um pouco tolos: o chip executa tudo que voc disser a ele para fazer, e no pergunta se voc tem certeza se quer sobrescrever isso ou aquilo. Todas as caractersticas de proteo devem ser programadas por voc, o chip faz exatamente aquilo que lhe comandado, mesmo que no faa sentido algum. Nenhuma janela o alertar, a menos que voc a tenha programado anteriormente. Para corrigir erros de digitao to fcil ou complicado como qualquer outra linguagem. Existem erros bsicos ou mais complicados. Porm: testar os programas nos chips ATMEL muito fcil. Se o chip no faz o que voc espera, voc pode facilmente adicionar algumas linhas de diagnstico ao cdigo, reprogram-lo e test-lo. Adeus, programadores de EPROM, lmpadas UV usadas para apagar o programa, pinos que no se encaixam mais no soquete aps t-los removido uma dzia de vezes. As mudanas agora so programadas rapidamente, compiladas imediatamente, ou mesmo simuladas no studio ou checadas no prprio circuito. Nenhum pino tem que ser removido, e nenhuma lmpada de UV te

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

deixar na mo justamente no momento em que voc teve uma excelente idia sobre aquele bug.

Teste!
Seja paciente nos seus primeiros passos! Se voc tem familiaridade com outra linguagem (alto nvel): esquea-a por enquanto. A maioria das caractersticas especiais de outras linguagens de computao no fazem nenhum sentido em assembler. As primeiras cinco instrues no so fceis de aprender, depois disso sua velocidade de aprendizado aumentar rapidamente. Depois que voc escreveu as primeiras linhas: pegue o conjunto de instrues e leia-o deitado em sua banheira, imaginando para que servem todas as outras instrues. Aviso srio: No tente criar uma mega-mquina logo de incio. Isto no faz sentido algum em nenhuma linguagem de programao, e apenas produz frustrao. Comece com pequenos exemplos tipo Ol Mundo, e.g., ligando e desligando LEDs por algum tempo, e s ento comece a explorar as caractersticas do hardware mais profundamente. Recomendao: Comente suas subrotinas e armazene-as em um diretrio especial, se debugadas: voc precisar delas em breve. Sucesso!

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Hardware para programao em Assembler AVR


Aprender assembler requer um equipamento simples para testar seus programas e ver se eles funcionam na prtica. Est pgina mostra dois esquemas fceis que permitem a voc construir em casa o hardware necessrio. Este hardware realmente fcil de construir. Desconheo qualquer esquema mais fcil do que este para o seus primeiros passo em software. Se voc quiser fazer mais experimentos, reserve espao para expanses futuras em sua placa de experimentos. Se voc no gosta do cheiro de solda, voc pode comprar uma placa pronta para uso. As placas disponveis esto listadas na seo abaixo.

A interface ISP da famlia de processadores AVR


Antes de entrarmos na prtica, temos que aprender alguns conceitos essenciais no modo de programao serial da famlia AVR. No, voc no precisa trs diferentes voltagens para programar e ler a memria flash do AVR. No, voc no precisa de outro microprocessador para programar os AVRs. No voc no precisa de 10 linhas de E/S para dizer ao chip o que voc gostaria que ele fizesse. E voc no tem sequer que remover o AVR da sua placa de experimentos, antes de program-lo. fcil assim. Tudo isto feito pela interface embutida em cada chip AVR, que permite a voc escrever e ler o contedo da memria flash e EEPROM embutidas. Esta interface trabalha serialmente e precisa de trs linhas de sinal: SCK: Um sinal de clock que move os bits a serem escritos na memria para um shift register interno, que move os bits para serem lidos por outro shift register. MOSI: Um sinal de dados que envia os bits para serem escritos no AVR, MISO: Um sinal de dados que recebe os bits lidos do AVR. Estes trs pinos de sinal so internamente conectados ao sistema de programao apenas se voc deixar o sinal RESET (algumas vezes chamado de RST ou restart) em nvel zero. Caso contrrio, durante a operao normal do AVR, estes pinos so portas de E/S programveis como todas as outras. Se voc quiser usar estes pinos para outros propsitos durante a operao normal, e para programao ISP, voc ter que faz-lo de forma que estes dois propsitos no conflitem. Normalmente voc deve desacoplar os sinais por um resistor ou utilizar um multiplexador. O necessrio para o seu caso, depende do seu uso dos pinos no modo de operao normal. Se voc tiver sorte, pode deixar estes pinos exclusivamente paa a programao ISP. No necessrio, porm recomendado para a programao ISP, que voc tenha uma tenso de alimentao para o hardware no prprio circuito de programao. Isto torna a programao mais fcil, e requer apenas duas linhas adicionais entre o programador e a placa AVR. GND o terra comum, VTG (target voltage) a tenso de alimentao (normalmente 5.0 Volts). Isto totaliza 6 linhas entre o programador e a placa AVR. A conexo ISP6 , conforme definida pela ATMEL, mostrada esquerda. Padres sempre tm padres alternativos. Esta a base tcnica que constitui a empresa de adaptadores. No nosso caso, o padro alternativo foi projetado utilizando um ISP10 e foi utilizado na placa STK200. um padro bastante disseminado, e mesmo o STK500 est equipado com este padro. O padro ISO10 tem um sinal adicional que aciona um LED vermelho. Este LED sinaliza que o programador est fazendo o seu trabalho. Uma boa idia. Conecte o LED a um resistor e fonte de tenso.

Programador para a porta paralela do PC


Agora, aquea o seu ferro de soldar e construiremos seu programador. um esquema bastante fcil e funciona com peas facilmente encontrveis na sua caixa de experimentos. Sim, tudo que voc precisa para programar um AVR. O plugue de 25 pinos se liga porta paralela do seu PC, e o conector ISP de 10 pinos se conecta placa de experimentos AVR. Se voc no tiver um 72LS245, voc pode utilizar tambm o 74HC245 (sem mudanas no circuito) ou um 74LS244/74HC244

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

(com pequenas mudanas no circuito). Se voc utilizar HC, no se esquea de conectar os pinos no utilizados ao terra ou tenso de alimentao, caso contrrio os buffers podem produzir rudo capacitivo pelo chaveamento.

Todo o algoritmo de programao necessrio feito pelo software ISP. Esteja ciente que esta interface paralela no mais suportada pelo software Atmel Studio. Portanto, se voc desejar programar seu AVR diretamente do studio, utilize programadores diferentes. A internet fornece diversas solues. Se voc j tiver uma placa de programao, voc no precisar construir este programador, porque voc encontrar a interface ISP em alguns pinos. Consulte o manual para localiz-los.

Placas experimentais
Voc provavelmente quer fazer seus primeiros programas com uma placa AVR feita em casa. Aqui apresentamos duas verses:

Uma bem pequena com um ATtiny13, ou uma mais complicada com um AT90S2313 ou ATmega2313, incluindo uma interface serial RS232.

Placa experimental com ATtiny13


Esta uma placa bem pequena que permite experimentos com o hardware interno do Attiny13. A figura mostra

A interface de programao ISP10 esquerda, com o LED de programao ligado a um resistor de 390 ohms, o ATtiny13 com um resistor pull-up de10k no pino RESET (pino 1),

1. a fonte de alimentao com um retificador em ponte, que aplica de 9 a 15V a partir de uma fonte AC ou DC, e um pequeno regulador de 5V.

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

O ATtiny13 no requer cristal externo ou gerador de clock, pois trabalha com o seu gerador RC interno de 9,6 Mcs/s e, por padro, com um divisor de clock em 8 (freqncia de clock de 1,2 Mcs/s). O hardware pode ser construido em uma pequena placa como a mostrada na figura. Todos os pinos do tiny13 so acessveis, e componentes externos ao hardware, como o LED mostrado, so facilmente conectados. Esta placa permite o uso dos componentes de hardware do Attiny13, como portas E/S, timers, conversores AD, etc.

Placa experimental com um AT90S2313/ATmega2313


Para fins de teste, ou se mais pinos de E/S ou comunicao serial forem necessrios, podemos utilizar um AT90S2313 ou Atmega2313 em uma placa experimental. O esquema mostra

uma pequena fonte de alimenao para coneco a um transformador AC e um regulador de tenso 5V/1A, um gerador de clock a cristal (aqui com um cristal de 10 MHz, qualquer freqncia abaixo do mximo especificado para o AT90S2313 funcionaro), os componentes necessrios para um reset seguro durante o momento da partida da alimentao, a interface de programao ISP (com o conector ISP10).

isto que voc precisa para iniciar. Conecte os outros perifricos e adicionais aos numerosos pinos livres de E/S ao 2313. O dispositivo de sada mais fcil pode ser um LED, conectado a um resistor tenso de alimentao. Com isso, voc pode escrever o seu primeiro programa em assembler para acender e apagar o LED. Se voc

no precisar da interface de comunicao serial, simplesmente ignore o hardware conectado aos pinos 2/3 e 14/16,

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

no precisar dos sinais de handshaking, ignore os pinos 14/16 e conecte RTS ao conector de 9 pinos via um resistor de 2,2k a +9V. o cristal externo no necessrio, pois o ATmega possui um gerador de clock RC interno, basta ignorar as conexes aos pinos 4 e 5, se voc quiser usar um cristal externo no lugar do circuito RC interno, voc ter que programar os fusveis do Atmega de acordo.

Se voc usar um ATmega2313 no lugar do AT90S2313, sero feitas as seguintes mundanas:


Placas de programao comerciais para a famlia AVR


Se voc no gosta de hardware feito em casa, e tem algum dinheiro extra e no sabe o que fazer com ele, voc pode comprar uma placa de programao comercial pronta. Dependendo da quantidade de dinheiro extra que voc gostaria de gastar, voc pode escolher entre verses mais baratas ou mais caras. Para o amador, a critrio de seleo deve ser baseado em:

preo, interface com o PC (de preferncia USB; menos conveniente ou durvel: RS232; requer software adicional para programao: porta paralela do PC), suporte a novos dispositivos (atualizaes so necessrias de tempos em tempos, caso contrrio voc montar em um cavalo morto), caractersticas do hardware (depende de suas necessidades para os prximos cinco anos).

A seo a seguir descreve trs placas padro da ATMEL, a STK200, a STK500 e a Dragon. A seleo baseada em minhas prprias experincias, e no uma recomendao.

STK200
A STK200 da ATMEL uma placa histrica. Se voc conseguir uma usada, voc ter

uma placa com alguns soquetes (para dispositivos de 8, 20, 28 e 40 pinos), oito chaves e LEDs, conectados permanentemente s portas D e B, um LCD com interface padro de 14 pinos, uma opo para conectar uma SRAM de 28 pinos, uma interface RS232 para comunicao, um cabo de interface com a porta paralela do PC em um lado e um ISP de 10 pinos do outro.

Programao em HV (alta voltagem) no suportada. A placa no pode ser programada do Studio, o software de programao no mais suportado, e voc deve usar programas externos capazes de programar via porta paralela. Se algum lhe oferecer esta placa, pegue-a apenas de graa, e se voc estiver acostumado a utilizar os softwares necessrios.

STK500
fcil obter a STK500 (e.g. direto da ATMEL). Esta placa tem o seguinte hardware:

Soquetes para programar a maioria dos tipos de AVR (e.g. Dispositivos de 14 pinos ou encapsulamentos TQFP, exigindo algum hardware adicional), programao serial e paralela em modo normal ou alta voltagem (programao HV traz de volta vida dispositivos mesmo se o pino RESET foi programado para ser uma porta de entrada), Conexes ISP6 e ISP10 para programao ISP, oscilador com freqncia e tenses de alimentao programveis, chaves e LEDs configurveis, um conector RS232C (UART), uma EEPROM-Flash serial (somente as placas mais antigas), acesso a todas as portas via conectores de 10 pinos.

A principal desvantagem desta placa que, aps programar um dispositivo, vrias conexes tm que ser feitas manualmente com os cabos que a acompanham. A placa conectada ao PC usando uma porta serial (COMx). Se o seu laptop no possui uma interface serial, voc pode utilizar um conversor USB-Serial comum com driver. Neste caso, o driver deve ser ajustada para usar entre COM1 e COM2 e uma velocidade de 115k para ser detectada automaticamente pelo software Studio.

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

A programao realizada e controlada pelas verses recentes do AVR studio, que est disponvel gratuitamente para download pela pgina da ATMEL aps o registro. Atualizaes na lista de dispositivos e algoritmos de programao so fornecidos com as verses do Studio, ento o suporte para novos dispositivos mais provvel do que com outras placas e softwares de programao. Os experimentos podem comear com o AVR fornecido (verses antigas: AT90S8515, novas placas incluem tipos diferentes). Este kit cobre todas as necessidades que o iniciante pode ter.

AVR Dragon
O AVR Dragon uma pequena placa. Ela possui uma interface USB, que alimenta a placa e a interface ISP de 6 pinos. A interface ISP de 6 pinos acompanhada pela interface de programao HV de 20 pinos. A placa preparada para receber alguns soquetes, mas no possui soquetes para dispositivos para gravao ou outro hardware. O dragon suportado pelo software Studio e atualizado automaticamente. Seu preo e design o torna um excelente presente para o amador de AVR.

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Ferramentas para programao assembly AVR


Quatro ferramentas bsicas so necessrios para programao em assembly. Estas ferramentas so:

o editor, o compilador, a interface para programao do chip, e o simulador. 1. todos as ferramentas em um s programa, 2. cada tarefa realizada por um programa especfico, e os resultados so armazenados em arquivos especficos.

Para realizar estas tarefas, existem dois caminhos:

Normalmente a primeira opo escolhida. Porm, como isto um tutorial, e voc deve compreencer o mecanismo primeiro, comearemos descrevendo a segunda opo.

De um arquivo texto a palavras de instruo para a memria flash


O editor
Os programas assembler so escritos com um editor. O editor simplesmente tem que criar e editar texto ASCII. Ento, basicamente, qualquer editor simples serve. Algumas caractersticas do editor podem ter efeitos positivos:

Erros, que o assembler detecta depois, so reportados juntamente com o nmero da linha do arquivo texto. Nmeros de linha so tambm uma poderosa inveno da era do computador com respeito a discusses no seu cdigo com algum. Ento o seu editor deve ser capaz de mostrar o nmero da linha. Infelizmente, quase todos os editores que uma poderosa empresa de software fornece como parte dos seus sistemas operacionais, no possuem esta caracterstica. Provavelmente o Windows 2019 reinvente esta caracterstica, e venda melhor entre os malucos por assembler. Erros de digitao so muito reduzidos, se estes erros forem marcados com cores. uma tima caracteristica de um editor, destacar os componentes de uma linha em diferentes cores. Reconhecimento inteligente dos erros facilita a escrita. Mas uma caracterstica que eu no sinto falta. Se seu editor permite a seleo de fonte, escolha uma fonte com espao fixo, como Courier. Os cabealhos ficam melhor assim. Seu editor deve ser capaz de reconhecer fim de linhas com qualquer combinao de caracteres (carriage return, line feed, ambos) sem produzir telas inaceitveis. Outro item na lista de desejos para o Windows 2013.

Se voc prefere matar moscas com canho, voc pode usar um software processador de texto poderodo para escrever os seus programas em assembler. Pode parecer mais bonito, com cabealhos em fonte grande e negritos, comentrios em cinza, avisos em vermelho, mudanas destacadas, e lembretes e todos em campos extra destacados. Algumas desvantagens, contudo: voc ter que converter o seu texto em texto simples no final, perdendo todo o seu trabalho de design, e o seu arquivo texto resultante no poder ter um nico byte de controle faltando. Caso contrrio, este nico byte gerar uma mensagem de erro, quando voc tentar processar o texto. E lembre-se: Nmeros de linha estaro apenas corretos na pgina do seu cdigo-fonte.

Avr-Asm-Tutorial

http://www.avr-asm-tutorial.net

Assim, qualquer programa de texto que voc quiser, escolha sua. Os exemplos a seguir foram escritos no wavrasm, um editor fornecido pela ATMEL h algum tempo. No campo do editor simples, escrevemos as nossas diretivas e comandos de assembler. altamente recomendado que estas linhas sejam acompanhadas por alguns comentados (comeando por ;). Entender o que voc havia planejado aqui so importantes na depurao posterior. Agora armazene o arquivo texto, chamado TEST.ASM, em um diretrio dedicado, usando o menu File. O programa assembly est completo agora Se voc gostaria de ver o que destaque pela sintaxe significa, coloquei a captura de uma tela do AVR editor aqui. O editor reconhece os comandos automaticamente e usa diferentes cores (destaque da sintaxe) para sinalizar ao usurio constantes e erros de digitao nestes comandos (em preto). O cdigo armazenado no arquivo .asm basicamente o mesmo, pois as cores no so armazenadas no arquivo. No tente encontrar este editor ou seu autor; o editor virou histria e no mais mantido.

O assembler
Agora temos um arquivo texto, com caracteres ASCII em branco. O prximo passo traduzir este cdigo para forma orientada para mquina, que ser compreendida pelo chip AVR. Isto chamado de assemblar, compilar, ou seja montar as palavras de comando corretas. Este programa l o arquivotexto e produz um tipo de sada chamada Assembler. O formato mais simples deste programa em linha de comando, e quando chamado com o endereo do arquivo texto e alguns parmetros adicionais, inicia a traduo dos comandos para um segundo arquivo-texto. Se o seu editor permite a chamada de programas externos, uma tarefa fcil. Se no (outro item para a lista de desejos para o editor do Windows 2010), mais conveniente escrever um arquivo batch (usando outro editor). Este arquivo batch deve ter uma linha assim: Path do Assembler\Assembler.exe -opes Path do Arquivo-Texto\Arquivotexto.asm Ao clicar no boto para executar programa externo, ou no arquivo batch, inicia-se o compilador. Este software reporta a traduo completa (na janela menor), neste caso sem erros. Se erros ocorrerem, eles so notificados, juntamente com o seu tipo e o nmero da linha onde ele ocorreu. A compilao resultou em uma palavra de cdigo que resultou da instruo RJMP que utilizamos. Durante o processo de assembler, nosso arquivo de texto produziu outros quatro arquivos (nem todos sero tratados aqui). O primeiro destes novos quatro arquivos, TEST.EEP, contm o que efetivamente dever ser gravado na EEPROM do AVR. Isto no muito interessante no nosso

Avr-Asm-Tutorial

10

http://www.avr-asm-tutorial.net

caso, porque no programamos nada para a EEPROM. O compilador, conseqentemente deletou este arquivo quando terminou a montagem, pois era vazio. O segundo arquivo, TEST.HEX, mais relevante pois ele guarda os comandos que sero posteriormente gravados no chip AVR. Este arquivo se apresenta assim. Os nmeros hexadecimais esto escritos em um formato ASCII especial, juntamente com as informaes de endereo e checksum para cada linha. Este formato chamado Intel-hex, muito antigo e remonta para os primrdios da computao. Este formato bem compreendido pelo software de programao. O terceiro arquivo, TEST.OBJ, ser explicado depois, este arquivo necessrio para simular um AVR. Seu formato hexadecimal e definido pela ATMEL. Usando um editor hexa, seu contedo assim. Ateno: Este formato de arquivo no compatvel com o software de programao, no use este arquivo para programar um AVR (um erro muito comum no incio). Arquivos OBJ so produzidos apenas por alguns assemblers ATMEL, no os espere de outros assemblers. O quarto arquivo, TEST.LST, um arquivo texto. Abrao com um editor simples. Ser visto uma tela como a mostrada aqui. O programa com todos os seus endereos, comandos e mensagens de erro so mostrados em uma forma legvel. Voc precisar deste arquivo em alguns casos para depurar erros. Arquivos de lista so gerados apenas se a opo especificada na linha de comando e se a diretiva .NOLIST no suprimir a listagem.

Programando os chips
Para programar nosso cdigo hexa, como codificado no arquivo .HEX, no AVR, um software programador necessrio. Este software l o arquivo .HEX e transfere o seu contedo, seja bit a bit (programao serial), seja byte a byte (programao paralela) para a memria flash do AVR. Iniciamos o software de programao e carregamos o arquivos hex que acabamos de gerar. Em nosso exemplo, a tela seria semelhante a esta. Note: a janela apresentada mostra a tela do ISP.exe, um programa histrico no mais distribudo pela ATMEL. Outros softwares programadores so semelhantes. Este software gravar nosso cdigo no local designado no chip. H algumas precondies necessrias para fazer isto, e vrias razes possveis para uma falta. Consulte a ajuda do software programador, se ocorrerem problemas. Hardware de programao e alternativas de software apropriadas para diferentes sistemas operacionais esto disponveis na Internet. Como exemplo de um programador pela porta paralela ou serial, menciono o PonyProg2000.

Avr-Asm-Tutorial

11

http://www.avr-asm-tutorial.net

Simulao no studio
s vezes, o cdigo escrito em assembly, mesmo que seja compilado sem erros, no faz exatamente o que deveria depois de gravado no chip. Testar o software no chip pode ser complicado, especialmente se voc tem um hardware mnimo e no tem oportunidade de visualizar resultados intermedirios ou sinais de debug. Nestes casos, o pacote de software Studio da ATMEL fornece oportunidades perfeitas para depurao. Testar o software ou somente partes possvel, e o cdigo do programa pode ser testado passo a passo mostrando os resultados. As imagens mostradas aqui so tiradas da Verso 3 do Studio. A Verso 4 atual visualmente diferente, mas faz praticamente a mesma coisa. Primeiramente abriremos um arquivo (menu FILE OPEN). Demonstraremos utilizando o arquivo tutorial test1.asm, pois nele h mais alguns comandos e aes do que em nosso programa de um nico comando acima.

Abra o arquivo TEST1.OBJ, que resultou da compilao do TEST1.asm. Lhe perguntado que opes voc gostaria de usar (se no voc pode alterar atravs do menu SIMULATOR OPTIONS). Selecione as seguintes opes:

Dispositivo um AT90S8515, Freqncia do clock 4 MHz.

Na seo de seleo de dispositivos, selecionamos o tipo de chip desejado. A frequncia correta deve ser selecionada, se voc deseja simular temporizao correta. Para podermos ver o contedo de alguns registradores e o que o status atual do processador, selecionamos VIEW PROCESSOR e REGISTERS. Agora a imagem deve ser a seguinte. A janela do processador mostra vrios valores, como onde o contador de comando est, os registradores de flag de status, e a informao sobre temporizao (aqui a um clock de 1 MHz). O cronmetro por ser usado para fazer uma medida exata do tempo necessrio para executar rotinas etc.

Agoa iniciaremos a execuo do programa. Usaremos o modo de passo a passo (TRACE INTO ou F11). Usando GO resultaria em uma execuo contnua e nada seria visto devido alta velocidade da simulao.

Avr-Asm-Tutorial

12

http://www.avr-asm-tutorial.net

Aps o primeiro passo ser executado, a janela do processador ficaria como ao lado. O contador de programa (Program Counter), mostrado na janela do processador, est no passo 1, o contador de ciclo em 2 (RJMP precisa de dois ciclos para executar). Com clock de 1 MHz, dois microssegundos foram gastos, os flags e registradores no foram alterados. A janela com a arquivo texto fonte mostra um ponteiro no prximo comando a ser executado. Pressionar F11 novamente executa o prximo comando, o registrador mp (=R16) ser setado para 0xFF. Agora a janela de registradores deve destacar esta mudana. O novo valor do registrador R16 mostrado em cor vermelha. Podemos alterar o valor de um registrador a qualquer momento para checar o que acontece. Agora o passo 3 foi executado, a sada direcionada ao registrador da porta B. Para mostrar, abrimos uma nova janela de visualizao de E/S e selecionamos porta B. A imagem deve ser como a seguir. O registrador de direo de dados na janela de visualizao de E/S na porta B agora mostra o novo valor. Os valores podem ser alterados manualmente, se desejado, pino a pino. Os prximos dois passos so simulados usando F11. Eles no sero mostrados aqui. Setando as portas de sada para nvel um com a instruo LDI mp, 0xFF e OUT PORTB, mp resulta na seguinte figura na visualizao de E/S. Agora todos os bits de sada da porta esto em nvel um, a visualizao de E/S mostra isso. Este o nosso pequeno passeio atravs do mundo do software de simulao. O simulador capaz de muito mais, devendo portanto ser utilizado extensivamente nos casos de erro de projeto. Visite os diferentes itens de menu, h muito mais do que o mostrado aqui.

Avr-Asm-Tutorial

13

http://www.avr-asm-tutorial.net

Registrador
O que um registrador?
Registradores so locais especiais de armazenagem com capacidade de 8 bits e so da seguinte forma: Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

Note a numerao destes bits: o bit menos significativo inicia com zero (20 = 1). Um registrador pode tanto armazenar nmeros de 0 a 255 (somente nmeros positivos), ou nmeros de 128 a +127 (nmero inteiro com o bit 7 indicando o sinal), ou o valor que representa um caractere ASCII (e.g. 'A'), ou apenas oito bits que no tm nada a ver um com outro (e.g., para oita flags usados para sinalizar oito decises sim/no diferentes). A caracterstica especial dos registradores, comparada a outros locais de armazenagem, que

eles podem ser usados diretamente por comandos assembler, operaes com o seu contedo requerem somente uma palavra de comando, eles so conectados diretamente unidade central de processamento chamada acumulador, eles so origem e destino para clculos.

H 32 registradores em um AVR. Eles so originalmente chamados R0 a R31, mas voc pode escolher nome-los com nomes que faam sentido em uma diretiva assembler. Um exemplo:
.DEF MeuRegistradorPreferido = R16

As diretivas de assembler sempre iniciam com um ponto na coluna 1 do texto. Instrues NUNCA iniciam na coluna 1, eles sempre sero precedidos por um caractere vazio ou de tabulao! Note que as diretivas de assembler como esta significam alguma coisa apenas para o compilador assembler mas no produzem nenhum cdigo executvel no chip destino AVR. No lugar de utilizar o registrador com nome R16, podemos utilizar nosso prprio nome MeuRegistradorPreferido, quando quisermos usar R16 com algum comando. Ento escrevemos um pouco mais cada vez que queremos utilizar este registrador, mas temos uma associao ao que pode ser o contedo deste registrador. Usando a linha de comando
LDI MeuRegistradorPreferido, 150

significa: carregue o nmero 150 imediatamente para o registrador R16, LoaD Immediate, carregar imediato. Isto carrega um valor fixo ou uma constante neste registrador. Se observarmos a traduo deste cdigo no programa escrito no AVR, veremos o seguinte:
000000 E906

O comando load, bem como o registrador destino (R16), assim como o valor da constante (150) parte do valor hexa E906, mesmo que voc no os veja diretamente. No tenha medo: voc no tem que lembrar esta codificao porque o compilador sabe traduzir tudo isto para o esquisito E906. Dentro de um nico comando, dois diferentes registradores podem desempenhar um papel. O comando mis fcil teste tipo o comando de cpia MOV. Ele copia o contedo de um registrador em outro. Assim:
.DEF MeuRegistradorPreferido = R16 .DEF OutroRegistrador = R15 LDI MeuRegistradorPreferido, 150 MOV OutroRegistrador, MeuRegistradorPreferido

As duas primeiras linhas deste programa monstruoso so diretivas que definem os novos nomes dos registradores R16 e R15 para o compilador assembler. Novamente, estas linhas no produzem nenhum cdigo para o AVR. As linhas de comando com LDI e MOV produzem o cdigo:
000000 E906 000001 2F01

Os comandos escrevem 150 no registrador R16 e copiam o seu contedo para o registrador destino R15. NOTA IMPORTANTE: O primeiro registrador sempre o registrador destino onde o resultado ser escrito! (Isto infelizmente diferente da forma normalmente esperada ou de como falamos. uma conveno simples que foi definida certa vez para confundir os iniciantes aprendendo assembler. por isso que assembler to complicado.)

Avr-Asm-Tutorial

14

http://www.avr-asm-tutorial.net

Registradores diferentes
O iniciante pode querer escrever os comandos acima assim:
.DEF OutroRegistrador = R15 LDI OutroRegistrador, 150

E: voc falha. Apenas os registradores de R16 a R31 carregam uma constante imediamente com o comando LDI, R0 a R15 no fazem isso. Esta restrio no muito interessante, mas no pde ser evitada durante a construo do conjunto de comandos dos AVRs. H uma exceo a esta regra: escrever Zero em um registrador. O comando
CLR MeuRegistradorPreferido

vlido para todos os registradores. Alm do comando LDI, voc descobrir que esta restrio de classes de registradores ocorre tambm com os seguintes comandos:

ANDI Rx,K ; Operao And dos bits do registrador Rx com os bits do valor constante K, CBR Rx,M ; zera todos os bits no registrador Rx que esto em um dentro do valor de mscara constante M. CPI Rx,K ; Compara o contedo do registrador Rx com o valor constante K, SBCI Rx,K ; Subtrai a constante K e o valor atual da flag de carry (transporte) do registrador Rx e armazena o resultado no registrador Rx, SBR Rx,M ; Seta todos os bits no registrador Rx para um, que so um na mscara constante M, SER Rx ; Seta todos os bits no registrador Rx para um (igual a LDI Rx,255), SUBI Rx,K ; Subtrai a constante K do contedo do registrador Rx e armazena o resultado no registrador Rx.

Em todos estes comandos o registrador deve ser entre R16 e R31! Se voc planeja utilizar estes comandos, voc deve selecionar um destes registradores para a operao. mais fcil de programar. H uma razo adicional pela qual voc deve definir o nome dos registradores, porque voc pode facilmente alterar a localizao dos registradores posteriormente.

Registradores ponteiros
Um papel muito especial desempenhado pelos pares de registradores R27:R26, R29:R28 e R31:R32. Este papel to importante que estes pares tm nomes extra curtos em AVR assembler: X, Y e Z. Estes nomes curtos so compreendidos pelo compilador. Estes pares so registradores ponteiros de 16 bits, capazes de apontar endereos da SRAM com at 16 bits (X, Y ou Z) ou localizaes na memria do programa (Z). O byte menor do endereo de 16 bits est localizado no registrador inferior, o byte superior na registrador superior. Ambas partes tm seu prprio nome, e.g., o byte mais alto de Z chamado de ZH (=R31), e o byte mais baixo ZL (=R30). Estes nomes so definidos no arquivo de cabealho padro para os chips. Dividir estes dois ponteiros de 16 bits em dois bytes diferentes feito da seguinte forma:
.EQU endereco = RAMEND ; RAMEND o endereo de 16 bits mais alto da SRAM (fim da memria) LDI YH,HIGH(endereco) ; Seta o MSB LDI YL,LOW(endereco) ; Set the LSB

Acessos via ponteiros so feitos com comandos especialmente designados. A leitura feita pelo comando chamado LD (LoaD, carregar), e a escrita pelo comando chamado ST (STore, armazenar), e.g. Com o ponteiro X:

Ponteiro X X+ -X

Seqncia L/Escreve do endereo X, no altera o ponteiro L/Escreve de/para endereo X e incrementa o ponteiro por um

Exemplos LD R1,X ou ST X,R1 LD R1,X+ ou ST X+,R1

Decrementa o ponteiro em um e l/escreve de/para o novo endereo LD R1,-X ou ST -X,R1

De forma similar, voc pode usar Y e Z para este propsito. H somente um comando para acesso leitura dos dados do programa. Ele definido pelo par de ponteiros Z e chamado LPM (Load from Program Memory, carregar da memria do programa). O comando copia o byte no endereo Z da memria do programa para o registrador R0. Como a memria do programa organizada na forma de palavras (um comando em um endereo consiste de 16 bits ou dois bytes ou uma palavra), o bit menos significativo seleciona o byte inferior ou superior (0=inferior, 1=superior). Por causa disto, o endereo original deve ser multiplicado por 2 e o acesso limitado a 15 bits ou 32kb da memria do programa. Desta forma:

Avr-Asm-Tutorial

15

http://www.avr-asm-tutorial.net

LDI ZH,HIGH(2*endereco) LDI ZL,LOW(2*endereco) LPM

Seguindo este comando, o endereo deve ser incrementado para apontar o prximo byte na memria do programa. Como isto usado freqentemente, um comando de incremento de pointeiro foi definido para fazer isto:
ADIW ZL,1 LPM

ADIW significa ADd Immediate Word, adicione palavra imediato, e um mximo de 63 pode ser adicionado desta forma. Note que o compilador espera o mais baixo do par de registradores ZL como primeiro parmetro. Isto pode causar confuso, pois a adio realizada como uma operao de 16 bits. O comando complementar, subtrair um valor constante entre 0 e 63 de um ponteiro de 16 bits chamado de SBIW (SuBtract Immediate Word, subtrair palavra imediato). ADIW e SBIW so possveis para os pares de registradores X, Y e Z e para o par de registradores R25:R24, que no tm um nome extra e no permitem acesso SRAM ou a localizaes da memria do programa. R25:R24 so ideais para manipular valores de 16 bits. Como inserir uma tabela de valores na memria do programa? Isto feito atravs das diretivas do assembler .DB e .DW. Com elas voc pode inserir uma lista de bytes ou uma lista de palavras. Listas de bytes organizados ficam assim:
.DB 123,45,67,89 ; uma lista de quatro bytes, escritos em formato decimal .DB "Isto e um texto. " ; uma lista de caracteres byte, escritos como texto

Voc deve sempre colocar um nmero par de bytes em cada linha. Caso contrrio o compilador adicionar um byte zero ao final, que pode ser indesejado. Uma lista similar de valores ficaria assim:
.DW 12345,6789 ; uma lista de duas palavras

No lugar de constantes, voc pode tambm colocar labels (destinos para salto) nesta lista, como:
Label1: [ ... aqui vo alguns comandos ... ] Label2: [ ... aqui vo mais alguns comandos ... ] Tabela: .DW Label1,Label2 ; uma lista de labels

Labels SEMPRE iniciam na coluna 1! Note que ler os labels com LPM primeiro traz o byte inferior da palavra. Uma aplicao muito especial para os ponteiros acessar os prprios registradores. Os registradores esto localizados nos primeiros 32 bytes do espao do chip (do endereo 0x0000 a 0x001F). Este acesso til se voc tiver que copiar o contedo dos registradores para a SRAM ou EEPROM ou ler estes valores destes locais de volta para os registradores. O uso mais comum dos ponteiros para acessar tabelas com valores fixos na memria do programa. Aqui est um exemplo, uma tabela com 10 diferentes valores de 16 bits, onde o quinto valor da tabela lido para R25:R24:
MinhaTabela: .DW 0x1234,0x2345,0x3456,0x4568,0x5678 ; Os valores da tabela .DW 0x6789,0x789A,0x89AB,0x9ABC,0xABCD ; organizados em palavras Read5: LDI ZH,HIGH(MinhaTabela*2) ; endereo do ponteiro Z LDI ZL,LOW(MinhaTabela*2) ; multiplicado por 2 para acesso tabela ADIW ZL,10 ; Aponta para o quinto valor da tabela LPM ; L o byte menos significativo da memria do programa MOV R24,R0 ; Copia o LSB para o registrador de 16 bits ADIW ZL,1 ; Aponta para o MSB na memria do programa LPM ; L o MSB da tabela de valores MOV R25,R0 ; Copia MSB para o registrador de 16 bits.

Este apenas um exemplo, Voc pode calcular o endereo da tabela em Z a partir de algum valor de entrada, levando os respectivos valores na tabela. As tabelas podem ser organizadas por byte ou caracteres tambm.

Recomendao para uso dos registradores


Defina nomes para os registradores com a diretiva .DEF, nunca os use diretamente com o seus nomes diretos Rx. Se voc precisar acesso aos ponteiros, reserve R26 a R31 para este propsito. A melhor localizao para contadores de 16 bits R25:R24. Se precisar ler da memria do programa, e.g. Tabelas fixas, reserve Z (R31;R30) e R0 para isso. Se voc pretende acessar bits dentro de certos registradores (flags), use R16 a R23 para isso.

Avr-Asm-Tutorial

16

http://www.avr-asm-tutorial.net

Portas
O que uma Porta?
As portas do AVR so caminhos entre a unidade central de processamento e os componentes externos de hardware e software. A CPU se comunica com estes componentes, lendo deles ou escrevendo neles, e.g. timers ou portas paralelas. A porta mais utilizada o registrador de flag, onde os resultados das operaes anteriores so escritos e de onde as rvores de condies (decises) so lidas. H 64 portas diferenentes, que no esto disponveis em todos tipos de AVR. Dependendo do espao de armazenamento e outros hardwares internos, as portas podem estar disponveis e acessveis ou no. A lista de portas que podem ser usadas est listada nos data sheets do processador. As portas tm endereo fixo, pelo qual a CPU se comunica. O endereo independente do tipo de AVR. Assim, por exemplo, o endereo da porta B sempre 0x18 (0x indica notao hexadecimal). Voc no tem que lembrar destes endereos das portas, elas tm apelidos convenientes. Estes nomes so definidos nos arquivos include (cabealhos) para os diferentes tipos de AVR, fornecidos pelo fabricante. Os arquivos include tm uma linha definindo o endereo da porta B como a seguir:
.EQU PORTB, 0x18

Ento temos que lembrar apenas o nome da porta B, no sua localizao no espao de E/S do chip. O arquivo de inclde 8515def.inc est envolvido atravs da diretiva do assembler
.INCLUDE "C:\Somewhere\8515def.inc"

e todos os registradores de 8515 estaro definidos e facilmente acessveis. As portas normalmente so organizadas como nmeros de 8 bits, mas podem manipular 8 bits individuais que no tm a ver uns com os outros. Se estes bits tm um significado, eles podem ter seu prprio nome associado no arquivo include, para permitir a manipulao deste bit. Graas conveno dos nomes, voc no tem que lembrar a posio destes bits. Estes nomes so definidos nos data sheets e esto includos nos arquivos include, tambm. Eles so fornecidos aqui nas tabelas das portas. Como exemplo, o registrador de controle geral MCU, chamado MCUCR, consiste de um nmero de bits de controle individuais que controlam algumas caractersticas gerais do chip (veja a descrio em MCUCR para maiores detalhes). uma porta, com 8 bits de controle e seus prprios nomes (ISC00, ISC01, ...). Quem quiser mandar o seu AVR para um sono mortal precisa saber pelo data sheet como setar os bits respectivos. Assim:
.DEF MeuRegistradorPreferido = R16 LDI MeuRegistradorPreferido, 0b00100000 OUT MCUCR, MeuRegistradorPreferido SLEEP

O comando Out envia o contedo do meu registrador preferido, um bit Sleep-Enable chamado SE, para a porta MCUCR e seta o AVR imediatamente para entrar em repouso, se houver uma instruo SLEEP sendo executada. Como todos os outros bits do MCUCR foram setados pelas instrues acima, e o bit SM (Sleep Mode) ficou zero, ocorrer um modo chamado meio-repouso: no haver execuo de nenhum outro comando, mas o chip ainda reage a timers e outras interrupes de hardware. Estes eventos externos interrompero o sono da CPU se eles acharem que devem notific-la. Ler o contedo de uma porta possvel na maioria dos casos utilizando o comando IN. A sequncia
.DEF MeuRegistradorPreferido = R16 IN MeuRegistradorPreferido, MCUCR

l os dados da porta MCUCR para o registrador. Como muitas portas so usadas parcialmente ou no utilizadas, normalmente os dados lidos so zeros. Mais freqentemente do que ler todos os 8 bits de uma porta, deve-se reagir a certos status de uma porta. Neste caso, no precisamos ler a porta toda e isolar o bit de interesse. Certos comandos permitem executar comandos dependendo do estado de certo bit (veja a seo JUMP). Setar ou zerar certos bits tambm possvel sem ter que ler e escrever os outros bits da porta. Os dois comandos so SBI (Set Bit I/o, setar bit E/S) e CBI (Clear Bit I/o, zerar bit E/S). A execuo assim:
.EQU BitAtivo=0 ; O bit que ser mudado SBI PortB, BitAtivo ; O bit ser setado para um CBI PortB, BitAtivo ; O bit ser setado para zero

Estas duas instrues tm uma limitao: somente portas com endereo inferior a 0x20 podem ser manipuladas desta forma. Para programadores mais exticos: as portas podem ser acessadas utilizando comandos de acesso SRAM, como ST e LD. Apenas some 0x20 ao endereo da porta (os primeiros 32 endereos so os registradores) e acesse a porta desta forma. Vamos demonstrar aqui:
.DEF MeuRegistradorPreferido = R16 LDI ZH,HIGH(PORTB+32) LDI ZL,LOW(PORTB+32)

Avr-Asm-Tutorial LD MeuRegistradorPreferido,Z

17

http://www.avr-asm-tutorial.net

Isto faz sentido apenas em certos casos, mas possvel. por esta razo que o primeiro endereo da SRAM sempre 0x60.

Deatlhes de portas relevantes do AVR


A tabela a seguir mostra as portas mais usadas. Nem todas portas esto listadas aqui, algumas do MEGA e AT90S4434/8535 foram omitidas. Se houver dvida, verifique as referncias originais. Componente Acumulador Pilha (stack) Interrupo Externa Interrupo de Timer Timer 0 Timer 1 Nome da porta SREG SPL/SPH GIMSK GIFR TIMSK TIFR TCCR0 TCNT0 TCCR1A TCCR1B TCNT1 OCR1A OCR1B ICR1L/H Timer Watchdog EEPROM WDTCR EEAR EEDR EECR SPI SPCR SPSR SPDR UART UDR USR UCR UBRR Comparador analgico Portas de E/S ACSR PORTx DDRx PINx Registrador da Porta Registrador de Status Stackpointer (apontador de pilha) Registrador de Controle Geral MCU Registrador de Interrupo Mascarado Registrador de Flag de Interrupo Registrador de Interrupo de Timer Mascarada Registrador de Interrupo de Flag de Timer Registrador controle de de Timer/Contador 0 Timer/Contador 0 Registrador controle de de Timer/Contador 1 A Registrador controle de de Timer/Contador 1 B Timer/Contador 1 Registrador Comparador de Sada 1 A Registrador Comparador de Sada 1 B Registrador de Captura de Entrada Registrador de Controle do Timer Watchdog Registrador de endereo da EEPROM Registrador de dados da EEPROM Registrador de controle da EEPROM Registrador de controle de perifricos Seriais Registrador de status de perifricos Seriais Registrador de dados de perifricos Seriais Registrador de dados da UART Registrador de status da UART Registrador de controle da UART Registrador de velocidade (baud rate) da UART Registrador de status e controle do comparador analgico Registrador de porta de sada Registrador de direo da porta Registrador de porta de entrada

SRAM Externa/Interrupo Externa MCUCR

O registrador de status como a porta mais utilizada


De longe, a porta mais freqentemente usada o registrador de status com seus 8 bits. Normalmente o acesso a esta porta feito somente por alterao dos bits pela CPU ou acumulador, alguns acessos so por leitura ou alterao dos bits na porta, e em raros casos possvel manipular estes bits diretamente (utilizando os comandos assembler SEx ou CLx, onde x a abreviao do bit). A maioria destes bits alterada por operaes de teste de bit, comparao ou clculos. A seguinte lista tem todos os comandos em assembler que podem alterar os bits de status, dependendo do resultado da execuo.

Avr-Asm-Tutorial

18

http://www.avr-asm-tutorial.net

Bit Z

Clculo ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, SBIW ADD, ADC, ADIW, SUB, SUBI, SBC, SBCI, SBIW ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, SBIW ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, SBIW SBIW

Lgico

Comparao

Bits

Rolagem

Outro CLR

AND, ANDI, OR, CP, CPC, CPI BCLR Z, ASR, LSL, ORI, EOR, COM, BSET Z, LSR, ROL, NEG, SBR, CBR CLZ, SEZ, ROR TST COM, NEG CP, CPC, CPI BCLR C, BSET C, CLC, SEC ASR, LSL, LSR, ROL, ROR

AND, ANDI, OR, CP, CPC, CPI BCLR N, ASR, LSL, ORI, EOR, COM, BSET N, LSR, ROL, NEG, SBR, CBR CLN, SEN, ROR TST AND, ANDI, OR, CP, CPC, CPI BCLR V, ASR, LSL, ORI, EOR, COM, BSET V, LSR, ROL, NEG, SBR, CBR CLV, SEV, ROR TST BCLR S, BSET S, CLS, SES -

CLR

CLR

ADD, ADC, SUB, SUBI, SBC, SBCI -

NEG

CP, CPC, CPI BCLR H, BSET H, CLH, SEH -

BCLR T, BSET T, BST, CLT, SET BCLR I, BSET I, CLI, SEI -

RETI

Detalhes das portas


Detalhes das portas mais comuns so mostrados na tabela extra (veja anexo).

Avr-Asm-Tutorial

19

http://www.avr-asm-tutorial.net

SRAM
Usando SRAM em linguagem assembler AVR
Praticamente todos os MCUs AVR tipo AT90S tm RAM esttica (SRAM, Static RAM) (alguns no). Somente compiladores muito simples evitam a utilizao deste espao da memria, colocando tudo nos registradores. Se os seus registradores acabarem, voc dever ser capaz de programar a SRAM para obter mais espao.

O que SRAM?
SRAM so memrias que no so diretamente acessveis da unidade de processamento central (Unidade Aritmtica e Lgica ALU (Arithmetic and Logical Unit), algumas vezes chamada de acumulador), como os registradores o so. Para acessar estas localidades de memria, voc normalmente usa um registrador como armazm intermedirio. No exemplo a seguir, um valor na SRAM ser copiado para o registrador R2 (primeiro comando), um clculo utilizando o valor de R3 feito e o resultado escrito em R3 (comando2). Depois disso, o valor escrito de volta na SRAM (comando 3, no mostrado aqui). evidente que operaes com valores armazenados na SRAM so mais lentas do que aquelas utilizando apenas os registradores. Por outro lado: o menor AVR tem 128 bytes de SRAM disponvel, muito mais do que os 32 registradores podem guardar. Os tipos mais recentes do que AT90S8515 oferecem a possibilidade de conectar RAM externa, expandindo a interna de 512 bytes. Do ponto de vista do assembler, a SRAM externa acessada da mesma forma que a interna. No existe nenhum comando extra para SRAM externa.

Para que propsitos posso usar a SRAM?


Alm de simples armazenagem de valores, a SRAM oferece outras possibilidades de uso. No apenas o acesso com endereos fixos pssvel, como tambm o uso de ponteiros, de forma que o acesso flutuante a localizaes subsequentes pode ser programado. Desta forma voc pode construir buffers em anel para armazenagem temporria de valores ou tabelas calculadas. Isto no feito frequentemente com registradores, pois eles so muito poucos e acesso fixo preferido. Outra forma de acesso utilizando um offset para um endereo de incio fixo em um dos ponteiros. Neste caso, o endereo fixo armazenado no ponteiro, e um valor constante adicionado a este endereo e os acesso de leitura e escrita so feitos a esse endereo com um offset. Com este tipo de acesso, as tabelas so melhores utilizadas. O uso mais interessande para a SRAM a chamada pilha ( stack). Voc coloca (empurra, push) valores para a pilha, seja um registrador, um endereo de retorno aps o fim de uma sub-rotina, ou o endereo de retorno aps uma interrupo disparada por hardware.

Como usar a SRAM?


Para copiar um valor para uma localizao da memria SRAM, voc tem que definir o endereo. O endereamento da SRAM comea em 0x0060 (notao hexa) at o fim da SRAM fsica no chip (no AT90S8515, o endereo mais alto da SRAM 0x025F). Com o comando
STS 0x0060, R1

o contedo do registrador R1 copiadao para o primeiro endereo da SRAM. Com


LDS R1, 0x0060

o contedo da SRAM no endereo 0x0060 copiado para o registrador. Este o acesso direto atravs do endereo definido pelo programador. Nomes simblicos devem ser evitados para evitar manipular endereos fixos, pois requerem muito trabalho se voc depois quiser alterar a estrutura da SRAM. Estes nomes so mais fceis de lembrar do que os nmeros hexa, ento voc pode nomear um endereo da seguinte forma:

Avr-Asm-Tutorial .EQU MeuEnderecoPreferido= 0x0060 STS MeuEnderecoPreferido, R1

20

http://www.avr-asm-tutorial.net

Sim, fica mais longo, mas mais fcil de lembrar. Use o nome que voc achar conveniente. Outro tipo de acesso SRAM com o uso de ponteiros. Voc precisa de dois registradores para este propsito, para acomodar o endereo em 16 bits. Como aprendemos na diviso dos ponteiros, os registradores ponteiros so os pares X (XH:XL, R27:R26), Y (YH:YL, R29:R28) e Z (ZH:ZL, R31:R30). Eles permite acesso localizao que apontam diretamente (e.g., com ST X, R1), antes da decrementao do endereo por um (e.g., ST -X, R1) ou antes do incremento deste endereo (e.g., ST X+, R1). Um acesso completo a trs endereos em seguida ficaria ento da seguinte forma:
.EQU MeuEnderecoPreferido= 0x0060 .DEF MeuRegistradorPreferido = R1 .DEF OutroRegistrador= R2 .DEF MaisUmRegistrador = R3 LDI XH, HIGH(MeuEnderecoPreferido) LDI XL, LOW(MeuEnderecoPreferido) LD MeuRegistradorPreferido, X+ LD OutroRegistrador, X+ LD MaisUmRegistrador, X

Fceis de operar, estes ponteiros. E to fcil quanto em outras linguagens diferentes do assembler, que dizem ser fcil de aprender. A terceira construo um pouco mais extica e somente utilizada por programadores experientes. Vamos assumir que precisamos acessar trs localizaes da SRAM com freqncia. Vamos tambm assumir que temos um par de registradores ponteiros sobrando, ento podemos utiliz-lo exclusivamente para nosso propsito. Se usssemos as instrues ST/LD, teramos que alterar o ponteiro a cada vez que precisssemos acessar outra localizao. No muito conveniente. Para evitar isso, e confundir o iniciante, o acesso com offset foi inventado. Durante este acesso, o valor do registrador no alterado. O endereo calculado adicionando temporariamente um offset fixo. No exemplo acima, o acesso localizao 0x0062 ficaria assim. Primeiro, o ponteiro setado para nossa localizao central 0x0060:
.EQU MeuEnderecoPreferido = 0x0060 .DEF MeuRegistradorPreferido = R1 LDI YH, HIGH(MeuEnderecoPreferido) LDI YL, LOW(MeuEnderecoPreferido)

Em algum lugar depois no programa, para acessar o endereo 0x0062:


STD Y+2, MeuRegistradorPreferido

Note que 2 no realmente adicionado a Y, apenas temporariamente. Para confundi-lo mais, isto pode ser feito apenas com os pares de registradores Y e Z, no com o ponteiro X! A instruo correspondente para ler a SRAM com um offset LDD MeuRegistradorPreferido, Y+2 tambm possvel. Esta a SRAM, mas espere: o uso mais interessante como pilha ainda deve ser aprendido.

O uso da SRAM como pilha


O uso mais comum da SRAM como pilha. A pilha uma torre de blocos de madeira. Cada bloco adicional vai no topo da torre, e cada chamada remove o bloco superior da torre. Esta estrutura chamada de Last-In-First-Out (o primeiro a entrar o ltimo a sair LIFO), ou mais fcil: o ltimo a ir no topo, ser o primeiro a sair.

Definindo SRAM como pilha


Para usar a SRAM como pilha, devemos ajustar o ponteiro de pilha (stack pointer) primeiro. O ponteiro de pilha um ponteiro de 16 bits, acessvel como uma porta. O registrador duplo chamado de SPH:SPL. SPH armazena o byte mais significativo, e o SPL, o menos significativo. Isto verdadeiro apenas se o AVR tiver mais de 256 bytes de SRAM. Caso contrrio, SPH indefinido, no pode e no deve ser usado. Vamos assumir que temos mais de 256 bytes nos exemplos a seguir. Para contruir a pilha, o ponteiro de pilha carregado com o endereo mais alto da SRAM. (No nosso caso, a torre cresce para baixo, em direo aos endereos menores!)
.DEF MeuRegistradorPreferido = R16 LDI MeuRegistradorPreferido, HIGH(RAMEND) ; Byte Superior OUT SPH,MeuRegistradorPreferido ; para o ponteiro de pilha LDI MeuRegistradorPreferido, LOW(RAMEND) ; Byte inferior OUT SPL,MeuRegistradorPreferido ; para o ponteiro de pilha

O valor RAMEND (que indica o endereo final da memria) , obviamente, especfico para o tipo de

Avr-Asm-Tutorial

21

http://www.avr-asm-tutorial.net

progrssador. Ele definido no arquivo INCLUDE para o tipo de processador.O arquivo 8515def.inc tem a linha:
.equ RAMEND =$25F ; Last On-Chip SRAM Location (n.t.: ltima localizao da SRAM no chip)

O arquivo 8515def.inc includo atravs da diretiva de assembler .INCLUDE "C:\algumlugar\8515def.inc" no incio do nosso cdigo fonte em assembler. Ento definimos a pilha agora, e no temos mais que nos preocupar sobre o ponteiro da pilha, porque as manipulaes do ponteiro so automticas.

Uso da pilha
Usar a pilha fcil. O contedo dos registradores so empurrados na pilha assim:
PUSH MeuRegistradorPreferido ; Coloca aquele valor no topo da pilha

Para onde o valor vai, no nos interessa. O ponteiro de pilha foi decrementado aps colocarmos este valor, e no temos que nos preocupar. Se precisarmos deste contedo de volta, simplesmente usamos a seguinte instruo:
POP MeuRegistradorPreferido ; L o valor de volta

Com POP simplesmente pegamos o ltimo valor colocado no topo da pilha. Empurrar e pegar registradores faz sentido, se

o contedo ser necessrio novamente algumas linhas de cdigo depois, todos os registradores esto em uso, e se no h como armazenar aquele valor em nenhum outro lugar.

Se nenhuma destas condies se verificarem, o uso da pilha para guardar registradores intil e apenas desperdia tempo do processador. Faz mais sentido usar a pilha em subrotinas, onde voc tem que retornar localizao do programa que chamou a rotina. Neste caso, o cdigo que chama a subrotina deve guardar o endereo de retorno (o valor atual do contador de programa, PC, program counter) na pilha e salta para a subrotina. Aps a sua execuo, a subrotina pega o endereo de retorno da pilha e carrega no contador de programa. A execuo do programa ento continua exatamente uma instruo aps a instruo de chamada:
RCALL AlgumLugar ; Salta para o label AlgumLugar: [...] aqui continuamos o programa

Aqui a execuo para para o label AlgumLugar em algum lugar do cdigo, AlgumLugar: ; este o endereo de salto
[...] Aqui fazemos alguma coisa [...] e aqui terminamos o que queramos fazer e saltamos de volta para o local onde essa rotina foi chamada: RET

Durante a execuo da instruo RCALL, o contador de programa (PC) j incrementado, com 16 bits, colocado na pilha usando dois pushes. Quando a instruo RET executada, o contedo anterior do contador de programa recarregado usando dois pops e a execuo continua. Voc no precisa se preocupar sobre o endereo da pilha, ou onde o contador est gravado. O endereo gerado automaticamente. Mesmo se voc chamar uma subrotina dentro de uma subrotina, a funo da pilha perfeita. Os dois endereos so colocados no topo da pilha, a subrotina dentro da primeira remove o primeiro endereo, e a subrotina de chamada remove o segundo. Enquanto haja SRAM suficiente, tudo funciona. A utilizao de interrupes de hardware no possvel sem a pilha. A interrupo pra a execuo normal do programa, onde quer que ele esteja. Aps a execuo do servio como reao quela interrupo, a execuo deve retornar localizao anterior, antes da interrupo. Isto no seria possvel se a pilha no fosse capaz de armazenar o endereo de retorno. As enormes vantagens de se ter uma pilha para interrupes so as razes de mesmo o menor dos AVRs que no tenham SRAM, tenham ao menos uma pequena pilha de hardware.

Bugs com a operao de pilhas


Para o iniciante, h uma grande possibilidade de bugs, aps aprender a usar a pilha. Muito inteligente o uso da pilha sem setar primeiro o ponteiro da pilha. Como o valor deste ponteiro zero no incio do programa, o ponteiro aponta para o registrador R0. Colocar algo na pilha resulta em escrever neste registrador, sobrescrevendo qualquer contedo que ali estivesse. Um outro push na pilha, e a pilha vai gravar em 0xFFFF, uma posio indefinida (se voc no tiver SRAM externa). RCALL e RET retornaro um endereo estranho na memria. E tenha certeza: no haver nenhum aviso, nenhuma janela indicando Acesso ilegal memria localizao xxxx.

Avr-Asm-Tutorial

22

http://www.avr-asm-tutorial.net

Outra possibilidade de ter bug esquecer de fazer o pop em um valor armazenado anteriormente, ou fazer pop sem fazer push antes. Em alguns poucos causos, a pilha estoura para abaixo do primeiro endereo da SRAM. Isto ocorre no caso de uma chamada recursiva infinita. Aps alcanar o endereo mais baixo da SRAM, os prximos pushes escrevem nas portas (0x005F at 0x0020), e ento os registradores (0x001F a 0x0000). Coisas engraadas e imprevisveis podem ocorrer com o chip, se isto ocorrer. Evite este bug, ele pode destruir o seu hardware!

Avr-Asm-Tutorial

23

http://www.avr-asm-tutorial.net

Saltos e Desvios
Agora discutiremos todos os comandos que controlam a execuo seqencial de um programa, iniciando com a seqncia inicial de partida do processador, continuando com saltos, interrupes, etc.

Controlando a execuo seqencial de um programa


O que acontece durante um reset?
Quando a tenso de trabalho de um AVR sobe e o processador inicia o seu trabalho, o hardware dispara uma seqncia de reset. O contador de passos do programa zerado. Neste endereo, a execuo sempre inicia. Aqui temos que ter nossa primeira palavra de cdigo. Mas este endereo pode ser ativado tambm de outras formas:

Durante um reset externo via pino de reset, o processador reiniciado. Se o contador Watchdog alcana a sua contagem mxima, um reset iniciado. O timer witchdog um temporizador interno que deve ser resetado de tempos em tempos pelo programa, caso contrrio ele reinicia o processador. Voc pode chamar o reset fazendo um salto direto a este endereo (veja a seo de saltos abaixo).

O terceiro caso no um reset real, pois o reincio de registradores e valores de porta a valores conhecidos, no executado. Portanto, esquea-o por enquanto. A segunda opo, o reset watchdog, deve ser habilitado pelo programa. Se estiver desabilitado por padro, a habilitao requer escrever comandos na porta do watchdog. Zerar o contador watchdog requer a execuo do comando
WDR

para evitar o reset. Aps a execuo de um reset, e restabelecimento dos registradores e portas para seus valores padro, o cdigo no endereo 0000 lido pela parte de execuo do processador, e executado. Durante esta execuo o contador de programa (PC, program counter) j incrementado em um e a prxima palavra do cdigo j lida para o buffer de busca de cdigo (Busca durante Execuo). Se o comando executado no requer um salto para outra localidade no programa, o prximo comando executado imediatamente. por isso que os AVRs executam extremamente rpido, cada ciclo de clock executa um comando (se no ocorrerem saltos). O primeiro comando de um executvel est sempre localizado no endereo 0000. Para dizer ao compilador que nosso cdigo fonte inicia aqui e agora, uma diretiva especial pode ser colocada no incio, antes do primeiro cdigo:
.CSEG .ORG 0000

A primeira diretiva diz ao compilador que a sada deve ser para a seo de cdigos. Tudo que se segue ser traduzido como cdigo, e ser escrito memria de programa do processador. Tambm possvel direcionar a sada para a seo EEPROM do chip, onde voc pode escrever bytes e palavras.
.ESEG

O terceiro segmento a poro SRAM do chip.


.DSEG

Diferente do contedo para EEPROM, que realmente gravado no EEPROM durante a programao, o segmento DSEG no programado no chip. utilizado somente para clculo dos labels durante o processo de compilao. A diretiva ORG indica a origem e manipula os endereos dentro do segmento de cdigo, onde as palavras montadas so gravadas. Como nosso programa sempre inicia a 0x0000, as diretivas CSEG/ORG so triviais, voc poder ignor-las sem obter um erro. Poderamos comear, por exemplo, a 0x0100, mas no faz sentido, visto que o processador inicia a execuo em 0000. Se voc quiser colocar uma tabela exatamente em uma certa localizao no segmento de cdigo, voc pode usar ORG. Se voc quiser demarcar onde realmente comea o seu programa, aps definir outras coisas com diretivas .DEF e .EQU, use a seqncia CSEG/ORG para sua orientao, mesmo sabendo que no necessrio utiliz-las. Como a primeira palavra de cdigo sempre inicia no endereo zero, esta localizao tambm chamada de vetor de reset. Procedendo os prximos endereos, 0x0001, 0x0002 etc., temos os vetores de interrupo. Estas so as posies para onde a execuo salta se uma interrupo externa ou interna foi habilitada e ocorre. Estas posies chamadas vetores so especficas para cada tipo de processador, e dependem do hardware interno disponvel (veja abaixo). Os comandos para reagir s interrupes devem ser colocadas nas localizaes de vetor apropriados. Se voc usar interrupes, o primeiro cdigo, no vetor de reset, deve ser um comando de salto (jump), para saltar por cima dos outros vetores. Cada vetor de interrupo deve possuir um comando de salto para a respectiva rotina para tratar a interrupo. A tpica seqncia do programa no incio como se segue:

Avr-Asm-Tutorial .CSEG .ORG 0000 RJMP Inicio RJMP TrataInterrupcao1

24

http://www.avr-asm-tutorial.net

[...] aqui colocamos os outros comandos no vetor de interrupo [...] e aqui um bom lugar para colocar as prprias rotinas de tratamento da interrupo Inicio: ; aqui que o programa inicia [...] Aqui colocamos o programa principal

O comando RJMP resulta em um salto para o label Inicio:, localizado algumas linhas abaixo. Lembre-se, labels sempre iniciam na coluna 1 do cdigo fonte e terminam com um :. Labels que no atendam esta condies no so interpretadas corretamente pelo compilador. Labels faltantes resultam em uma mensagem de erro (Label indefinido, Undefined Label), e a compilao interrompida.

Execuo linear do programa e desvios


A execuo de um programa sempre linear, se nada mudar a execuo sequencial. Estas mudanas so a execuo de uma interrupo, ou instrues de desvio. Os desvios normalmente so dependentes de alguma condio, chamados portanto desvios condicionais. Como exemplo, vamos imaginar que construmos um contador de 32 bits utilizando os registradores R1 a R4. O byte menos significativo R1 incrementado. Se o registrador estoura ( overflow) durante esta operao (255 + 1 = 0), temos que incrementar R2 similarmente. Se R2 estoura, incrementamos R3, e assim por diante. O incremento por um feito pela instruo INC. Se um estouro (overflow) ocorre durante esta execuo de INC R1, o bit zero do registrador de status setado para um (o resultado da operao zero). O carry do registrador de status, usualmente setado em overflows, no alterado durante um INC. Isto no para confundir o iniciante, mas o carry usado para outros propsitos. A flag de Zero ou bit de zero neste caso suficiente para detectar um estouro. Se no ocorrer nenhum estouro, mantemos a seqncia de contagem. Se o bit-Zero for setado, devemos executar um incremento adicional nos outros registradores. Para confundir o iniciante, o comando de desvio que temos que usar no chamado BRNZ mas BRNE (Branch if Not Equal, Desviar se no for igual). Uma questo de gosto... A seqncia de contagem inteira do contador de 32 bits ento deve ficar assim:
INC R1 BRNE Continue32 INC R2 BRNE Continue32 INC R3 BRNE Continue32 INC R4 Continue32:

s isso. A condio oposta a BRNE BREQ ou Branch EQual, desviar se for igual. Para saber quais os bits de status, tambm chamados de flags do processador so alterados durante a execuo de um comando, olhe a Lista de Instrues. Da mesma forma que o bit Zero, voc pode usar outros bits como:
BRCC label/BRCS label; Carry-flag 0 (BRCC) ou 1 (BRCS) BRSH label; Igual ou maior BRLO label; Menor BRMI label; Menos BRPL label; Mais BRGE label; Maior ou igual (com bit de sinal) BRLT label; Smaller (with sign bit) BRHC label/BRHS label; Flag de meio-overflow 0 ou 1 BRTC label/BRTS label; T-Bit 0 ou 1 BRVC label/BRVS label; Flag de complemento de dois 0 ou 1 BRIE label/BRID label; Interrupes habilitadas ou desabilitadas

para reagir a diferentes condies. Desvios sempre ocorrem quando as condies so cumpridas. No tenha medo, a maioria destes comandos raramente usada. Para o iniciante, apenas Zero e Carry so importantes.

Temporizao durante a execuo do programa


Como mencionado anteriormente, o tempo necessrio para executar uma instruo igual ao tempo de ciclo do clock do processador. Se o processador roda a 4 MHz. Ento uma instruo requer 1/4 s ou 250 ns, e a 10 MHz, apenas 100 ns. O clculo do tempo to preciso quanto o cristal do clock. Se voc precisa temporizao exata, um AVR a melhor soluo. Note que h poucos comandos que necessitam de dois ou mais ciclos, e.g. As instrues de desvio (se este ocorre) ou seqncias de leitura/escrita na

Avr-Asm-Tutorial

25

http://www.avr-asm-tutorial.net

SRAM. Veja a tabela de instrues para detalhes. Para definir o tempo exato, deve haver uma oportunidade para no fazer nada e retardar a execuo do programa. Voc pode utilizar outras instrues para fazer nada, mas mais inteligente a utilizao do comando NOP (NO oPeration, sem operao). Esta a instruo mais intil:
NOP

Esta instruo no faz nada alm de desperdiar tempo do processador. A 4 MHz, precisamos de 4 instrues desta para desperdiar 1 s. No h outros significados ocultos na instruo NOP. Para um gerador de sinal de 1 kHz no precisamos adicionar 4000 instrues destas em nosso cdigo fonte, mas utilizamos um contador por software e algumas instrues de desvio. Com isso, construmos um elo que executado por um certo nmero de vezes, provocando retardo. Um contador por ser um registrador de 8 bits que decrementado pela instruo DEC, e.g. Desta forma:
CLR R1 Conta: DEC R1 BRNE Conta

Contagem em 16 bit tambm pode ser usada para um retardo exato, assim:
LDI ZH,HIGH(65535) LDI ZL,LOW(65535) Conta: SBIW ZL,1 BRNE Conta

Se voc usar mais registradores para construir contadores compostos, voc pode conseguir qualquer retardo. E este absolutamente exato, mesmo sem um hardware de temporizao.

Macros e execuo do programa


Freqentemente voc tem que escrever seqncias de cdigo idnticas ou similares em diferentes ocasies no seu cdigo fonte. Se voc no quiser escrev-la uma vez e saltar para ela via chamada de subrotina, voc pode usar um macro para evitar escrever a mesma seqncia diversas vezes. Macros so sequncias de codigos, escritas e testadas uma vez, e inseridas no cdigo por seu nome macro. Como exemplo, vamos imaginar que precisamos retardar a execuo do programa vrias vezes de 1 S com clock de 4 MHz. Ento definimos uma macro em algum lugar do cdigo:
.MACRO Retardo1 NOP NOP NOP NOP .ENDMACRO

A definio da macro no produz ainda nenhum cdigo, silenciosa. O cdigo produzido quando voc chama a macro pelo seu nome:
[...] em algum lugar no cdigo fonte Retardo1 [...] o cdigo vai aqui

Isto resulta em quatro instrues NOP inseridas no cdigo nesta localizao. Um Retardo1 adicional insere mais 4 instrues NOP. Ao chamar um macro por seu nome voc pode adicionar alguns parmetros para manipular o cdigo produzido. Mais isto mais que um iniciante precisa saber sobre macros. Se seu macro tem longas sequncias de cdigo, ou se voc est com pouco espao de armazenamento, deve evitar o uso de macros e usar subrotinas no lugar.

Subrotinas
Ao contrrio das macros, uma subrotina economiza espao de armazenamento. A seqncia respectiva apenas armazenada uma vez no cdigo e chamada de qualquer parte. Para assegurar a execuo continuada da sequencia, voc deve retornar ao cdigo que chamou a subrotina. Para um retardo de 10 ciclos voc precisa escrever esta subrotina:
Retardo10: NOP NOP NOP RET

Subrotinas sempre iniciam com um label, caso contrrio voc no seria capaz de saltar para elas, no nosso caso, Retardo10:. Trs NOPs seguem a instruo RET. Se voc contar os ciclos necessrios, voc descobrir que so 7 (3 para os NOPs, 4 para o RET). Os 3 que faltam esto contidos nesta rotina:
[...] algum lugar do cdigo fonte: RCALL Retardo10

Avr-Asm-Tutorial [...] continuando com o cdigo fonte

26

http://www.avr-asm-tutorial.net

RCALL uma chamada relativa. A chamada codificada como um salto relativo, a distncia relativa da rotina de chamada para a subrotina calculada pelo compilador. A instruo RET volta rotina de chamada. Note que antes de voc usar chamadas de subrotina, voc deve setar o ponteiro de pilha (veja Pilha), porque o endereo para retorno deve ser colocado na pilha pela instruo RCALL. Se voc quiser saltar diretamente a algum outro lugar no cdigo, voc tem que usar a instruo jump:
[...] em algum lugar do cdigo fonte RJMP Retardo10 Retorno: [...] continuando com o cdigo fonte

A rotina para onde voc pulou no pode usar o comando RET neste caso. Para voltar localizao de onde voc chamou, requer outro label e que a rotina que voc chamou, salte de volta para este label. Este tipo de salto no chamado de subrotina, porque voc no pode cham-la de diferentes localidades do cdigo. RCALL e RJMP so desvios incondicionais. Para pular para uma localidade, dependendo de alguma condio, voc ter que combinar com instrues de desvio. A chamada condicional de uma subrotina pode ser feita com os seguintes comandos. Se voc quiser chamar uma subrotina dependendo de um certo bit em um registrador, use a sequncia seguinte:
SBRC R1,7 ; Pule a prxima instruo se o bit 7 for 0 RCALL OutroLabel ; Chame a subrotina

SBRC quer dizer Pule a prxima instruo se o Bit 7 no Registrador R1 for zero, skip next instruction if Bit 7 in Register R1 is Clear). A instruo RCALL para o OutroLabel: somente ser executada se o bit 7 no registrador R1 for 1, pois a prxima instruo ser pulada se for 0. Se voc desejar chamar a subrotina caso o bit seja 0, voc pode utilizar a instruo correspondente SBRS. A instruo que se segue a SBRS/ SBRC pode ser de um ou dois bytes, o processador sabe quanto ele tem que pular. Note que os tempos de execuo so diferentes neste caso. Para pular sobre mais de uma instruo, estes comandos no podem ser usados. Se voc tiver que pular uma instruo se dois registradores tiverem o mesmo valor, voc pode usar a instruo extica
CPSE R1,R2 ; Compara R1 e R2, pula se forem iguais RCALL AlgumaSubrotina ; Chama alguma subrotina

um comando raramente utilizado, esquea-o no comeo. Se voc quiser pular a instruo seguinte dependendo de um certo bit em uma porta, use as instrues SBIC e SBIS. Elas querem dizer Pule se o Bit no espao E/S estiver zero (ou Setado), Skip if the Bit in I/o space is Clear (ou Set), assim:
SBIC PINB,0 ; Pule se o Bit 0 na porta B for 0 RJMP DestinoA ; Pule para o label DestinoA

A instruo RJMP ser executada apenas se o bit 0 na porta B for 1. de alguma forma confuso para o iniciante. O acesso aos bits da porta limitado metade inferior, as 32 portas superiores no podem ser usadas aqui. Agora, outra aplicao extica para o expert. Pule esta parte se voc for iniciante. Imagine que temos 4 chaves, uma para cada bit, conectados porta B. Dependendo do estado destes 4 vits, gostaramos de pular para 16 diferentes localizaes no cdigo. Agora podemos ler a porta e usar diversas instrues de desvio para descobrir para onde teremos que pular hoje. Como alternativa, voc pode escrever uma tabela contendo os 16 endereos, assim:
MinhaTabela: RJMP Routine1 RJMP Routine2 [...] RJMP Routine16

Em nosso cdigo, copiamos o endereo da tabela para o ponteiro Z:


LDI ZH,HIGH(MinhaTabela) LDI ZL,LOW(MinhaTabela)

e adicionar o estado atual da porta B (em R16) a este endereo.


ADD ZL,R16 BRCC SemEstouro INC ZH SemEstouro:

Agora podemos saltar s localidades na tabela, da mesma forma que chamamos uma subrotina:
ICALL

ou pular, sem possibilidade de retorno:


IJMP

Avr-Asm-Tutorial

27

http://www.avr-asm-tutorial.net

O processador carrega o contedo do par de registradores Z no contador de programa e continua a operao a partir da. Mais inteligente que fazer desvios e mais desvios?

Interrupes e a execuo do programa


Frequentemente temos que reagir a condies do hardware e outos eventos. Uma exemplo, uma alterao em um pino de entrada. Voc pode programar uma reao como um loop, sempre verificando se houve alterao em um pino. Este mtodo chamado de busca, como uma abelha voando em crculos procurando por novas flores. Se voc tem que detectar pulsos curtos com durao inferior a microssegundos, este mtodo intil. Neste caso, voc ter que programar uma interrupo. Uma interrupo disparada por alguma condio de hardware. Esta condio tem que ser habilitada primeiro, todas as interrupes de hardware so disabilitadas por padro, no momento do reset. Os bits respectivos da porta que habilitam a resposta interrupo devem ser habilitados primeiro. O processador tem um bit no seu registrador de status que o habilita a responder interrupo de qualquer componente, a flag de habilitao de interrupo ( Interrupt Enable Flag). Habilitar a resposta s interrupes requer o seguinte comando:
SEI ; Seta bit de habilitao de Interrupo

Se a condio de interrupo ocorre, e.g. uma mudana no bit da porta, o processador coloca o contador de programa atual na pilha (que deve ser habilitada primeiro! Veja a inicializao do ponteiro de pilha na seo Pilha da descrio da SRAM). Sem isso, o processador no seria capaz de retornar ao ponto onde estava quando ocorreu a interrupo (o que pode ocorrer a qualquer momento em qualquer lugar da execuo do programa). Depois, o processamento salta para a localizao predefinida, o vetor de interrupo, e a executa as instrues. Normalmente a instruo um JUMP para a rotina de tratamento da interrupo, localizado em algum lugar do cdigo. A localizao do vetor de interrupo especfico do processador, e dependente dos componentes de hardware e da condio que levou interrupo. Quanto mais componentes de hardware e mais condies, mais vetores. Os diferentes vetores para alguns tipos de AVR esto listados na tabela a seguir (o primeiro vetor no uma interrupo, mas sim o vetor de reset, que no faz operao com a pilha!) Nome Endereo do vetor de interrupo 2313 RESET INT0 INT1 TIMER1CAPT TIMER1COMPA TIMER1 COMPB TIMER1 COMP1 TIMER1 OVF TIMER0 OVF SPI STC UART TX UART UDRE UART TX ANA_COMP 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 2323 0000 0001 0002 8515 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C Hardware Reset, Power-On-Reset, Watchdog Reset Mudana de nvel no pino externo INT0 Mudana de nvel no pino externo INT1 Evento de captura no Timer/Contador 1 Timer/Contador 1 = Valor de comparao A Timer/Contador 1 = Valor de comparao B Timer/Contador 1 = Valor de comparao 1 Estouro (overflow) de Timer/Contador 1 Estouro (overflow) de Timer/Contador 0 Transmisso Serial Completa Caractere UART disponvel no buffer de recepo Transmisso UART esgotada UART totalmente enviada Comparador Analgico Disparado por

Note que a capacidade de reagir a eventos muito diferente para os diferentes tipos. Os endereos so sequenciais, mas no idnticos para diferentes tipo. Consulte o datasheet para cada tipo de AVR. Quanto mais alto um vetor na lista, maior sua prioridade. Se dois ou mais componentes tm uma condio de interrupo ao mesmo tempo, o vetor com o menor endereo vence. A interrupo inferior tem que esperar at que a primeira tenha sido tratada. Para evitar que as interrupes inferiores interrompam a execuo do tratamento de uma interrupo superior, a primeira interrupo desabilita a flag I (interrupo) do processador. A rotina deve reabilitar esta flag aps o trmino do trabalho. Para reabilitar o bit de status I h duas formas. O tratamento da interrupo para terminar com o comando
RETI

Este comando retorna o bit I depois do contador de programa ter sido restabelecido com o valor do endereo de retorno.

Avr-Asm-Tutorial

28

http://www.avr-asm-tutorial.net

A segunda forma habilitar o bit I pela instruo


SEI ; Habilita bit de Interrupo RET ; Retorna

Isto no faz a mesma coisa do RETI, pois interrupes subsequentes estaro habilitadas antes do contador de programa ser recarregado com o endereo de retorno. Se outra interrupo estiver pendente, sua execuao j inicia antes que o endereo de retorno seja removido da pilha. Dois ou mais endereos de retorno permanecem na pilha. Isto no causa bug imediato, mas um risco desnecessrio. Portanto, use a instruo RETI para evitar fluxo desnecessrio na pilha. Um vetor de interrupo tem capacidade para apenas uma instruo de salto para a rotina de servio. Se certa interrupo no usada ou indefinida, colocamos simplesmente uma instruo RETI ali, no caso de uma falsa interrupo ocorrer. o caso da execuo do servio respectivo no resetar automaticamente a condio de interrupo do perifrico. Neste caso, um simples RETI causaria um loop contnuo de resets. Este o caso com algumas interrupes da UART. Quando uma interrupo est em tratamento, a execuo de outras interrupes de menor prioridade bloqueada. Por este motivo, todas as rotinas de tratamento de interrupo devem ser to curtas quanto possvel. Se voc precisar de uma longa rotina de tratamento da interrupo, use um dos seguintes mtodos. O primeiro permitir interrupes com SEI dentro da rotina de tratamento, enquanto voc executa as tarefas mais urgentes. No muito inteligente. Mais conveniente seria executar as tarefas urgentes, setar uma flag em algum lugar em um registrador para as reaes mais lentas, e retornar da interrupo imediatamente. Uma regra muito importante para o tratamento de interrupes : A primeira instruo sempre tem que guardar o registrador de status na pilha, antes de voc utilizar instrues que possam alterar as flags do registrador de status. O programa principal, que foi interrompido, pode precisar utilizar uma flag que estava setada, para tomar alguma deciso, e a interrupo alterou justamente esta flag. Coisas engraadas podem acontecer de tempos em tempos. A ltima instruo antes de RETI dever ser recuperar o contedo do registrador de status da pilha e restaurar seu contedo original. Pela mesma razo, todos os registradores usados no tratamento da interrupo devem ser reservados exclusivamente para aquele propsito, ou salvos na pilha e restaurados ao fim da rotina. Nunca altere o contedo de um registrador dentro de uma tratamento de interrupo que for usado em outras partes do programa, sem restaur-lo antes. Devido a todas estas necessidades, um exemplo mais sofisticado de tratamento de interrupo, mostrado aqui.
.CSEG ; Segmento de cdigo comea aqui .ORG 0000 ; Endereo zero RJMP Inicia; O vetor de reset no endereo 0 RJMP ServicoInt ; 0001: Primeiro vetor de interrupo, tratamento de INT0 [...] aqui outros vetores Inicia: ; Aqui o programa principal inicia [...] aqui h espao suficiente para definir pilha e outras coisas ServicoInt: ; Aqui iniciamos a rotina de tratamento da interrupo PUSH R16 ; salvamos um registrador na pilha IN R16,SREG ; lemos o registrador de status (n.t. e colocamos em R16) PUSH R16 ; e o colocamos na pilha [...] Aqui a rotina de tratamento da interrupo faz alguma coisa e usa R16 POP R16 ; obtemos o registrador de flags de volta da pilha (n.t. Para R16) OUT SREG,R16 ; e o restauramos na flag de status POP R16 ; obtemos o contedo anterior de R16 na pilha RETI ; e retornamos da interrupo

Parece um pouco complicado, mas um pr-requisito para usar interrupes sem produzir srios bugs. Ignore PUSH R16 e POP R16 se voc pode reservar este registrador exclusivamente para uso no tratamento das interrupes. Como o tratamento da interrupo no pode ser interrompido (a no ser que voc permita, no cdigo), todas as rotinas de tratamento de interrupo podem usar o mesmo registrador. isso para o iniciante. H mais algumas coisas com interrupes, mas o suficiente para comear e no o confundir.

Avr-Asm-Tutorial

29

http://www.avr-asm-tutorial.net

Clculos
Agora discutiremos os comandos necessrios para calcular em linguagem assembler AVR. Isto inclui sistemas numricos, setar e zerar bits, deslocar e rotacionar, e adicionar/subtrair/comparar e converso de formatos numricos.

Sistemas numricos em assembler


Os seguintes formatos numricos so comuns em assembler:

Nmeros positivos inteiros (Bytes, Palavras, etc.), Nmeros com sinal (inteiros), Dgitos codificados em binrio (BCD, Binary Coded Digits) BCDs compactados, Nmeros formatados em ASCII.

Nmeros positivos inteiros (bytes, palavras, etc.)


O menor nmero inteiro a ser manipulado em assembler um byte com oito bits. Ele codifica nmeros entre 0 e 255. Tais bits encaixam perfeitamente em um registrador da MCU. Todos os nmeros maiores devem ser baseados neste formato bsico, usando mais do que um registrador. Dois bytes formam uma palavra, word, (que vai de 0 a 65.535), trs bytes formam uma palavra maior (vai de 0 a 16.777.215) e quatro bytes formam uma palavra dupla, double word (de 0 a 4.294.967.295). Os bytes de uma palavra ou palavra dupla podem ser armazenados no registrador que voc quiser. Operaes com estes bytes so programados byte por byte, ento voc no tem que se preocupar em coloc-los em ordem. Para formar um conjunto de uma palavra dupla, podemos armazenar assim:
.DEF r16 = dw0 .DEF r17 = dw1 .DEF r18 = dw2 .DEF r19 = dw3

dw0 a dw3 esto em ordem nos registradores. Se quisermos iniciar esta palavra dupla no incio de uma aplicao, devemos fazer da seguinte forma:
.EQU dwi = 4000000 ; definimos a constante LDI dw0,LOW(dwi) ; Os 8 bits mais baixos em R16 LDI dw1,BYTE2(dwi) ; bits 8 .. 15 em R17 LDI dw2,BYTE3(dwi) ; bits 16 .. 23 em R18 LDI dw3,BYTE4(dwi) ; bits 24 .. 31 em R19

Ento, convertemos este nmero decimal, chamado dwi, em suas pores binrias e as quebramos em quatro pacotes de bytes. Agora voc pode fazer clculos com esta palavra dupla.

Nmeros com sinal (inteiros)


Algumas vezes, mas em raros casos, voc precisa calcular com nmeros negativos. Um nmero negativo definido interpretando o bit mais significativo de um byte como um bit de sinal. Se for 0, o nmero positivo. Se for 1, o nmero negativo. Se for negativo, usualmente no armazenamos o nmero em sua forma normal, mas usamos seu valor invertido. Invertido significa que -1 como um byte inteiro no escrito 1000.0001 mas 1111.1111. Isto significa: subtraia 1 de 0 e esquea o estouro (overflow). O primeiro bit o bit de sinal, sinalizando que este um nmero negativo. O porqu deste formato diferente (subtrair o nmero negativo de 0) ser usado fcil de entender. Somar -1 (1111.1111) e +1 (0000.0001) d exatamente zero, se voc esquecer o estouro que ocorre durante esta operao (o nono bit). Em um byte, o maior nmero inteiro +127 (binrio 0,111111), o menor -128 (binrio 1,0000000). Em outras linguagens de computador, este formato numrico chamado de inteiro curto (short integer). Se voc precisar de uma faixa de valores maior, voc pode adicionar outro byte para formar um nmero inteiro, indo de +32.767 at -32.768, enquanto que quatro bytes fornecem uma faixa de +2.147.483.647 at -2.147.483.648, usualmente chamado de Inteiro longo (LongInt) ou Inteiro Duplo (DoubleInt).

Dgitos Codificados em Binrio, BCD (Binary Coded Digits)


Nmeros inteiros positivos ou com sinal nos formatos assima utilizam o espao disponvel da forma mais eficiente. Outra formato numrico, menos denso, mas fcil de trabalhar, armazenar os nmeros decimais em um byte para cada dgito. O dgito decimal armazenado em sua forma binrio em um byte. Cada dgito de 0 a 9 precisa de quatro bits (0000 a 1001), os quatro bits superiores so zeros, desperdiando muito espao em cada byte). Por exemplo, para mostrarmos o nmero 250, precisamos de no mnimo trs bytes:

Avr-Asm-Tutorial

30

http://www.avr-asm-tutorial.net

Valor do bit R16, Dgito 1 =2 R17, Dgito 2 = 5 R18, Dgito 3 = 0

128 0 0 0

64 0 0 0

32 0 0 0

16 0 0 0

8 0 0 0

4 0 1 0

2 1 0 0

1 0 1 0

;Instrues para codificar: LDI R16,2 LDI R17,5 LDI R18,0

Voc pode calcular com estes nmeros, mas um pouco mais complicado em assembler do que calcular com valores binrios. A vantagem dste formato que voc pode manipular nmeros to grandes quanto voc quiser, desde que haja espao suficiente. Os clculos so to precisos quanto voc quiser (se voc programa AVRs para aplicaes de banco), e voc pode convert-los facilmente para cordes (strings) de caracteres.

BCDs compactados
Se voc comprimir dois dgitos decimais dentro de um byte, voc no perder tanto espao de armazenagem. Este mtodo chamado de dgitos codificados em binrio compactados (packed binary coded digits). As duas partes de um byte so chamados de nibble superior e inferior. O nibble superior normalmente guardo o dgito mais significativo, o que tem vantagens no clculo (instrues especiais na linguagem assembler do AVR). O nmero decimal 250 ento ficaria assim formatado em BCD compactado: Byte 2 1 Dgitos 4&3 2&1 Valor 02 50 8 0 0 4 0 1 2 0 0 1 0 1 8 0 0 4 0 0 2 1 0 1 0 0

; Instrues para codificar LDI R17,0x02 ; Byte superior LDI R16,0x50 ; Byte inferior

Para fazer isto corretamente, voc pode usar a notao binria (0b...) ou a notao hexadecimal (0x...) para colocar os bits na posio correta dentro dos nibbles. O clculo com BCDs compactados um pouco mais complicado comparado com a forma binria. Para converter em cordes de caracteres, to fcil quanto com BCDs. O comprimento dos nmeros e a preciso dos clculos limitado somente pelo espao de armazenagem.

Nmeros em formato ASCII


Muito similar ao formato BCD a armazenagem de nmeros em formato ASCII. Os dgitos 0 a 9 so armazenados utilizando sua representao ASCII (ASCII = American Standard Code for Information Interchange, Padro de Cdigos Americanos para Intercmbio de Informao). O ASCII um formato muito antigo, desenvolvido e otimizado para escritores de teletipo, desnecessariamente complicado para utilizao em computadores (voc sabe o que um caractere chamado End Of Transmission (fim da transmisso) EOT significava quando foi inventado?), muito limitado para outras lnguas que no o ingls (somente 7 bits por caractere), ainda usado em comunicaes hoje devido aos esforos limitados de programadores de sistemas operacionais no sentido de mudar para sistemas de caracteres mais efetivos. Este sistema antigo s ultrapassado pelo conjunto de caracteres de 5 bit Europeu chamado conjunto Baudot ou o cdigo Morse, ainda em uso por algumas pessoas com dedos rpidos. Dentro do sistema de codificao ASCII, o dgito decimal 0 representado pelo nmero 48 (hexa 0x30, binrio 0b0011.0000), dgito 9 57 (hexa 0x39, binrio 0b0011.1001). O ASCII no foi projetado para ter estes nmeros no incio do conjunto de cdigo, pois j h alguns caracteres de comando como o EOT mencionado para teletipo. Ento temos que adicionar 48 a um BCD (ou setar os bit 4 e 5 para 1) para converter BCD para ASCII. Os nmeros formatados em ASCII precisam do mesmo espao de armazenagem que o BCD. Carregar 250 para um conjunto de registradores representando este nmero ficaria desta forma:
LDI R18,'2' LDI R17,'5' LDI R16,'0'

A representao ASCII destes caracteres so escrito nos registradores.

Manipulao de bits
Para converter um dgito codificado em BCD para sua representao em ASCII, temos que setar os bits 4 e 5 para um. Em outras palavras, precisamos fazer uma operao OR no BCD com um valor hexa de 0x30. Em assembler isto feito da seguinte forma:

Avr-Asm-Tutorial ORI R16,0x30

31

http://www.avr-asm-tutorial.net

Se temos um registrador que j tem o valor hexa 0x30, podemos fazer OR com este registrador para convert-lo para BCD:
OR R1,R2

Converter um ASCII de volta para BCD fcil. A instruo


ANDI R16,0x0F

isola os quatro bits mais baixos (= o nibble inferior). Note que ORI e ANDI so possveis apenas com registradores acima de R15. Se precisar utiliz-los, use um dos registradores entre R16 e R31! Se o valor hexa 0x0F j estiver no registrador R2, voc pode fazer AND o caractere ASCII com este registrador:
AND R1,R2

As outras instrues para manipular bits em um registrador so tambem limitados para os registradores acima de R15. Eles podem ser formulados assim:
SBR R16,0b00110000 ; Seta bits 4 e 5 para um CBR R16,0b00110000 ; zera bits 4 e 5 para zero

Se um ou mais bits de um byte tm que ser invertidos, voc pode usar a seguinte instruo (que no possvel usar com uma constante):
LDI R16,0b10101010 ; Inverte todos os bits pares EOR R1,R16 ; do registrador R1 e armazena o resultado em R1

Inverter todos os bits de um byte chamado de Complemento de Um.


COM R1

inverte o contedo do registrador R1 e substitui zeros por uns e vice versa. Isto diferente do Complemento de Dois, que converte um nmero com sinal positivo pelo seu complemento negativo (subtraindo de zero). Isto feito com a instruo
NEG R1

Ento +1 (decimal: 1) vira -1 (binrio 1.1111111), +2 vira -2 (binrio 1.1111110), e assim por diante. Alm da manipulao de bits em um registrador, a cpia de apenas um bit possvel usando a bit T do registrador de status. Com
BLD R1,0

O bit T carregado com uma cpia do bit 0 do registrador R1. O bit T pode ser setado ou zerado, e seu contedo pode ser copiado para qualquer bit em qualquer registrador:
CLT ; zera bit T, ou SET ; seta bit T, ou BST R2,2 ; copia bit T para o bit 2 do registrador R2

Desloca e rotaciona
Deslocamento e rotao de nmeros binrios significa multiplicao ou diviso por 2. O deslocamento tem vrias sub-instrues. A multiplicao por 2 facilmente feita deslocando todos os bits de um byte um dgito binrio esquerda e escrevendo um zero no bit menos significativo. Isto chamado desvio esquerda lgico (Logic Shift Left). O antigo bit 7 do byte ser deslocado para o carry no registrador de status.
LSL R1

O inverso, diviso por 2 a instruo chamada desvio direita lgico (Logic Shift Right) LSR R1 O antigo bit 7, agora deslocado para o bit 6, preenchido com 0, enquanto o antigo bit 0 deslocado para o carry do registrador de status. Este carry poderia ser usado para arredondar para cima e para baixo (se estiver setado, adicionar um ao resultado). Exemplo, diviso por quatro com arredondamento:
LSR R1 ; diviso por 2 BRCC Div2 ; Pula se no arredondar INC R1 ; arredonda para cima Div2: LSR R1 ; Mais uma diviso por 2 BRCC DivE ; Pula se no arredondar INC R1 ; Arredonda DivE:

Avr-Asm-Tutorial

32

http://www.avr-asm-tutorial.net

Assim, dividir fcil com binrios, contanto que voc divida por mltiplos de 2. Se inteiros com sinal forem usados, o desvio direito sobrescreveria o bit de sinal 7. A instruo desvio direita aritmtico (arithmetic shift right) ASR deixa o bit 7 intocado e desloca os 7 bits inferiores, inserindo um bit zero na localizao 6.
ASR R1

Da mesma forma que o desvio lgico, o antigo bit 0 vai para o carry no registrador de status. Que tal multiplicarmos uma palavra de 16 bits por 2? O bit mais significativo do byte inferior tem que ser deslocado para se tornar o bit inferior do byte superior. Neste passo, um desvio setaria o bit mais baixo para zero, mas precisamos deslocar o carry do deslocamento anterior do byte mais baixo para o bit 0. Isto chamado rotao. Durante a rotao, o carry no registrador de status alterado para bit 0, e o antigo bit 7 deslocado para o carry durante a rotao.
LSL R1 ; Desvio Esquerda Lgico do byte mais baixo ROL R2 ; Rotaciona para esquerda (ROtate Left) do byte superior

O desvio esquerda lgico da primeira instruo desloca o bit 7 para o carry, a instruo ROL rola o carry para o bit 0 do byte superior. Aps a segunda instruo, o carry tem o antigo bit 7. O carry pode ser usado tanto para indicar um estouro (se for feito um clculo de 16 bits) ou para ser rolado para bytes superiores (se est sendo feito clculo com mais de 16 bits). A rolagem para a direita tambm possvel, dividindo por 2 e deslocando o carry para o bit 7 do resultado:
LSR R2 ; Desvio lgico direita, bit 0 vai para o carry ROR R1 ; Rotaciona para direita (ROtate Right) e desvia o carry para o bit 7

fcil dividir nmeros grandes. Voc v que aprender assembler no TO complicado. A ltima instruo que desloca quatro bits em um nico passo normalmente usado em BCDs compactados. Esta instruo desloca um nibble inteiro da posio superior para a inferior e vice-versa. Em nosso exemplo, precisamos deslocar o nibble superior para o nibble inferior. No lugar de usarmos
ROR R1 ROR R1 ROR R1 ROR R1

podemos fazer isso com um simples


SWAP R1

Esta instruo troca os nibbles superior e o inferior entre si. Note que o contedo do nibble superior ser diferente aps aplicar estes dois mtodos.

Somando, subtraindo e comparando


As seguintes operaes de clculo so complicadas demais para os iniciantes e demonstram que assembler apenas para experts extremos. Leia por seu prprio risco! Para comear a complicar, somaremos dois nmeros de 16 bits, em R1:R2 e R3:R4. (Nesta notao, queremos dizer que o primeiro registrador o byte mais significativo, o segundo o menos significativo).
ADD R2,R4 ; primeiro soma os dois bytes inferiores ADC R1,R3 ; depois os dois bytes superiores

No lugar do segundo ADD, usamos ADC na segunda instruo. Isso significa somar com o carry ( Add with Carry), que setado ou zerado durante a primeira instruo, dependendo do resultado. J est apavorado o suficiente por essa matemtica complicada? Se no: tome isso! Subtrairemos R3:R4 de R1:R2.
SUB R2,R4 ; primeiro o byte inferior SBC R1,R3 ; depois o byte superior

Novamente o mesmo truque: durante a segunda instruo subtramos outro 1 do resultado caso o resultado da primeira instruo teve um estoruo. Ainda respirando? Se sim, siga adiante! Agora comparemos uma palavra de 16 bits em R1:R2 com outro em R2:R4 para avaliar se maior do que o segundo. No lugar de SUB, usamos uma instruo de comparao CP, e no lugar de SBC usamos CPC:
CP R2,R4 ; compara bytes inferiores CPC R1,R3 ; compara bytes superiores

Se a flag de carry estiver setada agora, R1:R2 maior que R3:R4 Agora adicionamos coisas mais complicadas. Comparemos o contedo de R16 com a constante 0b10101010.

Avr-Asm-Tutorial CPI R16,0xAA

33

http://www.avr-asm-tutorial.net

Se o bit de Zero do registrador de status for 1 depois disso, sabemos que R16 0xAA. Se o carry for 1, sabemos que menor. Se nem o carry nem o Zero forem 1, sabemos que maior. E agora o teste mais complicado. Avaliamos se R1 zero ou negativo:
TST R1

Se o bit Z estiver setado, o registrador R1 zero e podemos utilizar uma das seguintes instrues: BREQ, BRNE, BRMI, BRPL, BRLO, BRSH, BRGE, BRLT, BRVC or BRVS para desviarmos um pouco. Ainda conosco? Se sim, h alguns clculos para BCD compactados. Somar dois BCDs compactados pode resultar em dois estouros diferentes. O carry usual mostra um overflow, se o nibble superior resultar em mais do que 15 decimal. Outro estouro ocorre do nibble inferior para o superior, se a soma dos dois nibbles der mais do que 15 decimal. Para servir de exemplo, vamos somar os BCDs compactados 49 (=hexa 49) e 99 (=hexa 99) para chegar a 148 (=hexa 0x0148). Som-los usando matemtica binria resultaria em um byte com o hexa 0xE2, e no ocorreria estouro. O mais baixo dos nibbles deveria ter dado um overflow, pois 9+9=18 (mais que 9) e o nibble inferior pode somente manipular nmeros at 15. O estouro foi somado ao bit 4, o bit menos significativo do nibble superior. O que est correto! Mas o nibble inferior deveria ser 8 e somente 2 (18 = 0b0001.0010). Deveramos adicionar 6 a este nibble para chegarmos ao resultado correto. O que lgico, porque sempre que o nibble inferior passar de 9, temos que adicionar 6 para corrigi-lo. O nibble superior est totalmente incorreto, porque est 0xE e deveria ser 3 (com um 1 estourando para o prximo dgito do BCD compactado). Se adicionarmos 6 a este 0xE, conseguiremos 0x4 e o carry setado (=0x14). Ento o truque primeiro somarmos estes dois nmeros e depois adicionarmos 0x66 para corrigir os dois dgitos do BCD compactado. Mas espere: e se a soma do primeiro e do segundo dgitos no resultarem em estouro para o prximo nibble e no resultar em um nmero maior do que 9 no nibble inferior? Somar 0x66 ento resultaria em um resultado totalmente incorreto. O 6 inferior deve ser adicionado se o nibble inferior estoura para o nibble superior, ou resulta em um dgito maior que 9. O mesmo com o nibble superior. Como sabemos, se ocorre um estouro do nibble inferior para o superior? A MCU seta o bit H no registrador de status, o bit meio-carry ( half-carry). A seguir mostramos o algoritmo para diferentes casos que so possveis aps somar dois nibbles e somar o hexa 0x6 a eles. 1. Some os nibbles. Se ocorrer estouro (C para os nibbles superiores, ou H para os inferiores), adicione 6 para corrigir. Se no, passe para o passo 2. 2. Some 6 ao nibble. Se ocorrer estouro (C ou H), est terminado. Se no, subtraia 6. Para programar um exemplo, vamos assimir que dois BCDs compactados esto em R2 e R3, R1 ficar com o estouro, e R16 e R17 esto disponveis para clculos. R16 o registrador de soma para adicionar 0x66 (o registrador R2 no pode receber um valor constante), R17 usado para corrigir o resultado dependendo das diferentes flags. Somar R2 com R3 fica assim:
LDI R16,0x66 ; para somar 0x66 ao resultado LDI R17,0x66 ; para depois subtrai-lo do resultado ADD R2,R3 ; soma os dois BCDs de dois dgitos BRCC NoCy1 ; pula se no ocorrer estouro INC R1 ; incrementa o prximo byte superior ANDI R17,0x0F ; no subtraia 6 do nibble inferior NoCy1: BRHC NoHc1 ; pula se no ocorrer meio-carry ANDI R17,0xF0 ; no subtraia 6 do nibble inferior NoHc1: ADD R2,R16 ; some 0x66 ao resultado BRCC NoCy2 ; pule se no ocorreu carry INC R1 ; incremente o prximo byte superior ANDI R17,0x0F ; no subtraia 6 do nibble superior NoCy2: BRHC NoHc2 ; pule se no ocorreu meio-carry ANDI R17,0xF0 ; no subtraia 6 do nibble inferior NoHc2: SUB R2,R17 ; correo da subtrao

Um pouco mais curto:


LDI R16,0x66 ADD R2,R16 ADD R2,R3 BRCC NoCy INC R1 ANDI R16,0x0F NoCy: BRHC NoHc ANDI R16,0xF0 NoHc: SUB R2,R16

Pergunta para pensar: porque ambos esto corretos, e a segunda verso ocupa metade do tamanho e

Avr-Asm-Tutorial

34

http://www.avr-asm-tutorial.net

menos complicado, onde est o truque?

Converso de formatos numricos


Todos os formatos numricos podem ser convertidos. A converso entre BCD e ASCII e vice-versa j foi mostrada acima (Manipulao de bits). A converso para BCDs compactados no muito complicada tambm. Primeiro temos que copiar o nmero para outro registrador. Com o valor copiado, trocamos os nibbles usando a instruo SWAP (trocar) para trocar o superior com o inferior. A parte superior zerada, e.g. Fazendo AND com 0x0F. Agora temos o BCD do nibble superior e podemos us-lo como BCD ou setar bit 4 e 5 para convert-lo em um caractere ASCII. Depois disso, copiamos novamente o byte e tratamos o nibble inferior sem fazer SWAP para obter o BCD inferior. Um pouco mais complicada a converso de dgitos BCD para binrio. Dependendo dos nmeros a serem manipulados, primeiramente liberamos os bytes necessrios que recebero o resultado da converso. Ento iniciamos com o dgito BCD mais alto. Antes de adicionar este resultado, multiplicamos o resultado por 10. (Note que no primeiro passo isto no necessrio, pois o resultado zero). Para fazermos esta multiplicao por 10, copiamos o resultado para algum lugar. Depois multiplicamos o resultado por 4 (duas rolagens esquerda). Adicionar o nmero anteriormente copiado resulta na multiplicao por 5. Agora uma multiplicao por 2 (uma rolagem esquerda) chega ao resultado decaduplicado. Finalmente adicionamos o BCD e repetimos este algoritmo at todos os dgitos estarem convertidos. Se, em uma destas operaes, ocorrer um carry (transporte) do resultado, o BCD grande demais para ser convertido. Este algoritmo funciona com nmeros de qualquer comprimento, desde que haja registradores suficientes. A converso de binrios para BCD um pouco mais complicada. Se convertermos um binrio de 16 bits podemos subtrair 10.000 (0x2710) at que ocorra um estouro, obtendo o primeiro dgito. Ento repetimos com 1000 para obtermos os segundo dgito. E assim por diante com 100 (0x0064) e 10 (0x000A), e ento o que remanescente o ltimo dgito. As constantes 10.000, 1.000, 100 e 10 podem ser colocados na memria do programa em uma tabela de palavras, organizada da seguinte forma:
DezTab: .DW 10000, 1000, 100, 10

e podem ser lidas as palavras com uma instruo LPM da tabela. Uma alternativa uma tabela que contm o valor decimal de cada bit do binrio de 16 bits, e.g.,
.DB 0,3,2,7,6,8 .DB 0,1,6,3,8,4 .DB 0,0,8,1,9,2 .DB 0,0,4,0,9,6 .DB 0,0,2,0,4,8 ; e assim por diante at .DB 0,0,0,0,0,1

E ento voc desloca os bits do binrio para que este desloque dos registradores para o carry. Se for um, voc adiciona o nmero na tabela ao resultado, lendo on nmeros da tabela usando LPM. Isto mais complicado para programar e um pouco mais lento do que o mtodo acima. O terceiro mtodo calcular o valor da tabela, iniciando com 000001, adicionando-o ao BCD, cada vez que voc desloca um bit do seu binrio para a direita e adiciona ao BCD. Muitos mtodos, muito a ser otimizado.

Multiplicao
A multiplicao de nmeros binrios ser explicada aqui.

Multiplicao decimal
Para multiplicarmos dois nmeros binrios de 8 bits, vamos lembrar como fazemos com os nmeros decimais: 1234 * 567 = ? -----------------------1234 * 7 = 8638 + 1234 * 60 = 74040 + 1234 * 500 = 617000 -----------------------1234 * 567 = 699678 ======================== Passo a passo, em decimal:

Avr-Asm-Tutorial

35

http://www.avr-asm-tutorial.net

Multiplicamos o primeiro nmero com o dgito menos significativo do segundo nmero e adicionamos ao resultado. Multiplicamos o primeiro nmero por 10 e pelo prximo dgito do segundo nmero e adicionamos ao resultado. Multiplicamos o primeiro nmero por 100, e ao terceiro dgito, e adicionamos ao resultado.

Multiplicao binria
Agora em binrio. A multiplicao com dgitos simples no nececssria, pois h somente os dgitos 1 (some o nmero) e 0 (no some o nmero). A multiplicao por 10 em decimal equivale multiplicao por 2 em modo binrio. Multiplicao em 2 feita facilmente, adicionando o nmero a si mesmo, ou deslocando todos os bits uma posio para a esquerda e escrevendo um 0 para a posio vazia direita. Veja que matemtia binria muito mais fcil que decimal. Porque a humanidade no a usou desde o comeo?

Programa em Assembler AVR


O cdigo fonte a seguir demonstra a realizao de multiplicao em assembler.
; Mult8.asm multiplica dois nmeros de 8 bit para chegar a um resultado de 16 bits. ; .NOLIST .INCLUDE "C:\avrtools\appnotes\8515def.inc" .LIST ; ; Fluxo da multiplicao ; ; 1. O binrio a ser multiplicado deslocado no sentido do carry. Se for um, o nmero adicionado ao resultado, se no for um, o nmero no adicionado. ; 2. O nmero binrio multiplicado por 2, rotacionando uma posio esquerda, e preenchendo a posio vazia com 0. ; 3. Se o binrio com que ser multiplicado no for zero, o ciclo de multiplicao repetido. Se for zero, a multiplicao est terminada. ; ; Registradores usados ; .DEF rm1 = R0 ; Nmero binrio a ser multiplicado (8 Bit) .DEF rmh = R1 ; Armazm intermedirio .DEF rm2 = R2 ; Nmero binrio com que o primeiro ser multiplicado (8 Bit) .DEF rel = R3 ; Resultado, LSB (16 Bit) .DEF reh = R4 ; Resultado, MSB .DEF rmp = R16 ; Registrador multi propsitos para carregamento ; .CSEG .ORG 0000 ; rjmp START ; START: ldi rmp,0xAA ; exemplo binrio 1010.1010 mov rm1,rmp ; para o primeiro registrador ldi rmp,0x55 ; examplo binrio 0101.0101 mov rm2,rmp ; para o segundo registrador ; ; Aqui iniciamos a multiplicao de um dos binrios em rm1 e rm2, o resultado vai para reh:rel (16 bits) ; MULT8: ; ; Zera valores de incio clr rmh ; zera armazm intermedirio clr rel ; zera registradores de resultado clr reh ; ; Aqui iniciamos o ciclo de multiplicao ; MULT8a: ; ; Passo 1: Rotaciona o bit mais baixo do nmero 2 para a flag de carry (divide por 2, rotaciona um zero no bit 7) ; clc ; zera carry ror rm2 ; bit 0 vai para o carry, bit 1 a 7 vo uma posio para direita, carry vai para o bit 7 ; ; Passo 2: Deciso dependendo se foi 0 ou 1 que foi rotacionado para o carry ; brcc MULT8b ; pula por cima da adio, se o carry for 0 ; ; Passo 3: Soma 16 bits em rmh:rml ao resultado, com estouro do LSB para o MSB ; add rel,rm1 ; soma o LSB de rm1 ao resultado adc reh,rmh ; soma carry e MSB de rm1 ; MULT8b: ;

Avr-Asm-Tutorial

36

http://www.avr-asm-tutorial.net

; Passo 4: Multiplicar rmh:rm 1 por 2 (16 bits, desvio esquerda) ; clc ; zera carry (clear carry bit) rol rm1 ; rotaciona o LSB esquerda (multiplica por 2) rol rmh ; rotaciona o carry para o MSB e o MSB uma casa esquerda ; ; Passo 5: Checa se h ainda nmeros 1 no binrio 2, se sim, continua multiplicando ; tst rm2 ; todos os bits zero? brne MULT8a ; se no, v para o loop ; ; Fim da multiplicao, resultado em reh:rel ; ; Loop sem fim ; LOOP: rjmp loop

Rotao binria
Para entender a operao de multiplicao, necessrio entender os comandos de rotao binria ROL e ROR. Estas instrues deslocam todos os bits de um registrador uma posio esquerda (ROL) ou direita (ROR). A posio vazia no registrador recebe o contedo do carry do registrador de status, e o bit que rola para fora do registrador vai para o carry. Esta operao demonstrada usando 0xAA como exemplo de ROL e 0x55 como exemplo de ROR.

Multiplicao no studio
A tela abaixo mostra o programa de multiplicao no simulador.

O cdigo-objeto foi aberto, e o cursor colocado na primeira instruo executvel. F11 executa um passo.

Avr-Asm-Tutorial

37

http://www.avr-asm-tutorial.net

Os registradores R0 e R2 so setados para 0xAA e 0x55, nossos binrios de teste, para serem multiplicados.

R2 rotacionado direita, para rolar o bit menos significativo para o carry, 0x55 (0101.0101) vira 0x2A (0010.1010).

Com o carry era 1, o contedo dos registradores R2:R1 somado ao par de registradores R4:R3 (vazio), resultando em 0x00AA nestes.

Avr-Asm-Tutorial

38

http://www.avr-asm-tutorial.net

Agora o par de registradores R1:R0 rotacionado uma posio esquerda para multiplicar este binrio por 2. A partir de 0x00AA, a multiplicao por 2 resulta 0x0154. O ciclo de multiplicao repetido enquanto haja ao menos um binrio 1 no registrador R2. Os passos seguintes no so mostrados aqui.

Usando a tecla F5 no studio podemos pular estes loops at um ponto de parada no fim da rotina de multiplicao. O resultado no par de registradores R4:R3 mostra o resultado da multiplicao de 0xAA por 0x55: 0x3872.

No foi to complicado, basta lembrar na similaridade com as operaes decimais. A multiplicao em binrio muito mais fcil do que decimal.

Diviso
Diviso decimal
Novamente comeamos com diviso decimal, para compreender melhor a diviso binria. Vamos assumir uma diviso de 5678 por 12. Isto feito assim: 5678 : 12 = ? -------------------------- 4 * 1200 = 4800 ---878 - 7 * 120 = 840 --38 - 3 * 12 = 36 -2 Resultado: 5678 : 12 = 473 Resto 2

Avr-Asm-Tutorial

39

http://www.avr-asm-tutorial.net

===================================

Diviso binria
Em binrio, a multiplicao do segundo nmero (4 * 1200, etc) no necessria, devido ao fato que temos apenas 0 e 1 como dgitos. Infelizmente, nmeros binrios tm muito mais dgitos do que seu equivalente decimal, ento transferir a diviso decimal em binria um pouco inconveniente. Assim, o programa trabalha de forma um pouco diferente. A diviso de um nmero binrio de 16 bits por um nmero de 8 bits em assembler AVR est listado na seo seguinte.
; Div8 divide um nmero de 16 bits por um nmero de 8 bits (Testee: nmero de 16 bits: 0xAAAA, nmero de 8 bits: 0x55) .NOLIST .INCLUDE "C:\avrtools\appnotes\8515def.inc" .LIST ; Registradores .DEF rd1l = R0 ; LSB do nmero de 16 bits a ser dividido (dividendo) .DEF rd1h = R1 ; MSB do nmero de 16 bits a ser dividido (dividendo) .DEF rd1u = R2 ; registrador intermedirio .DEF rd2 = R3 ; nmero de 8 bits divisor .DEF rel = R4 ; LSB do resultado .DEF reh = R5 ; MSB do resultado .DEF rmp = R16; registrador multi-propsito para carregamento ; .CSEG .ORG 0 rjmp start start: ; Carregamos os nmeros do teste para os registradores apropriados ldi rmp,0xAA ; 0xAAAA o dividendo mov rd1h,rmp mov rd1l,rmp ldi rmp,0x55 ; 0x55 o divisor mov rd2,rmp ; Divide rd1h:rd1l por rd2 div8: clr rd1u ; zera registrador intermedirio clr reh ; zera resultado (os registradores de resultado) clr rel ; tambm usados para contar at 16 para inc rel ; os passos da diviso, setado em 1 no incio) ; Aqui o loop de diviso inicia div8a: clc ; zera carry rol rd1l ; rotaciona o prximo bit superior do nmero rol rd1h ; para o registrador intermedirio (multiplica por 2) rol rd1u brcs div8b ; um foi rolado para a esquerda, portanto subtraia cp rd1u,rd2 ; Resultado da diviso 1 ou 0? brcs div8c ; pule sobre a subtrao, se for menor div8b: sub rd1u,rd2; subtraia os nmeros para dividir sec ; set carry, o resultado 1 rjmp div8d ; pule para o desvio do bit de resultado div8c: clc ; zere o carry, o bit resultado 0 div8d: rol rel ; rotacione o carry para dentro dos registradores de resultado rol reh brcc div8a ; enquanto zero rotacionar para fora dos registradores de resultado: v para o loop de diviso ; Fim da diviso stop: rjmp stop ; loop sem fim

Passos do programa durante a diviso


Durante a execuo do programa os seguintes passos so seguidos

Definio e pr-ajuste dos registradores com os binrios de teste, pr-ajuste do registrador intermedirio e o par de registradores de resultado (os registradores de resultado so pr-ajustados para 0x0001! Aps 16 rotaes, a rolagem do 1 para fora interrompe as divises.), o binrio de 16 bits em rd1h:rd1l rotacionado para o registrador intermedirio rd1u (multiplicao por 2), se um 1 for rotacionado para fora de rd1u, o programa desvia para o passo de subtrao no passo 4 imediatamente. O contedo do registrador intermedirio comparado com o binrio de 8 bits em rd2. Se rd2 for menor, ele subtrado do registrador intermedirio e o carry setado 1, se rd2 for maior, a subtrao pulada e um zero setado na flag de carry. O contedo da flag de carry rotacionada no registrador de resultado reh:rel da direita.

Avr-Asm-Tutorial

40

http://www.avr-asm-tutorial.net

Se um zero foi rotacionado para fora do registrador de resulltado, temos que repetir o loop de diviso. Se foi um 1, a diviso est completa.

Se voc no entende rotao ainda, voc encontrar esta operao discutida na seo de multiplicao.

Diviso no simulador
A tela a seguir demonstra os passos do programa no studio. Para fazer isto, voc tem que compilar o cdigo fonte e abrir o arquivo objeto resultante no studio. O cdigo objeto foi iniciado, o cursor est na primeira instruo executvel. F11 executa passo a passo.

O teste, binrios 0XAAAA e 0x55, sero divididos, e so escritos nos registradores R1:R0 e R3.

O registrador intermedirio R2 e o par de registradores do resultado so setados para seus valores predefinidos.

Avr-Asm-Tutorial

41

http://www.avr-asm-tutorial.net

R1:R0 foi rotacionado esquerda para R2, a partir do valor 0xAAAA chegamos ao valor dobrado 0x015554.

No houve estouro da rotao para o carry e 0x01 em R2 era menor que 0x55 em R3, ento a subtrao foi pulada. Um zero no carry foi rotacionado para o registrador de resultado R5:R4. O contedo anterior destes registradores, um bit na posio 0 foi rotacionado para a posio 1 (contedo agora: 0x0002). Como um zero foi rotacionado para fora do registrador de resultados, o prximo passo a ser executado um desvio para o incio do loop de diviso e o loop repetido. Aps executar o loop 16 vezes, chegamos ao ponto de parada no final da rotina de diviso. O registrador de resultado R5:R4 tem 0x0202, o resultado da diviso. Os registradores R2:R1:R0 esto vazios, portanto no temos resto. Se houvesse resto, poderamos us-lo para decidir um incremento do resultado, arredondando-o para cima. Este passo no foi codificado aqui.

Avr-Asm-Tutorial

42

http://www.avr-asm-tutorial.net

Toda a diviso precisou de 60 microssegundos do tempo do processador (abra o processor view do menu studio). Um tempo bastante grande para uma diviso.

Converso numrica
Rotinas de converso numricas no so includas aqui. Por favor visite o website, se precisar do cdigo fonte ou uma melhor compreenso.

Fraes decimais
Primeiro: No use pontos flutuantes, a menos que voc realmente precise deles. Pontos flutuantes so vorazes consumidores de recursos em um AVR, e precisam de muito tempo de execuo. Voc estar neste dilema, se voc pensa que assembler muito complicado, e preferir Basic ou outras linguagens como C e Pascal. Mas no, se voc usa assembler. Lhe ser demonstrado aqui, como voc pode realizar uma multiplicao de um nmero real em menos de 60 microssegundos, em casos especiais at com 18 microssegundos, usando uma freqncia de clock de 4 MHz. Sem quaisquer extenses para ponto flutuante ou outros truques caros para pessoas preguiosas demais para usar o seu crebro. Como fazer isto? De volta razes de matemtica! A maioria das tarefas com reais usando ponto flutuante pode ser feita usando nmeros inteiros. Inteiros so fceis de programar em assembler, e so velozes. O ponto decimal est somente no crebro do programador, e adicionado depois no fluxo digital. Ningum se d conta disso, este o truque.

Converses lineares
Como um exemplo, a tarefa seguinte: um conversor AD de 8 bits mede a entrada de um sinal de entrada variando de 0,00 a 2,55 Volts, e retorna como resultado um binrio entre $00 e $FF. O resultado uma voltagem, para ser mostrada em um display LCD. Exemplo to simples quanto fcil: O binrio convertido em uma string ASCII decimal entre 000 e 255, e logo depois do primeiro dgito, o ponto decimal tem que ser inserido. Pronto! O mundo eletrnico mais complicado. E. g., o conversor AD retorna um hexa de 8 bits para tenses de entrada entre 0,00 e 5,00 Volt. Agora complicou e no sabemos como fazer. Para mostrar o valor correto no LCD, teramos que multiplicar o binrio por 500/255, que 1,9608. Este um nmero complicado, pois quase 2, mas apenas quase. E no queremos este tipo de impreciso de 2%, j que temos um conversor AD com cerca de 0,25% de preciso. Para resolver isso, multiplicamos a entrada por 200/255*256 ou 501,96 e dividimos o resultado por 256. Porque primeiro multiplicar por 256 e depois dividir por 256? apenas para maior preciso. Se multiplicarmos a entrada por 502 ao invs de 501,96, o erro da ordem de 0,008%. Isto est bom para nosso conversor AD, podemos conviver com isso. E dividir por 256 uma tarefa fcil, pois uma potncia de 2 bem conhecida. Dividir nmeros que so potncia de 2, o AVR se sente muito confortvel e realiza de forma muito rpida. Para dividir por 256, o AVR ainda mais rpido, pois basta pularmos o ltimo byte do nmero binrio. No precisamos nem mesmo deslocar e rotacionar! Na multiplicao de um binrio de 8 bits com o binrio de 9 bits 502 (hex 16F), podemos obter um valor maior do que 16 bits. Portanto temos que reservar 24 bits ou 3 registradores para o resultado. Durante a multiplicao, a constante 502 tem que ser deslocada esquerda (multiplicao por 2) para somar estes nmeros ao resultado cada vez que um 1 rola para fora do nmero de entrada. Como podem ser necessrios 8 desvios esquerda, precisamos de mais trs bytes para esta constante. Ento escolhemos a seguinte combinao dos registradores para multiplicao:

Nmero Valor de entrada Multiplicador Resultado

Valor (exemplo) 255 502 128,010

Registrador R1 R4 : R3 : R2 R7 : R6 : R5

Avr-Asm-Tutorial

43

http://www.avr-asm-tutorial.net

Aps colocar o valor 502 (00.01.F6) em R4:R3:R2 e zerar os registradores de resultado R7:R6:R5, a multiplicao segue da seguinte forma: 1. Testar, se o nmero da entrada j zero. Se for, terminamos. 2. Se no, um bit do nmero de entrada deslocado para fora do registrador para a direita, no carry, enquanto um bit zero colocado no bit 7. Esta instruo chamada desvio direta lgico ou LSR (Logical Shift Right) 3. Se o bit no carry for um, somamos o multiplicador (durante o passo 1 o valor 502, no passo 2 1004 e assim por diante) ao resultado. Durante a adio, tomamos o cuidado com qualquer carry (somando R2 a R5 por ADD, somando R3 a R6 e R4 a R7 com instruo ADC!). Se o bit no carry era zero, no adicionamos o multiplicador ao resultado e pulamos para o prximo passo. 4. Agora o multiplicador foi multiplicado por 2, pois o prximo bit deslocado para fora do nmero de entrada vale o dobro. Ento deslocamos R2 para a esquerda (inserindo um zero no bit 0) usando LSL. O bit 7 deslocado para o carry. Ento rotacionamos este carry para R3, rotacionando seu contedo um bit esquerda, e o bit 7 para o carry. O mesmo com R4. 5. Agora terminamos com um dgito do nmero de entrada, e prosseguimos no passo 1 novamente. O resultado da multiplicao por 502 agora est nos registradores de resultado R7:R6:R5. Se simplesmente ignorarmos o registrador R5 (diviso por 256), temos o nosso resultado desejado. Para aumentar a preciso, podemos usar o bit 7 em R5 para arredondar o resultado. Agora temos que converter o resultado de sua forma binria para o ASCII decimal (veja a tabela de converso para decimal-ASCII no website). Se colocarmos um ponto decimal no local correto na string ASCII, nossa string de tenso est pronta para ser mostrada. O programa todo, desde o nmero de entrada at a ASCII resultado, requer entre 79 e 228 ciclos de relgio, dependendo do nmero de entrada. Aqueles que quiserem vencer com rotinas de ponto flutuante de uma linguagem de programao mais sofisticada que assembler, sinta-se vontade para me escrever o seu tempo de converso (e a utilizao de memria flash e de programa).

Exemplo 1: Conversor AD 8-bit para sada decimal com ponto fixo


; Demontra converso de ponto flutuante em Assembler, 2003 www.avr-asm-tutorial.net ; ; A tarefa: Voc l um resultado de 8 bits de um conversor analgico-digital, o nmero est na faixa de hex 00 a FF. ; Voc precisa convert-lo em um nmero com ponto flutuante na faixa de 0,00 a 5,00 Volts. ; O esquema do programa: ; 1. Multiplicao por 502 (hex 01F6). Este passo multipllica por 500, 256 e divide por 255 em um passo! ; 2. Arredondar e cortar o ltmo byte do resultado. Este passo divide por 256 ao ignorar o ltimo byte do resultado. ; Antes de fazer isso, o bit 7 usado para arredondar o resultado. ; 3. Converter a palavra resultante para ASCII e setar o sinal decimal correto. A palavra resultante que varia de 0 a 500 ; mostrada em caracteres ASCII como 0.00 a 5.00. ; Os registradores usados: ; As rotinas usam os registradores R8..R1 sem salv-los antes. Tambm necessrio um registrador multipropsito rmp, ; localizado na metade superior dos registradores. Assegure-se que estes registradores no conflitem com registradores ; em uso no restante do programa. ; O nmero de 8 bits esperado no registrador R1. A multiplicao usa R4:R3:R2 para guardar o multiplicador 502 ; ( deslocado esquerda at oito vezes durante a multiplicao). O resultado da multiplicao calculado nos ; registradores R7:R6:R5. O resultado da diviso por 256 feita ignorando R5 no resultado, usando somente R7:R6. ; R7:R6 arredondado, depenendo do bit mais alto de R5, e o resultado copiado para R2:R1. ; A converso para ASCII-string usa a entrada em R2:R1, o par de registradores R4:R3 como divisor para conveso, e ; coloca o resultado ASCII em R5:R6:R7:R8 (R6 o caractere decimal). ; Outras convenes: ; A converso usa subtotinas e a pilha. A pilha deve estar funcionando para uso de trs nveis (seis bytes de SRAM). ; Temos de converso: ; A rotina inteira requer 228 ciclos de relgico no mximo (convertendo $FF), e 79 no mnimo (convertendo $00). ; A 4 Mhz os tempos so 56,75 microssegundos e 17,75 microssegundos, respectivamente. ; Definies: ; Registradores .DEF rmp = R16 ; usado como registrador multipropsito ; tipo de AVR: Testado em AT90S8515, necessrio para pilha, as rotinas devem funcionar com outros tipos AT90S-. .NOLIST .INCLUDE "8515def.inc" .LIST ; Incio do programa de teste ; Escreve um nmero em R1 e inicia a converso da rotina, para propsitos de teste somente .CSEG .ORG $0000 rjmp main main: ldi rmp,HIGH(RAMEND) ; Inicia a pilha out SPH,rmp ldi rmp,LOW(RAMEND) out SPL,rmp ldi rmp,$FF ; Converte $FF mov R1,rmp rcall fpconv8 ; chama a rotina de converso no_end: ; loop infinito, quando terminar rjmp no_end ; Rotina de converso, chama diferentes passos da converso

Avr-Asm-Tutorial

44

http://www.avr-asm-tutorial.net

fpconv8: rcall fpconv8m ; multiplica pot 502 rcall fpconv8r ; arredonda e divide por 256 rcall fpconv8a ; converte para string ASCII ldi rmp,'.' ; seta caractere decimal mov R6,rmp ret ; tudo pronto ; Subrotina de multiplicao por 502 fpconv8m: clr R4 ; seta o multiplicador como 502 ldi rmp,$01 mov R3,rmp ldi rmp,$F6 mov R2,rmp clr R7 ; zera o resultado clr R6 clr R5 fpconv8m1: or R1,R1 ; checa se o nmero zero brne fpconv8m2 ; ainda tem um, continuamos com a verso ret ; pronto, retorne fpconv8m2: lsr R1 ; desloca nmero direita (divide por 2) brcc fpconv8m3 ; se o nmero mais baixo era 0, pula adio add R5,R2 ; some o nmero em R6:R5:R4:R3 ao resultado adc R6,R3 adc R7,R4 fpconv8m3: lsl R2 ; multiplica R4:R3:R2 por 2 rol R3 rol R4 rjmp fpconv8m1 ; repete para o prximo bit ; Arredonda o valor em R7:R6 com o valor do bit 7 de R5 fpconv8r: clr rmp ; coloca zero em rmp lsl R5 ; rotaciona bit 7 para o carry adc R6,rmp ; soma LSB com carry adc R7,rmp ; soma MSB com carry mov R2,R7 ; copia o valor para R2:R1 (divide por 256) mov R1,R6 ret ; Converte a palavra em R2:R1 para uma string ASCII em R5:R6:R7:R8 fpconv8a: clr R4 ; Seta o valor do divisor decimal para 100 ldi rmp,100 mov R3,rmp rcall fpconv8d ; obtm o dgito ASCII por subtraes repetidas mov R5,rmp ; seta caractere como sendo da centena ldi rmp,10 ; Seta o valor do divisor decimal para 10 mov R3,rmp rcall fpconv8d ; obtm o prximo dgito ASCII mov R7,rmp ; seta caractere como sendo da dezena ldi rmp,'0' ; converte o resto para dgito ASCII add rmp,R1 mov R8,rmp ; seta caractere como sendo da unidade ret ; Converte palavra binria em R2:R1 para dgito decimal subtraindo o valor do divisor decimal em R4:R3 (100,10) fpconv8d: ldi rmp,'0' ; inicia com o valor decimal '0' fpconv8d1: cp R1,R3 ; Compara palabra com o valor do divisor decimal cpc R2,R4 brcc fpconv8d2 ; zera carry, subtrai valor do divisor ret ; subtrao feita fpconv8d2: sub R1,R3 ; subtrai valor do divisor sbc R2,R4 inc rmp ; soma um rjmp fpconv8d1 ; de novo ; Fim da rotina de converso

Exemplo 2: Conversor AD de 10 bits com sada decimal fixa


Este exemplo um pouco mais complicado. Veja o website se precisar dele.

Avr-Asm-Tutorial

45

http://www.avr-asm-tutorial.net

Anexo
Instrues ordenadas por funo
Para as abreviaes usadas, veja a lista de abreviaes. Funo 0 Registrador 255 Constante Registrador => Registrador SRAM => Registrador, direto SRAM => Registrador SRAM => Registrador e INC DEC, SRAM => Registrador SRAM, deslocado => Registrador Porta => Registrador Cpia Pilha => Registrador Program storage Z => R0 Registrador => SRAM, direto Registrador => SRAM Registrador => SRAM e INC DEC, Registrador => SRAM Registrador => SRAM, deslocado Registrador => Porta Registrador => Pilha 8 Bit, +1 Soma 8 Bit 8 Bit + carry 16 Bit, constante 8 Bit, -1 8 Bit Subtrao 8 Bit, constante 8 Bit - carry 8 Bit - carry, constante 16 Bit Lgico, esquerda Lgico, direita Desvio Rotao, esquerda sobre carry Rotao, direita sobre carry Aritmtica, direita Troca de nibbles E (And) E, constante Ou (Or) Binrios Ou, constante Ou-Exclusivo (XOR) Complemento de Um Complemento de Dois Sub funo Comando CLR r1 SER rh LDI rh,c255 MOV r1,r2 LDS r1,c65535 LD r1,rp LD r1,rp+ LD r1,-rp LDD r1,ry+k63 IN r1,p1 POP r1 LPM STS c65535,r1 ST rp,r1 ST rp+,r1 ST -rp,r1 STD ry+k63,r1 OUT p1,r1 PUSH r1 INC r1 ADD r1,r2 ADC r1,r2 ADIW rd,k63 DEC r1 SUB r1,r2 SUBI rh,c255 SBC r1,r2 SBCI rh,c255 SBIW rd,k63 LSL r1 LSR r1 ROL r1 ROR r1 ASR r1 SWAP r1 AND r1,r2 ANDI rh,c255 OR r1,r2 ORI rh,c255 EOR r1,r2 COM r1 NEG r1 ZNV ZNV ZNV ZNV ZNV ZCNV ZNV Flags ZNV Clk 1 1 1 1 2 2 2 2 2 1 2 3 2 2 2 2 2 1 2 1 ZCNVH 1 ZCNVH 1 ZCNVS 2 ZNV 1 ZCNVH 1 ZCNVH 1 ZCNVH 1 ZCNVH 1 ZCNVS 2 ZCNV ZCNV ZCNV ZCNV ZCNV 1 1 1 1 1 1 1 1 1 1 1 1

ZCNVH 1

Avr-Asm-Tutorial

46

http://www.avr-asm-tutorial.net

Funo

Sub funo Registrador, seta Registrador, zera

Comando SBR rh,c255 CBR rh,255 BST r1,b7 BLD r1,b7 SBI pl,b7 CBI pl,b7 SEZ SEC SEN Z C N V H S T I Z C N V H S T I

Flags ZNV ZNV T

Clk 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Troca Bits

de Registrador, copia para Flag T Registrador, copia da Flag T Porta, seta Porta, zera Flag de Zero Flag de carry Flag de Negativo

Flag de carry de Complemento de SEV Seta bit de Dois Status Flag de meio carry SEH Flag de Sinal Flag de Transferncia Flag de Habilitao de Interrupo Flag de Zero Flag de carry Flag de Negativo SES SET SEI CLZ CLC CLN

Flag de carry de Complemento de CLV zera bit de Dois status Flag de meio carry CLH Flag de Sinal Flag de Transferncia Flag de Desabilitao de Interrupo Registrador, Registrador Compara Registrador, Registrador + carry Registrador, constante Registrador, 0 Relativo Indireto, Endereo em Z Salto Imediato Subrotina, relativo Subrotina, Endereo em Z Retorna da Subrotina Retorna da Interrupo CLS CLT CLI CP r1,r2 CPC r1,r2 CPI rh,c255 TST r1 RJMP c4096 IJMP RCALL c4096 ICALL RET RETI

ZCNVH 1 ZCNVH 1 ZCNVH 1 ZNV 1 2 2 3 3 4 I 4

Avr-Asm-Tutorial

47

http://www.avr-asm-tutorial.net

Funo

Sub funo Bit de status setado Bit de status zera Salta se igual Salta se diferente Salta se carry setado Salta se carry zero Salta se igual ou maior Salta se menor Salta se negativo

Comando BRBS b7,c127 BRBC b7,c127 BREQ c127 BRNE c127 BRCS c127 BRCC c127 BRSH c127 BRLO c127 BRMI c127 BRPL c127 BRGE c127 BRLT c127 BRHS c127 BRHC c127 BRTS c127 BRTC c127

Flags

Clk 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2/3 1/2/3 1/2/3 1/2/3 1/2/3 1 1 1

Salta se positivo Salto Salta se igual ou maior (com sinal) Condicional Salta se menor que zero (com sinal) Salta se meio carry setado Salta se meio carry zero Salta se Flag T setada Salta se Flag T zera

Salta se flag de complemento de 2 BRVS c127 setado Salta se flag de complemento de 2 BRVC c127 zero Salta se interrupo habilitada Salta se interrupo desabilitada Bit do registrador=0 Bit do registrador=1 Salto Bit da porta=0 condcionado Bit da porta=1 Compara, salta se for igual Sem Operao Outros Repouso Watchdog Reset BRIE c127 BRID c127 SBRC r1,b7 SBRS r1,b7 SBIC pl,b7 SBIS pl,b7 CPSE r1,r2 NOP SLEEP WDR

Lista de Diretivas e Instrues em ordem alfabtica


Diretivas de Assembler em ordem alfabtica
Diretiva .CSEG .DB .DEF .DW .ENDMACRO .ESEG .EQU .INCLUDE .MACRO .ORG ... significa ... Compilar para o segmento de cdigo Inserir bytes de dados Definir o nome de um registrador Insirir palavras de dados A macro est completa, parar a gravao Compilar para o segmento da EEPROM Definir uma constante por nome e setar o seu valor Inserir o contedo de um arquivo neste local como se fosse parte deste arquivo Iniciar a gravao das seguintes instrues como definies de macro Setar o endereo de sada do assembler para o seguinte nmero

Instrues em ordem alfabtica


Instruo ADC r1,r2 ADD r1,r2 ADIW rd,k63 ... faz ... Soma r2 com carry com r1, e armazena o resultado em r1 Soma r2 com r1 e armazena o resultado em r1 Soma a palavra constante imediata k63 ao registrador duplo rd+1:rd (rd = R24, R26, R28, R30)

Avr-Asm-Tutorial AND r1,r2 ANDI rh,c255 ASR r1 BLD r1,b7 BRCC c127 BRCS c127 BREQ c127 BRGE c127 BRHC c127 BRHS c127 BRID c127 BRIE c127 BRLO c127 BRLT c127 BRMI c127 BRNE c127 BRPL c127 BRSH c127 BRTC c127 BRTS c127 BRVC c127 BRVS c127 BST r1,b7 CBI pl,b7 CBR rh,k255 CLC CLH CLI CLN CLR r1 CLS CLT CLV CLZ COM r1 CP r1,r2 CPC r1,r2 CPI rh,c255 CPSE r1,r2 DEC r1 EOR r1,r2 ICALL IJMP IN r1,p1 INC r1

48 Faz operao and de r1 com o valor em r2 e armazena o resultado em r1

http://www.avr-asm-tutorial.net

Faz operao and com o registrador superior rh com a constante c255 e armazena o resultado em rh Desvio direita aritmtico do registrador r1 Copia a flag T do registrador de status para o bit b7 do registrador r1 Desvia ou volta para instrues c127 se a flag de carry for 0 Desvia ou volta para instrues c127 se a flag de carry for 1 Desvia ou volta para instrues c127 se a flag de zero for 1 Desvia ou volta para instrues c127 se a flag de carry for 0 Desvia ou volta para instrues c127 se a flag de meio-carry for 0 Desvia ou volta para instrues c127 se a flag de meio-carry for 1 Desvia ou volta para instrues c127 se a flag de interrupo for 0 Desvia ou volta para instrues c127 se a flag de interrupo for 1 Desvia ou volta para instrues c127 se a flag de carry for 1 Desvia ou volta para instrues c127 se as flags de negativo e estouro forem 1 Desvia ou volta para instrues c127 se a flag de negativo for 1 Desvia ou volta para instrues c127 se a flag de zero for 1 Desvia ou volta para instrues c127 se a flag de negativo for 0 Desvia ou volta para instrues c127 se a flag de carry for 0 Desvia ou volta para instrues c127 se a flag de transferncia for 0 Desvia ou volta para instrues c127 se a flag de transferncia for 1 Desvia ou volta para instrues c127 se a flag de estouro for 0 Desvia ou volta para instrues c127 se a flag de estouro for 1 Copia o bit 7 no registrador r1 para a flag de transferncia no registrador de status Zera bit b7 na porta mais baixa pl Zera todos os bits no registrador superior rh, que esto setados na constante k255 (mscara) Zera o bit de carry Zera o bit de meio-carry Zera o bit de interrupo, desabilita a execuo de interrupes Zera o bit de negativo no registrador de status Zera o registrador r1 Zera a flag de sinal no registrador de status Zera a flag de transferncia no registrador de status Zera a flag de overflow do registrador de status Zera a flag de zero do registrador de status Complementa registrador r1 (complemento de um) Compara registrador r1 com registrador r2 Compara registrador r1 com registrador r2 e flag de carry Compara o registrador superior rh com a constante imediata c255 Compara r1 com r2 e pula sobre a prxima instruo se for igual Decrementa o registrador r1 por 1 Ou-exclusive dos bits do registrador r1 com registrador r2 e armazena resultado em r1 Chama a subrotina no endereo no par de registradores Z (ZH:ZL, R31:R30) Salta para o endereo no par de registradores Z (ZH:ZL, R31:R30) Incrementa o registrador r1 por 1

LD r1,(rp,rp+,-rp) Carrega o registrador r1 com o contedo localizado no endereo apontado pelo par de registradores rp (X, Y ou Z) (rp+ incrementa o par de registradores depois da carga, -rp decrementa o par antes da carga) LDD r1,ry+k63 LDI rh,c255 LDS r1,c65535 LPM LPM r1 LPM r1,Z+ LPM r1,-Z LSL r1 LSR r1 Carrega o registrador r1 com o contedo localizado no endereo apontado pelo par de registradores ry (Y ou Z), deslocado pela constante k63 Carrega o registrador superior rh com a constante c255 Carrega o registrador r1 com o contedo do endereo c65535 Carrega o registrador R0 com o contedo da memory flash localizado no endereo apontado pelo par de registradores Z (ZH:ZL, R31:R30), dividido por 2, bit 0 em Z aponta para o byte inferior (0) ou superior (1) no flash (Carrega registrador r1, Z+ incrementa Z depois da carga, -Z decrementa Z antes da carga). Desvio esquerda lgico do registrador r1 Desvio direita lgico do registrador r1

Avr-Asm-Tutorial MOV r1,r2 NEG r1 NOP OR r1,r2 ORI rh,c255 OUT p1,r1 POP r1 PUSH r1 RCALL c4096 RET RETI RJMP c4096 ROL r1 ROR r1 SBC r1,r2 SBCI rh,c255 SBI pl,b7 SBIC pl,b7 SBIS pl,b7 SBIW rd,k63 SBR rh,c255 SBRC r1,b7 SBRS r1,b7 SEC SEH SEI SEN SER rh SES SET SEV SEZ SLEEP Move registrador r2 para o registrador r1 Subtrai registrador r1 de Zero Sem operao

49

http://www.avr-asm-tutorial.net

Faz operao OR do registrador r1 com r2 e armazena o resultado em r1 Faz operao OR do registrador superior r1 com a constante c255 Copia registrador r1 para porta de E/S p1 Incrementa o ponteiro de pilha e retira o ltimo byte da pilha e o coloca no registrador r1 Coloca o contedo do registrador r1 na pilha e decrementa o ponteiro de pilha Coloca o contador de programa na pilha e adiciona a constante com sinal c4096 ao contador de programa (chamada relativa) Recupera o contador de programa da pilha (retorna ao endereo de chamada) Habilita interrupes e recupera o contador de programa da pilha (retorna de interrupo) Salto relativo, soma constante com sinal c4096 ao endereo do programa Rotaciona registrador r1 esquerda, copia a flag de carry para o bit 0 Rotaciona o registrador r1 direita, copia a flag de carry para o bit 7 Subtrai r2 e a flag de carry do registrador r1 e armazena o resultado em r1 Subtrai constante c255 e carry do registrador superior rh e armazena o resultado em rh Seta o bit b7 na porta baixa pl Se o bit b7 na porta baixa pl for zero, pula a prxima instruo Se o bit b7 na porta baixa pl for um, pula a prxima instruo Subtrai a constante k63 do par de registradores rd (rd+1:rd, rd = R24, R26, R28, R30) Seta os bits no registrador superior rh, que so 1 da constante c255 Se o bit b7 do registrador r1 for zero, pula a prxima instruo Se o bit b7 no registrador r1 for um, pula a prxima instruo Seta flag de carry no registrador de status Seta flag de meio carry no registrador de status Seta flag de interrupo no registrador de status, habilita a execuo de interrupo Seta flag de negativo no registrador de status Seta todos os bits no registrador superior rh Seta flag de sinal no registrador de status Seta flag de transferncia no registrador de status Seta flag de estouro (overflow) no registrador de status Seta flag de zero no registrador de status Coloca o controlador no modo de repouso selecionado

ST (rp/rp+/-rp),r1 Armazena o contedo do registrador r1 na localizao da memria indicada pelo par de registradores rp (rp = X, Y, Z; rp+: incrementa o par de registradores depois do armazenamento; -rp: decrementa o par de registradores antes do armazenamento) STD ry+k63,r1 STS c65535,r1 SUB r1,r2 SUBI rh,c255 SWAP r1 TST r1 WDR Armazena o contedo do registrador r1 na localizao apontada pelo par de registradores ry (Y ou z), deslocado pela constante k63. Armazena o contedo do registrador r1 na localizao c65535 Subtrai o registrador r2 do registrador r1 e escreve o resultado em r1 Subtrai a constante c255 do registrador superior rh Troca os nibbles superior com o inferior no registrador r1 Compara o registrador r1 com Zero Watchdog reset

Detalhes das Portas


Esta tabela contm as portas importantes nos AVR tipo AT90S2313, 2323 e 8515. Portas ou pares de registradores acessveis no so mostradas em detalhes. No h garantias da exatido destes dados, confira os data sheets originais!

Avr-Asm-Tutorial

50

http://www.avr-asm-tutorial.net

Registrador de Status, Flags do Acumulador


Porta SREG 7 I Bit Nome 7 6 5 4 3 2 1 0 I T H S V N Z C Funo Endereo da porta Endereo da RAM 0x5F 3 V 2 N Indica CLI SEI CLT SET CLH SEH CLS SES CLV SEV CLN SEN CLZ SEZ CLC SEC 1 Z 0 C Comando

Acumulador do registrador 0x3F de status 6 T 5 H Significado Flag de Global 4 S

Interrupo 0: Interrupes desabilitadas 1: Interrupes habilitadas 0: O bit armazenado 0 1: O bit armazenado 1 0: No ocorreu meio-carry 1: Ocorreu meio-carry 0: Sinal positivo 1: Sinal negativo

Armazm de bits Flag de Meio-Carry Flag de Sinal

Flag de complemento de 0: No ocorreu transporte (carry) dois 1: Ocorreu transporte (carry) Flag de Negativo Flag de Zero Flag de Carry 0: O resultado no era negativo/menor 1: O resultado era negativo/menor 0: Resultado no era zero/diferente 1: Resultado era zero/igual 0: No ocorreu transporte (carry) 1: Ocorreu transporte (carry)

Ponteiro de pilha
Porta SPL/SPH Nome SPL SPH Funo Endereo da porta Endereo da RAM 0x5D/0x5E Disponibilidade Do AT90S2313 para frente, no em 1200 Do AT90S8515 para frente, apenas para dispositivos com mais de 256 bytes de SRAM interna.

Ponteiro de 003D/0x3E pilha Significado

Byte baixo do ponteiro de pilha Byte alto do ponteiro de pilha

SRAM e controle externo de interrupes


Porta MCUCR 7 SRE Bit Nome 7 SRE Funo Endereo da porta Endereo da RAM 0x55 3 ISC11 2 ISC10 Indica 0=No h SRAM externa conectada 1=H SRAM externa conectada 1 ISC01 0 ISC00

Registrador de Controle Geral 0x35 MCU 6 SRW 5 SE Significado Habilita SRAM Externa 4 SM

Avr-Asm-Tutorial

51

http://www.avr-asm-tutorial.net

Bit Nome 6 5 4 3 2 1 0 SRW SE SM ISC11

Significado

Indica

Estados de espera (wait 0=Sem wait state extra na SRAM externa states) da SRAM Ext. 1=Wait state adicional na SRAM externa Habilita repouso (sleep) Modo de respouso 0=Ignora comando SLEEP 1=Aceita comando SLEEP 0=Inatividade (Meio-repouso) 1=Desligamento (Repouso total)

00: Nvel baixo inicia interrupo Pino de controle de 01: Indefinido interrupo INT1 ISC10 (conectado a GIMSK) 10: Borda de descida dispara interrupo 11: Borda de subida dispara interrupo ISC01 00: Nvel baixo inicia interrupo Pino de controle de 01: Indefinido interrupo INT0 ISC00 (conectado a GIMSK) 10: Borda de descida dispara interrupo 11: Borda de subida dispara interrupo

Controle de Interrupo Externa


Porta GIMSK 7 INT1 Bit Nome 7 6 0...5 INT1 INT0 Funo Registrador mascarado Interrupo Geral 6 INT0 5 Significado de 4 Endereo da Porta 0x3B 3 Endereo da RAM 0x5B 2 Indica 1 0 -

Interrupo por pino externo 0: INT1 Externa desabilitada INT1 (conectado a MCUCR) 1: INT1 Externa habilitada Interrupo por pino externo 0: INT0 Externa desabilitada INT0 (conectado a MCUCR) 1: INT0 Externa habilitada (No usados)

Porta

Funo

Endereo da Porta 0x3A 3 -

Endereo da RAM 0x5A 2 1 0 Indica Zera o bit pela execuo da rotina de tratamento ou por comando

GIFR Registrador geral de Interrupes 7 INTF1 Bit 7 6 0...5 Name 6 INTF0 5 4 Significado

INTF1 Ocorreu interrupo externa pelo pino INT1 INTF0 Ocorreu interrupo externa pelo pino INT0

(No usados)

Avr-Asm-Tutorial

52

http://www.avr-asm-tutorial.net

Controle do Timer de Interrupo


Port TIMSK 7 TOIE1 Funo Endereo da Porta Endereo da RAM 0x59 3 TICIE1 2 1 TOIE0 0 -

Registrador mascarado do 0x39 timer de interrupo 6 OCIE1A 5 OCIE1B 4 -

Avr-Asm-Tutorial

53

http://www.avr-asm-tutorial.net

Bit 7

Nome TOIE1

Significado Estouro de Timer/Contador 1-Interrupo

Indica 0: Sem estouro int no

1: Int no estouro 6 5 4 3 2 1 0 TOIE0 TICIE1 OCIE1A Interrup. do Timer/Contador 1 Comparador A OCIE1B Interrup. do Timer/Contador 1 Comparador B (No usado) Captura do Timer/Contador 1 Interrupo (No usado) Estouro de Timer/Contador 0-Interrupo (No usado) 0: Sem estouro int no 0: Sem captura int na 0: Sem int igual a A 1: Int igual a A 0: Sem int em B 1: Int em B

1: Int na captura

1: Int no estouro

Port TIFR 7 TOV1 Bit 7 6 5 4 3 2 1 0 TOV0 ICF1 Nome TOV1 Registrador interrupo 6

Funo de 5 OCF1B timer de 4 -

Endereo da Porta 0x38 3 ICF1

Endereo da RAM 0x58 2 1 TOV0 Indica Modo-Interrupo: Zero pela execuo da rotina da interrupo OU Zero por comando 0 -

OCF1A

Significado Timer/Contador 1 estourou

OCF1A Timer/Contador 1 chegou a Compara A OCF1B Timer/Contador 1 chegou a Compara B (No usado) Evento de captura de Timer/Contador 1 (No usado) Timer/Contador 0 estourou (No usado)

Avr-Asm-Tutorial

54

http://www.avr-asm-tutorial.net

Timer/Contador 0
Port TCCR0 7 Bit Nome Funo Endereo da Porta Endereo da RAM 0x53 2 CS02 Indica 000: Pra timer 001: Clock = clock do chip 010: Clock = clock do chip / 8 2..0 CS02..CS00 Timer Clock 011: Clock = clock do chip / 64 100: Clock = clock do chip / 256 101: Clock = clock do chip / 1024 110: Clock = borda de descida do pino T0 111: Clock = borda de subida do pino T0 3..7 (No usado) 1 CS01 0 CS00

Registrador de controle de Timer/ 0x33 Contador 0 6 5 Significado 4 3 -

Port TCNT0

Funo

Endereo da Porta

Endereo da RAM 0x52

Registrador de Controle de 0x32 Timer/Contador 0

Timer/Contador 1
Port TCCR1A Funo Endereo da Porta Endereo da RAM 0x4F

Registrador de Controle A de Timer/ 0x2F Contador 1

3 Indica

2 -

1 PWM11

0 PWM10

COM1A1 COM1A0 COM1B1 COM1B0 Bit 7 6 5 4 3 2 Nome COM1A1 COM1A0 Significado

Sada Comparadora A 00: OC1A/B no conectado 01: OC1A/B troca polaridade 10: OC1A/B para zero COM1B1 Sada Comparadora B 11: OC1A/B para um COM1B0 (No usado) 00: PWM desligado Modulador por largura 01: 8-Bit PWM de pulso (PWM) 10: 9-Bit PWM 11: 10-Bit PWM

PWM11 1..0 PWM10

Avr-Asm-Tutorial

55

http://www.avr-asm-tutorial.net

Port TCCR1B 7 ICNC1 Bit 7

Funo

Endereo da Porta

Endereo da RAM 0x4E

Registrador de Controle B de Timer/ 0x2E Contador 1 6 ICES1 5 Significado 4 3 CTC1 2 CS12 Indica

1 CS11

0 CS10

Nome ICNC1

0: desabilitado, primeira borda inicia a Cancelador de amostragem rudo no pino ICP 1: habilitado, pelo menos quatro ciclos Seleo de bordo 0: borda de descida dispara captura na captura 1: borda de subida dispara captura Limpa quando a comparao for 1: Contador zera se for igual igual a A 000: Contador parado 001: Clock 010: Clock / 8 011: Clock / 64 100: Clock / 256 101: Clock / 1024 110: borda de descida em pino T1 111: borda de subida em pino T1

ICES1

5..4 (No usado) 3 CTC1

2..0 CS12..CS10 Seleo do clock

Port

Funo

Endereo da Porta 0x2C/0x2D

Endereo da RAM 0x4C/0x4D

TCNT1L/H Registrador Timer/Contador 1

Port

Funo

Endereo da Porta

Endereo da RAM 0x4A/0x4B hex

OCR1AL/H Timer/Contador 1 Output Compare register A 0x2A/0x2B

Port OCR1BL/H

Funo

Endereo da Porta

Endereo da RAM 0x48/0x49

Registrador de Sada do Comparador B 0x28/0x29 Timer/Contador 1

Port ICR1L/H

Funo

Endereo da Porta

Endereo da RAM 0x44/0x45

Registrador de Entrada de Captura do 0x24/0x25 Timer/Contador 1

Avr-Asm-Tutorial

56

http://www.avr-asm-tutorial.net

Watchdog-Timer
Port WDTCR 7 Bit 7..5 4 3 WDTOE WDE Nome Funo Registrador de Watchdog Timer 6 5 Controle 4 WDTOE Significado (No usado) Habilita ciclo de Watchdog Habilita Watchdog Requerido setar antes de desabilitar o WDE 1: Watchdog ativo 000: 15 ms 001: 30 ms 010: 60 ms 011: 120 ms 100: 240 ms 101: 490 ms 110: 970 ms 111: 1,9 s do Endereo da Porta 0x21 3 WDE 2 WDP2 Endereo da RAM 0x41 1 WDP1 0 WDP0

Ciclo-WDT a 5,0 Volts

2..0 WDP2..WDP0 Tempo do Watchdog

EEPROM
Port EEARL/H Funo Endereo da Porta Endereo da RAM 0x3E/0x3F

Registrador de Endereo da 0x1E/0x1F EEPROM

EEARH apenas nos tipo com EEPROM com mais de 256 Bytes (do AT90S8515 para frente)

Port EEDR

Funo

Endereo da Porta

Endereo da RAM 0x3D

Registrador de Dados da 0x1D EEPROM

Port EECR 7 Bit 7.. 3 2 1 0 EEMWE EEWE EERE Nome

Funo

Endereo da Porta

Endereo da RAM 0x3C

Registrador de Controle da 0x1C EEPROM 6 5 Significado (No usado) Habilita EEPROM Escrita Master 4 3 -

2 EEMWE

1 EEWE

0 EERE

Funo

Habilita ciclo de leitura Setar para iniciar gravao Setar para iniciar leitura

Habilita Escrita EEPROM Habilita Leitura EEPROM

Avr-Asm-Tutorial

57

http://www.avr-asm-tutorial.net

Interface de Perifricos Seriais (SPI)


Port SPCR 7 SPIE Bit Nome 7 6 5 4 3 2 1 0 SPIE SPE Funo Registrador Controle SPI 6 SPE de 5 DORD Endereo da Porta 0x0D 4 MSTR Endereo da RAM 0x2D 3 CPOL 2 CPHA Funo 0: Interrupes desabilitadas 1: Interrupes habilitadas 0: SPI desabilitado 1: SPI habilitado 0: MSB primeiro 1: LSB primeiro 0: Slave 1: Master 0: Fase positiva do Clock 1: Fase negativa do Clock 0: Amostragem no incio da fase do clock 1: Amostragem no fim da fase do clock 00: Clock / 4 Freqncia do clock 01: Clock / 16 SCK 10: Clock / 64 11: Clock / 128 1 SPR1 0 SPR0

Significado Interrupes SPI Habilita SPI

DORD Ordem de Dados MSTR Seleo Master/Slave CPOL Polaridade do Clock CPHA Fase do Clock SPR1 SPR0

Port SPSR 7 SPIF Bit Nome 7 6 5..0 SPIF WCOL

Funo Registrador Status SPI 6 WCOL de 5 -

Endereo da Porta 0x0E 4 -

Endereo da RAM 0x2E 3 Indica 2 1 0 -

Significado

Flag de Interrupo Requisita Interrupo SPI Flag de Coliso de Ocorreu Escrita escrita (No usado) coliso na

Port SPDR

Funo Registrador Dados da SPI de

Endereo da Porta 0x0F

Endereo da RAM 0x2F

Avr-Asm-Tutorial

58

http://www.avr-asm-tutorial.net

UART
Port UDR Funo Endereo da Porta Endereo da RAM 0x2C

Registrador de Dados da 0x0C E/S UART

Port USR 7 RXC Bit Nome 7 6 5 4 3 2..0 RXC TXC UDRE FE OR

Funo

Endereo da Porta

Endereo da RAM 0x2B

Registrador de Status 0x0B da UART 6 TXC 5 UDRE Significado Recepo UART Completa Transmisso Completa UART 4 FE

3 OR

2 Funo

1 -

0 -

1: Caractere recebido 1: Shift register vazio de

Registrador de Dados da 1: Registrador UART Vazio transmisso disponvel Erro de (framing) enquadramento 1: Bit de Parada Ilegal 1: Caractere perdido (No usado)

Perda (Overrun)

Port UCR 7 RXCIE Bit Nome 7 6 5 4 3 2 1 0 RXCIE TXCIE UDRIE RXEN TXEN CHR9 RXB8 TXB8

Funo

Endereo da Porta

Endereo da RAM 0x2A

Registrador de Controle 0x0A da UART 6 TXCIE 5 UDRIE 4 RXEN

3 TXEN

2 CHR9

1 RXB8 Funo

0 TXB8

Significado Habilita Interrupo terminada Habilita Interrupo completo quando quando

RX 1: Interrupo caractere

quando

recebe

TX 1: Interrupo quando transmisso completada

Habilita Interrupo Registrador de Dados vazio Recepo Habilitada Transmisso Habilitada Caracteres de 9 bits Recebe Bit de Dado 8 Transmite Bit de Dado 8

quando 1: Interrupo quando buffer de dados vazio 1: Receptor habilitado 1: Transmissor habilitado 1: Tamanho do caractere 9 bits (segura nono bit na recepo) (escreve nono bit para transmisso)

Port UBRR

Funo

Endereo da Porta

Endereo da RAM 0x29

Registrador de velocidade 0x09 da UART (Baud Rate)

Avr-Asm-Tutorial

59

http://www.avr-asm-tutorial.net

Analog Comparator
Port ACSR 7 ACD Bit Nome 7 6 5 4 3 2 1 ACO ACI ACIE ACIC ACIS1 ACD Funo Registrador de Status Comparador Analgico 6 5 ACO Significado Desabilita (No usado) Sada do Comparador Sada dos Comparadores Flag de Interrupo Habilita Interrupo 1: Interrupo requisitada 1: Interrupo habilitada e 4 ACI de Controle 3 ACIE Funo Desabilita Comparadores do Endereo da Porta 0x08 2 ACIC 1 ACIS1 Endereo da RAM 0x28 0 ACIS0

Habilita Captura de 1: Conecta a Captura do Timer1 entrada 00: Interrupo na mudana de nvel em em borda borda de de

01: (No usado) Habilita Captura de 10: Interrupo ACIS0 Entrada descida 11: Interrupo subida

Portas E/S
Port Register PORTA A DDRA PINA PORTB B DDRB PINB PORTC C DDRC PINC PORTD D DDRD PIND Funo Registrador de Dados Registrador da Direo dos Dados Endereo dos Pinos de Entrada Registrador de Dados Registrador da Direo dos Dados Endereo dos Pinos de Entrada Registrador de Dados Registrador da Direo dos Dados Endereo dos Pinos de Entrada Registrador de Dados Registrador da Direo dos Dados Endereo dos Pinos de Entrada Endereo da Porta 0x1B 0x1A 0x19 0x18 0x17 0x16 0x15 0x14 0x13 0x12 0x11 0x10 Endereo da RAM 0x3B 0x3A 0x39 0x38 0x37 0x36 0x35 0x34 0x33 0x32 0x31 0x30

Avr-Asm-Tutorial

60

http://www.avr-asm-tutorial.net

Portas, ordem alfabtica


ACSR, Registrador de Status e Controle do Comparador Analgico DDRx, Registrador da Direo dos Dados da Porta x EEAR, Registrador de endereo da EEPROM EECR, Registrador de controle da EEPROM EEDR, Registrador de Dados da EEPROM GIFR, Registrador da Flag de Interrupo Geral GIMSK, Registrador de Interrupo Mascarada Geral ICR1L/H, Registrador de Captura de Entrada 1 MCUCR, Registrador de Controle Geral da MCU OCR1A, Registrador de Sada do Comparador 1 A OCR1B, Registrador de Sada do Comparador 1 B PINx, Acesso Porta de Entrada PORTx, Port x Output Register SPL/SPH, Ponteiro de Pilha SPCR, Registrador de Controle de Perifricos Seriais SPDR, Registrador de Dados de Perifricos Seriais SPSR, Registrador de Status de Perifricos Seriais SREG, Registrador de Status TCCR0, Registrador de Controle do Timer/Contador Timer0 TCCR1A, Registrador de Controle do Timer/Contador 1 A TCCR1B, Registrador de Controle do Timer/Contador 1 B TCNT0, Registrador do Timer/Contador, Contador 0 TCNT1, Registrador do Timer/Contador, Contador 1 TIFR, Flag de Interrupo do Timer TIMSK, Registrador Mascarado de Interrupo do Timer UBRR, Registrador de velocidade da UART (Baud Rate) UCR, Registrador de Controle da UART UDR, Registrador de Dados da UART WDTCR, Registrador de Controle do Timer Watchdog

Lista de abreviaes
As abreviaes usadas foram escolhidas para inclurem a faixa de valores. Pares de registradores so nomeadas pelo menor dos dois registradores. Constantes em comandos de salto so automaticamente calculadas das respectivas labels durante a compilao. Categ. Abrev. r1 r2 Register rh rd rp ry k63 c127 Constant c255 c4096 c65535 Bit Port b7 p1 pl Significa ... Registradores comuns origem e destino R0..R31 R16..R31 R24(R25), R26(R27), R28(R29), R30(R31) X=R26(R27), Y=R28(R29), Z=R30(R31) com Y=R28(R29), Z=R30(R31) 0..63 -64..+63 0..255 -2048..+2047 0..65535 0..7 0..63 0..31 ponteiro Faixa de Valores

Registrador fonte comum Registrador de pgina superior Registrador gmeo Registrador de ponteiro Registrador de deslocamento Constante ponteiro Distncia de salto condicional Constante de 8 bits Distncia de salto relativo Endereo de 16 bits Posio do bit Porta comum Porta de pgina inferior

Você também pode gostar