Índice:

AVR Assembler Tutorial 1: 5 Steps
AVR Assembler Tutorial 1: 5 Steps

Vídeo: AVR Assembler Tutorial 1: 5 Steps

Vídeo: AVR Assembler Tutorial 1: 5 Steps
Vídeo: AVR Assembly Tutorial: Part 1 (Basic Commands) 2024, Novembro
Anonim
AVR Assembler Tutorial 1
AVR Assembler Tutorial 1

Decidi escrever uma série de tutoriais sobre como escrever programas em linguagem assembly para o Atmega328p, que é o microcontrolador usado no Arduino. Se as pessoas continuarem interessadas, continuarei a lançar um por semana ou até que acabe o tempo livre ou então as pessoas parem de lê-los.

Estou executando o Arch linux e trabalhando em um atmega328p-pu configurado em um breadboard. Você pode fazer isso da mesma forma que eu ou simplesmente conectar um arduino ao computador e trabalhar no microcontrolador dessa forma.

Estaremos escrevendo programas para o 328p como o que está na maioria dos arduino, mas você deve notar que esses mesmos programas e técnicas também funcionarão para qualquer um dos microcontroladores Atmel e mais tarde (se houver interesse) trabalharemos com alguns dos os outros também. Os detalhes do microcontrolador podem ser encontrados nas folhas de dados Atmel e no Manual do Conjunto de Instruções. Estou anexando-os a este instrutível.

Aqui está o que você precisa:

1. Um breadboard

2. Um Arduino ou apenas o microcontrolador

3. Um computador com Linux

4. O avra assembler usando git: git clone https://github.com/Ro5bert/avra.git ou se você estiver usando ubuntu ou um sistema baseado em debian apenas digite "sudo apt install avra" e você obterá o avr assembler e avrdude. NO ENTANTO, se você obtiver a versão mais recente usando o github, também obterá todos os arquivos de inclusão necessários, em outras palavras, ele já possui os arquivos m328Pdef.inc e tn85def.inc.

5. avrdude

O conjunto completo de meus tutoriais de assembler AVR pode ser encontrado aqui:

Etapa 1: construir uma placa de teste

Construir uma placa de teste
Construir uma placa de teste

Você pode simplesmente usar seu arduino e fazer tudo nesses tutoriais se quiser. No entanto, como estamos falando sobre codificação em linguagem assembly, nossa filosofia é inerentemente remover todos os periféricos e interagir diretamente com o próprio microcontrolador. Então você não acha que seria mais divertido fazer dessa forma?

Para aqueles de vocês que concordam, você pode puxar o microcontrolador de seu arduino e, em seguida, começar construindo um "Breadboard Arduino" seguindo as instruções aqui:

Na imagem, mostro minha configuração, que consiste em dois Atmega328p independentes em uma grande placa de ensaio (quero ser capaz de manter o tutorial anterior conectado e carregado em um microcontrolador enquanto trabalho no próximo). Eu tenho a fonte de alimentação configurada de forma que o trilho superior seja de 9 V e todos os outros estejam a 5 V do regulador de tensão. Eu também uso uma placa de breakout FT232R para programar os chips. Eu os comprei e coloquei bootloaders neles, mas se você apenas puxou um de um Arduino, então está tudo bem.

Observe que se você está tentando fazer isso com um ATtiny85, você pode obter o Sparkfun Tiny Programmer aqui: https://www.sparkfun.com/products/11801# e simplesmente conectá-lo à porta USB do seu computador. Você precisará instalar um bootloader no Attiny85 primeiro e a maneira mais fácil é apenas usar o IDE do Arduino. No entanto, você precisará clicar no arquivo e nas preferências e, em seguida, adicionar este URL de novos painéis: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json que irá permitem que você instale o gerenciador de inicialização (se o seu ATtiny85 ainda não veio com um).

Etapa 2: Instale o Assembler e o Avrdude

Agora você pode baixar e instalar o assembler e o avrdude a partir dos links fornecidos na primeira etapa deste tutorial. É provável que, se você já trabalhou com o Arduino, já tenha o avrdude instalado.

