Programando – HCS08
Instruções básicas e programação
Programação ASSEMBLER: Para programar devemos lembrar que o
processador HCS08 possui 2 registradores: A => Acumulador de 8 bits H:X => registrador de bits
Acum.
H X
Zerando registradores Existem instruções explícitas para zerar os
registradores: CLRA; A = 0 CLRX; X = 0 CLRH; H = 0
O que segue o ponto-vírgula é comentário
Não é necessário usar o ‘;’Somente se for fazer comentário
Carregando nos registradores... Carrega algo no Acum.
LDA #10 ; A = 10 LDA var ; A = var, onde var é um end. de memória LDX #10 ; X = 10 LDX var ; X = var LDHX var ; H:X = mem[var] : mem[var] +1
Lembrando que H e X são cada um de 8 bits. H receberá a posição de memória onde está ‘var’; X receberá a posição de memória seguinte... Como se fosse uma
variável de 16 bits
H X
M[var] M[var+1]
Salvando os registradores Instruções para salvar o acumulador:
STA var ; var = A ou ‘var’ recebe o Acum. STA PTAD ; porta A = A STX var ; var = X STHXvar ; var = H e var+1 = X
‘var +1’ é a posição de memória seguinte à ‘var’
Instruções básicas As operações são sempre com os
registradores. Ex. soma sem carry
ADD #5 ; A = A + 5
Constantes Versus End. De Memória Quando se quer operar com constantes,
deve-se usar o símbolo ‘#’. Se não for usado o ‘#’, o compilador entende
como uma posição de memória.
Ex. ADD #80 ; A = A + 80 Ex. ADD 80 ; A = A + Mem[80]
‘#’ Indica que é uma constante
Sem ‘#’ Indica que é uma posição de memória
Formatos de números O compilador usa $ e % para representar
número sem Hexadecimal e binário, respectivamente. Ex. ADD #10 ; A = A + 10, em decimal Ex. ADD #$A ; A = A + 10, em hexadecimal Ex. ADD #%00001010 ; A = A+10 em binário
Então $ = hexadeximal % = binário
Outras funções Agora que já sabemos os formatos de números usados, vejamos
algumas instruções básicas. Já conhecemos a soma sem carry
Ex. ADD #5 ;A = A+5 No Reference Manual (pág. 157), tem-se a figura abaixo.
Aprendamos a interpretar:
Operação
O que faz: (A = A + operando que pode ser imediato (número) ou memória
Número de clocks gasto
Detalhando um pouco maisSoma um imediato no Acum. Ex. ADD #6
Soma um end. de mem. de 8 bits no Acum. Ex. ADD $80
Soma um end. de mem. de 16 bits no Acum. Ex. ADD $A1BC
Forma usada para trabalhar com vetor.Ex. Caso queira carregar o acumulador com a variável B[10]
CLRHLDX #10 ; X = 10ADD B,X ; A = A+B[x], ou A = A + B[10]
No exemplo acima, a var. B é como se fosse um ponteiro, que Indica uma posição de memória.X é o deslocamento a partir do endereço de B.
INSTRUÇÕES A lista completa de instruções está na
manual de referência, pg 157 em diante.
VOCÊ DEVE TER O MANUAL E CONSULTÁ-LO
PARA VER AS INSTRUÇÕES.
Vejamos outras funções Soma com carry
Ex. ADC var ; A = A + var + carry ADC #5 ; A = A + 5 + carry
Subtração Ex. SUB var ; A = A – var SUB #$F ; A = A - 15
Operações Lógicas Lógica AND (bit a bit)
Ex. AND #2 ; A = A and (0000 0010) Neste exemplo, se inicialmente A = 0000 0111, A 0000 0111 AND 0000 0010 Resulta 0000 0010, que é feito ‘and’ bit a bit
Outras instruções lógicas Lógica OR
Ex. ORA #7 ; A = A or 0000 0111 Lógica XOR
Ex. EOR #3 ; A = A xor 0000 0011 Complemento de 1
COMA ; COM var ; COMX ;
Outras instruções aritméticas Incremento
Ex. INCA ; A = A +1 Ex. INCX ; X = X+1 Ex. INC var ; var = var +1
Decremento DECA ; A = A -1 DECX ; X = X -1 DEC var ; var = var -1.
Somente para endereços de 8 bits...
Funções de desvio Desvios incondicionais
JMP algum_lugar ; pula pra algum_lugar
BRA L1 ; pula pra L1
Loop: LDA #10INCASTA varJMP Loop
Loop: LDA #10INCASTA varBRA Loop
BRA somente pula pra um local
próximo de onde está.
Multiplicação HCS08 possui multiplicação por hardware.
Vejamos o manual:
Faz o produto de X *A. Como X e A são de 8 bits, o resultado é de 16
bits. A parte alta fica em X ,e a parte baixa em A.X
A
AX
*
Multiplicação Vejamos um exemplo.
Leia a porta A e multiplique o valor por 10. A seguir, quarde o resultado em R_alto e R_baixo
Loop: LDA PTAD ;A = Porta ALDX #10 ;X = 10MUL ; faz o produtoSTX R_alto ; salva X em R_altoSTA R_baixo ; salva A em R_baixoJMP Loop ; pula pra Loop
Trabalhando com bits Setar um bit (posições de memória de 8 bits)
BSET 3,PTAD ; PTAD[3] = 1
Zerar um bit BCLR5,PTAD ; PTAD[5] = 0
BCLR7,var ; var[7] = 0
Setar Bit 3 Da porta A
Zerar Bit 5 Da porta A
Testes (IF) Várias instruções de desvio condicional
podem ser usadas. A maioria dos testes é feita, considerando-se
os bits de flag do CCR – ver p. 148.
Testes Desvia se bit for 1
BRSET 3, PTAD, L1
Ex.
Branch if set‘se for 1’
Bit3 da porta A
Então vai pra L1;Senão, segue na próxima linha
BRSET 3,PTAD,L1ADD #3JMP Fim
L1: SUB #5Fim:
Se PTA[3] = 1, então faz A = A – 5 senão, faz A = A + 3
Testes Desvia se bit for 0
BRCLR 3, PTAD, L1
Ex.
Branch if set‘se for 0’
Bit3 da porta A
Então vai pra L1;Senão, segue na próxima linha
BRCLR 3,PTAD,L1ADD #3JMP Fim
L1: SUB #5Fim:
Se PTA[3] = 0, então faz A = A – 5 senão, faz A = A + 3
Desvia se Z=1 Z é um bit do ccr, que fica =1 sempre que o resultado de uma operação for zero. Ex. CLRA; A = 0. Como o resultado deu zero, então Z=1
Testes
LDA var ; A = varSUB #3 ; A = A - 3BEQ Fim ; se ultimo resultado deu zero, vai pra FIMSUB #5 ; senão, A = A -5
Fim:
Testes Desvia se deu overflow (carry = 1)
Desvia se o resultado da última operação foi maior que zero
BCS Fim ; se carry =1, vai pra FIMSUB #5 ; senão, A = A -5
Fim:
BGT Fim ; se última op. deu > 0, vai pra FIMSUB #5 ; senão, A = A -5
Fim:
Testes Desvia se o resultado da última operação foi
maior ou igual a zero
Compara acumulador com número ou mem
BGE Fim ; se última op >= 0, vai pra FIMSUB #5 ; senão, A = A -5
Fim:
CBEQA $3,Fim ; se a=3, vai pra FIMSUB #5 ; senão, A = A -5
Fim:
CBEQA var,Fim ; se a=var, vai pra FIMSUB #5 ; senão, A = A -5
Fim:CBEQ = Compare and bra
nch if equal
Trabalhando com as PORTAS Em DSPs e Microcontroladores, os pinos de
entrada/saída são tratados como PORTAS. Sinais elétricos, na forma binária, são lidos e
escritos diretamente nas PORTAS.
Isso só pode ocorrer se a PORTA A for configurada como entrada.
LDA PTAD ; Acum. Recebe o valor digital da PORTA A
PORTAS Para ler um valor de uma porta, a porta deve
ser configurada como entrada. Para escrever em uma porta, ela deve ser
configurada como saída. Existe um registrador que define a direção
dos dados para cada porta. É o registrador de Direção de Dados
Ex. PTADD ; porta A Data Direction PTBDD ; porta B Data Direction e assim por diante, em todas as portas.
Portas
Exemplo de pinos ePortas em um
microcontrolador
PORTAS Por padrão, todas as portas são
consideradas entradas, no microcontrolador. Assim sendo, os pinos ficam em alta
impedância e aceitam que outros circuitos escrevam (0s ou 1s) na porta.
Isso evita que ocorra um curto-ciruito, ao inicializar o microcontrolador.
PORTAS Para definir um bit de uma porta como
entrada, o registrador de Direção de Dados daquele bit deve ser colocado em 1.
Para ser definido com saída, deve ser colocado em 0.
1 = Saída;0 = Entrada;
PORTAS Exemplos
MOV #%00000000,PTADD ; todos os bits de PTA são entradaMOV #$FF,PTBDD ; todos os bits de PTB são saídaMOV #%00001111,PTCDD ; PTC[7..4] = out e PTC[3..0] = in
1 = Saída;0 = Entrada;
PORTAS Valores das portas
Um registrador de dados armazena o valor a ser lido/escrito.
Ex.
MOV #0,PTADD ; todos os bits de PTA são entradaMOV #$FF,PTBDD ; todos os bits de PTB são saídaLDA PTAD ; A = PTASTA PTBD ; PTB = A
Data direction
Dado
Lê os sinais digitais, nos pinos do chip
Escreve os sinais digitais nos pinos do chip
Exercício Fazer um programa que fique lendo
ciclicamente um valor na porta A e armazene-o em uma variável chamada a.
Logo após, escreva na porta B o valor de a+10.
ORG RAMStartA rmb 1 ; define uma var. de 1 byte
ORG ROMStartMAIN: clra ;limpa o acumulador
MOV #$FF, PTBDD ;Porta B é saídaMOV #$00, PTADD ;Porta A é entradaSEI ;desliga interrupções
Loop: LDA PTAD ; Acum. <= Porta ASTA A ; var. A recebe AcumuladorADD #10 ; Acum. <= Acum. + 10STA PTBD ; Porta B <= AcumuladorJMP Loop ; retorna ao Loop
ORG é diretiva de compilador: coloca o código abaixona posição de memória reservada:
às variáveisao programa
Compilador é muito chato.... Cuide os espaçamentos de coluna... Senão não compila:Labels e variáveis na coluna 1.....Código tem q ser recuado....
Exercício 2 Fazer um programa que fique lendo
ciclicamente um valor na porta A e armazene-o em uma variável chamada a.
Logo após, escreva na porta B o valor de a*9-7.
Exercício 3 Ler um valor em um teclado (na porta B) e escrevê-
lo na porta A. O número de entrada fica entre 0 e 9. O esquema do teclado é o seguinte:
Considere que os pull-ups das entradasDevem estar ligados.
1 2 3
4 5 6
7 8 9
* 0 #
B0
B1
B2
B3
B4 B5 B6
Inputs
Out
puts
Exercício 4 Ler um valor em um teclado (na porta B) e escrevê-
lo na porta A. O número de entrada é composto de 2 algarismos. O esquema do teclado é o seguinte:
Considere que os pull-ups das entradasDevem estar ligados.
1 2 3
4 5 6
7 8 9
* 0 #
B0
B1
B2
B3
B4 B5 B6
Inputs
Out
puts
Conversor A/D Grandezas analógicas, do mundo real, como
Temperatura (T), Pressão (P), Corrente (I), Tensão (V), etc Devem ser todas passadas para tensão, para
serem lidas por um microcontrolador. Além disso, deve-se ter cuidado para que a
conversão fique em um intervalo que o conversor A/D trabalhe. Tipicamente, entre 0V e 5V ou 0V e 3.3V... Depende do controlador.
Conversor A/D Por exemplo: Se você quer ler uma tensão
que varia entre 0 e 400V, um divisor resistivo é suficiente, tal como apresentado abaixo. Deve-se calcular R1 e R2, de forma que a tensão
em R2 não ultrapasse 3.3V.
Conversor A/D O HCS08 possui um conversor A/D de
aproximações sucessivas, de 12 bits. O conversor tem a entrada multiplexada, ou
seja, 28 entradas podem ser ligadas no conversor A/D, mas somente 1 pode ser efetuada, cada vez.
Conversor A/D
Conversor A/D
As conversões são feitas entre os valores de referência máximo VREFH e mínimo VREFL .
O valor convertido terá uma representação linear entre 0 e 4096 (12bits) entre as referências.
Conversor A/D
Veja um exemplo, no gráfico abaixo, supondo as referencias em 0V e 3.3V:
4096
0 0V
3.3V
Vin = 1V1241
Uma tensão de 1V seria lida como o número 1241, nas escalas de referência.
Configurando o A/D Registrador de Configuração: ADCCFG
Low Power: Configuração de velocidade/potência0 : alta velocidade1: baixo consumo
Divisor do clockPre-scaler de divisão do clock.
Configurando o A/D Registrador de Configuração: ADCCFG
Long Sample Mode: Configuração de tempo de amostragem do sinal0 : amostra de tempo curta;1: amostra de tempo longa.
Modo de 8, 10 ou 12 bits00: 8 bits01: 12 bits10: 10 bits
Fonte do clock00: Barramento interno01: Barramento interno 210: Clock alternativo (ALTCLK)11: Clock assíncrono (ADACK)
Configurando o A/D Registrador de Configuração: ADCCFG
Por padrão, se não mexer neste registrador, terás: Conver~soa rápida, Clock interno Tempo de amostra curto 8 bits
Se quiser ter conversão de 12bits, faça:
MAIN: MOV #%00000100,ADCCFG
O registrador ADCSC1 controla o conversor da seguinte forma:
Conversão Completa: Bit que indica quando uma conversão terminou0: não terminou;1: Conversão terminou. Este bit é zerado quando o resultado da conversão for lido.... Daí fica pronto para outra conversão.
Configurando o Conversor A/D
Conversão Contínua: 0 : faz somente uma conversão, qdo se escrever em ADCSC1;1: faz conversões sucessivas. Termina uma e começa outra, imediatamente.
Interrupt Enable0: após conversão, não gera interrupção.1: após conversão, gera interrupção.
Configurando o Conversor A/D
Channel Select: Seleciona o canal a ser convertido, conforme tabela abaixo
E o resultado? O resultado da conversão fica em dois
registradores ADCRH, ADCRL. Como o resultado tem 12 bits, deve ser
armazenado em 2 registradores:
ADCRLADCRH
8 bits8 bits
Exemplo Ler um valor analógico no pino AD0, e
armazená-lo.ORG RAMStart
resultado rmb 2 ; define uma var. de 2 bytes
ORG ROMStartMAIN: SEI ; desliga interrupçõesLoop: MOV #%00000100,ADCCFG ; 12 bits
MOV #%00000000,ADCSC1 ; configura e começa a conv.
BRCLR 7,ADCSC1, * ;enquanto ADCSC1[7] = 0;pula pra mesma linha
LDA ADCRH ;acum <= parte altaSTA resultado ;resultado <= acumLDA ADCRL ;acum <= parte baixaSTA resultado+1 ;resultado+1 <= acumLoop ; retorna ao Loop
Canal A0
Só uma conversãoSem interrupções Espera conversão terminar... Quando terminar, bit 7 vai pra ‘1’
Exemplo 2 Ler um valor analógico na porta A0, e
armazená-lo. ORG RAMStart
resultado rmb 2 ; define uma var. de 2 bytes
ORG ROMStartMAIN: SEI ; desliga interrupções MOV #%00000100,ADCCFG ; 12 bits
MOV #%00100000,ADCSC1 ; configura e começa a conv.
Loop: BRCLR 7,ADCSC1, * ;enquanto ADCSC1[7] = 0;pula pra mesma linha
LDA ADCRH ;acum <= parte altaSTA resultado ;resultado <= acumLDA ADCRL ;acum <= parte baixaSTA resultado+1 ;resultado+1 <= acumLoop ; retorna ao Loop
Canal A0
Conversão contínua
Sem interrupçõesEspera conversão terminar...
Quando terminar, bit 7 vai pra ‘1’Com conv. Contínua, o Loop mudou pra cá!
Lê resultado e já começa
outra conversão.
Exemplo 3 Ler um valor analógico na porta A0, e
armazená-lo. Use interrupção.ORG RAMStart
resultado rmb 2 ; define uma var. de 2 bytes
ORG ROMStartMAIN: CLI ; Habilita interrupções
MOV #%00000100,ADCCFG ; 12 bitsMOV #%01100000,ADCSC1 ; configura e começa a conv.
Loop: JMP Loop ; espera gerar uma interrupção
INT_ADC:LDA ADCRH ;acum <= parte altaSTA resultado ;resultado <= acumLDA ADCRL ;acum <= parte baixaSTA resultado+1 ;resultado+1 <= acumRTI
Canal A0
Conversão contínua
Liga interrupções Com int. ligadas, qdo COCO ficar nível alto, irá gerar uma interrupção.
Exercícios: 1.Leia 2 valores analógicos, e escreva o
menor deles em uma saída digital (portas C e D – lembre que são 12bits).
2. Um sinal de tensão entre 0 e 100V foi ajustado para ser lido no A/D do microcontrolador. Leia o valor, e mostre-o em uma saída digital (porta B). O valor lido ficará entre 0 e 4096... Ajuste-o para
representar entre 0V e 100V.
Recommended