MICROCONTROLADORES HOLTEK - PARTE 4


Nesta última parte da série sobre os microcontroladores Holtek HT48EXX será demonstrado o set de instruções, as interrupções, além do uso de algumas funções especiais importantes: interrupção externa, Timer/Event Couter, função Buzzer.



O QUE JÁ FOI MOSTRADO

Nas três primeiras partes, foram apresentados os seguintes itens:

- Principais características do microcontrolador Holtek;
- Ferramentas de trabalho disponíveis (Starter Kit MTP e Emulador HT ICE);
- Ambientes para desenvolvimento – software HT-IDE3000;
- Hardware interno – estrutura e arquitetura;
- Controle do stack pointer;
- Organização da memória (programa e dados);
- Registradores de uso especial;
- Pinos de I/O e seus registradores de controle;
- Circuitos de Reset;
- Circuitos de Clock.

Se você está interessado em conhecer mais sobre o microcontrolador Holtek - família HT48EXX, recomendo a leitura das partes anteriores (parte 1, parte 2 e parte 3).



SET DE INSTRUÇÕES

O set de instruções implementado para a família de microcontroladores HT48EXX possui 60 instruções que são executadas com um ou dois ciclos de máquina (ou ciclo do sistema) no microcontrolador. Por ciclo de máquina pode-se entender o período interno necessário para decodificar e executar uma determinada operação. Em alguns casos, a leitura, decodificação e execução de uma instrução cabem em um único ciclo de máquina e em outros, em dois ciclos.

Devido a sua arquitetura a família HT48EXX divide internamente o clock externo (gerado por um cristal/ressonador ou ainda uma rede RC) por "4" e o resultado desta divisão passa então a se chamar clock do sistema (FOSC/4).

Cada ciclo de máquina necessita de quatro pulsos de clock para ser executado. Assim, operando com um cristal externo de 4 Mhz, por exemplo, o clock do sistema será de 1 Mhz e um ciclo de máquina será executado a cada 1 us (T=1/F). A figura abaixo demonstra o que acabou de ser explicado.


A tabela abaixo mostra o “set” de instruções do microcontrolador Holtek, família HT48EXX. A tabela foi dividida, classificando as instruções de acordo com sua função: aritmética, de desvio, manipulação de dados, etc. No final da tabela você encontrará algumas orientações que o ajudarão a compreender melhor a mesma.

Tabela – Set de instruções Holtek HT48EXX

Mnemônicos Descrição Ciclo de
instruções
Flags afetados
Instruções aritméticas
ADD A, [m] Soma conteúdo da memória e do Acc. Resultado no Acc 1 Z,C,AC, OV
ADDM A, [m] Soma Acc e o conteúdo de memória. Resultado na memória 1(1) Z,C,AC, OV
ADD A, c Soma constante ao conteúdo do Acc. Resultado no Acc 1 Z,C,AC, OV
ADC A, [m] Soma conteúdo da memória com conteúdo do Acc e carry. Resultado no Acc 1 Z,C,AC, OV
ADCM A, [m] Soma conteúdo da memória com conteúdo do Acc e carry. Resultado na memória 1(1) Z,C,AC, OV
SUB A, c Subtrai constante numérica do conteúdo do Acc. Resultado no Acc. 1 Z,C,AC, OV
SUB A, [m] Subtrai conteúdo numérico da memória do conteúdo do Acc. Resultado no Acc. 1 Z,C,AC, OV
SUBM A, [m] Subtrai conteúdo numérico da memória do conteúdo do Acc. Resultado na memória. 1(1) Z,C,AC, OV
SBC A, [m] Subtrai conteúdo da memória do conteúdo do Acc e carry. Resultado no Acc. 1 Z,C,AC, OV
SBCM A, [m] Subtrai conteúdo da memória do conteúdo do Acc e carry. Resultado na memória. 1(1) Z,C,AC, OV
DAA [m]

Ajuste decimal com resultado no conteúdo da memória

1(1)

C