Depois de instalar o avra, você notará que há um subdiretório que o acompanha chamado "fontes" e dentro desse diretório há vários arquivos de inclusão. Esses são todos os microcontroladores que você pode programar com o avra. Você perceberá imediatamente que não há nenhum arquivo para o 328p que estamos usando aqui. Eu anexei um. O nome do arquivo deve ser m328Pdef.inc e você deve colocá-lo dentro do diretório includes ou em qualquer outro lugar que desejar. Iremos incluí-lo em nossos programas de linguagem assembly. Tudo o que isso faz é dar a cada um dos registros no microcontrolador os nomes da planilha de dados para que não tenhamos que usar seus nomes hexadecimais. O arquivo de inclusão acima contém "diretivas pragma", uma vez que foi projetado para programação C e C ++. Se você se cansar de ver o montador cuspir reclamações de "ignorar a diretiva pragma", vá até o arquivo e exclua ou comente todas as linhas que começam com # pragma

Ok, agora que você tem seu microcontrolador pronto, seu montador pronto e seu programador pronto, podemos escrever nosso primeiro programa.

Nota: Se você estiver usando o ATtiny85 em vez do ATmega328P, será necessário um arquivo de inclusão diferente denominado tn85def.inc. Vou anexá-lo também (note que tive que chamá-lo de tn85def.inc.txt para que o Instructables me permitisse carregá-lo.) NO ENTANTO, se você obteve o assembler avra do github, então você já tem esses dois arquivos com ele. Portanto, recomendo obtê-lo e compilá-lo você mesmo: git clone

Etapa 3: Olá, mundo

O objetivo deste primeiro tutorial é construir o primeiro programa padrão que alguém escreve ao aprender qualquer nova linguagem ou explorar qualquer nova plataforma eletrônica. "Olá Mundo!." Em nosso caso, queremos simplesmente escrever um programa em linguagem assembly, montá-lo e enviá-lo ao nosso microcontrolador. O programa fará com que um LED acenda. Fazer com que um LED "pisque" como acontece com o programa normal hello world do Arduino é, na verdade, um programa muito mais complicado em linguagem assembly e, portanto, não faremos isso ainda. Vamos escrever o código "esqueleto" mais simples com o mínimo de detalhes desnecessários.

Primeiro conecte um LED do PB5 (veja o diagrama de pinagem), que também é chamado de Saída Digital 13 em um Arduino, a um resistor de 220 ohms e, em seguida, ao GND. Ou seja, PB5 - LED - R (220 ohm) - GND

Agora, para escrever o programa. Abra seu editor de texto favorito e crie um arquivo chamado "hello.asm"

; hello.asm

; liga um LED que está conectado a PB5 (saída digital 13).include "./m328Pdef.inc" ldi r16, 0b00100000 saída DDRB, r16 saída PortaB, r16 Iniciar: rjmp Iniciar

O acima é o código. Analisaremos linha por linha em um minuto, mas primeiro vamos ter certeza de que podemos fazer com que funcione em seu dispositivo.

Depois de criar o arquivo, em um terminal, você o monta da seguinte maneira:

avra hello.asm

isso montará seu código e criará um arquivo chamado hello.hex, que podemos carregá-lo da seguinte maneira:

avrdude -p m328p -c stk500v1 -b 57600 -P / dev / ttyUSB0 -U flash: w: hello.hex

se estiver usando um arduino de breadboard, você terá que apertar o botão reset no arduino de breadboard antes de executar o comando acima. Observe que também pode ser necessário adicionar um sudo na frente ou executá-lo como root. Observe também que em alguns arduino (como o Arduino UNO) você provavelmente terá que alterar a taxa de bits para -b 115200 e a porta -P / dev / ttyACM0 (se você receber um erro de avrdude sobre uma assinatura de dispositivo inválida, basta adicionar um - F ao comando)

Se tudo funcionou como deveria, você terá agora um LED aceso….. "Hello World!"

Se você estiver usando o ATtiny85, o comando avrdude será:

avrdude -p attiny85 -c usbtiny -U flash: w: hello.hex

Etapa 4: Hello.asm linha por linha

Para terminar este tutorial introdutório, examinaremos o programa hello.asm linha por linha para ver como ele funciona.

; hello.asm

; liga um LED que está conectado ao PB5 (saída digital 13)

Tudo após um ponto-e-vírgula é ignorado pelo montador e, portanto, essas duas primeiras linhas são simplesmente "comentários" explicando o que o programa faz.

.include "./m328Pdef.inc"

Esta linha diz ao assembler para incluir o arquivo m328Pdef.inc que você baixou. Você pode querer colocá-lo em um diretório de arquivos de inclusão semelhantes e, em seguida, alterar a linha acima para apontar para lá.

