1. “Problem Based Learning – PBL” / Aprendizado Baseado em Problemas
Assembly AVR com Atmega328P / Arduino UNO
- Para realizar esse estudo você deverá consultar as referências listadas no final deste
documento;
- Use o software Atmel Studio para inserção dos exemplos e programas em Linguagem Assembly
bem como, para simulação.
1. Programa que soma dois números
Um possível algoritmo para somar dois números é apresentado abaixo:
Algoritmo 1
1 Obtenha a primeira parcela
2 Obtenha segunda parcela
3 Some as duas parcelas
4 Guarde o resultado
5 Fim do programa
O objetivo central desse algoritmo é a SOMA e a Instrução Assembly AVR que realiza tal
operação é “ADD – Add without Carry” cuja operação realizada é: Rd ← Rd + Rr.
1.a. Quais podem ser os registradores Rd e Rr?
1.b. Formate a instrução ADD para que some os conteúdos dos registradores R16 e R17. Onde
é armazenado o resultado?
ADD ____, ____ ; ____ ←____+____
Sabemos como a instrução ADD opera, mas, não sabemos que valores ou conteúdos os
registradores Rd e Rr tinham. A instrução “LDI – Load Immediate” faz a carga de um registrador
com uma constante: Rd ← k. Seu formato é: LDI RD,k.
1.c. No caso da instrução LDI quais registradores podem assumir o papel de Rd?
1.d. Qual é a faixa de valores para a constante K?
1.e. Complete o programa Assembly AVR para que some os conteúdos dos registradores R16 e
R17 e armazene uma cópia do resultado em R18, para tal use a instrução “MOV – Copy Register”
cuja operação é: Rd ← Rr.
2. 1.f. Abra o Atmel Studio, crie um projeto Assembly para o Microcontrolador Atmega328P e simule
passo a passo Programa 1. Verifique o conteúdo dos registradores à medida em que a simulação
avança.
Programa 1
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 LDI R16,253 ; R16 = 253 R16 ← 253
2 ; R17 = 1 R17 ← 1
3 R17 ← R17+R16
4 R18 ← R17
5 FIM: RJMP FIM
3. 2. Programa que decrementa o conteúdo de um registrador
Algoritmo 2
1 Carregue R16 com o valor 4
2 Decremente o conteúdo de R16
3 Decremente o conteúdo de R16
4 Decremente o conteúdo de R16
5 Decremente o conteúdo de R16
6 Decremente o conteúdo de R16
7 Fim do programa
O ponto principal do Algoritmo 2 é a instrução de Decremento – “DEC – Decrement” que na
linguagem Assembly AVR tem o mnemônico: DEC Rd e realiza a operação: Rd ← Rd -1
2.a. Escreva em Assembly o programa o programa descrito no Algoritmo 2
2.b. Qual será o valor do conteúdo do registrador R16 ao final da execução de cada linha, 1, 2,
3, ...,6?
Os Microcontroladores AVR, assim como todos os demais microprocessadores e
Microcontroladores, tem circuitos associados à ALU cuja finalidade é a de monitorar ou sinalizar
certos acontecimentos – os “Flags” -. O “Zero Flag” (Z) ou “Sinalizador de Zero” é ligado quando
uma operação na ALU resultou em Zero ou desligado, caso contrário; O “Carry Flag” (C) ou
“Sinalizador de Carry/Transporte” é alterado quando ocorre um transporte do bit 7 fazendo o
papel de um “suposto bit 8”. Nos Microcontroladores AVR os “Flags” estão contidos em um
registrador especial denominado “Status Register”.
2.c. Consulte a seção 7.3 da do Data Sheet Atmega328P [4] e esquematize os oitos bits do
“Status Register”
2.d. Abra o Atmel Studio, crie um projeto Assembly para o Microcontrolador Atmega328P e
simule passo a passo Programa 2. Verifique o conteúdo do R16 bem como do “Zero Flag” (Z) à
medida em que a simulação avança. Observe que (Z) muda para a cor vermelha quando é ligado.
Programa 2
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 R16 ← 4
2 R16 ← R16-1
3
4
5
6
7 FIM: RJMP FIM
4. 3. Fazer a soma R16 = R16 + R17 o número de vezes definido em R18
Abaixo são mostrados o Algoritmo e o Fluxograma 3. Em um Fluxograma as Setas indicam a
direção do Fluxo; as Elipses definem os pontos terminais (início e fim); os Retângulos definem
as ações realizadas durante a execução do programa; e o Losango representa uma tomada de
decisão. Nesse algoritmo, compara-se o valor do registrador R18 com a constante 0 (zero). Como
resultado da comparação pode-se obter uma resposta “Sim” caso seja verdadeira (V) a avaliação
da expressão ou “Não” caso seja falsa (F).
Algoritmo 3 Fluxograma 3
1 R16 ← 5
2 R17 ← 7
3 R18 ← 4
4 R16 ← R16 + R17
5 R18 ← R18 -1
6 Se R18 <> 0 : Salte para 4
6.1 Senão: continue
7 Fim
Nos Microcontroladores AVR existem instruções para se tomar decisões em função do “Zero
Flag” (Z), do “Carry Flag” (C) ou por outros. Particularmente, a instrução “BRNE – Branch if Not
Equal” : BRNE k realiza a operação:
IF (Z = 0) : PC ← PC + 1 + k , else PC ← PC + 1
Onde: PC + 1: é o endereço da próxima instrução;
k: é o endereço (relativo) para o salto.
A instrução BRNE k, pode ser interpretada da seguinte forma: - “Se o “Zero Flag” estiver
desligado (Z=0, indicando que uma operação na ALU não resultou em zero) salte, isto é, some
“k” a PC+1. Como “k” pode ser positivo ou negativo o novo valor de PC poderá ser maior ou
menor do que era; caso contrário, isto é, Z=1 não salte, execute a próxima instrução”.
3.a. Escreva em Assembly AVR o programa referente ao Algoritmo e Fluxograma 3.
5. 3.b. Consulte a AVR Assembler User Guide a respeito das “Directives” / Pseudo Instruções
presentes nas linhas 1 a 5.
3.c. Abra o Atmel Studio, crie um projeto Assembly para o Microcontrolador Atmega328P e simule
passo a passo Programa 3. Verifique o conteúdo do R18 bem como do “Zero Flag” (Z) à medida
em que a simulação avança. Observe que (Z) muda para a cor vermelha quando é ligado.
Programa 3
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 .EQU PARC_1=5
2 .EQU PARC_2=7
3 .EQU NVEZES=4
4 .CSEG
5 .ORG 0
6 R16 ← PARC_1
7 R17 ← PARC_2
8 R18 ← NVEZES
9 REPITA: R16 ← R16+R17
10 R18 ← R18 - 1
11 Se Z=0: Salte par REPITA
12 FIM: RJMP FIM
6. 4. Somar dois números de 16 bits
Primeiramente será exposta a técnica para se somar dois números/parcelas de dezesseis bits.
Cada parcela requer dois registradores de 8 bits; A primeira parcela ou PAR_1 ocupará os
registradores R25 e R24, a segunda parcela usará os registradores R27 e R6 e o resultado será
armazenado nos registradores R29 e R28.
PAR_1
HIGH(PAR_1) LOW(PAR_1)
R25 R24
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
PAR_2
HIGH(PAR_2) LOW(PAR_2)
R27 R26
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RES
HIGH(RES) LOW(RES)
R29 R28
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Algoritmo 4
1 Obtenha LOW(PAR_1)
2 Obtenha LOW(PAR_2)
3 Some LOW(PAR_1) a LOW(PAR_2)
4 Guarde o resultado em LOW(RES)
5 Obtenha HIGH(PAR_1)
6 Obtenha HIGH(PAR_2)
7 Some HIGH(PAR_1) a HIGH(PAR_2) com (C) Carry
8 Guarde o resultado em HIGH(RES)
9 Fim do Programa
Observe a linha 7 do algoritmo 4, ela deverá fazer uso de uma instrução de adição que leva em
conta o “Carry” (C) (Transporte; vai um ou vai zero) da soma anterior. Isso pode parecer estranho
mas, segue o mesmo princípio que usamos nas somas de números decimais quando se
considera o transporte (vai um, dois, três, ..., nove) de uma coluna à esquerda para a próxima à
direita (digamos das centenas para os milhares). Essa instrução é: “ADC – Add with Carry” ;
realiza a operação: Rd <- Rd + Rr + C e tem o formato: ADC Rd,Rr
8. 5. O “Stack” ou Pilha
5.a. No data Sheet do Atmega328P, seção 7.5 há uma breve explicação sobre o “Stack” ou Pilha.
Se preciso for, use o “google translate” para lê-la. A Pilha é implementada em uma área de
memória RAM interna. O nome pilha refere-se à analogia que se faz com pilhas de objetos
(caixas, livros, etc.) na qual o último item inserido ocupa sempre o Topo da Pilha e o item a ser
retirado da pilha é sempre o do Topo. Pede-se:- Liste as instruções que usam o a Pilha.
5.b As operações elementares realizadas na Pilha são: Empilhar ou inserir dados na pilha (“data
is pushed onto the Stack”); e Desempilhar ou retirar dados da pilha (“data is popped from the
Stack”) Consulte no data Sheet do Conjunto de Instruções as instruções das seções 90 e 89.
Instrução para Empilhar Instrução para Desempilhar
Instrução: Instrução:
Insere dado no Topo da Pilha [SP] ← rd Atualiza o Topo da Pilha SP ← SP+1
Atualiza o Topo da Pilha SP ← SP-1 Retira dado do Topo da Pilha rd ← [SP]
5.c (RESOLVIDO) O registrado SP (“Stack Pointer” ou Apontador/Ponteiro da Pilha) deve ser
carregado com um endereço de memória RAM (normalmente usa-se RAMEND, que significa o
último endereço da memória RAM). Suponha que SP = 0x08FF; R16 = 0x01; R17=0x24;
R18=0xA9. O prefixo “0x” especifica base 16 ou hexadecimal. Esquematize a Pilha ao final da
execução das instruções: PUSH R16, PUSH R17, PUSH R18.
0x08FB ?? 0x08FB ?? 0x08FB ?? SP→ 0x08FB ??
0x08FC ?? 0x08FC ?? SP→ 0x08FC ?? 0x08FC A9
0x08FD ?? SP→ 0x08FD ?? 0x08FD 24 0x08FD 24
SP→ 0x08FF ?? 0x08FF 01 0x08FF 01 0x08FF 01
5.e. Nas seções 91 e 92 são apresentadas as instruções RCALL e RET. A primeira é usada para
Chamar uma Sub-rotina e a segunda para retornar dela. A instrução RCALL empilha o endereço
de retorno (o endereço da próxima instrução) e realiza o equivalente a um Salto/Jump para o
endereço da Sub-rotina. A instrução RET faz o inverso, desempilha o endereço de retorno e faz
um Salto/Jump para tal endereço. Esquematize a pilha (de forma semelhante à do item 5.d) para
demonstrar o que acontece quando o trecho de programa abaixo e executado. Considere
SP=0x08FF; R16 = 0x42
Programa 5
ENDEREÇO LABEL INSTRUÇÃO OPERANDOS COMENTÁRIO
0005 LOOP: PUSH R16
0006 RCALL FUNC_1 ; (1)
0008 POP R16
RJMP LOOP
0123 FUNC_1: NOP
0124 RCALL FUNC_2 ; (2)
0126 RET
0137 FUNC_2: NOP
0138 RET
9. 0x08F9 ?? 0x08F9 0x08F9 0x08F9
0x08FA ?? 0x08FA 0x08FA 0x08FA
0x08FB ?? 0x08FB 0x08FB 0x08FB
0x08FC ?? 0x08FC 0x08FC 0x08FC
0x08FD ?? 0x08FD 0x08FD 0x08FD
SP→ 0x08FF ?? 0x08FF 0x08FF 0x08FF
Vazia PUSH R16 RCALL(1) RCALL (2)
0x08F9 0x08F9 0x08F9 0x08F9
0x08FA 0x08FA 0x08FA 0x08FA
0x08FB 0x08FB 0x08FB 0x08FB
0x08FC 0x08FC 0x08FC 0x08FC
0x08FD 0x08FD 0x08FD 0x08FD
0x08FF 0x08FF 0x08FF 0x08FF
RET RET POP R16 RET
5.e. Visualize a dinâmica das chamadas e retornos de Sub Rotinas simulando o seguinte trecho
de programa no Atmel Studio. Para isso deverá ser criado um projeto Assembler; a simulação
deverá ser feita usando o comando “Step Into”.
Programa 5
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 .CSEG ; Segmento de Programa
2
3 LDI R16,LOW(RAMEND) ; Inicializa “Stack Pointer” / Apontador de Pilha
4 OUT SPL,R16
5 LDI R16,HIGH(RAMEND) ; para o último endereço da RAM interna
6 OUT SPH,R16
7 LOOP: LDI R16,3 ; Ajusta parâmetro para SUBR1
8 RCALL SUBR1 ; Chama Sub Rotina 1: SUBR1
9 LDI R16,2 ; Ajusta parâmetro para SUBR1
10 RCALL SUBR1 ; Chama Sub Rotina 1: SUBR1
11 RJMP LOOP ; Voltar ao início do programa
12
13 SUBR1: NOP ; Sub Rotina 1
14 REPEAT: PUSH R16 ; Salva R16 na Pilha
15 RCALL SUBR2 ; Chama Sub Rotina 2: SUBR2
16 POP R16 ; Restaura R16 da Pilha
17 DEC R16 ; Decrementa R16
18 BRNE REPEAT ; Repita enquanto R16 for diferente de zero
19 RET ; Retorna ao endereço da Instrução da linha 7/9
20
21 SUBR2: NOP ; Sub Rotina 2
22 ADD R16,R16 ; Altera R16
23 RET ; Retorna ao endereço da Instrução da linha 14
10. 6. Temporização ou “Delay” por Software
Cada Instrução AVR Assembly requer uma quantidade de Ciclos de Clock (oscilador de onda
quadrada usado para sincronizar as operações dos circuitos digitais) para ser buscada
decodificada e executada.
No Sistema Alvo (Arduino UNO) a frequência do Clock é de 16 MHz (16x106
Hz):
fosc = 16 MHz
6.a. Consulte o documento – “Atmel AVR 8-bit Instruction Set” e tome nota de quantos Ciclos
(Cycles ou Cy) cada uma das instruções listadas abaixo requer. Algumas tem seus Ciclos
variáveis em função de ocorrer ou não um desvio condicional; outras apresentam notas que
podem modificar a contagem desses Ciclos. NOP, LDI, DEC, MOV, ADD, RJMP, RCALL, RET,
BRNE, BRE, SBI, CBI, SBIS, SBIC.
A unidade básica de temporização é o Cy :
𝐶𝑦 =
1
𝑓𝑜𝑠𝑐
O “delay” (d) é conseguido repetindo-se um Cy por n vezes:
𝑑 = 𝑛 . 𝐶 𝑦
6.b. Quantos Cy são necessários para se temporizar 1 ms (0,001 s ou 1x10-3
s)? Um registrador
tem 8 bits: 28
=256.
No Programa e Fluxograma 6, é apresentada uma técnica para aumentar o número de Ciclos
sem que para isso seja necessário aumentar a quantidade de instruções. Nas linhas 14 a 17,
está um trecho de programa que realiza uma temporização em função do valor de “N”. O valor
de “N” é definido na linha 1 pela diretiva ou Pseudo Instrução .EQU. Na seção de comentários
das linhas 14 a 17 está a correlação entre cada linha deste trecho com os blocos do Fluxograma
5. O cálculo de tempo gasto pela sub-rotina “Delay” é feito da seguinte forma:
Delay = 1.Cy + (N . Cy) + [(N-1). 2.Cy] + (1.Cy) + 4. Cy
Delay = 1.Cy + N.Cy + 2.N.Cy – 2.Cy + 1.Cy + 4.Cy
Delay = 4.Cy + 3.N.Cy
Delay = (4+3.N).Cy
Delay = (4+3.N).1/fosc
11. Fluxograma 6
Forma usada para Sub-rotinas
6.c. Qual a faixa de valores para “N”? O que acontece na sub-rotina “Delay” se N=0?
6.d. Para N=255 e fosc = 16 MHz, quanto tempo gasta a sub-rotina “Delay”?
6.e. Crie um projeto Assembly no Atmel Studio para o Microcontrolador Atmega328P, digite o
Programa 5.. Faça a simulação usando a opção “Step Into” e “Step Over”
6.f. Qual é o número inteiro para “N” que gera uma frequência de oscilação no pino PD7 de
aproximadamente 15 KHz?
Programa 6
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 .EQU N=4
2 .CSEG ; Segmento de Programa
3 LDI R16,LOW(RAMEND) ; Inicializa “Stack Pointer” / Apontador de Pilha
4 OUT SPL,R16
5 LDI R16,HIGH(RAMEND) ; para o último endereço da RAM interna
6 OUT SPH,R16
7 SBI DDRD,7 ; PD7: SAÍDA
8 LOOP: CBI PORTD,7 ; PD7 = ‘1’
9 RCALL Delay ; Temporiza
10 SBI PORD,7 ; PD7 = ‘0’
11 RCALL Delay ; Temporiza
12 RJMP LOOP ; REPETIR
13
14 Delay: LDI R16, N ; 1: 1Cy
15 DLY_1: DEC R16 ; 2: 1Cy
16 BRNE DLY_1 ; 3: 2Cy (Saltar) / 4: 1Cy (Seguir adiante)
17 RET ; 5: 4Cy
12. 7. Ler Push-button e ativar LED
Para se acionar um LED, deve-se inserir um Resistor limitador de corrente em serie com o
mesmo. A menos que se adquiram os LEDs a partir de um código de fabricante, mediante
catálogos, fica difícil apenas pela observação saber suas características elétricas: VLED e ILED.
Analisando a malha de um LED, pela 2ª. Lei de Kirchhoff, temos que : “ O somatório da elevações
de potencial é igual ao somatório da quedas de pontencial ao longo de uma malha”. Para Vcc =
5V , VLED = 2 V e ILED = 10 mA, calcule R.
𝑉𝑐𝑐 = 𝑅 . 𝐼𝐿𝐸𝐷 + 𝑉𝐿𝐸𝐷
7.a. Calcule ILED para o resistor recebido para ILED= 10mA .
7.b. Qual será ILED para R = 470 Ω ?
Será usado o sistema de desenvolvimento denominado Arduíno Uno o qual, tem por
Microntrolador principal o ATmega328P, Figura 7.1a. Esse Microcontrolador do fabricante Atmel
é um dos muitos implementados sob a arquitetura AVR. Os pinos do Microcontrolador podem
ser acessados pelos conectores da placa do Arduíno UNO , Figura 7.1b.
(a)
(b)
Figura 7.1: (a) Microcontrolador; (b) Arduino Uno
O ATmega328P contém três portas digitais de entrada e saída programáveis: PORTB (PB0-
PB5), PORTC (PC0-PC5) e PORTD (PD0-PD7).
A estrutura funcional de cada bit de uma porta pode ser vista na Figura 7.2. A direção de cada
Pino é regida por três Registradores de função especial: DDR (Data Direction Register) , PORT
e PIN. O Registrador DDR define a direção: ‘1’ para Saída / ‘0’ para Entrada Digital; O Registrador
PORT é usado para se “escrever”/ ”gravar” no pino ou para ativar o Resistor de Pull-Up interno
(R) se esse pino for entrada; O Registrador PIN serve para se “ler” o “status” ou nível lógico do
pino de uma dada porta.
13. Figura 7.2: Estrutura de Pino de Porta
Os pinos das Portas podem ter suas direções definidas individualmente ou em conjunto.
7.c. As instruções SBI A,b e CBI A,b servem respectivamente para Ligar / “Set” e Deligar / “Clear”
um bit “b” no Registrador designado pelo campo “A”. Consulte essas instruções no Data Sheet
do Conjunto de Instruções
7.d. Monte o circuito da Figura 7.3b
7.d. Configure o Atmel Stdudio para que possa gravar no Arduino. Para isso foi escrito um tutorial
(está no portal) chamado “Tutorial – Gravar Arduino com Atmel Studio 7.pdf”. É muito importante
ajustar a porta serial corretamente.
7.f. Crie um projeto Assembly no Atmel Studio;copie o Programa 7; realize a montagem/ “Build”;
Carregue/Grave esse programa no Arduino (Tools -> Gravar Arduino) programa em Assembly
monitore o push-button e acenda/apage o LED conferme for pressionado/despressionado. O pino
PD7 será programado para operar com saída e o pino PB0 como entrada.
Figura 7.3 (a) Representação da montagem (b) Circuito feito no Fritzing
14. Programa 7
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 SBI DDRD, PD7 ; PD7 CONFIG. SAÍDA :DDRD.7 = 1
2 CBI DDRB, PB0 ; PB0 CONFIG. ENTRADA
3 SBI PORTB,PB0 ; LIGA RESISTOR PULL-UP
4 ChkButton: SBIC PINB,PB0 ; LE PINO DE ENTRADA: SKIP/PULE SE PB0 = 0
5 RJMP DESLLED ; PB0 = 1, SALTE PARA DESLIGAR
6 LIGALED: SBI PORTD,PD7 ; LIGUE O LED
7 RJMP ChkButton ; VOLTA A VERIFICAR O BOTÃO
8 DESLLED: CBI PORTD,PD7 ; DESLIGUE O LED
15. 8. Acionamento de Display de 7 Segmentos
Display de 7 Segmentos
Esses displays poder ter seus LEDs internos conectados na configuração Ânodo-comum ou
Cátodo-Comum. A Figura 1 exemplifica o Display de 7 Segmentos do tipo Ânodo-
comum.Lembre-se que um LED é um Diodo Emissor de Luz (Light Emitting Diode) e como tal,
tem polaridade. No Display Cátodo-comum ao terminal (8) ou (3) deve ser ligado o Gnd (negativo)
pois todos os seus Cátodos estão ligados nesse ponto comum.
Figura 8:1 (a) Circuito interno (b) Aspecto de um Display de 7 Segmentos Ânodo Comum
8.1 Monte o circuito da Figura 8.2. Certifique-se de que o display seja anodo comum, caso
contrário terminal (3) deverá ser ligado ao GND. Os pinos de 7 a 1 do conector do Arduino
correspondem à porta D (PORTD) , veja Figura 7.1b.
8.2 Quais pinos da PORTD acionam quais segmentos dos Display?
8.3 Faça o Fluxograma da Sub-rotina D500ms.
8.4 Equacione em função do valor carregado em R16 e do valor carregado ao par de
registradores R25 R24; considerando-se Fosc= 16 MHz quanto tempo a Sub-rotina
D500ms leva para ser executada.
16. Programa 8.1
;
; Disp7SegAsm.asm
;
; Created: 06/10/2016 08:16:47
; Author : Manoel
;
;; Conectores ARDUINO UNO
;; 7 6 5 4 3 2 1 0
;; Segmentos do Display 7 Segmentos
;; a b c d e f g -
;; Pinos do PORTD
;; 7 6 5 4 3 2 1
;; Iniciliza Stack Pointer
LDI R16,HIGH(RAMEND) ; Obtem parte alta do último endereço da RAM
OUT SPH,R16 ; Carrega na parte alta de Stack Pointer
LDI R16,LOW(RAMEND) ; Obtem parte baixa do último endereço da RAM
OUT SPL,R16 ; Carrega na parte baixa de Stack Pointer
;; Programa PORTD para atuar como porta de Saída
LDI R16,0b11111111 ; ajusta todos os bits em nível lógico 1
OUT DDRD,R16 ; Programa todos os bits de PORTD como saída
REPITA:
LDI R16,0b11111100 ; abcdefg-
COM R16 ; para display Anodo-comum: R16 <-- /R16
OUT PORTD,R16
RCALL D1000mS ; Chama Sub rotina para temporizar 1000 ms ( 1s )
LDI R16,0b01100000 ; abcdefg-
COM R16 ; para display Anodo-comum: R16 <-- /R16
OUT PORTD,R16
RCALL D1000mS ; Chama Sub rotina para temporizar 1000 ms ( 1s )
RJMP REPITA
;;
;; Sub rotina para temporizar 1000 ms
;;
D1000mS:
RCALL D500ms ; Chama Sub rotina para temporizar 500 ms ( 0,5 s)
RCALL D500ms ; Chama Sub rotina para temporizar 500 ms ( 0,5 s)
RET
;;
;; Sub rotina para temporizar 500 ms
;;
D500ms:
LDI R16,50 ; Número de vezes a executar o Loop Externo (LOOPE)
LOOPE: LDI R24,LOW(25535) ; Número de Vezes a executar o Loop Interno (LOOPI)
LDI R25,HIGH(25535) ; R25 = 0x63 , R24 = 0xBF
LOOPI: ADIW R24,1 ; Soma 1 unidade ao par R25,R24
BRNE LOOPI ; Se Z=0, salte
DEC R16 ; caso contrário, decremente R16
BRNE LOOPE ; salte se R16 nao chegou ao valor zero
RET
8.5 Estude o Programa 8.2. Nele as Sub-rotinas D1000ms e D500ms são as mesmas do
Programa 8.1 mas, foram omitidas por questões de espaço no texto. Faça o
Fluxograma do trecho compreendido entre INICIO e RJMP INICIO
8.6 Estude a Sub-rotina “bin7seg”. Esquematize com a instrução “LPM” faz a leitura de
uma constante armazena e memória de programa. O que isso tem a ver com uma
técnica chamada “Lookup Table” ou Consulta a Tabela?
17. Programa 8.2
;
; Disp7SegCntAsm.asm
;
; Created: 06/10/2016 08:58:39
; Author : Manoel
;
;; Conectores ARDUINO UNO
;; 7 6 5 4 3 2 1 0
;; Segmentos do Display 7 Segmentos
;; a b c d e f g -
;; Pinos do PORTD
;; 7 6 5 4 3 2 1
;; Iniciliza Stack Pointer
LDI R16,HIGH(RAMEND) ; Obtem parte alta do último endereço da RAM
OUT SPH,R16 ; Carrega na parte alta de Stack Pointer
LDI R16,LOW(RAMEND) ; Obtem parte baixa do último endereço da RAM
OUT SPL,R16 ; Carrega na parte baixa de Stack Pointer
;; Programa PORTD para atuar como porta de Saída
LDI R16,0b11111111 ; Ajusta todos os bits em nível lógico 1
OUT DDRD,R16 ; Programa todos os bits de PORTD como saída
;; Programa Principal
INICIO:
LDI R16,0 ; Inicializa Contador
REPITA:
RCALL bin7Seg ; Converte contagem para 7 Segmentos
COM R17 ; Para display Anodo-comum: R17 <-- /R17
OUT PORTD,R17 ; Envie código de 7 Segmentos ao Display
RCALL D1000ms ; Temporize 1000 ms
INC R16 ; Avance a contagem
CPI R16,16 ; Compare a contagem com o valor dezesseis
BRNE REPITA ; Se R16 <> 16, Salte para REPITA
RJMP INICIO ; Caso contrário conte novamente
;;
;; Sub rotina para conversao de binário para 7 segmentos
;; obs.: Lógica Positiva ('1' acende ; '0' apaga)
;; bits 7 6 5 4 3 2 1 0
;; seg a b c d e f g -
;; O Registrador Z na realidade é o nome que se dá ao par de Registradores R30, R31
;; quando operam como um apontador (endereçador) ou ponteiro para a memória
;;
;; Entrada: R16 = numero binário de 0000 a 1111
;; Saída: R17 = código em 7 segmentos
;;
bin7Seg:
LDI ZH,HIGH(bint7SegTable << 1); Obtém parte alta do ender. da tabela
LDI ZL,LOW(bint7SegTable << 1) ; Obtém parte baixa do ender. da tabela
ANDI R16,0b00001111 ; Mascara (zera) o nibble alto
ADD ZL,R16 ; Soma índice à parte baixa do ender. da Tab.
CLR R0 ; R0 = 0
ADC ZH,R0 ; ZH = ZH + 0 + (C) . O Carry é da soma anterior
LPM R17,Z ; Le o código da Tab. e o armazena em R17
RET
.CSEG
bint7SegTable: .DB 0b10000000, 0b01000000, 0b00100000, 0b00010000, 0b00001000,
0b00000100, 0b00000010, 0b11000000, 0b01100000, 0b00110000, 0b00011000,
0b00001100,0b00000010, 0b10100000, 0b01010000, 0b00101000
18. Referências
Ref. Materiais e Links Relacionados aos Microcontroladores AVR
1 Atmel AVR 8-bit Instruction Set http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf
2 Complete Instruction Set Sumary http://www.avr-
tutorials.com/sites/default/files/Instruction%20Set%20Summary.pdf
3 AVR Assembler User Guide http://www.atmel.com/webdoc/index.html
4 ATMEL 8-BIT
MICROCONTROLLER WITH
4/8/16/32KBYTES IN-SYSTEM
PROGRAMMABLE FLASH
DATASHEET
http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-
ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
5 Beginners Introduction to the
Assembly Language of
ATMEL-AVR-Microprocessors
http://www.avr-asm-download.de/beginner_en.pdf
6 AVR Tutorials- The Best AVR
Microcontroller Tutorials on the Web
http://www.avr-tutorials.com/assembly/avr-assembler-directives
7 Avrfreaks: Forum sobre
Microcontroladores AVR
http://www.avrfreaks.net/
8 AVR WebRing: Forum AVR http://hub.computersninternet.org/hub/avr
9 Practical AVR Microcontrollers
Games, Gadgets, and Home
Automation with the Microcontroller
Used in the Arduino
http://dl.hajiahmadi.ir/microcomputers/Practical%20AVR%20Microcontrollers.pdf
10 Arduino Cheat Sheet https://br.pinterest.com/pin/362610207473172163/