Operações Lógicas
AND A, [m] Operação ‘E’ com o conteúdo da memória e o conteúdo do Acc. Resultado no Acc. 1 Z
OR A, [m] Operação ‘OU’ com o conteúdo da memória e o conteúdo do Acc. Resultado no Acc. 1 Z
XOR A, [m] Operação ‘OU exclusivo’ com o conteúdo da memória e o conteúdo do Acc. Resultado no Acc. 1 Z
ANDM A, [m] Operação ‘E’ com o conteúdo da memória e o conteúdo do Acc. Resultado na memória. 1(1) Z
ORM A, [m] Operação ‘OU’ com o conteúdo da memória e o conteúdo do Acc. Resultado na memória. 1(1) Z


Mnemônicos Descrição Ciclo de
instruções
Flags afetados
XORM A, [m] Operação ‘OU exclusivo’ com o conteúdo da memória e o conteúdo do Acc. Resultado na memória. 1(1) Z
AND A, c Operação ‘E’ com constante e o conteúdo do Acc. Resultado no Acc. 1 Z
OR A, c Operação ‘OU’ com constante e o conteúdo do Acc. Resultado no Acc. 1 Z
XOR A, c Operação ‘OU exclusivo’ com constante e o conteúdo do Acc. Resultado no Acc. 1 Z
CPL [m] Complementa conteúdo da memória 1(1) Z
CPLA [m] Complementa conteúdo da memória com resultado no Acc. 1 Z
Incremento e decremento
INCA [m] Incrementa o conteúdo da memória com o conteúdo do Acc. 1 Z
INC [m] Incrementa o conteúdo da memória 1(1) Z
DECA [m] Decrementa conteúdo da memória com conteúdo do Acc. 1 Z
DEC [m] Decrementa o conteúdo da memória 1 Z
Rotação
RRA [m] Rotaciona o conteúdo da memória à direita e insere resultado no Acc. 1 nenhum
RR [m] Rotaciona o conteúdo da memória à direita. 1(1) nenhum
RRCA [m] Rotaciona o conteúdo da memória à direita com carry e insere resultado no Acc. 1 C
RRC [m] Rotaciona o conteúdo da memória à direita com carry 1(1) C
RLA [m] Rotaciona o conteúdo da memória à esquerda e insere resultado no Acc. 1 nenhum
RL [m] Rotaciona o conteúdo da memória à esquerda. 1(1) nenhum
RLCA [m] Rotaciona o conteúdo da memória à esquerda com carry e insere resultado no Acc. 1 C
RLC [m] Rotaciona o conteúdo da memória à esquerda com carry 1(1) C
Movimentação de dados
MOV A, [m] Move o conteúdo da memória para o Acc. 1 nenhum
MOV [m], A Moce o conteúdo do Acc para a memória 1(1) nenhum
MOV A, c Move uma constante para o Acc 1 nenhum
Operação de bit
CLR [m].b Limpa o bit especificado em “b” da memória -> torna nível lógico do bit = “0” 1(1) nenhum
SET [m].b Seta o bit especificado em “b” da memória -> torna nível lógico do bit = “1” 1(1) nenhum

