Este artigo é continuação da série Intel 8051 e tem como principal objetivo apresentar o sistema de interrupção do 8051. Além disso, a função do registrador SP será destacada no contexto de interrupções e chamada de subrotinas no Intel 8051. Os exemplos de interrupção serão apresentados nos artigos referentes a cada periférico.
Interrupções
Vimos que na condição de reset o sistema é iniciado a partir do endereço zero da memória de programa. Isso ocorre devido à localização dos vetores de interrupção. Especificamente, os vetores de interrupção ocupam posições fixas na memória de programa, e o reset é considerado uma “interrupção” estabelecida no endereço zero. Isso é ilustrado na Figura 1.

Alguns periféricos podem gerar interrupções e para isso alguns endereços são reservados:
- IE0: 0x0003, Interrupção externa 0;
- TF0: 0x000B, Interrupção por overflow do timer 0;
- IE1: 0x0013, Interrupção externa 1;
- TF1: 0x001B, Interrupção por overflow do timer 1;
- RI e TI: 0x0023, Interrupção do canal serial.
Se a interrupção não é utilizada, seu endereço é considerado de propósito geral. Além disso, os vetores são espaçados em 8 bytes. Portanto, se a rotina de interrupção é curta, essa região de 8 bytes pode ser utilizada, já as rotinas longas podem utilizar instruções de jump.
Registradores
As interrupções são controladas pelos registradores Interrupt Enable (IE) e Interrupt Priority (IP). O registrador IE, ilustrado na Figura 2, pode ser endereçado bit a bit e está localizado no endereço A8H. Esse registrador tem como função controlar as interrupções que o sistema deve atender.

- 7 – EA: Interrupções globais
- 4 – ES: Interrupção do canal serial
- 3 – ET1: Interrupção do temporizador/contador 1
- 2 – EX1: Interrupção externa 1
- 1 – ET0: Interrupção do temporizador/contador 0
- 0 – EX0: Interrupção externa 0
O registrador IP, ilustrado na Figura 3, também pode ser endereçado bit a bit e está localizado no endereço B8H. Esse registrador tem como função determinar a prioridade de uma fonte de interrupção, podendo ser alta ou baixa.

- 4 – PS: Prioridade da interrupção do canal serial
- 3 – PT1: Prioridade da interrupção do temporizador/contador 1
- 2 – PX1: Prioridade da interrupção externa 1
- 1 – PT0: Prioridade da interrupção do temporizador/contador 0
- 0 – PX0: Prioridade da interrupção externa 0
Para utilizar uma interrupção deve-se:
- Escrever a rotina de interrupção com início no endereço do vetor correspondente. Isso é feito a partir da diretiva ORG <endereço da interrupção>;
- O bit correspondente a interrupção desejada deve ser habilitado no registrador IE;
- O bit EA (Enable All) deve ser ativado no registrador IE.
Além desses dois registradores, é importante citar a função do Program Status Word (PSW). Esse registrador, ilustrado na Figura 4, contém as flags de estado da CPU, pode ser endereçado bit a bit e está localizado no endereço D0H.

- 7 – CY: Flag de Carry out
- 6 – AC: Flag auxiliar de Carry out – operações de adição
- 5 – F0: Flag de propóstio geral
- 4 e 3 – RS1 e RS0: Seleção do banco de registradores
- 2 – OV: Overflow de operações aritméticas
- 1 – x : Flag definida pelo usuário
- 0 – P: Flag de paridade – É definida pelo hardware (é igual a 1 quando o acumulador possui um número ímpar de bits em 1)
Cabe ressaltar que esse registrador determina qual banco de registradores está sendo utilizado. Isso implica na referência dos nomes dos registradores R0~R7.

