Escolar Documentos
Profissional Documentos
Cultura Documentos
PBL - Assembly AVR Como Atmega328P - Rev.1!1!26!03!21
PBL - Assembly AVR Como Atmega328P - Rev.1!1!26!03!21
- 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.
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.b. Formate a instrução ADD para que some os conteúdos dos registradores R16 e R17. Onde
é armazenado o resultado?
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
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
Algoritmo 3 Fluxograma 3
1 R16 ← 5
2 R17 ← 7
3 R18 ← 4
5 R18 ← R18 -1
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.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.
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
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.
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
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.
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.
1
𝐶𝑦 =
𝑓𝑜𝑠𝑐
𝑑 = 𝑛 . 𝐶𝑦
Fluxograma 6
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.
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.
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
;
;;
;; 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