Mnemônicos Descrição Ciclo de
instruções
Flags afetados
Desvio e Salto
JMP addr Desvio incondicional para o endereço especificado em addr 2 nenhum
SZ [m] Desvia se conteúdo da memória for igual a zero 1(2) nenhum
SZA [m] Desvia se conteúdo da memória for igual a zero com resultado em Acc 1(2) nenhum
SZ [m].b Desvia se o bit especificado no conteúdo da memória for igual a zero 1(2) nenhum
SNZ [m].b Desvia se o bit especificado no conteúdo da memória não for igual a zero 1(2) nenhum
SIZ [m] Desvia se o conteúdo da memória incrementado é zero 1(3) nenhum
SDZ [m] Desvia se o conteúdo da memória decrementado é zero 1(3) nenhum
SIZA [m] Desvia se o conteúdo da memória decrementado é zero com resultado no Acc 1(2) nenhum
SDZA [m] Desvia se o conteúdo da memória decrementado é zero com resultado no Acc 1(2) nenhum
CALL addr Chama sub-rotina especificada em addr 2 nenhum
RET Retorno de sub-rotina 2 nenhum
RET A,c Retorno de sub-rotina com carga imediata de uma constante no Acc 2 nenhum
RETI Retorno de interrupção 2 nenhum
Leitura de tabela
TABRDC [m] Move código ROM (página atual) para o conteúdo da memória e o registrador TBLH 2(1) nenhum
TABRDL [m] Move código ROM (última página) para o conteúdo da memória e registrador TBLH 2(1) nenhum
Miscelânea
NOP Não operando 1 nenhum
CLR [m] Limpa o conteúdo da memória -> todos os bits recebem nível lógico “0” 1(1) nenhum
SET [m] Seta o conteúdo da memória -> todos os bits recebem nível lógico “1” 1(1) nenhum
CLR WDT Reseta o Watch Dog Timer 1 TO,PD
CLR WDT1 Pré-reseta o Watch Dog Timer 1 TO(4),PD(4)
CLR WDT2 Pré-reseta o Watch Dog Timer 1 TO(4),PD(4)
SWAP [m] Troca os nibbles do conteúdo da memória 1(1) nenhum
SWAPA [m] Troca os nibbles do conteúdo da memória. Resultado no Acc. 1 nenhum
HALT Entra no modo de baixo consumo 1 TO,PD


Obs.:
m – conteúdo da memória
c – constante
Acc – acumulador
b – número do bit (0 – 7)
addr – endereço de memória


(1) – A execução da instrução pode consumir mais um ciclo de máquina se houver um carregamento no PCL
(2) - A execução da instrução pode consumir mais um ciclo de máquina se ocorrer um salto ou desvio na instrução seguinte.
(3) – itens (1) e (2)
(4) - Se o Watchdog Timer for resetado pelas instruções CLR WDT1 ou CLR WDT2, os flags TO e PD são “limpos” (bit igual a zero). Caso contrário nenhum flag é alterado.

Você compreenderá melhor o uso das instruções quando utilizá-las em algum projeto prático com o microcontrolador Holtek HT48EXX.

O ambiente de desenvolvimento HT-IDE3000 Holtek trás também um compilador free para a Linguagem “C” e sem qualquer limitação. Eu já o usei em um projeto para um cliente e gostei bastante. O mesmo segue o padrão ANSI e o resultado da compilação não "engorda" o arquivo final.

Acredito ser de suma importância para o desenvolvedor conhecer ambas as linguagens, pois geralmente o compilador C “traduz” o seu código fonte para um segundo código em linguagem Assembly (ASM), e este é então compilado para gerar o arquivo que será definitivamente gravado na memória do microcontrolador. Em alguns casos, o desenvolvedor pode necessitar “melhorar” o que foi implementado pelo “compilador C” no arquivo ASM, visando uma maior economia de memória e/ou performance do código final. Neste caso, o conhecimento da linguagem Assembly é altamente necessário.



INTERRUPÇÕES

Uma interrupção é um evento que obriga o microcontrolador (ou microprocessador) a parar suas atividades temporariamente e atender tal evento. Este “atendimento” nada mais é que o desvio do processamento atual, para um novo endereço, onde será executado um processamento diferente do atual para tratar o evento. Ao final deste tratamento (interrupção) o programa segue de onde foi interrompido.

Para isso, antes de realizar o desvio para tratar a interrupção, o microcontrolador insere no stack o endereço atual presente no PC (Program Counter), realiza o desvio e ao encontrar a instrução RETI, soma um ao endereço contido no stack e devolve este endereço ao PC. A partir daí, o processamento segue seu fluxo normal.

O microcontrolador Holtek HT48E10 possui duas interrupções distintas: interrupção externa (para controle de um evento externo) e a interrupção do contador Timer/Event (que pode ser gerada por um evento interno – timer, ou ainda externo – event). O desvio para tratamento de uma interrupção é sempre feito para um endereço conhecido como “vetor de interrupção”.

A tabela abaixo mostra o endereço de desvio para cada uma das interrupções, assim como sua prioridade.

Tabela – Vetores de interrupções e prioridades

Interrupção Endereço de desvio Prioridade
Externa 04H 1
Timer/Event 08H 2

É importante salientar que a prioridade define qual das interrupções será atendida primeira caso ambas ocorram ao mesmo tempo. A interrupção externa tem maior prioridade que a interrupção do contador Timer/Event e assim, caso ocorra a chamada simultânea de ambas as interrupções, a interrupção externa será atendida primeiro.

O controle/monitoração das interrupções é feito através do registrador INTC. A tabela abaixo mostra como os bits do registrador INTC devem ser configurados para o correto tratamento das interrupções.

Tabela – Configuração do registrador INTC

Nome do bit Posição Função
----- 7 Não usado. Lido sempre como “0”.
----- 6 Não usado. Lido sempre como “0”.
TF 5 Flag de interrupção do contador Timer/Event. Se = “1” ativo, se = “0” inativo.
EIF 4 Flag de interrupção externa. Se = “1” ativo, se = “0” inativo.
----- 3 Não usado. Lido sempre como “0”.
ETI 2 Controle da interrupção do contador Timer/Event. Se = “1” interrupção liberada, se = “0” não liberada.
EEI 1 Controle da interrupção externa. Se = “1” interrupção liberada, se = “0” não liberada.
EMI 0 Controle geral das interrupções. Se = “1” interrupção libera todas interrupções, se = “0” não libera interrupções.

Um detalhe importante sobre as interrupções no microcontrolador Holtek HT48EXX é que durante o tratamento de uma das interrupções, o bit EMI é desligado automaticamente pelo microcontrolador. Caso o projeto necessite priorizar o atendimento de uma interrupção mesmo durante o tratamento da outra, o bit EMI deverá ser setado (nível lógico = “1”) pelo programa.

Neste caso, todo cuidado deve ser tomado, pois o microcontrolador HT48E10 possui apenas 4 níveis de stack e caso sejam solicitados mais de 4 desvios sem a inserção da instrução RETI ou RET (no caso de uma chamada CALL dentro do vetor de interrupção) o programa provocará o estouro da pilha (stack overflow) com sérias conseqüências ao processamento.

Obs.: Todas as interrupções tem capacidade de “acordar” o microcontrolador quando este estiver operando no modo HALT (economia de energia).




INTERRUPÇÃO EXTERNA

Esta interrupção é ideal para contagem de eventos externos. Ela ocorre sempre que uma transição de cima para baixo (borda de descida) é gerada por um evento lógico externo ligado ao pino /INT. Para configurar esta interrupção basta “ligar” os bits EEI e ETI. A cada interrupção ocorrerá o desvio para o vetor de interrupção 04H.



INTERRUPÇÕES NO PERIFÉRICO CONTADOR TIMER/EVENT


O Timer/Event tem como função principal realizar uma contagem, que pode ser de tempo ou eventos, de maneira independente do processamento principal. Desta forma o microcontrolador precisa apenas programar o periférico e seguir com o processamento normalmente. Quando a contagem chegar ao seu fim, o periférico timer/event fará uma interrupção no processamento principal, para que o microcontrolador possa realizar o tratamento desta.

O microcontrolador Holtek HT48E10 possui um timer/event programável de 8 bits e prescale de 8 estágios (2, 4, 8, 16, 32, 64, 128, 256). Isso significa que ele pode realizar uma contagem de 0 a 255 (8 bits) e esta pode ainda ser dividida através do prescale.

Para realizar tal contagem o timer/event conta com um contador interno independente e seu clock pode ser controlado tanto pelo clock do sistema quanto por um clock externo. Se o periférico for programado como timer, então o clock do periférico será retirado do clock do sistema (FOSC/4), e se programado como event (contador de eventos) ou ainda “medidor de largura de pulsos” o clock deverá ser externo, aplicado a entrada TMR0.

Para programar o periférico timer/event é necessário interagir com dois registradores distintos: TMR e TMRC. No registrador TMR deve ser inserido o valor da contagem inicial (0 a 255). No registrador TMRC deve-se configurar seus bits de acordo com a operação desejada para o periférico. A tabela abaixo mostra tal configuração.

Tabela – configuração do registrador TMRC (HT48E10)

Nome do bit Posição Função
TM1 e TM0 7 e 6 Define o modo de operação.
00 – não usado
01 – Modo contador de eventos (clock externo)
10 – Modo timer (clock interno)
11 – Modo medida de largura de pulso
------- 5 Não usado. Lido sempre como “0”.
TON 4 Quando = “1”, liga o contador timer/event
TE 3 Define o modo de ativação, de acordo com a borda no contador Timer/Event. Se = “0” ativa de baixo para cima, se = “1” ativa de cima para baixo
PSC0 a PSC2 0 a 2 Define o estágio do prescaler.
000 = FINT = FSYS/2
001 = FINT = FSYS/4
010 = FINT = FSYS/8
011 = FINT = FSYS/16
100 = FINT = FSYS/32
101 = FINT = FSYS/64
110 = FINT = FSYS/128
111 = FINT = FSYS/256

FINT = Freqüência interna no contador Timer/Event
FSYS = Freqüência do sistema (FOSC/4)



USANDO O CONTADOR TIMER/EVENT NO MODO TIMER

Neste modo o contador pode ser utilizado para contar pequenos intervalos de tempo fixos, baseado no clock do sistema. Sempre que a contagem chegar ao seu fim, o periférico gera uma interrupção para o microcontrolador, que será desviado para o endereço de memória 04H para realizar o tratamento da interrupção.

Para operar neste modo, basta configurar os bits TM1=1 e TM0=0. Em seguida deve-se inserir no registrador TMR o valor da contagem. A contagem será feita sempre de maneira crescente. Se for necessário o uso do prescale, o mesmo deve ser programado também através dos bits PSC0 a PSC2. Para ativar o periférico basta configurar o bit TON.

Porém, como dito anteriormente, o periférico gera uma interrupção para avisar o microcontrolador sobre o final da contagem. Sendo assim, antes de ativar o bit TON no registrador TMRC, é prudente configurar o registrador INTC habilitando a interrupção do contador Timer/Event através do bit ETI e o controle geral e interrupções através do bit EMI.



USANDO O CONTADOR TIMER/EVENT NO MODO EVENT

Neste modo o periférico contará um número de transições de eventos lógicos externos, alertando o microcontrolador através de uma interrupção quando a contagem chegar ao final. A entrada física para o periférico, neste modo, deve ser necessariamente o pino TMR. Este pino deve ser configurado como entrada para uso neste modo.

Para realizar uma contagem qualquer, basta configurar os bits TM1=0 e TM0=1. Em seguida deve-se programar o registrador TMR com o valor da contagem. Se o bit TE for igual a “0” o periférico incrementará o valor em TMR a cada transição lógica, mas se TE for igual a “1” ocorrerá o decremento do valor presente em TMR. Assim quando a contagem estiver completa (TMR=FFH) o timer estoura e gera uma interrupção.

Se for necessário o uso do prescale, o mesmo deve ser programado também através dos bits PSC0 a PSC2 no registrador TMRC. Para ativar o periférico basta configurar o bit TON no mesmo registrador.

A mesma observação feita em relação ao periférico operando no modo timer é valida aqui também. Sendo assim, antes de ativar o bit TON, é prudente configurar o registrador INTC habilitando a interrupção do contador Timer/Event através do bit ETI e o controle geral e interrupções através do bit EMI.




USANDO O CONTADOR TIMER/EVENT NO MODO MEDIDA DE LARGURA DE PULSO