ldi r16, 0b00100000

ldi significa "carregar imediatamente" e diz ao montador para pegar um registro de trabalho, r16 neste caso, e carregar um número binário nele, 0b00100000 neste caso. O 0b à frente indica que nosso número está em binário. Se quiséssemos, poderíamos ter escolhido outra base, como hexadecimal. Nesse caso, nosso número seria 0x20, que é hexadecimal para 0b00100000. Ou poderíamos ter usado 32, que é decimal de base 10 para o mesmo número.

Exercício 1: tente mudar o número na linha acima para hexadecimal e depois decimal em seu código e verifique se ele ainda funciona em cada caso.

Usar o binário é mais simples devido à maneira como as portas e registros funcionam. Discutiremos as portas e registros do atmega328p com mais detalhes em tutoriais futuros, mas por agora apenas declararei que estamos usando r16 como nosso "registro de trabalho", o que significa que vamos usá-lo apenas como uma variável que armazenamos números em. Um "registro" é um conjunto de 8 bits. Significa 8 pontos que podem ser 0 ou 1 ('desligado' ou 'ligado'). Quando carregamos o número binário 0b00100000 no registro usando a linha acima, simplesmente armazenamos esse número no registro r16.

saída DDRB, r16

Esta linha diz ao compilador para copiar o conteúdo do registro r16 para o registro DDRB. DDRB significa "Data Direction Register B" e configura os "pinos" na PortaB. No mapa de pinagem do 328p, você pode ver que há 8 pinos identificados como PB0, PB1,…, PB7. Esses pinos representam os "bits" da "Porta B" e quando carregamos o número binário 00100000 no registro DDRB, estamos dizendo que queremos PB0, PB1, PB2, PB3, PB4, PB6 e PB7 definidos como pinos de ENTRADA, uma vez que eles têm 0 está neles, e PB5 é definido como um pino de SAÍDA, já que colocamos um 1 nesse local.

porta B, r16

Agora que fixamos as direções dos pinos, podemos definir as tensões neles. A linha acima copia o mesmo número binário de nosso registro de armazenamento r16 para o PortB. Isso define todos os pinos para 0 volts, exceto o pino PB5 para HIGH, que é de 5 volts.

Exercício 2: Pegue um multímetro digital, conecte o fio preto ao aterramento (GND) e teste cada um dos pinos PB0 a PB7 com o fio vermelho. As tensões em cada um dos pinos são exatamente aquelas correspondentes a colocar 0b00100000 na porta B? Se houver algum que não seja, por que você acha que é? (veja o mapa de alfinetes)

Começar:

rjmp Start

Finalmente, a primeira linha acima é um "rótulo" que rotula um ponto no código. Neste caso, rotular esse local como "Início". A segunda linha diz "salto relativo para o rótulo Iniciar." O resultado líquido é que o computador é colocado em um loop infinito que continua girando de volta para a Inicialização. Precisamos disso porque não podemos simplesmente terminar o programa, ou cair de um penhasco, o programa tem que continuar funcionando para que a luz fique acesa.

Exercício 3: Remova as duas linhas acima de seu código para que o programa caia de um penhasco. O que acontece? Você deve ver algo que se parece com o programa tradicional "blink" usado pelo Arduino como seu "hello world!". Por que você acha que funciona assim? (Pense no que deve acontecer quando o programa cair de um penhasco …)

Etapa 5: Conclusão

Se você chegou até aqui, parabéns! Agora você pode escrever código assembly, montá-lo e carregá-lo em seu microcontrolador.

Neste tutorial, você aprendeu como usar os seguintes comandos:

ldi hregister, number carrega um número (0-255) em uma metade superior do registrador (16-31)

fora do ioregister, register copia um número de um registro de trabalho para um registro de E / S

O rótulo rjmp salta para a linha do programa rotulado como "rótulo" (que não pode estar mais longe do que 204 instruções - ou seja, salto relativo)

Agora que esses princípios básicos estão fora do caminho, podemos continuar a escrever códigos mais interessantes e circuitos e dispositivos mais interessantes sem ter que discutir a mecânica de compilar e enviar.

Espero que você tenha gostado deste tutorial introdutório. No próximo tutorial, adicionaremos outro componente de circuito (um botão) e expandiremos nosso código para incluir portas de entrada e decisões.

Recomendado: