Interrupções e Subrotinas no Intel 8051

Instruções do Intel 8051 Mapa de Memória no Intel 8051 8051 Arquitetura Intel 8051

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.

Interrupções e Subrotinas no Intel 8051 - Localização dos vetores de interrupção
Figura 1: Localização dos vetores de interrupção [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.

Registrador IE
Figura 2: Registrador IE [1].
  • 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.

Registrador IP
Figura 3: Registrador IP [1].
  • 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:

  1. 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>;
  2. O bit correspondente a interrupção desejada deve ser habilitado no registrador IE;
  3. 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.

Registrador PSW
Figura 4: Registrador PSW [1].
  • 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.

Banco de Registradores
Figura 5: Banco de Registradores [1].

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.

Sistema de Interrupções
Figura 6: Sistema de Interrupções [1].

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.

cicloinstrucaoint
Figura 7: Ciclo de instrução [2].

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.

retornoint
Figura 8: Fluxo de execução durante uma interrupção [2].

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

Outros artigos da série

<< Conjunto de Instruções do Intel 8051Entradas e Saídas Digitais do Intel 8051 >>
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
5 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Ricardo Munhoz
Ricardo Munhoz
26/10/2016 12:20

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.

Francesco Sacco
Reply to  Ricardo Munhoz
26/10/2016 12:34

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:
http://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://www.embarcados.com.br/compilando-c-para-8051-com-sdcc/

Espero ter ajudado. No que precisar, conte conosco.
Um abraço

Ricardo Munhoz
Ricardo Munhoz
Reply to  Francesco Sacco
26/10/2016 13:04

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.

Fernando Deluno Garcia
Fernando Deluno Garcia
Reply to  Ricardo Munhoz
26/10/2016 19:32

Olá, Ricardo. Obrigado pelo retorno!

Acredito que com o programador USBASP você consegue programar esse dispositivo.

http://www.fischl.de/usbasp/

Montei esse programado um tempo atrás e funcionou muito bem.

Ricardo Munhoz
Ricardo Munhoz
Reply to  Fernando Deluno Garcia
27/10/2016 12:42

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.

Talvez você goste:

Séries



Outros da Série

Menu