Nesse modo pode-se medir a largura de um pulso, aplicado ao pino TMR. Para tal, o pino TMR deve ser configurado como entrada e os bits TM1 e TM0, no registrador TMRC, ambos com nível lógico “1”.

Se o bit TE=0, a contagem da largura de pulso terá inicio quando ocorrer uma transição de cima para baixo (borda de descida) no pulso e será finalizada quando ocorrer uma próxima transição igual. Já se TE=1 a contagem será iniciada quando a transição se der de baixo para cima (borda de subida) e será finalizada numa transição idêntica e seguinte.

Seja qual for a condição do bit TE, ao final da contagem o valor da mesma será inserida no registrador TMR e o bit TON será limpo (bit igual a zero). É importante perceber que apenas neste modo o bit TON é limpo pelo microcontrolador. Nos outros modos o bit TON não sofre qualquer interferência no seu estado por parte do microcontrolador.

Após o reset do bit, uma interrupção é gerada e o programa poderá ler o valor presente no registrador TMR que representará o comprimento ou largura do pulso presente em TMR0. Após o tratamento da interrupção o programa deverá ligar o bit TON para uma nova leitura.

É importante salientar que o valor é dado em relação ao clock do sistema. Assim, a cada clock do sistema o registrador TMR é incrementado. Caso o pulso tenha comprimento maior que 255 x prescaler o timer limpará o bit TON e ira gerar uma interrupção. Você percebe assim que é importante programar corretamente o prescaler para evitar o estouro do timer, caso este seja indesejável, neste modo.

Os bits ETI e EMI do registrador INTC (controle de interrupções) também devem ser “ligados” (fazer igual a “1”) para habilitar a interrupção do contador e em seguida o bit TON deve ser ligado para a primeira leitura.



DIVISOR DE FREQÜÊNCIA PROGRAMADA (PFD) - CONTROLE DE BUZZER

Os microcontroladores da família Holtek HT48EXX fornecem uma maneira bastante interessante para o controle de um buzzer (Piezo). Ela é feita através dos pinos BZ e /BZ (complemento de BZ). Este controle (ou função) é selecionado através do aplicativo de desenvolvimento HT-IDE3000 Holtek e os pinos de I/O ligados a este recurso devem, necessariamente, ser configurados como saída.

O sinal do timer será a fonte de clock para o circuito de controle do buzzer. A função carrega previamente no registrador onde esta contido o controle do prescale os valores exigidos para gerar a freqüência do buzzer. O contador inicia a contagem e após o seu overflow os pinos BZ e /BZ são complementados (invertidos). O contador é carregado automaticamente para um novo ciclo.

É importante salientar que o controle dos pinos fica por conta do programa. Assim, o desenvolvedor só tem que ligar o pino BZ pelo período desejado (o pino /BZ será controlado automaticamente pelo microcontrolador). A função buzzer implementará o PWM necessário para que o buzzer entre em oscilação. A figura abaixo mostra um gráfico que permitirá um melhor entendimento do que foi dito.



CONCLUSÃO

Chegamos ao fim de mais uma pequena série sobre os microcontroladores, desta vez tratando dos microcontroladores Holtek família HT48EXX. Nesta pequena série, dividida em quatro partes, foram passadas informações importantes sobre a estrutura interna do microcontrolador assim como o uso correto dos seus registradores, memória, pinos de I/O, periféricos especiais, interrupções, e outras. Não se pode esperar sucesso na prática sem uma boa base teórica. Esta pequena série que fiz foi apenas um início, e deve ser considerado apenas como referência. Muito há para se aprender sobre estes microcontroladores. No site do fabricante há muita informação esperando por você! Não deixe de visitá-lo! Bons estudos e até a próxima!



Copyright deste conteúdo reservado para Márcio José Soares e protegido pela Lei de Direitos Autorais LEI N° 9.610, de 19 de Fevereiro de 1998. É estritamente proibida a reprodução total ou parcial do conteúdo desta página em outros pontos da internet, livros ou outros tipos de publicações comerciais ou não, sem a prévia autorização por escrito do autor.