Você está na página 1de 19

“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. Ref [1] item
6.

1.a. Quais podem ser os registradores Rd e Rr?


Rd = R0, R1, R2, ..., R31 ; Rr= R0, R1, R2, ..., R31

1.b. Formate a instrução ADD para que some os conteúdos dos registradores R16 e R17. Onde
é armazenado o resultado?

ADD R16,R17 ; R16 ←R16+R17

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. Ref [1] item 73.

1.c. No caso da instrução LDI quais registradores podem assumir o papel de Rd?
Do R16 ao R31
1.d. Qual é a faixa de valores para a constante K?
A constante K está na faixa de 0 a 255 (00000000 – 11111111), pois tem 8 bits.

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. Ref [1] item 79.
Programa 1
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 LDI R16,253 ; R16 = 253 R16 ← 253
2 LDI R17,1 ; R17 = 1 R17 ← 1
3 ADD R17,R16 ; R17 = R17+R16 R17 ← R17+R16
4 MOV R18,R17 ; R18 = R17 R18 ← R17
5 FIM: RJMP FIM ; Ref [1] item 94.

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.
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 Ref [1]
item 53.
2.a. Escreva em Assembly o programa o programa descrito no Algoritmo 2

Programa 2
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 LDI R16,4 ; R16 = 4 R16 ← 4
2 DEC R16 ; R16 = R16-1 R16 ← R16-1
3 DEC R16 ; R16 = R16-1 R16 ← R16-1
4 DEC R16 ; R16 = R16-1 R16 ← R16-1
5 DEC R16 ; R16 = R16-1 R16 ← R16-1
6 DEC R16 ; R16 = R16-1 R16 ← R16-1
7 FIM: RJMP FIM

2.b. Qual será o valor do conteúdo do registrador R16 ao final da execução de cada linha, 1, 2,
3, ...,6?
LINHA 1: R16= 4 (000001002)
LINHA 2: R16= 3 (000000112)
LINHA 3: R16= 2 (000000102)
LINHA 4: R16= 1 (000000012)
LINHA 5: R16= 0 (000000002)
LINHA 6: R16= -1 (111111112)
Os Microcontroladores AVR, assim como todos os demais microprocessadores e
Microcontroladores, tem circuitos associados à ALU (Arithmetic Logic Unit) 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” (ATMEL 8-BIT MICROCONTROLLER WITH 4/8/16/32KBYTES IN-SYSTEM PROGRAMMABLE FLASH DATASHEET)

I T H S V N Z C

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.
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: Ref [1] item 27.

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.


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 LDI R16,PARC_1 ; R16=5 R16 ← PARC_1
7 LDI R17, PARC_1 ;R17=7 R17 ← PARC_2
8 LDI R18, NVEZES ;R18=4 R18 ← NVEZES
9 REPITA: ADD R16,R17 ;R16=R16+R17 R16 ← R16+R17
10 DEC R18 ;R18=R18-1 R18 ← R18 - 1
11 BRNE REPITA ;SE R18<>0: Salte Se Z=0: Salte par REPITA
12 FIM: RJMP FIM

3.b. Consulte a AVR Assembler User Guide a respeito das “Directives” / Pseudo Instruções
presentes nas linhas 1 a 5. (Seção 4.5.17 Ref.[3])
.EQU : Atribui um valor a um label (rótulo) : .EQU label = expression.

.CSEG : Define o seguimento de Code (código/progrma)


.ORG : Define o contador de posições de memória; define um endereço inicial

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.
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 R26 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) 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) de uma coluna à esquerda para a próxima à direita (digamos das centenas
para os milhares). Essa instrução é: “ADC – Add with Carry” ; Ref [1] item 5
realiza a operação: Rd <- Rd + Rr + C e tem o formato: ADC Rd,Rr
4.a. Faça a soma da PAR_1 com a PAR_2:

PAR_1
R25 R24

C=1 1 1 1 1 1
0 1 1 0 0 0 0 0 0 1 1 1 0 1 1 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

PAR_1
R27 R26
0 0 0 1 0 1 1 0 1 1 0 1 0 1 1 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

RES
R29 R28
0 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

4.b) Converta os valores de PAR_1 e PAR_2 para hexadecimal e decimal.


PAR_1: 0x6076 (HEXADECIMAL) OU 24694
PAR_2: 0x16D7 OU 5847
4.c. Codifique o algoritmo 4 usando Instruções Assembly AVR

Programa 4
L LABEL INSTR. OPERANDOS COMENTÁRIOS
1 .EQU PAR_1=0x6076 ;PAR_1 = 24694
2 .EQU PAR_2=0x16D7 ;PAR_2 = 5847
3
4 .CSEG ; Segmento de Programa
5 .ORG 0
; R24=0x76 R24 ← LOW(PAR_1)
6 LDI R24,LOW(PAR_1)
;R26=0Xd7 R26 ← LOW (PAR_2)
7 LDI R26,LOW(PAR_2)
;R24 = R24+R26 R24 ← R24 + R26
8 ADD R24,R26
;R28 = R24 R28 ← R24
9 MOV R28,R24
;R25=0x60 R25 ← 0x60
10 LDI R25,HIGH(PAR_1)
;R27=0x16 R27 ← 0x16
11 LDI R27,HIGH(PAR_2)
;R25=R25+R27+C R25 ← R25+R27+C
12 ADC R25,R27
;R29=R25 R29 ← R25
13 MOV R29,R25
14 FIM: RJMP FIM
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
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
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-3s)? 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
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

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?
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.
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


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
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.
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?
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
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://academy.cba.mit.edu/classes/embedded_programming/doc1022.pdf

4 ATMEL 8-BIT http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-


MICROCONTROLLER WITH ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
4/8/16/32KBYTES IN-SYSTEM
PROGRAMMABLE FLASH
DATASHEET

5 Beginners Introduction to the http://www.avr-asm-download.de/beginner_en.pdf


Assembly Language of
ATMEL-AVR-Microprocessors

6 AVR Tutorials- The Best AVR http://www.avr-tutorials.com/assembly/avr-assembler-directives


Microcontroller Tutorials on the Web

7 Avrfreaks: Forum sobre http://www.avrfreaks.net/


Microcontroladores AVR

8 AVR WebRing: Forum AVR http://hub.computersninternet.org/hub/avr

9 Practical AVR Microcontrollers http://dl.hajiahmadi.ir/microcomputers/Practical%20AVR%20Microcontrollers.pdf


Games, Gadgets, and Home
Automation with the Microcontroller
Used in the Arduino

10 Arduino Cheat Sheet https://br.pinterest.com/pin/362610207473172163/

Você também pode gostar