O Sistema de Interrupção
A Figura 6 mostra o sistema de interrupção. Nessa figura é possível observar a função dos registradores Interrupt Enable (IE) e Interrupt Priority (IP). Mas o que acontece quando interrupções simultâneas são capturadas? Bom, nesse caso é necessário avaliar a prioridade da interrupção, e no caso de interrupções com a mesma prioridade a seguinte ordem de avaliação é estabelecida: primeiro IE0, em seguida TF0, IE1, TF1, RI e por ultimo, TI.
Quando a interrupção é disparada, uma operação LCALL é realizada com destino ao vetor de interrupção correspondente. Durante a execução de LCALL, somente o contador de programas (PC) é armazenado na pilha. Portanto, os registradores PSW, Acumulado e B não são gravados na pilha durante a chamada de uma rotina de interrupção. Diante disso o ciclo de instrução apresentado no ultimo artigo pode ser modificado conforme a Figura 7.
Cabe ressaltar que a instrução atual é finalizada antes da interrupção ser atendida.
O Ponteiro de Pilha (Stack Pointer)
O Stack Pointer é um registrador que possui uma função muito importante na CPU. Esse registrador, que é inicializado com o valor 07H durante a operação de Reset, tem como função gerenciar a chamada e o retorno de eventos de interrupção e chamada de subrotinas. O valor 07H indica que o registrador aponta para o endereço 07H, isto é, para o registrador R0 do segundo banco de registradores. Nesse sentido, o endereço armazenado em SP é chamado de topo da pilha. Para isso acontecer, duas instruções operam diretamente sobre esse registrador, são elas: PUSH e POP:
- A operação PUSH faz com que um dado seja armazenado no endereço seguinte ao indicado pelo SP, isto é, no topo da pilha. Após essa operação o registrador SP é incrementado;
- A operação POP recupera o valor armazenado no topo da pilha. Após essa operação o registrador SP é decrementado.
Sabendo dessas duas operações, e tendo em vista um evento de interrupção, como será que a CPU gerencia o fluxo de execução do programa no momento de uma interrupção? Foi dito que durante a interrupção o programa é desviado por meio LCALL para o endereço do vetor de interrupção. Nesse momento, o contador de programa, que indica a próxima instrução que será buscada na memória, é armazenado na pilha. A Figura 8 ilustra essa transferência entre o programa em execução e a rotina de interrupção.
Quando a instrução RETI é executada, o contador de programa é restabelecido com os valores que estavam armazenados na pilha, isto é, o endereço da próxima instrução que seria executada antes de ocorrer a interrupção! Esse mesmo procedimento ocorre com as outras instruções de chamada de subrotina, contudo a instrução de retorno deve ser RET, pois RETI é restrito ao contexto das interrupções. É importante lembrar que a pilha não fica limitada a essas funções, e pode ser utilizada normalmente pelo programador.
Referências
- [1] MCS® 51 Microcontroller Family User’s Manual.
- [2] STALLINGS, W. Arquitetura e organização de computadores. Pearson Prentice-Hall, 8ª ed, São Paulo. 2010.
- Crédito da Imagem Destacada





Muito bom seus posts, estou lendo como se estivesse numa sala de aula.
Há uns dois meses atrás eu comprei apenas o Microcontrolador AT89S8253 pra aprender, sei que ele é 8501 mas nem sei por onde começar .. queria montar um circuitinho básico e depois programar. Alguma dica?
Parabéns.
Olá Ricardo,
Esse 8051 é da Atmel. Ele permite gravação através do canal SPI. Normalmente fazíamos a ligação pela porta paralela do PC, não sei se você tem disponível.
O Rafael Ferrari fez um processo de gravação com um cabo conversor USB Serial. Segue o link do gravador dele:
https://rafa.eng.br/grava.htm
Para programar C para ele, fizemos um artigo aqui no Embarcados sobre o SDCC. Segue o link também:
https://embarcados.com.br/compilando-c-para-8051-com-sdcc/
Espero ter ajudado. No que precisar, conte conosco.
Um abraço
Obrigado, vou precisar sim rsrs.
Pelo que vi antigamente era na paralela, no link ele usa um DB9 com MAX232 para conversão. Acredito que se eu trabalhar em cima do CI do Arduíno para USB eu consiga algo melhor, vou tentar.
Uma coisa que não vi no esquema é o cristal oscilador.
Olá, Ricardo. Obrigado pelo retorno!
Acredito que com o programador USBASP você consegue programar esse dispositivo.
https://www.fischl.de/usbasp/
Montei esse programado um tempo atrás e funcionou muito bem.
Boa Fernando.
Eu vi “esse carinha” pela Internet, pensei em comprar e agora com suas palavras vou comprar.
Mas o que eu preciso mesmo é de um esquema pra montar o uC numa placa, nem que seja na protoboard, pra poder usar o gravador e depois ir adicionando mais componentes.
Vou partir do exemplo que o Francesco passou .. Apenas não entendi porque não tem o cristal oscilador .. porém sei que existe um oscilador interno.
Obrigado.