"conjunto de instruções" endereço

Propaganda
Disciplina de Microprocessadores
Curso de Engenharia Elétrica - UEL
José Alexandre de França
Londrina, 22 de outubro de 2001
1
2
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Índice Geral
CAPÍTULO 1 - VISÃO GERAL................................................................................................ 8
1.1
Um Pouco de História ............................................................................. 8
1.2
Componentes do Sistema.........................................................................10
1.3
Execução de Instruções..........................................................................13
1.4
Mais um Pouco Sobre a Arquitetura de von Neumann .........................................14
1.5
1.5.1.
Microprocessadores e a Memória Principal .....................................................15
Ordem dos Bytes ............................................................................................................................................ 15
1.6
Controladores de Dispositivos ...................................................................16
1.7
1.7.1.
Compartilhando as Informações .................................................................18
Pinagem e Encapsulamento............................................................................................................................ 18
1.8
Comentários .......................................................................................20
CAPÍTULO 2 - MICROPROGRAMAÇÃO ............................................................................. 21
2.1
Um Exemplo de Microarquitetura ...............................................................21
2.1.1.
Componentes Básicos .....................................................................................................................................22
2.1.1.1.
ALU e Deslocador .................................................................................................................................22
2.1.1.2.
Relógio (clock)........................................................................................................................................22
2.1.1.3.
Memória Principal..................................................................................................................................23
2.1.2. As Vias de Dados ............................................................................................................................................24
2.1.3. Microinstruções ..............................................................................................................................................26
2.1.4. Temporização de Microinstruções..............................................................................................................27
2.1.5. Seqüenciamento de Microinstruções .........................................................................................................29
2.2
2.2.1.
2.2.2.
Um Exemplo de Macroarquitetura...............................................................30
Pilhas .................................................................................................................................................................30
O Conjunto de Macroinstruções............................................................................................................. 31
2.3
Um Exemplo de Microprograma..................................................................33
2.3.1. A Microlinguagem de Montagem .................................................................................................................33
2.3.2.
Um Exemplo de Microprograma..............................................................................................................34
2.3.2.1.
3.3.2.1. Comentários sobre o Microprograma .................................................................................35
2.4
2.4.1.
2.4.2.
2.4.3.
2.4.4.
2.4.5.
Mais um Pouco Sobre Endereçamento...........................................................36
Endereçamento Imediato .............................................................................................................................36
Endereçamento Direto .............................................................................................................................36
Endereçamento de Registrador..............................................................................................................36
Endereçamento Indireto..........................................................................................................................37
Indexação ....................................................................................................................................................38
1
2.5
Nossa Macroarquitetura Real ................................................................... 38
2.5.1. Conjunto de Registradores .......................................................................................................................... 38
2.5.2.
Pinagem e Sinais de Barramento ............................................................................................................ 40
2.5.3.
Modos de Endereçamento ....................................................................................................................... 40
2.5.3.1.
Endereçamento Imediato (IMM) ...................................................................................................... 40
2.5.3.2.
Endereçamento Estendido (EXT).......................................................................................................41
2.5.3.3.
Endereçamento Direto (DIR)..............................................................................................................41
2.5.3.4.
Endereçamento Indexado (IND)........................................................................................................41
2.5.3.5.
Endereçamento Inerente (INH) ........................................................................................................41
2.5.3.6.
Endereçamento Relativo (REL) ...........................................................................................................41
2.5.4.
Conjunto de Instruções ........................................................................................................................... 42
2.6
Comentários ...................................................................................... 43
CAPÍTULO 3 - ENTRADA E SAÍDA......................................................................................50
3.1
E/S Programada ................................................................................. 50
3.2
Interrupção ...................................................................................... 51
3.2.1. Modo de Operação ......................................................................................................................................... 52
3.2.1.1.
Vetor de Interrupção .......................................................................................................................... 52
3.2.1.2.
Tempo de Latência ............................................................................................................................... 53
3.2.1.3.
Prioridade ............................................................................................................................................... 54
3.2.1.4.
Interrupções Mascaráveis e Não-Mascaráveis.............................................................................. 55
3.2.2.
O Controlador 8259A............................................................................................................................... 56
3.2.2.1.
Diagrama de Blocos .............................................................................................................................. 56
3.2.2.2.
Seqüência de Interrupção .................................................................................................................. 57
3.2.2.3.
Interfaceamento .................................................................................................................................. 58
3.2.2.4.
Programação........................................................................................................................................... 59
3.2.3.
Interrupções no 68HC11.......................................................................................................................... 59
3.2.3.1.
O vetor de interrupção ....................................................................................................................... 59
3.2.3.2.
Interrupção IRQ e XIRQ ................................................................................................................ 60
3.2.3.3.
Interrupção do Timer Overflow (TOI) ............................................................................................61
3.2.3.4.
Interrupções na placa EVB ................................................................................................................. 62
3.2.4.
Interrupções no IBM PC AT ................................................................................................................... 63
3.2.4.1.
O Vetor de Interrupção do IBM PC AT .......................................................................................... 63
3.2.4.2.
Trabalhando com Interrupção na Linguagem C .............................................................................. 64
3.3
3.3.1.
3.3.2.
3.3.3.
3.3.4.
3.3.5.
3.3.6.
E/S via DMA ..................................................................................... 67
Como o DMA funciona ................................................................................................................................... 68
Tipos e modos de transferências........................................................................................................... 68
Operação do controlador ......................................................................................................................... 69
Implementação de DMA no IBM PC e no PC/XT ................................................................................ 69
Implementação de DMA no PC AT......................................................................................................... 69
Gerenciando o controlador de DMA ...................................................................................................... 70
3.4
Interface de Comunicação Serial............................................................... 70
3.4.1. Especificações ................................................................................................................................................ 70
3.4.1.1.
Características Elétricas.................................................................................................................... 70
3.4.1.2.
Sinais de Controle e Handshake ........................................................................................................ 70
2
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
3.4.1.3.
Características Mecânicas.................................................................................................................. 71
CAPÍTULO 4 - CONVERSORES A/D E D/A......................................................................... 72
4.1
Discretização .....................................................................................72
4.2
Teorema da Amostragem ........................................................................72
4.3
Quantização.......................................................................................75
4.4
Codificação........................................................................................77
4.5
Recuperação do Sinal Codificado ................................................................78
4.6
4.6.1.
4.6.2.
4.6.3.
Critérios de Performance ........................................................................79
Resolução ..........................................................................................................................................................79
Velocidade ...................................................................................................................................................79
Linearidade..................................................................................................................................................80
4.7
4.7.1.
4.7.2.
Tipos de Conversores D/A .......................................................................80
Conversor D/A à Resistores Ponderados ..................................................................................................80
Conversor D/A à Rede R-2R....................................................................................................................82
4.8
4.8.1.
4.8.2.
Tipos de Conversores A/D .......................................................................83
Paralelo ou Flash .............................................................................................................................................83
Aproximações Sucessivas ........................................................................................................................84
CAPÍTULO 5 - PROJETO DE SISTEMAS MICROCONTROLADOS ................................... 86
5.1
5.1.1.
5.1.2.
5.1.3.
Principais Componentes de um Sistema Microprocessado ......................................86
Memória RAM ..................................................................................................................................................86
Memória EPROM .............................................................................................................................................87
Microcontrolador 68HC11.............................................................................................................................88
5.2
Interface entre o 68HC11 com Outros Dispositivos ..........................................88
5.3
Cristal Oscilador .................................................................................94
5.4
RESET.............................................................................................95
5.5
Projetos com o 80C31. ..........................................................................96
3
Índice de Figuras
Figura 1 – Uma pequena fração do ENIAC......................................................................................................................8
Figura 2 - A máquina original de von Neumann. .............................................................................................................9
Figura 3 - Diagrama de blocos de um sistema microprocessado. ............................................................................ 11
Figura 4 – Fluxo de dados de uma máquina de von Neumann típica.........................................................................15
Figura 5 – (a) Memória big endian. (b) Memória little endian. .................................................................................16
Figura 6 – Esquema de ligação de um dispositivo de E/S e um CPU, através de um controlador de
dispositivo. ...................................................................................................................................................................17
Figura 7 – Pinagem lógica de um MCU bastante simples (hipotético).....................................................................19
Figura 8 – (a) encapsulamento DIP, (b) encapsulamento PLCC, (c) encapsulamento PGA, (d) encapsulamento
SMD...............................................................................................................................................................................19
Figura 9 – Encaixe de um circuito integrado DIP em seu respectivo soquete. ................................................... 20
Figura 10 –(a) ALU e (b) deslocador utilizados no exemplo..................................................................................... 22
Figura 11 – (a) Relógio com 4 saídas em atraso. (b) O diagrama de temporização das saídas. ........................ 23
Figura 12 – Os registradores utilizados para acionar os barramentos de endereço e dados. ......................... 24
Figura 13 – As vias de dados da microarquitetura exemplo. ................................................................................... 25
Figura 14 – O layout e a descrição de alguns dos campos da microinstrução que controla as vias de dados
da Figura 13. ............................................................................................................................................................... 27
Figura 15 – O diagrama de blocos completo de nossa microarquitetura exemplo. ............................................. 28
Figura 16 – (a) Uma pilha. (b) A mesma pilha após o armazenamento da constante 5. .......................................31
Figura 18 – Comparações entre os endereçamentos direto e indireto. (a) Endereçamento direto. (b)
Endereçamento indireto. ......................................................................................................................................... 37
Figura 19 – Conjunto de registradores do 68HC11. ................................................................................................... 39
Figura 20 – Notação utilizada pela Tabela 4............................................................................................................... 42
Figura 21 – Esquema de compartilhamento de um pino de IRQ por até oito dispositivos. ............................... 53
Figura 22 – Seqüência temporal de um exemplo de múltiplas interrupções. (RSI = Rotina de Serviço de
Interrupção.).............................................................................................................................................................. 55
Figura 23 – Diagrama de blocos do 8259A.................................................................................................................. 56
Figura 24 – Interface padrão do 8259A com o barramento................................................................................... 58
Figura 25 – O 8259A utilizado em cascata. ................................................................................................................ 59
Figura 26 – Registrador OPTION. .................................................................................................................................61
Figura 27 – Registrador TFLG2. .................................................................................................................................... 62
Figura 28 – Registrador TMSK2.................................................................................................................................... 62
Figura 29 - (a) representação de um discretizador, (b) representação gráfica de um discretizador e (c)
sinal analógico (linha contínua) e sinal discreto (pontos grossos) . ................................................................ 73
Figura 30 – (a) sinal analógico f(t), (b) Transformada de Fourier de f(t), F(ω), (c) representação gráfica de
um discretizador de Nyquist, (d) Transformada de Fourier do discretizador de Nyquist, (e) sinal
discreto no tempo e em amplitude e (f) Transformada de Fourier do sinal discreto no tempo e em
amplitude..................................................................................................................................................................... 74
Figura 31 – (a) sinal discretizado, f(n), (b) Transformada de Fourier de f(n), (c) gráfico da função sinc, (d)
Transformada de Fourier da função sinc, (e) sinal analógico f(t) e (f) Transformada de f(t). .............. 75
Figura 32 – Diversos exemplos da Transformada de Fourier de um sinal amostrado a uma freqüência
inferior a de Nyquist................................................................................................................................................ 76
Figura 33 – Esboço da função de transferência de um filtro passa-baixas real (apenas as componentes de
freqüência positivas). ............................................................................................................................................... 76
Figura 34 – Quantização da temperatura em sete níveis de quantização. ........................................................... 77
Figura 35 – Processo de quantização e o erro intrínseco ao processo.................................................................. 78
4
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Figura 36 – Processo de quantização e codificação. ..................................................................................................78
Figura 37 – (a) sinal digitalizado, quantizado e codificado, (b) sinal na saída do conversor D/A e (c) sinal na
saída do filtro "suavizador".....................................................................................................................................79
Figura 38 – Conversão A/D com 4 bits de resolução.................................................................................................80
Figura 39 – Linha reta aparente adquirida com um conversor A/D e o gráfico do desvio dos postos
digitalizados em relação a linha reta real. ........................................................................................................... 81
Figura 40 – Característica ideal de um conversor A/D e característica de um A/D com uma linearidade
diferencial pobre (com um código faltando em 120 µs). ................................................................................... 81
Figura 41 – Conversor D/A à resistores ponderados.................................................................................................82
Figura 42 – (a) Conversor R-2R de 3 bits e (b) conversor R-2R com saída amplificada....................................82
Figura 43 – Diagrama de blocos de um conversor A/D Flash. .................................................................................84
Figura 44 - Conversor A/D de 16 bits baseado em dois conversores de 8 bits..................................................84
Figura 45 – Diagrama de blocos de um conversor A/D baseado em aproximações sucessivas. .......................85
Figura 46 – Pinagem física de uma chip de memória 6264. ......................................................................................86
Figura 47 – Gravador para a família de microcontroladores da Microchip. .........................................................87
Figura 48 – Pinagem do EPROM 2764. ..........................................................................................................................88
Figura 49 –(a) Todos os 52 pinos do 68HC11, (b) Os pinos mais importantes quando deseja-se interfacea-lo
com dispositivos externos, e (c) Configuração sugerida para alguns desses pinos.....................................89
Figura 50 – (a) Diagrama de tempo de um ciclo de escrita típico no 68HC11; (b) Diagrama de tempo de um
ciclo de leitura típico no 68HC11............................................................................................................................90
Figura 51 – Barramento de um sistema baseado no 68HC11. O 74HC373 é utilizado para “separar” as linhas
de endereço das linhas de dados............................................................................................................................90
Figura 52 – Interface entre o 68HC11 e uma memória 6264.................................................................................. 91
Figura 53 - Interface entre o 68HC11 e uma memória 6264. Neste caso, a memória possui endereço base
$0000...........................................................................................................................................................................92
Figura 54 – Interface entre o 68HC11 e uma memória 6264 (base $0000) e uma memória EPROM 2764
($E000)........................................................................................................................................................................92
Figura 55 - Interface entre o 68HC11 e uma memória 6264 (base $4000) e uma memória EPROM 2764
($E000). Neste caso, foi utilizado o 74HC138 para atribuir os endereços base. ......................................93
Figura 56 – Mapa de memória do 68HC11. ...................................................................................................................94
Figura 57 – (a) esquema de ligação do cristal oscilador no 68HC11. (b) sugestão para confecção da placa de
circuito impresso. ......................................................................................................................................................95
Figura 58 – Diversas configurações para RESET. ......................................................................................................96
Figura 59 – Pinagem do microcontrolador 80C31. ......................................................................................................96
Figura 60 – Sistema microprocessado baseado no 80C31. .......................................................................................96
Figura 61 - Sistema microprocessado baseado no 80C31 com espaços de endereçamentos diferentes para
dados e instruções.....................................................................................................................................................97
5
6
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1 - Visão Geral
Índice de Tabelas
Tabela 1 – Exemplos dispositivos de E/S e a maneira de como eles representam as informações................. 17
Tabela 2 – O Conjunto de instruções do Mac-1. .........................................................................................................32
Tabela 3 – Significado dos bits do registrador CCR. ................................................................................................39
Tabela 4 – Conjunto de macroinstruções do 68HC11.................................................................................................44
Tabela 5 – Descrição dos pinos do 8259A. ..................................................................................................................57
Tabela 6 - Fonte de interrupção, vetor de interrupção e a sua máscara. ............................................................60
Tabela 7 – Conteúdo do vetor de interrupção da placa EVB....................................................................................63
Tabela 8 – Canais de interrupção dos dois controladores 8259A do PC AT e suas posições no vetor de
interrupção..................................................................................................................................................................64
Tabela 9 – Descrição de cada uma das posições do vetor de interrupção do PC AT..........................................67
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
7
Curso de Microprocessadores
Capítulo 1 - Visão Geral
1.1
Um Pouco de História1
O estímulo para o computador eletrônico foi a Segunda Guerra Mundial. O exército americano
precisava de tabelas de alcance para calibragem de mira de sua artilharia pesada, e achava que calculá-las
manualmente consumia muito tempo e era sujeito a erros.
John Mauchley, um desconhecido professor de física da Universidade da Pennsylvania, sabia que o
exército estava interessado em calculadoras mecânicas. Da mesma maneira que muitos cientistas da
computação que vieram depois dele, Mauchley apresentou um pedido de auxílio ao exército para
financiamento da construção de um computador eletrônico. A proposta foi aceita em 1943, e Mauchley e
seu aluno de pós-graduação, J. Presper Eckert, construíram um computador eletrônico que eles
denominaram ENIAC (Electronic Numerical, Integrator And Computer, ou seja, Computador e Integrador
Numérico Eletrônico). Ele era constituído de 18.000 válvulas e 1.500 relés. O ENIAC pesava 30 toneladas
e consumia 140 KW de potência. Arquiteturalmente, a máquina possuía 20 registradores, cada um capaz de
armazenar um número decimal de 10 dígitos. Sua programação era feita através de cerca de 6.000 chaves
multiposicionais e da interconexão de um grande número de soquetes através de um verdadeiro
emaranhado de cabos.
Figura 1 – Uma pequena fração do ENIAC.
A máquina só ficou pronta em 1946, quando já era muito tarde para ter qualquer uso em seus
objetivos originais. Entretanto, logo que a guerra acabou, Mauchley e Eckert obtiveram permissão para
organizar um curso de verão para descrever o trabalho deles para seus colegas cientistas. Aquele curso de
verão deu início a uma explosão de interesse na construção de grandes computadores digitais.
Após esse histórico curso de verão, muitos outros pesquisadores começaram a construir
computadores eletrônicos. O primeiro computador operacional foi o EDSAC (1949), construído na
Universidade de Cambridge, na Inglaterra, por Maurice Wilkes. Dentre outros, temos o JOHNIAC, na
Rand Corporation, o ILLIAC, na University of Illinois, o MANIAC, no Los Alamos Laboratory, e o WEIZAC,
no Weizmann Institute, em Israel.
Eckert e Mauchley começaram a construir uma nova máquina, o EDVAC (Electronic Discrete Variable
Automatic Computer, ou seja, Computador Automático Eletrônico de Variáveis Discretas), mas este
projeto foi seriamente afetado quando eles deixaram a Universidade da Pennsylvania para criar uma
companhia, a Eckert-Mauchley Computer Corporation, em Philadelphia (o Vale do Silício não existia ainda).
Após uma série de fusões, esta companhia tornou-se a atual Unisys Corporation.
1
A maior parte desta seção foi retirada do livro Organização Estruturada de Computadores, de Tanenbaun, ed. Prentice/Hall.
8
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
Enquanto isso, uma das pessoas envolvidas no projeto ENIAC, John von Neumann, foi para o
Instituto de Estudos Avançados de Princeton, para construir sua própria versão do EDVAC, a máquina
IAS. Von Neumann era um gênio do tipo Leonardo da Vinci. Falava muitas línguas, era um especialista em
ciências físicas e matemáticas, e tinha total lembrança de tudo que ouvia, via ou lia. Era capaz de citar de
cor, literalmente, o texto de livros que ele havia lido anos antes. Quando ele se interessou por
computadores, já era o mais eminente matemático do mundo.
Uma das coisas óbvias para ele era que a programação de computadores com um grande número de
chaves e cabos era lenta, tediosa e inflexível. Ele começou a perceber que o programa poderia ser
representado em forma digital na memória do computador, juntamente com os dados.
Observou também que a desajeitada aritmética decimal utilizada pelo ENIAC, em que cada dígito
era representado por 10 válvulas (uma ligada e nove desligadas), poderia ser substituída por uma
aritmética binária paralela (válvula ligada ou desligada).
Seu projeto básico, agora conhecido como máquina de von Neumann, foi utilizado no EDSAC, o
primeiro computador com programa armazenado, e‚ ainda é a base de quase todos os computadores
digitais, até mesmo hoje, mais de meio século depois. Este projeto, e a máquina IAS, construída em
colaboração com Herman Goldstine, tem tido tanta influência que vale uma breve descrição. Um esboço da
arquitetura é dado na Figura 2.
Figura 2 - A máquina original de von Neumann.
A máquina de von Neuman possuía cinco partes básicas: a memória, a unidade lógica-aritmética, a
unidade de controle de programa e os equipamentos de entrada e saída. A memória consistia de 4.096
palavras, cada palavra possuindo 40 bits (0 ou 1). Cada palavra armazenava duas instruções de 20 bits ou
um inteiro de 39 bits com sinal. As instruções possuíam 8 bits dedicados a dizer o tipo da instrução, e 12
bits para especificar uma dentre 4.096 palavras de memória. Dentro da unidade lógico-aritmética, a
precursora da atual CPU (Central Processing Unit, ou seja, Unidade Central de Processamento), havia um
registrador interno especial de 40 bits denominado acumulador. Uma instrução típica adicionava uma
palavra de memória ao acumulador ou armazenava o acumulador na memória. A máquina não possuía
aritmética de ponto-flutuante, pois von Neumann achava que qualquer matemático competente deveria ser
capaz de acompanhar de cabeça a posição do ponto decimal (na realidade, ponto binário).
Em 1948, o transistor foi inventado no Bell Labs por John Bardeen, Walter Brattain e William
Shockley, pelo qual foram agraciados com o Prêmio Nobel de Física de 1956. Nos 10 anos seguintes, o
transistor revolucionou os computadores, e no final dos anos 50 os computadores a válvula estavam
obsoletos. O primeiro computador transistorizado foi construído no Lincoln Laboratory do MIT, uma
máquina de 16 bits baseada no Whirlwind I. Foi denominada TX-0 (Transistorized eXperimental computer
0, ou seja, computador transistorizado experimental 0), que visava meramente a ser um protótipo para
testar o TX-2, uma versão melhorada.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
9
Curso de Microprocessadores
O primeiro circuito integrado comercial foi inventado por Jack Kilby da Texas Instruments
(http://www.ti.com) em 1958. Esta invenção foi tão significativa que Jack Kilby recebeu o maior prêmio da
área tecnológica dos EUA, a National Medal of Science. O circuito integrado possibilitou que dezenas de
transistores fossem colocados em uma única pastilha. Este encapsulamento tornou possível construir
computadores menores, mais rápidos e mais baratos que seus predecessores transistorizados.
Em 1968, a Intel Corporation (http://www.intel.com/) foi criada para fabricar pastilhas de memória.
Logo depois, ela foi contactada por um fabricante de calculadoras que queria uma CPU em uma única
pastilha para a sua calculadora, e por um fabricante de terminais que queria um controlador em uma única
pastilha para o seu terminal. A Intel produziu ambas as pastilhas, o 4004, uma CPU de 4 bits, e o 8008,
uma CPU de 8 bits. Estas foram as primeiras CPUs numa única pastilha do mundo.
A lntel não esperava outros interessados além dos clientes originais, de maneira que estabeleceu
uma linha de produção de baixo volume. Estavam errados. Houve um interesse tremendo, por isto
começaram a projetar uma pastilha de CPU de uso geral, que resolvesse o problema do limite de 16K de
memória do 8008 (imposto pelo número de pinos da pastilha). Este projeto resultou no 8080, uma pequena
CPU de uso geral. Este produto tomou a indústria de assalto, e instantaneamente tornou-se um item de
venda em massa. Porém, ao invés de vender milhares de unidades, como outros fabricantes, a Intel vendeu
milhões.
Dois anos mais tarde, em 1976, a Intel lançou o 8085, um 8080 encapsulado com alguns detalhes
extras de entrada/saída. Depois surgiu o 8086, uma verdadeira CPU de 16 bits numa única pastilha. O
8086 foi projetado para ter uma certa semelhança com o 8080, mas não era completamente compatível
com o 8080. O 8086 foi seguido pelo 8088, que possuía a mesma arquitetura que o 8086 e executava os
mesmos programas, mas possuía um barramento de 8 bits, ao invés de um barramento de 16 bits, o que o
tornava mais lento, porém mais barato que o 8086. Quando a IBM escolheu o 8088 para CPU do IBM PC
original, esta pastilha tornou-se rapidamente o padrão da indústria de computadores pessoais.
Nos anos seguintes, a Intel lançou o 80186 e o 80188, essencialmente novas versões do 8086 e
8088, respectivamente, mas contendo também uma grande quantidade de circuitaria de entrada/saída.
Nunca foram amplamente utilizados.
Com o passar dos anos, tornou-se possível colocar dezenas de milhares, depois centenas de milhares,
e finalmente milhões de transistores em uma única pastilha. Este avanço tornou os microprocessadores
mais rápidos e principalmente mais baratos. Deste modo, eles passaram a ser muito utilizados em sistemas
baratos, para implementar soluções poderosas, para problemas simples. Isto atraiu dezenas de fabricantes
a desenvolver centenas de famílias de microprocessadores, para milhares de consumidores. Cada
fabricante necessitava atrair a atenção dos consumidores. Evidentemente, isto poderia ser conseguido
desenvolvendo-se CPUs com características especiais que facilitassem o desenvolvimento de sistemas
microprocessados. Em busca disto, vários fabricantes começaram a dotar suas CPUs com dispositivos
extras. Por exemplo, uma pastilha com uma CPU e um conversor A/D2 poupa o projetista de adquirir e
interfacear um A/D externo, ou seja, o sistema fica mais barato e mais simples. Com o passar dos anos,
isto tornou-se comum e fez nascer uma nova classe de dispositivos: a dos microcontroladores (MCU's).
1.2
Componentes do Sistema
Sozinho, um computador não faz absolutamente nada. É tão inútil quanto um guarda-chuva em dia de
sol. Para fazer algo útil, precisamos programa-lo ou comprar (piratear) um programa para ele. Acredito que
você tenha uma noção de como um computador funciona e de como ele é programado. Neste curso, este
conhecimento será algo bastante positivo. Pois um computador nada mais é do que um sistema
microprocessado bastante complexo. Desse modo, não será difícil acreditar que, assim como um
computador, um sistema microprocessado geral é composto por uma CPU, memórias e dispositivos de
entrada e saída (E/S). Na Seção 1.1, vimos que na maioria dos sistemas estes blocos básicos relacionam-se
2
Um conversor A/D converte uma grandeza analógica em um número digital
10
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
segundo uma arquitetura baseada no esquema da Figura 2. Esta arquitetura recebe o nome de Arquitetura
de von Neumann e é ilustrada na Figura 3.
Para entender a função de cada componente da Figura 3, temos que nos perguntar qual a função
primária de um sistema microprocessado. Como todo sistema, um sistema microprocessado
constantemente recebe dados e realiza um conjunto de operações sobre eles. Estas operações podem ser
operações lógicas (deslocamentos, operações booleanas, etc) ou aritméticas (somar, multiplicar, etc). Para
suportar tais instruções, um sistema microprocessado necessita de um bloco funcional que as execute.
Este bloco existe e é denominado de ALU (unidade lógica e aritmética). Você já deve saber que uma ALU
é um dispositivo digital que recebe dois operandos e realiza uma operação (escolhida dentre um conjunto
de possíveis) entre eles.
Os operandos recebidos pela ALU devem vir de algum lugar. Da mesma forma, o resultado da
operação deve também ser armazenado em algum lugar. Este “lugar” é um conjunto de registradores. Ou
seja, os registradores provêem operandos para a ALU e podem armazenar o resultado da operação.
Agora que temos um local para armazenar nossos operandos e podemos realizar operações,
necessitamos de um local para armazenar as instruções que definirão as operações realizadas pela ALU.
Note que, ao contrário dos dados armazenados nos registradores, estas instruções são utilizadas durante
todo o tempo no qual o sistema estiver ativo. Isto sugere a criação de um novo local para armazenar as
instruções. Este novo local, geralmente com uma capacidade de armazenamento muito maior que os
registradores, é chamado de memória principal. Eventualmente, podemos ter um conjunto de dados
(operandos) que é utilizado durante toda a execução de um programa (como uma tabela de conversão).
Além disso, podemos necessitar armazenar mais operandos que nossos registradores permitem. Por isto, a
memória principal também é utilizada para armazenar dados, porém dados mais significativos. É por esta
razão, que o conjunto de registradores de um sistema microprocessado é chamado de memória de
rascunho.
CPU
Unidade
de
Controle
Unidade
Lógica e
Aritmética
(ALU)
Dispositivos de entrada e saída
Registradores
Memória
Principal
Teclado
Display de
Cristal Líquido
Barramento
Figura 3 - Diagrama de blocos de um sistema microprocessado.
Na realidade, a característica mais marcante da arquitetura de von Neumann é a forma como a CPU
acessa os dados e as instruções. Nesta arquitetura, as instruções e os dados são buscados em tempos
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
11
Curso de Microprocessadores
distintos. Em oposição, arquiteturas como a de Harvard possibilitam que a CPU busque as instruções e os
dados ao mesmo tempo. Isto provoca um ganho substancial de performance. Contudo, provoca também um
aumento significativo nos custos de produção. Por esta razão, a Arquitetura de Harvard é muito pouco
utilizada.
Evidentemente, em um sistema microprocessado deve haver uma fonte externa que provenha dados
ao sistema. Além disso, após processar estes dados o sistema precisa apresentar um resultado ao mundo
exterior. Por exemplo, em um sistema de controle de temperatura em uma estufa, precisamos alimentar o
sistema de controle com dados sobre a temperatura dentro da estufa, para que este possa calcular uma
ação de controle e manter a temperatura constante. Dispositivos que desempenham estas tarefas são
chamados de dispositivos de entrada e saída, ou simplesmente, dispositivos de E/S. Exemplos são:
conversores A/D e D/A, teclado (keypad), visores de cristal líquido, push-button, porta serial, PIO, etc.
(Não se preocupe com os nomes, até o final do curso você ficará bastante íntimo deles.)
Registradores, memórias, operandos, instruções, dispositivos de E/S, todos estes itens fazem parte
do mesmo sistema. Logo, eles devem interagir entre si. Ou seja, durante a execução de um programa,
dados e instruções vêm (e vão) de (e para) todos os componentes do sistemas. Para que isto aconteça, eles
devem estar interligados por uma estrutura (caminho) comum. Este caminho é denominado barramento.
Acredito que o conceito de barramento já esteja bem definido em sua mente desde o curso
anterior. Contudo, quero reforçar o conceito comparando o barramento às estradas de uma cidade. Por
estas estradas, veículos de todos os tipos vão (e vem) de (e para) todos os lugares de uma cidade, de uma
forma bastante ordenada (pelo menos em tese), controlados por regras e sinais de controle bem
determinados. É exatamente assim que se comporta um barramento em um sistema microprocessado.
Neste ponto, pode parecer que todos os componentes do sistema estejam trabalhando em harmonia
e em perfeito sincronismo. Contudo, para que isto realmente aconteça é necessário a inclusão de mais um
componente. Este componente deve controlar todos os outros, deve sincronizar as operações e tomar
decisões baseadas em seus resultados. Este bloco é denominado unidade de controle.
Deve-se notar que, pelo que está escrito nos parágrafos anteriores, apenas a ALU, os registradores
e a Unidade de Controle estão diretamente envolvidas no processamento dos dados. Desse modo, estes
três blocos são agrupados para formar uma unidade maior e mais poderosa. É esta unidade que chamamos
de Unidade Central de Processamento (CPU).
Não se preocupe se a idéia de um circuito digital cuja função é determinada por um conjunto de
instruções, que contenha operandos trafegando como veículos em uma cidade, e de unidade funcionais
tomando decisões baseadas em acontecimentos anteriores, parecer abstrato a você. Na verdade, só quero
passar a visão do todo. As partes menores ficarão bem mais claras quando forem abordadas
individualmente de forma mais detalhada.
A seguir, vamos agora definir formalmente a função dos blocos funcionais da Figura 3.
Unidade de Lógica e Aritmética: como o próprio nome informa, realiza todas as operações lógicas e
aritméticas da CPU. Em tese, a complexidade das operações da ALU define o poder de processamento da
CPU, ou seja, uma CPU que contém uma ALU que execute um conjunto de operações fraco e irrelevante,
torna-se uma CPU muito pouco poderosa.
Registradores: são utilizados pela CPU como uma memória temporária que armazena os dados que
estão sendo (ou vão ser) utilizados pela a ALU, e os resultados intermediários das operações.
Memória Principal: armazena as instruções que serão executadas pela CPU e os dados mais
permanentes (aqueles que serão utilizados durante toda a execução do programa ou representem dados
importantes).
Dispositivos de E/S: fazem a interface entre o sistema e o mundo exterior. São eles que provêem os
dados utilizados pelo sistema e é através deles que os resultados são apresentados externamente.
Barramento: é um meio elétrico que provê um caminho para o tráfego de informações e os sinais de
controles necessários ao funcionamento do sistema. Toda a comunicação entre os componentes do sistema
microprocessado é realizada através deste dispositivo.
12
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
Unidade Central de Processamento: formada pela unidade de controle, a ALU e o conjunto de
registradores, é responsável pela coordenação de todas as ações do sistema microprocessado.
1.3
Execução de Instruções3
Na Seção 1.2, soubemos que, para um sistema microprocessado desempenhar uma função útil,
precisamos fornecer um conjunto de instruções que devem ser executadas pela CPU. Estas instruções são
armazenadas na memória principal do sistema e são analisadas pela Unidade de Controle. Contudo, para que
a Unidade de Controle possa analisar a instrução, ela deve ser trazida da memória para dentro da CPU.
Sabendo que a unidade de controle precisará desta instrução apenas por um intervalo de tempo muito
curto, não é difícil aceitar que esta instrução fica armazenada em um registrador especial chamado
registrador de instrução (IR). Além disso, a Unidade de Controle precisa saber qual será a próxima
instrução a ser executada, ou seja, a UC tem que seguir a lógica de execução do programa. Para isto,
existe um outro registrador especial chamado de contador de programa (PC). Na verdade, o PC não conta
absolutamente nada, ele apenas aponta para a posição na memória principal, na qual localiza-se a próxima
instrução a ser executada. Podemos resumir as operações realizadas pela CPU durante a execução de uma
instrução em 8 passos:
1. Busca a próxima instrução da memória para o registrador de instrução.
2. Atualiza o contador de programa para que ele aponte para a instrução seguinte.
3. Determina o tipo da instrução.
4. Se a instrução usa dados da memória, determina onde eles estão.
5. Busca os dados, se houver algum, para registradores internos da CPU.
6. Executa a instrução.
7. Armazena os resultados em locais apropriados.
8. Volta ao passo 1 para iniciar a execução da próxima instrução.
Esta seqüência de passos é freqüentemente referida como o “ciclo busca-decodifica-executa". Ela
é o centro da operação de todos os microprocessadores.
Esta descrição de como uma CPU funciona pode facilmente ser representada por um algoritmo na
forma de um programa, por exemplo, em linguagem C ou assembler.
O fato de ser possível escrever um programa que pode imitar a função de uma CPU mostra que um
programa não precisa ser executado diretamente pelo hardware de uma CPU, constituído por um
emaranhado de circuitos elétricos. Em vez disso, um programa pode ser executado tendo-se um outro
programa que busca, analisa e executa suas instruções. Um programa que busca, analisa e executa as
instruções de outro programa é chamado de interpretador.
Esta equivalência entre processadores em hardware e interpretadores tem implicações importantes.
Após ter sido especificada a linguagem de máquina L para uma nova CPU (linguagem com a qual os
programadores poderão programa-la), o grupo projetista pode decidir se eles querem construir um
processador (uma ALU) para executar instruções em L diretamente ou se eles querem escrever um
interpretador. Se escolherem escrever um interpretador, também, precisam prover uma máquina para
executá-lo. Como um interpretador quebra a instrução de sua máquina-alvo (instruções em L) em pequenos
passos, a máquina na qual o interpretador é executado pode freqüentemente ser muito mais simples que o
processador para a máquina-alvo (CPU que, para o programador, parece poder executar as instruções em L
diretamente pelo hardware). Devido a razões econômicas, entre outras, os programas no nível de máquina
convencional da maioria das CPUs modernas são executados por um interpretador em execução em uma
máquina de nível 1 completamente diferente e muito mais primitiva, que chamamos nível de
microprogramação.
Acredito que o parágrafo anterior tenha parecido muito confuso para você. Por isso, observe um
exemplo bastante simples. Uma operação de subtração A-B pode ser representada por A-B = A+1+ B . Ou
Boa parte desta seção foi retirada do livro Organização Estruturada de Computadores, de Tanenbaun, ed. Prentice/Hall.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
3
13
Curso de Microprocessadores
seja, conseguimos emular uma operação de subtração através de duas operações de soma e uma negação. O
mesmo pode ser aplicado a operações mais complexas, por exemplo, podemos simular uma multiplicação
com uma seqüência de somas e deslocamentos. Qual a vantagem disto? Simular uma operação a partir de
outras (geralmente mais simples), diminui a complexidade da CPU. Esta diminuição de complexidade
reflete-se em um projeto mais simples (do ponto de vista do projetista da CPU), um custo menor, e até um
consumo mais baixo. Contudo, não se pode querer que todas as vezes que um programador tenha de
executar uma simples multiplicação, ele inclua um algoritmo para emula-la. Por isto, a CPU tem que ter este
algoritmo já pronto para que ele possa ser utilizado sempre que o programador necessite. O conjunto de
algoritmos internos à CPU que emulam operações complexas a partir de operações mais simples é chamado
de microprograma.
O microprograma é escrito a partir de um conjunto de instruções que podem ser executadas
diretamente pelo hardware (através da ALU), chamadas de instruções de nível 1. Na verdade, este
conjunto de instruções não é acessível ao programador. Ele é utilizado apenas pelo projetista da CPU para
escrever o microprograma. Uma vez escrito, ninguém, nem mesmo o projetista, tem acesso ao
microprograma. Os programadores de microprocessadores, utilizam um conjunto de instruções,
geralmente chamado de linguagem assembler (ou linguagem de nível 2), que, como dito anteriormente, é
emulado pelo microprograma.
A coleção de todas as instruções disponíveis ao programador em um nível é chamada conjunto de
instruções daquele nível. O número de instruções de um conjunto de instruções varia de máquina para
máquina e de nível para nível. Para o nível de máquina convencional, por exemplo, o tamanho do conjunto de
instruções está tipicamente na faixa de 20 a 300. Um conjunto de instruções numeroso não é
necessariamente melhor que um pequeno. De fato, o oposto tende a ser verdade. Um conjunto de
instruções numeroso muitas vezes significa que as instruções não são muito gerais. Os compiladores para
linguagens de alto nível, como Ada, Modula 2 e Pascal, geralmente atuam melhor em máquinas com
conjuntos de instruções pequenos e bem escolhidos do que em máquinas com conjuntos de instruções
grandes e desajeitados. Máquinas com conjunto de instruções muito pequeno, chamadas máquinas RISC,
serão discutidas em breve. Estas máquinas não usam microprogramação e são extremamente rápidas.
Certifique-se de compreender que o conjunto de instruções e a organização do nível de
microprogramação são, de fato, o conjunto de instruções e a organização do hardware (CPU). O conjunto
de instruções e a organização do nível de máquina convencional são, em contraste, determinados pelo
microprograma, e não pelo hardware.
1.4
Mais um Pouco Sobre a Arquitetura de von Neumann4
A organização interna de parte de uma CPU von Neumann clássica é mostrada na Figura 4 em mais
detalhe. Esta parte é chamada de fluxo de dados e consiste em registradores (tipicamente 1 a 16) e da
ALU (unidade lógica e aritmética). Os registradores alimentam os dois registradores de entrada da ALU,
chamados de A e B na figura. Esses registradores mantêm as entradas da ALU enquanto ela está
executando a operação.
A própria ALU executa adição, subtração e outras operações simples com suas entradas, produzindo
um resultado no seu registrador de saída. Este resultado pode ser armazenado de volta em um registrador
e, de lá, de volta à memória, se desejado. O exemplo ilustra a adição.
As instruções podem ser divididas em três categorias: registrador-memória, registradorregistrador e memória-memória (muito raras). Instruções registrador-memória permitem que palavras
sejam buscadas da memória para registradores, onde podem ser usadas como entradas para a ALU em
instruções seguintes, por exemplo. Uma instrução típica registrador-registrador busca dois operandos dos
registradores, os traz para os registradores de entrada da ALU, executa alguma operação com eles e
armazena o resultado de volta em um registrador. A operação do fluxo de dados é o coração da maioria
4
Todo o conteúdo desta seção foi retirada do livro Organização Estruturada de Computadores, de Tanenbaun, ed. Prentice/Hall.
14
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
dos sistemas. Extrapolando, ela define o que a máquina pode fazer. Voltaremos a este importante tópico
em breve.
Figura 4 – Fluxo de dados de uma máquina de von Neumann típica.
1.5
Microprocessadores e a Memória Principal
Não vou perder meu tempo explicando como funciona um chip de memória ou falando de bits e bytes.
Tenho certeza que estes conceitos estão bem claros para você. No entanto, gostaria de reforçar o
conceito de nibble.
No ínicio da era dos microprocessadores, surgiram várias pastilhas de 4 bits que eram usadas em
calculadoras e outros aparelhos digitais. Quando refiro-me a microprocessadores de 4 bits, quero dizer
que os operandos manipulados pela CPU eram de apenas de 4 bits. Em vista disto, a memória era
endereçada em grupos de 4 bits chamados de nibbles. Nos dias atuais, poucos são os fabricantes, como a
National Semiconductor (http://www.national.com/), que comercializam tais CPUs. Contudo, o termo nibble
ainda é muito utilizado. Principalmente, porque quando se programa um microprocessador é bem mais fácil
lidar com números em binário e em hexadecimal (você descobrirá isto com o tempo).
Mesmo com as CPUs de 8, 16, 32 ou 64 bits, ainda podemos pensar em termo de nibble. Assim, um
byte é composto de dois nibbles: o mais e o menos significativo. Além disso, como você deve saber, para
converter-se um número binário em hexadecimal, pode-se operar sobre os nibbles de um byte. Por
exemplo, o número 10101101b pode ser convertido para hexadecimal convertendo-se 1010b = Ah e 1101b =
Eh, ou seja, 10101101b = AEh. De forma semelhante, podemos converter números em hexadecimal para
binário.
1.5.1.
Ordem dos Bytes
Os bytes em uma palavra podem ser numerados da esquerda para a direita ou da direita para a
esquerda. A princípio, parece que esta escolha não é importante, mas, como veremos brevemente, tem
maiores implicações. Considere que desejamos armazenar na memória do sistema dois números de 16 bits
(A037h e 1224h) e uma string de 4 bytes (“ALEX”). Duas possibilidades são apresentadas na Figura 5. Na
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
15
Curso de Microprocessadores
Figura 5(a), os números e a string são armazenados da esquerda para a direita (como estamos
acostumados), como na família Motorola (http://www.mot.com/). Já na Figura 5(b), a parte mais
significativa de um operando de 16 bits é armazenada no endereço de memória mais alto (o que também
parece lógico), porém a string continua sendo armazenada da esquerda para a direita, como na família
Intel.
O primeiro sistema, onde primeiro é armazenado a parte mais significativa ("big"), é chamado de
sistema "big endian", em contraste com o "little endian" da Figura 5(b). Estes termos são devidos a
Jonathan Swift, cujo livro “Aventuras de Gulliver” satirizou políticos que fizeram guerra por causa da
disputa sobre se os ovos deviam ser quebrados do lado largo (big end) ou do lado estreito (little end). O
termo foi usado pela primeira vez no encantador artigo “On Holy Wars and a Plea for Peace" de Danny
Cohen (1980).
Os problemas com estas duas representações começam a ocorrer quando queremos trocar dados
entre duas CPUs diferentes. Por exemplo, suponha que um sistema big endian esteja conectado a um little
endian por um meio que permita a transferência de um byte por vez. Para realizar a conexão, poderíamos
transmitir os bytes começando no byte 0 e terminado no 3 (0, 1, 2, 3, 4, 5, 6, 7). Neste caso, as posições
de memória do little endian seriam idênticas as do big endian. Com isto, a string ficaria na ordem correta,
mas os números não. Caso trocássemos a ordem de envio dos dados (1, 0, 3, 2, 5, 4, 7, 6) teríamos os
números corretos, mas a string não.
Endereço
Big endian
Endereço
Little endian
0
A0h
37h
0
37h
A0h
2
12h
24h
2
24h
12h
4
‘A’
‘L'
4
‘A’
‘L'
6
‘E’
‘X’
6
‘E’
‘X’
(a)
(b)
Figura 5 – (a) Memória big endian. (b) Memória little endian.
Quero que você termine esta seção com a idéia clara de que a falta de um padrão para a ordem dos
bytes é um grande problema na troca de dados entre CPUs diferentes.
1.6
Controladores de Dispositivos
Como dito na Seção 1.2, a CPU precisa receber dados e enviar resultados para o “mundo exterior”.
Você já sabe que isto é feito pelos dispositivos de E/S. Contudo, os tipos de dispositivos que podem ser
utilizados dependem da aplicação e são infinitos. Além disso, a maneira como os diversos tipos de
dispositivos representam uma informação também é infinita. A título de exemplo, são apresentados na
Tabela 1 alguns dispositivos de E/S e a maneira que eles representam as informações.
Evidentemente, seria muito difícil para o projetista realizar a interface entre o microprocessador e
todos esses dispositivos, em vista das diferentes formas de representar a informação. Por isto, centenas
de fabricantes comercializam dispositivos que realizam a interface entre a CPU e os dispositivos de E/S.
Estes dispositivos são chamados de Controladores de Dispositivos.
Um controlador de dispositivo faz com que a operação de E/S seja realizada (quase) como uma
leitura/escrita na memória. De um lado, os controladores de dispositivos são conectados ao dispositivo de
E/S da maneira adequada. Do outro, os controladores de dispositivos são conectados ao barramento do
sistema. Desse modo, a CPU pode usar as linhas de endereço e os sinais de controle (WR/ RD , CS , etc)
para receber e enviar as informações aos dispositivos de E/S.
Na verdade, isto só é completamente correto se a CPU utilizar E/S mapeada em memória, ou seja, as
mesmas instruções usadas para acessar a memória lêem/escrevem dados nos controladores de dispositivos
(CD). Em outras CPUs, como as da família Intel, existem instruções próprias para trabalhar com E/S.
Estas instruções podem desativar um pino de saída da CPU [algumas vezes chamado de MREQ
16
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
(REQuisição de Memória)] para avisar que trata-se de uma leitura/escrita em um CD. O sinal deste pino
deve então ser incluído na lógica de seleção dos chips de memória e dos controladores de dispositivos.
Tipo de Dispositivo
Representação da Informação
Serial
Representa uma palavra binária de n bits através de uma saída (ou entrada)
digital de um único pino, um bit por vez. A palavra é identificada observando-se
o estado do pino em n instantes de tempo.
Paralelo
Representa uma palavra binária de n bits através de uma saída (ou entrada)
digital de n pinos, n bits por vez. A palavra é identificada observando-se o
estado dos n pinos em um único instante de tempo.
Transdutores Analógicos Representam uma grandeza física qualquer, através de uma grandeza elétrica
(tensão, corrente, resistência, potência, etc), geralmente na forma analógica.
Teclado
Representam uma tecla através da sua localização linha-coluna em uma matriz
de teclas.
Visor de Caracteres
Representa um caractere através de um conjunto de pontos em uma matriz de
pontos.
Tabela 1 – Exemplos dispositivos de E/S e a maneira de como eles representam as
informações.
A CPU interage com um controlador de dispositivos através de um conjunto de registradores
internos ao controlador. Estes registradores são divididos em três categorias: registradores de
configuração, registradores de status e registradores de dados, como é ilustrado na Figura 6.
É através dos registradores de configuração que a CPU diz ao controlador como quer que o
dispositivo de E/S trabalhe. Ela pode definir, por exemplo, que os caracteres de um display de cristal
líquido tenham uma dimensão de 5x7 pontos.
Figura 6 – Esquema de ligação de um dispositivo de E/S e um CPU, através de um
controlador de dispositivo.
Os registradores de status são utilizados pela CPU para saber o andamento da operação de E/S ou a
sua configuração. Em um dispositivo serial, por exemplo, tem-se que verificar se o dado anterior já foi
enviado com sucesso antes de enviar o próximo dado. Além disso, através desses registradores a CPU pode
saber se existe um dado novo em um dispositivo de entrada.
É através dos registradores de dados que a CPU envia e recebe os dados de um dispositivo. Uma
leitura em um desses registradores é equivalente a receber um dado do dispositivo, já uma escrita,
corresponde ao envio de um dado.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
17
Curso de Microprocessadores
Por último, devemos saber que quando utilizamos dispositivos de E/S, como regra geral, primeiro a
CPU deve acessar os registradores de controle para configurar o dispositivo de E/S. Em seguida, caso
quisermos enviar ou receber dados, a CPU precisa ler as informações contidas nos registradores de status.
Só assim, ela poderá receber ou enviar os dados desejados, através do registrador de dados.
Preste atenção! No parágrafo anterior, falei que sempre que desejarmos receber um dado de um
dispositivo de E/S, a CPU precisa verificar o registrador de status. Agora, imagine um sistema que
contenha uma infinidade de dispositivos de E/S. Neste caso, a CPU gastaria a maior parte do tempo de
processamento verificando se existe dados novos em seus dispositivos. Na maior parte das vezes, a
resposta seria negativa. Isto significa que a maior parte do tempo de processamento seria perdida. Para
evitar esta tragédia, em alguns casos, o próprio controlador de dispositivo avisa a CPU quando existe um
dado novo no dispositivo de E/S. Quando recebe este aviso, a CPU para o que está fazendo e realiza a
operação de E/S. Este aviso é feito através da ativação de um sinal de controle do barramento chamado
de sinal de interrupção. No Capítulo 3, estudaremos está técnica de E/S em mais detalhes.
1.7
Compartilhando as Informações
Vimos até aqui a maioria dos componentes de um sistema microprocessado. Contudo, para que eles
realmente façam parte de um sistema, é necessário que estejam interligados através de um caminho
comum (trilhas em uma placa de circuito impresso, fios elétricos, fibra ótica, ou qualquer outra coisa que
inventaram ou venham a inventar). Como você deve estar imaginando, este caminho comum é o barramento.
Podem estar conectados a um barramento os pinos de saída de diversos dispositivos elétricos. Por
isto, o barramento é dito um recurso compartilhado. Além disso, para que um dispositivo possa ser
conectado ao barramento (sem “torrar” os pinos de saída de todos os outros), é necessário que o mesmo
tenha saídas tri-state (por favor, tente lembrar-se disto). Isto também significa que, em um mesmo
instante de tempo, apenas os pinos de saída de um dispositivo podem estar conectados ao barramento, ou
seja, o barramento suporta apenas um mestre por vez. Chama-se mestre o dispositivo que está escrevendo
dados no barramento. Já o dispositivo a que se destina os dados, chama-se escravo. Observe que esta
limitação não se aplica aos escravos, isto é, podem haver mais de um escravo por vez.
Você já sabe como realizar operações de Leitura/Escrita em um chip de memória. Um chip deste
tipo contém pinos de endereço, dados e controle (WR/ RD , CS , etc). Estes pinos também são comuns aos
outros componentes de um sistema microprocessado. Logo, os sinais que fazem parte de um barramento
também podem ser divididos nestes três grupos: endereço, dados e controle. Na Seção 1.6, vimos que um
controlador de dispositivo pode enviar um sinal de interrupção para a CPU. Este sinal também é
transmitido pelo barramento. Isto que dizer que neste curso você verá outros sinais, além dos quais você
já está acostumado (da sua experiência com chips de memória).
1.7.1.
Pinagem e Encapsulamento
A pinagem lógica de uma CPU geral pode parecer-se com a da Figura 7. A pinagem real pode ser
diferente. Por exemplo, em 99,99% (100% é um valor muito perigoso) das CPUs, os pinos de dados são
multiplexados com os de endereço. Isto acontece porque os pinos de dados e os pinos de endereço nunca
são necessários em um mesmo instante (basta usarmos alguns 74373s para sustentar o endereço enquanto
recebe/envia o dado). Além disso, uma CPU com menos pinos é uma CPU mais barata.
Muito pode ser dito sobre um MCU observando-se apenas a sua pinagem. Principalmente com relação
aos pinos de dados e endereço. Pois o poder de processamento de uma CPU é intimamente ligado com a
quantidade de pinos de endereço e de dados que ela possui. Quanto maior o número de pinos de dados,
maior será a velocidade da CPU, a sua complexidade e o seu custo final. Além disso, o número de bits dos
registradores de uma CPU, geralmente, é igual ao número de pinos de dados. Evidentemente, quanto maior
a capacidade dos registradores maior o poder de processamento (velocidade) da CPU. Em muitas
aplicações, a velocidade é uma fator importantíssimo.
Sistemas que trabalham com grande quantidade de dados exigem grande quantidade de memória.
Desde que, para endereçar 2n bytes uma CPU necessita de n pinos de endereço, o número de linhas de
18
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 1- Visão Geral
endereço também é um fator limitante. Contudo, quando trabalha com endereços uma CPU precisa realizar
operações de soma, subtração, deslocamentos, etc. Por isso, aumentando-se o número de bits dos
endereços com os quais a CPU trabalha, aumenta-se também a complexidade dessas operações. Por isso,
uma CPU com um grande número de linhas (pinos) de endereço, geralmente, é muito poderosa e altamente
complexa.
Figura 7 – Pinagem lógica de um MCU bastante simples (hipotético).
Apesar da multifunção de alguns pinos, algumas CPUs apresentam uma quantidade enorme de pinos.
(Isto deixa os fabricantes realmente malucos na hora de encapsular o circuito integrado.) Por isso, com o
passar dos anos (e o aumento dos pinos), foram surgido vários tipos de encapsulamento. Alguns, são
apresentados na Figura 8.
(a)
(b)
(c)
(d)
Figura 8 – (a) encapsulamento DIP, (b) encapsulamento PLCC, (c)
encapsulamento PGA, (d) encapsulamento SMD.
A maior parte dos pinos de uma CPU são compostos pelos pinos de endereço. As CPUs mais simples
possuem no máximo 20 linhas de endereço. Essas CPUs podem facilmente ser enc1apsuladas em um
encapsulamento DIP (Dual in Parallel) de 40 pinos, Figura 8(a). A CPU mais conhecida que utiliza este
encapsulamento talvez seja a Intel 8088.
É importante lembrar que as CPUs nem sempre são soldadas sobre a placa de circuito impresso.
Solda-se primeiro um soquete na placa e encaixa-se o circuito integrado neste soquete, Figura 9.
Como dito na Seção 1.1, os microcontroladores possuem diversos dispositivos de E/S encapsulados
em um único chip. De fato, os microcontroladores (MCUs) são, por si só, um sistema microprocessado. Os
MCUs precisam de um encapsulamento que suporte mais pinos, por isto, muitos deles utilizam o
encapsulamento PLCC (Plastic Leadless Chip Carrier), um encapsulamento plástico barato que tem
terminais saindo pelos quatro lados do CI, na maioria das vezes dobrado para baixo, de modo a encaixar-se
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
19
Curso de Microprocessadores
perfeitamente em um soquete apropriado, Figura 8(b). Este encapsulamento torna a retirada do chip deste
soquete uma tarefa muito delicada.
Figura 9 – Encaixe de um circuito integrado DIP em seu respectivo soquete.
Nos encapsulamento da Figura 8(a) e da Figura 8(b), cada terminal do chip recebe um número de
identificação próprio. Por exemplo, chamamos "pino 20" ao vigésimo terminal contando a partir do
primeiro.
O terceiro tipo de padrão de pinagem que existe para circuitos integrados é o PGA (Pin Grid Array),
em que os terminais saem por baixo do circuito integrado (Figura 8(c)), formando linhas e colunas que são
referidas não mais por uma numeração seqüencial, mas sim por uma numeração baseada em linhas e
colunas, como em uma batalha naval (por exemplo, chamamos de C3 o terminal localizado na interseção da
terceira linha com a terceira coluna), pois agora a quantidade de terminais é imensa.
Existe ainda um quarto tipo de invólucro, chamado PQFP (Piastic Quad Fiat Packa,ge), em que os
terminais saem lateralmente pelos quatro cantos do invólucro (Figura 8(d)). Diferentemente do PLCC, que
é projetado para ser encaixado em soquetes apropriados, o PQFP é projetado para ser soldado
diretamente sobre a placa de circuito impresso com uma técnica especial, chamada SMD (Surface
Mountage Devices - Dispositivos em Montagma de Superfície). Por isso, o encapsulamento PQFP é mais
conhecido como encapsulamento SMD.
A técnica SMD também está relacionada com a disposição dos terminais de um circuito integrado e
permitiu a diminuição do circuito como um todo em uma placa de circuito impresso. Esta técnica consiste
em soldar diretamente um circuito integrado sobre a placa de circuito impresso através de calor indireto
utilizando, para isso, modernos equipamentos de automação e robótica. Isto faz com que os circuitos
sejam menores por um simples motivo: são os terminais e o encapsulamento que são os responsáveis pela
maior parte do tamanho de um CI. Com esta técnica, o tamanho do encapsulamento é reduzido
consideravelmente, bem como os terminais. Em uma grande linha de montagem, tais circuitos são soldados
automaticamente por máquinas autômatas após a confecção da placa de circuito impresso. A grande
maioria dos circuitos integrados possuem versões em SMD, mesmo os circuitos integrados mais antigos em
MSI e LSI. Com isto, temos aparelhos e circuitos cada vez menores – leia-se aí qualquer tipo de circuito
eletrônico como aparelhos de videocassete, aparelhos de controle remoto, etc.
1.8
Comentários
Pronto! Você já sabe o que é um sistema microprocessado. Mais ainda, você sabe as partes que o
compõem e com elas relacionam-se. Os capítulos que seguem, simplesmente, descrevem bem mais
detalhadamente este relacionamento. Além disso, nos ensina como projetar nosso próprio sistema
microprocessado. Para isto, procurei fornecer a maior quantidade de informação possível. No entanto,
devido a grande variedade de microprocessadores e microcontroladores existentes no mercado, tenho
certeza que não será tudo (se é que “tudo” realmente existe). Como já disse, um fato está do nosso lado: a
filosofia de todas as CPUs é a mesma, o que muda entre uma família e outra é a maneira de fazer a mesma
coisa. Algumas dessas maneiras serão discutidas quando falarmos sobre arquiteturas avançadas de
microprocessadores.
20
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
Capítulo 2 - Microprogramação5
O limite entre hardware e software não é bem definido e, além disso, está constantemente se
alterando. Os primeiros computadores tinham instruções para operações aritméticas, booleanas,
deslocamentos, comparações, entre outras, que eram executadas diretamente pelo hardware. Para cada
instrução, um circuito especifico de hardware estava presente para executá-la. Poder-se-ia, pelo menos
em princípio, desparafusar o painel traseiro e apontar os componentes eletrônicos usados pela instrução
de divisão.
Nas CPUs de hoje, não é mais possível isolar os circuitos de divisão, porque não existem circuitos de
divisão. Todas as instruções disponíveis no nível de máquina convencional (por exemplo, instruções
aritméticas, booleanas, deslocamentos, comparações e MCUs) são executadas passo a passo por um
interpretador executado no nível de microprogramação. O equivalente atual de olhar para os circuitos de
divisão é obter uma listagem do microprograma e procurar pela parte que interpreta as instruções de
divisão.
Embora programas em qualquer nível possam ser executados por um software interpretador, e
embora este interpretador possa, também, ser executado por outro interpretador, essa hierarquia não
pode prosseguir indefinidamente. No nível mais baixo, deve existir fisicamente uma máquina em hardware,
com circuitos integrados e objetos "sólidos" similares. Neste capítulo, iremos estudar como os
componentes eletrônicos são controlados pelo microprograma e como este interpreta o nível de máquina
convencional. Em breve, estudaremos uma classe de máquinas que não são microprogramadas (máquinas
RISC6).
Como a arquitetura do nível de microprogramação, chamada de microarquitetura, é definida pelo
hardware, ela é normalmente primitiva e difícil de programar. As considerações de tempo são, por
exemplo, freqüentemente importantes. Na realidade, ninguém programa com microinstruções. Elas são
utilizadas apenas uma única fez pelos projetistas para escrever o microprograma. Por isso, não as trate
como as instruções que você está acostumado.
O nível de microprogramação tem uma função específica: executar interpretadores para outras
máquinas virtuais (esperançosamente mais razoáveis). Esta meta de projeto leva naturalmente a uma
organização altamente otimizada no sentido de buscar, examinar e executar instruções de máquina
convencional e, em alguns casos, instruções mais sofisticadas. Os problemas e compromissos envolvidos na
organização e projeto deste nível serão examinados neste capítulo, através do projeto de uma CPU CISC
(Complex Instruction Set Computers, ou seja, máquinas com um conjunto de instruções complexo, como
são chamadas as CPUs que possuem um microprograma) bastante simples.
2.1
Um Exemplo de Microarquitetura
No clássico livro “The C programming Language” (2ed., Prentice Hall, 1988), Brian Kernighan e
Dennis Ritchie começam a discutir a linguagem C com o agora famoso programa “Hello, word!”:
#include <stdio.h>
main()
{
printf(“Hello, word!\n”);
}
5
6
Todo o conteúdo deste capítulo foi retirado do livro Organização Estruturada de Computadores, de Tanenbaun, ed. Prentice/Hall.
Reduced Instructions Set Computers, ou seja, computadores com um conjunto reduzidos de instruções.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
21
Curso de Microprocessadores
Este programa foi escrito o mais simples possível, apenas para começar uma discussão sobre as
características de um programa em C. Neste capítulo, começo com o projeto de uma CPU tão simples
quanto possível, apenas para discutir os problemas e compromissos envolvidos na organização e projeto de
uma CPU.
2.1.1.
Componentes Básicos
O trabalho do microprogramador é escrever um programa para controlar os registradores da
máquina, seus barramentos, ALUs, memórias e outros componentes de hardware. Estes componentes
foram estudados exaustivamente por você no ano que passou. Começaremos esta seção definido estes
componentes para a nossa microarquitetura.
2.1.1.1.
ALU e Deslocador
Toda CPU precisa, de alguma maneira, realizar operações aritméticas. O circuito mais simples é
apenas um somador, que pega duas entradas de n bits e produz sua soma como saída. Um circuito
aritmético mais geral é a ALU. Ela possui duas entradas de dados e uma saída de dados, mas também
possui algumas entradas e saídas de controle. A ALU da Figura 10(a) tem dois bits de função, F0 e F1, que
determinam qual a função que a ALU deve realizar. A ALU que usaremos em nosso exemplo pode calcular A
+ B, A AND B, A e também A . As duas primeiras funções são auto-explicativas; a terceira simplesmente
copia A para a saída; a quarta produz o inverso de A. A terceira função pode parecer inútil, mas veremos
mais tarde para que ela é muito usada.
Uma ALU pode também ter saídas de controle. Saídas típicas são linhas que estão em 1 quando a
saída da ALU é negativa, quando é zero, quando existe um vai-1 do bit de mais alta ordem, ou quando
ocorreu overflow. O exemplo da Figura 10(a) tem duas saídas de controle: N, que indica que a saída da ALU
é negativa, e Z, que indica que a saída é zero. O bit N é apenas uma cópia do bit de mais alta ordem da
saída. O bit Z é o NOR de todos os bits de saída da ALU.
Embora algumas ALUs possam também realizar operações de deslocamento, na maioria das vezes é
necessário ter uma unidade de deslocamento separada. Como você já sabe, um deslocador pode deslocar
uma entrada multibit de 1 bit para a esquerda ou direita, ou, ainda, não realizar nenhum deslocamento. A
Figura 10(b) é o símbolo que usaremos para um deslocador.
(a)
(b)
Figura 10 –(a) ALU e (b) deslocador utilizados no exemplo.
2.1.1.2.
Relógio (clock)
Os circuitos de sistema microprocessado são normalmente acionados por um relógio, um dispositivo
que emite uma seqüência periódica de pulsos. Estes pulsos definem os ciclos de máquina. Tudo que
acontece na CPU (alguma atividade básica, tal como a execução de uma microinstrução), ocorre em um
intervalo de tempo múltiplo de um ciclo de máquina. É freqüentemente útil dividir o ciclo de máquina em
subciclos, de modo que diferentes partes da microinstrução possam ser realizadas em uma ordem bem
22
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
definida. (Lembra da Seção 1.3) Lá você viu que uma instrução é executada em diversos passos.) Por
exemplo, as entradas para a ALU devem ser colocadas disponíveis e se tornarem estáveis antes que a saída
possa ser armazenada.
A Figura 11(a) mostra um relógio simbólico com quatro saídas. A de cima é a saída primária; as outras
três são derivadas dela pela inserção de diversos atrasos nas linhas de saída. O relógio primário tem uma
largura de pulso igual a um quarto do período do ciclo (Figura 11(b), linha superior). As outras três saídas
são obtidas por atraso de uma, duas e três vezes a largura do pulso. O resultado é um circuito que divide
cada ciclo em quatro subciclos de mesma duração.
Para provocar quatro transições diferentes que devem ocorrer em um ciclo em uma certa ordem, o
projetista da CPU pode fazer um AND do sinal habilitador de cada um com uma linha diferente do relógio.
A transição ligada à linha de relógio primária ocorrerá primeiro, a transição ligada à linha de relógio com o
menor atraso ocorrerá em segundo lugar, e assim por diante.
(a)
(b)
Figura 11 – (a) Relógio com 4 saídas em atraso. (b) O diagrama de temporização das
saídas.
2.1.1.3.
Memória Principal
Os processadores precisam ser capazes de ler e escrever dados na memória. A maioria das CPUs
possui um barramento de endereço, um barramento de dados e um barramento de controle para a
comunicação entre a CPU e a memória. Para ler da memória, a CPU coloca um endereço de memória no
barramento de endereço e estabelece os sinais de controle apropriados, ativando RD (READ), por exemplo.
A memória coloca, então, o conteúdo requisitado no barramento de dados. Em algumas CPUs, a
leitura/escrita da memória é síncrona, isto é, a memória deve responder dentro de um tempo fixo (todas
as CPUs utilizadas no curso utilizam esta técnica). Em outras, a memória pode demorar quanto quiser,
sinalizando a presença de dados usando uma linha de controle quando terminar.
Escritas na memória são feitas de modo similar. A CPU coloca o dado a ser escrito no barramento de
dados e o endereço a ser armazenado no barramento de endereços, e então ativa WR (WRITE). (Uma
alternativa para RD e WR é ter MREQ, que indica que se deseja uma requisição de memória, e RW, que
distingue leitura de escrita.)
Um acesso à memória é quase sempre consideravelmente mais demorado que o tempo necessário
para executar uma única microinstrução. Conseqüentemente, o microprograma deve manter os valores
corretos nos barramentos de dados e endereços por várias microinstruções. Para simplificar esta tarefa,
é muitas vezes conveniente ter-se dois registradores, o MAR (Memory Address Register, ou registrador
de endereço de memória) e o MBR (Memory Buffer Register, ou registrador de dados de memória), que
alimentam os barramentos de endereços e dados, respectivamente. Para os nossos propósitos, será
conveniente organizar os barramentos como indicado na Figura 12. Ambos os registradores ficam
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
23
Curso de Microprocessadores
(logicamente e não fisicamente) entre a CPU e o barramento do sistema. O barramento de endereços é
unidirecional em ambos os lados e é carregado do lado da CPU quando a linha de controle é ativada. A saída
para as linhas de endereço do sistema está sempre habilita [ou possivelmente apenas durante as leituras e
escritas, o que requer uma linha de habilitação de saída ativada pelo OR de RD e WR (não mostrado)]. A
linha de controle de MBR faz com que o dado seja carregado do barramento de "Entrada de dados" no lado
da CPU. A linha de "Saída de dados" está sempre habilitada. O barramento de dados do sistema é
bidirecional, dando saída de MBR quando WR é ativado e carregando MBR quando RD é ativado.
Figura 12 – Os registradores utilizados para acionar os barramentos de endereço e
dados.
2.1.2.
As Vias de Dados
Agora que já vimos todos os componentes básicos com os quais se constrói o nível de
microprogramação, é o momento de vermos como estes são conectados. Como, nesta área, os princípios
gerais são poucos e dispersos, introduziremos o assunto através de um exemplo detalhado.
As vias de dados de nossa microarquitetura exemplo estão apresentadas na Figura 13. (As vias de
dados correspondem àquela parte da CPU que contém a ALU, suas entradas e suas saídas.) Elas possuem 16
registradores idênticos de 16 bits, denominados PC, AC, SP, e assim por diante, que formam uma memória
de rascunho acessível apenas ao nível de microprogramação, ou seja, apenas ao microprogramador. Os
registradores rotulados 0, +1 e -1 serão usados para armazenar as constantes indicadas; o significado dos
nomes dos outros registradores serão explicado mais tarde. (Na realidade, 0 não foi utilizado em nossos
exemplos simples, mas provavelmente o seria em uma máquina mais complicada; de qualquer forma, foi
incluído porque temos mais registradores do que podemos usar.) Cada registrador pode dar saída de seu
conteúdo em um ou nos dois barramentos internos, o barramento A e o barramento B, e cada um pode ser
carregado a partir de um terceiro barramento interno (menos aqueles que armazenam constantes), o
barramento C, como mostra a figura.
Os barramentos A e B alimentam uma ALU de largura de 16 bits, que pode realizar quatro funções:
A + B, A AND B, A e NOT A. A função a ser executada é especificada pelas duas linhas de controle da
ALU, F0 e F1. A ALU gera dois bits de status, com base na saída corrente da ALU: N, que é ligado quando a
saída da ALU é negativa, e Z, que é ligado quando a saída da ALU é zero.
A saída da ALU entra em um deslocador, que pode deslocá-la de 1 bit em qualquer direção ou
nenhuma. É possível executar um deslocamento de 2 bits à esquerda do conteúdo de um registrador, R,
calculando R + R na ALU (que é um deslocamento de 1 bit para a esquerda) e então deslocando a soma de
outro bit à esquerda utilizando o deslocador.
Nem o barramento A, nem o barramento B, alimenta a ALU diretamente. Em vez disso cada um
alimenta um latch (isto é, um registrador) que, por sua vez, alimenta a ALU. Os latches são necessários
porque a ALU é um circuito combinatório - ela calcula continuamente a saída a partir das entradas
correntes e do código de função. Esta organização pode causar problemas ao calcular, por exemplo, A = A
24
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
+ B. Como A está sendo armazenado, o valor no barramento A começa a se modificar, fazendo com que a
saída da ALU, e portanto também o barramento C, se modifiquem. Conseqüentemente, um valor errado
pode ser armazenado em A. Em outras palavras, na atribuição A = A + B, o A do lado direito é o valor
original de A, e não alguma mistura bit a bit dos valores velho e novo. Inserindo latches nos barramentos A
e B, podemos congelar lá os valores originais de A e B no início do ciclo, de modo que a ALU fica protegida
de mudanças nos barramentos enquanto um novo valor está sendo armazenado na memória de rascunho. A
carga dos latches é controlada por L0 e L1.
Figura 13 – As vias de dados da microarquitetura exemplo.
Vale a pena notar que nossa solução para este problema (isto é, a inserção de latches na frente da
ALU) não é a única. Se todos os registradores fossem flip-flop’s em vez de latches, então um projeto de
dois barramentos seria também possível, carregando os operandos nos barramentos A e B no início do ciclo
e lendo o resultado de um dos barramentos mais tarde, no ciclo. Os compromissos entre os projetos de
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
25
Curso de Microprocessadores
dois e três barramentos envolvem complexidade, paralelismo e quantidade de ligações. Um tratamento
mais detalhado dessas considerações está fora do escopo deste curso.
Para a comunicação com a memória, incluímos um MAR e um MBR na microarquitetura. O MAR pode
ser carregado a partir do latch B, em paralelo com a operação da ALU. A linha M0 controla a carga do
MAR. Nas escritas, o MBR pode ser carregado com a saída do deslocador, em paralelo, ou no lugar de uma
escrita na memória de rascunho. M1 controla a carga de MBR a partir da saída do deslocador. M2 e M3
controlam leituras e escritas da memória. Nas leituras, o dado lido da memória pode chegar à entrada
esquerda da ALU através do multiplexador A, indicado por Amux na Figura 13. A linha de controle, A0,
determina se é o latch A ou o MBR que deve alimentar a ALU.
2.1.3.
Microinstruções
Para controlar as vias de dados da Figura 13, precisamos de 59 sinais. Estes podem ser divididos em
oito grupos funcionais, como descrito abaixo.
16 sinais para controlar a carga do barramento A a partir da memória de rascunho;
16 sinais para controlar a carga do barramento B a partir da memória de rascunho;
16 sinais para controlar a carga da memória de rascunho a partir do barramento C;
2 sinais para controlar os lanches A e B;
2 sinais para controlar a função da ALU;
2 sinais para controlar o deslocador;
4 sinais para controlar o MAR e o MBR (sendo que RD é conectado à M2 e WR é conectado à M3,
como apresentado na Figura 12), e;
1 sinal para controlar o Amux.
Dados os valores dos 59 sinais, podemos realizar um ciclo nas vias de dados. Um ciclo consiste em
colocar valores nos barramentos A e B, armazená-los nos dois latches de barramento, passar os valores
através da ALU e do deslocador e, finalmente, armazenar o resultado na memória de rascunho e/ou MBR.
Além disso, o MAR pode também ser carregado, e um ciclo de memória iniciado. Como uma primeira
aproximação, podemos ter um registrador de controle de 59 bits, com um bit para cada sinal de controle.
Um bit em 1 significa que o sinal está ativado, e em 0 significa que ele está desativado.
Entretanto, pelo preço de um pequeno aumento na circuitaria, podemos reduzir consideravelmente o
número de bits necessário para controlar as vias de dados. Para começar, temos 16 bits para controlar a
entrada do barramento A, o que permite 216 combinações de registradores fonte. Apenas 16 dessas
combinações são permitidas - ou seja, apenas um dos 16 registradores de cada vez. Portanto, podemos
codificar a informação sobre o barramento A em 4 bits e usar um decodificador para gerar os 16 sinais de
controle. O mesmo se aplica ao barramento B.
A situação é ligeiramente diferente para o barramento C. Em princípio, são possíveis
armazenamentos simultâneos múltiplos na memória de rascunho, mas este aspecto virtualmente nunca é
utilizado na prática, e a maioria das implementações não o provê. Assim, codificaremos o controle do
barramento C em 4 bits. Tendo economizado 3 x 12 = 36 bits, precisamos agora de 23 bits de controle
para acionar as vias de dados. L0 e L1 sempre são necessários em instantes bastante determinados, de
forma que podem ser supridos pelo relógio, deixando-nos com 21 bits de controle. Um sinal adicional que
não é estritamente necessário, mas que é freqüentemente útil, é um para habilitar/inibir o armazenamento
do valor existente no barramento C na memória de rascunho. Em algumas situações, deseja-se meramente
executar uma operação da ALU para gerar os sinais N e Z, mas não se quer armazenar o resultado. (Você
consegue pensar em um caso desses?) Com este bit extra, que denominaremos ENC (ENable C, ou habilita
C), podemos indicar se o barramento C deve ser armazenado (ENC = 1) ou não (ENC = 0). Agora, podemos
controlar as vias de dados com um número de 22 bits.
26
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
O próximo passo no projeto da microarquitetura é inventar um formato de microinstrução contendo
22 bits. A Figura 14 mostra um formato desse tipo, com dois campos adicionais, COND e ADDR, que serão
descritos em breve. A microinstrução contém 13 campos 11 dos quais estão apresentados na Figura 14.
AMUX
ALU
SH
MBR
MAR
RD
WR
ENC
C
B
A
AMUX
0 = latch A
1 = MBR
- controla a entrada esquerda da ALU: 0 = latch A, 1 = MBR
- função da ALU: 0 = A + B, 1 = A AND B, 2 = A, 3 = A
- função do deslocador: 0 = nenhum deslocamento, 1 = à direita, 2 = à esquerda
- carrega MBR a partir do deslocador: 0 = não carrega, 1 = carrega MBR
- carrega MAR a partir do latch B: 0 = não carrega, 1 = carrega MAR
- requisita leitura de memória: 0 = nenhuma leitura, 1 = carrega MBR a partir da
memória
- requisita escrita na memória: 0 = nenhuma escrita, 1 = escreve o conteúdo de
MBR na memória
- controla armazenamento na memória de rascunho: 0 = não armazena, 1 = armazena
- seleciona registrador para armazenamento se ENC = 1: 0 = PC, 1 = AC, etc.
- seleciona fonte do barramento B: 0 = PC, 1 = AC, etc.
- seleciona fonte do barramento A: 0 = PC, 1 = AC, etc.
COND
ALU
0 = Não desvie
1= Desvie se N=1
2 = Desvie se Z = 1
3 = Desvie sempre
0=A+B
1 = A AND B
2=A
3=
A
SH
0 = Não desloque
1 = Desloque 1 bit à esq.
2 = Desloque 1 bit à dir.
3 = (não utilizado)
MBR, MAR, RD, WR, ENC
0 = Não
1 = Sim
Figura 14 – O layout e a descrição de alguns dos campos da microinstrução que controla
as vias de dados da Figura 13.
A ordem dos campos é completamente arbitrária. Esta ordem foi escolhida para minimizar os
cruzamentos de linhas na figura subsequente. (Na realidade, este critério não é tão maluco como parece;
cruzamentos de linhas em figuras geralmente correspondem a cruzamentos de fios em placas de circuito
impresso ou em pastilhas, que causam problemas em projetos bidimensionais.)
2.1.4.
Temporização de Microinstruções
Apesar de que nossa discussão de como uma microinstrução pode controlar as vias de dados durante
um ciclo esteja quase completa, negligenciamos um assunto até agora: a temporização. Um ciclo básico de
ALU consiste em utilizar os latches A e B, prover tempo para que a ALU e o deslocador executem seu
trabalho e para armazenar os resultados. É óbvio que esses eventos devem ocorrer nesta seqüência. Se
tentarmos armazenar o valor existente no barramento C na memória de rascunho antes que os latches A e
B sejam carregados, será armazenado lixo em vez de dados úteis. Para conseguir o seqüenciamento
correto de eventos, vamos agora introduzir um relógio de quatro fases da Figura 11. Os eventos chave
durante cada um dos subciclos são:
1. Carregar a próxima microinstrução a ser executada em um registrador chamado MIR
(MicroInstruction Register), o registrador de microinstrução;
2. Colocar os conteúdos dos registradores nos barramentos A e B e armazená-los nos latches A e B;
3. Agora que as entradas estão estáveis, dar tempo para que a ALU e o deslocador produzam uma
saída estável, e carregar o MAR se requisitado, e;
4. Agora que a saída do deslocador está estável, armazenar o valor existente no barramento C na
memória de rascunho e carregar o MBR, se for necessário.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
27
Curso de Microprocessadores
A Figura 15 é um diagrama de blocos detalhado da microarquitetura completa de nossa máquina
exemplo. Pode parecer complicado inicialmente, mas vale a pena estudá-lo cuidadosamente. Ao
compreender totalmente cada bloco e cada linha, estará bem encaminhado no entendimento do nível de
microprogramação. O diagrama de blocos tem duas partes: as vias de dados, à esquerda, que já discutimos
em detalhe, e a seção de controle, à direita, que veremos agora.
Figura 15 – O diagrama de blocos completo de nossa microarquitetura exemplo.
O maior e mais importante item na seção de controle da máquina é a memória de controle. Esta ROM
rápida especial é onde as microinstruções são mantidas. Em nosso exemplo as microinstruções terão
largura de 32 bits (Figura 14) e o espaço de endereçamento das microinstruções consistirá em 256
palavras de forma que a memória de controle ocupará um máximo de 256 x 32 = 8.192 bits.
Como qualquer outra memória, a memória de controle precisa de um MAR e de um MBR. Chamaremos
o MAR de MPC (MicroProgram Counter, ou contador de microprograma), porque sua única função é apontar
para a próxima microinstrução a ser executada. O MBR é apenas o MIR, como mencionado acima. Note que
a memória de controle e a memória principal são completamente diferentes, a primeira guarda o
microprograma, e a segunda, o programa na linguagem de máquina convencional.
A partir da Figura 15 fica claro que a memória de controle tenta continuamente copiar a
microinstrução endereçada pelo MPC para o MIR. Entretanto, o MIR somente é carregado durante o
subciclo 1, como indicado pela linha tracejada vinda do relógio para ele. Durante os outros três subciclos
ele não é afetado, independente do que ocorre com MPC.
Durante o subciclo 2, o MIR fica estável, e os vários campos começam a controlar as vias de dados.
Em particular, A e B fazem com que os dados sejam colocados nos barramentos A e B. Os blocos
decodificador A e decodificador B no diagrama de blocos provêm a decodificação de 4-para-16 de cada
campo necessário para acionar as linhas OE1 (habilita saída para o barramento A) e OE2 (habilita saída
28
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
para o barramento B) nos registradores. O relógio ativa os latches A e B durante este subciclo, provendo
entradas estáveis para a ALU durante o resto do ciclo. Enquanto os dados estão sendo colocados nos
barramentos A e B, a unidade de incremento na seção de controle da máquina calcula MPC + 1, preparando
a carga da próxima microinstrução da seqüência durante o ciclo seguinte. Sobrepondo estas duas
operações, a execução das instruções pode ser acelerada.
No terceiro subciclo, dá-se tempo à ALU e ao deslocador para a produção de resultados válidos. O
campo AMUX da microinstrução determina a entrada esquerda da ALU; a entrada da direita é sempre o
latch B. Embora a ALU seja um circuito combinatório, o tempo que ela gasta para calcular uma soma é
determinado pelo tempo de propagação de vai-1, e não pelo atraso normal das portas. O tempo de
propagação de vai-1 é proporcional ao número de bits da palavra. Enquanto a ALU e o deslocador estão
calculando, o MAR é carregado a partir do barramento B, se o campo MAR da microinstrução for 1 (um).
Durante o quarto e último subciclo, o valor existente no barramento C pode ser armazenado de volta
na memória de rascunho e no MBR, dependendo de ENC e MBR. O bloco rotulado "decodificador C" pega
ENC, a quarta linha do relógio, e o campo C da microinstrução como entradas e gera os 16 sinais de
controle. Internamente, ele realiza uma decodificação de 4-para-16 do campo C e então faz um AND de
cada um destes sinais com um sinal derivado do AND da linha do subciclo 4 com ENC. Assim, um
registrador da memória de rascunho somente é carregado se prevalecerem três condições:
1. ENC = 1;
2. É o subciclo 4, e;
3. registrador foi selecionado pelo campo C.
O MBR também é carregado durante o subciclo 4 se MBR = 1, os dois sinais que controlam a
memória, RD e WR, são ativados se estiverem presentes em MIR. Na verdade, os campos correspondentes
em MIR agem como latches.
2.1.5.
Seqüenciamento de Microinstruções
A única consideração pendente é como a próxima microinstrução é escolhida. Embora algum tempo
seja suficiente para buscar a próxima microinstrução da seqüência, algum mecanismo é necessário para
permitir desvios condicionais no microprograma, para possibilitar que ele tome decisões. Por esta razão,
deixamos dois campos em cada microinstrução: ADDR, que é o endereço da sucessora potencial da
microinstrução corrente, e COND, que determina (juntamente com as saídas N e Z da ALU) se a próxima
microinstrução será buscada de MPC + 1 ou de ADDR. Toda microinstrução contém potencialmente um
desvio condicional. Esta decisão foi tomada porque desvios condicionais são muito comuns em
microprogramas, e, ao permitir que toda microinstrução tenha duas sucessoras possíveis, tornamo-las de
execução mais rápida do que a alternativa de estabelecer alguma condição em uma microinstrução e depois
testa-la na próxima. A maioria das microarquiteturas existentes usam nossa estratégia de uma forma ou
outra.
A escolha da próxima microinstrução é determinada pelo bloco rotulado "Lógica de
Microsseqüenciamento" durante o subciclo 4, quando os sinais N e Z da saída da ALU são válidos. A saída
deste bloco (não mostrada na figura) controla o multiplexador (Mmux), que roteia MPC + 1 ou ADDR para
MPC, de onde será buscada a próxima microinstrução. Fornecemos ao microprogramador quatro escolhas
quanto à seleção da próxima microinstrução. A escolha é indicada fazendo o campo COND igual a:
0 = Não desvie; a próxima microinstrução será tomada de MPC + 1
1 = Desvie para ADDR se N = 1
2 = Desvie para ADDR se Z = 1
3 = Desvie para ADDR incondicionalmente
A lógica de microsseqüenciamento combina os dois bits da ALU, N e Z, e os dois bits de COND, L
(Left) e R (Right), isto é, esquerda e direita, para gerar uma saída, O sinal correto é
Mmux = LRN + LRZ + LR = RN + LZ + LR
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
29
Curso de Microprocessadores
Em palavras, o sinal de controle para Mmux é 1 (roteando ADDR para MPC) se LR é 01b e N = 1, ou
LR é 10b e Z = 1, ou LR é 11b. Caso contrário, ele é 0, e a próxima microinstrução na seqüência é buscada. O
circuito para a geração do sinal Mmux pode ser construído a partir de componentes SSI ou ser parte de
uma PLA.
Para tornar nossa máquina exemplo ligeiramente mais real, vamos assumir que um ciclo de memória
principal tome mais tempo que uma microinstrução. Em particular, se uma microinstrução inicia uma leitura
à memória principal, fazendo RD = 1, ela também deve ter RD = 1 na próxima microinstrução executada
(que pode ou não estar localizada no próximo endereço da memória de controle). O dado torna-se
disponível duas microinstruções após a leitura ter sido iniciada. Se o microprograma não tem nada mais útil
a fazer na microinstrução seguinte à que iniciou a leitura de memória, a microinstrução simplesmente tem
RD = 1 e é efetivamente desperdiçada. Do mesmo modo, uma escrita na memória também gasta dois
tempos de microinstrução para ser completada.
2.2
Um Exemplo de Macroarquitetura
Para Continuar nosso exemplo do nível de microprogramação, vamos agora nos voltar para a
arquitetura do nível de máquina convencional a ser suportada pelo interpretador em execução na máquina
da Figura 15. Por conveniência, vamos chamar a arquitetura da máquina de nível 2 ou 3 de
macroarquitetura, em contraste com o nível 1, a microarquitetura. [Para os propósitos deste texto, vamos
ignorar o nível 3 (nível de sistema operacional), porque suas instruções são praticamente aquelas do nível 2,
e as diferenças não são importantes aqui.] Similarmente, as instruções de nível 2 serão chamadas
macroinstruções. Assim, as instruções normais de ADD, MOVE e outras do nível de máquina convencional
serão chamadas macroinstruções. Vamos algumas vezes nos referenciar à nossa máquina exemplo de nível 1
como Mic-1, e à máquina de nível 2 como Mac-1. Antes de descrever a Mac-1, entretanto, vamos
digressionar ligeiramente para motivar seu projeto.
2.2.1.
Pilhas
Uma das questões mais importantes de projeto de macroarquiteturas é o endereçamento. Um
programa qualquer é normalmente implementado de tal modo que, quando se sai de um procedimento ou
função, a área de memória que estava sendo utilizada para variáveis locais é liberada. A maneira mais fácil
para se conseguir isto é através de uma estrutura de dados denominada pilha. Uma pilha é um bloco
contíguo de memória contendo alguns dados e um apontador de pilha (SP, de Stack Pointer) dizendo onde
está o topo da pilha. O fundo da pilha está em um endereço fixo, e não mais nos interessará. A Figura 16(a)
mostra uma pilha ocupando seis palavras de memória. O fundo da pilha está no endereço 4020, e o topo da
pilha, para onde SP aponta, está no 4015. Nossas pilhas crescerão dos endereços de memória mais altos
para os mais baixos, mas a escolha oposta é igualmente boa.
Muitas operações são definidas para pilhas. Duas das mais importantes são PUSH X e POP Y. PUSH
avança o apontador da pilha (decrementando-o, no nosso exemplo) e então armazena X na posição de
memória agora apontada por SP. PUSH aumenta o tamanho da pilha de um item. POP Y, em contraste,
reduz o tamanho da pilha, armazenando o item do topo da pilha em Y, e então removendo-o através do
incremento do apontador de pilha com o tamanho do item retirado. A Figura 16(b) mostra como a pilha da
Figura 16(a) fica depois que uma palavra contendo 5 foi empilhada.
30
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
(a)
(b)
Figura 16 – (a) Uma pilha. (b) A mesma pilha após o armazenamento da constante 5.
Outra operação que pode ser realizada numa pilha é avançar o apontador da pilha sem realmente
inserir qualquer dado. Isto é normalmente feito na entrada de um procedimento ou função, para reservar
espaço para as variáveis locais [depois que o espaço for reservado, pode-se utilizar os modos de
endereçamento (você verá em breve) para armazenar itens]. É importante observar que apenas as
instruções PUSH e POP podem armazenar e retirar itens da pilha. Por isso, não pense que você poderá
armazenar um item na pilha (utilizando a instrução MOVE, por exemplo) e avançar o ponteiro da pilha (SP)
“manualmente” (isto seria muito perigoso).
Você viu que o melhor local para armazenar dados temporários (fora da CPU) é a pilha. Contudo, a
pilha é uma estrutura dinâmica, quer dizer, seu topo está constantemente mudando de endereço (SP muda
de conteúdo). Neste caso, todas as vezes que um procedimento ou função for chamado, o topo da pilha
pode estar em um local diferente. Isto quer dizer que um item que está armazenado na pilha só pode ser
referenciado em relação ao SP. Em outras palavras, o Mac-1 precisa de um modo de endereçamento que
busque ou armazene uma palavra a uma distância conhecida relativa ao apontador de pilha (ou algum modo
de endereçamento equivalente).
Caso você não tenha entendido esta seção, pode fazer uma nova tentativa lendo o livro “Organização
Estruturada de Computadores” de Tanenbaum, páginas 142 e 143. Lá, você encontrará um exemplo mais
detalhado do uso de pilhas. Por enquanto, seguiremos com o nosso projeto.
2.2.2.
O Conjunto de Macroinstruções
Com esse modo de endereçamento em mente, estamos agora prontos para analisar a arquitetura do
Mac-1. Basicamente, ela consiste em uma memória com 4.096 palavras de 16 bits e três registradores
visíveis ao programador de nível 2. Os registradores são o contador de programa, PC, a apontador de pilha,
SP, e o acumulador, AC, que é usado para movimentação de dados, cálculos e outros propósitos. São
providos três modos de endereçamento: direto, indireto e local. As instruções que usam o endereçamento
direto contêm um endereço absoluto de memória de 12 bits nos 12 bits de baixa ordem. Tais instruções
são úteis para acessar variáveis globais. O endereçamento indireto permite que o programador calcule um
endereço de memória, coloque-o em AC e então leia ou escreva a palavra endereçada. Esta forma de
endereçamento é muito genérica e é usada para acessar elementos em arranjos (vetores), entre outras
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
31
Curso de Microprocessadores
estruturas. O endereçamento local especifica uma distância a partir de SP e é usado para acessar
variáveis locais, como acabamos de ver. Juntos, estes três modos provêem um sistema de endereçamento
simples, mas adequado.
O conjunto de instruções do Mac-1 é apresentado na Tabela 2. Cada instrução contém um código de
operação (opcode) e, algumas vezes, um endereço de memória ou uma constante. A primeira coluna mostra
o código binário da instrução. A segunda mostra seu mnemônico para a linguagem de montagem. A terceira
mostra seu nome, e a quarta descreve o que ela faz, através de um trecho em Pascal. Nestes trechos, m[x]
se refere à palavra de memória x. Assim, LODD carrega o acumulador com a palavra de memória
especificada em seus 12 bits de baixa ordem. LODD usa então endereçamento direto, enquanto LODL
carrega o acumulador com uma palavra a uma distância x acima de SP, usando portanto o endereçamento
local. LODD, STOD, ADDD e SUBD realizam quatro funções básicas usando endereçamento direto, e
LODL, STOL, ADDL e SUBL realizam as mesmas funções usando endereçamento local.
Binário
Mnemônico
Instrução
Significado
0000xxxxxxxxxxxx LODD
Carrega direto
Ac := m[x]
0001xxxxxxxxxxxx
STOD
Armazena direto
M[x] := ac
0010xxxxxxxxxxxx
ADDD
Adiciona direto
Ac := ac + m[x]
0011xxxxxxxxxxxx
SUBD
Subtrai direto
Ac := ac - m[x]
0100xxxxxxxxxxxx
JPOS
Desvia se positivo
If ac ≥ o then pc := x
0101xxxxxxxxxxxx
JZER
Desvia se zero
If ac = 0 then pc := x
0110xxxxxxxxxxxx
JUMP
Desvia sempre
Pc := x
0111xxxxxxxxxxxx
LOCO
Carrega constante
Ac := x (0 ≤ x ≤ 4095)
1000xxxxxxxxxxxx
LODL
Carga local
Ac := m[sp + x]
1001xxxxxxxxxxxx
STODL
Armazena local
M[x + sp] := ac
1010xxxxxxxxxxxx
ADDL
Adiciona local
Ac := ac + m[sp + x]
1011xxxxxxxxxxxx
SUBL
Subtrai local
Ac := ac - m[sp + x]
1100xxxxxxxxxxxx
JNEG
Desvia se negativo
If ac < 0 then pc := x
1101xxxxxxxxxxxx
JNZE
Desvia se não zero
If ac ≠ 0 then pc := x
1110xxxxxxxxxxxx
CALL
Chama procedimento
Sp := sp – 1; m[sp] := pc; pc := x
1111000000000000
PSHI
Empilha indireto
Sp := sp – 1; m[sp] := m[ac]
1111001000000000
POPI
Desempilha indireto
M[ac] := m[sp]; sp := ac
1111010000000000
PUSH
Coloca na pilha
Sp := sp – 1; m[sp] := ac
1111011000000000
POP
Retira da pilha
Ac := m[sp]; sp := sp + 1
1111100000000000
RETN
Retorna
Pc := m[sp]; sp := sp + 1
1111101000000000
SWAP
Troca ac, sp
tmp := ac; ac := sp; sp := tmp
11111100yyyyyyyy
INSP
Incrementa sp
Sp := sp + y (0 ≤ y ≤ 255)
11111110yyyyyyyy
DESP
Decrementa sp
Sp := sp – y (0 ≤ y ≤ 255)
xxxxxxxxxxxx é um endereço de máquina de 12 bits; na coluna 4, ele é chamado de x.
yyyyyyyy é uma constante de 8 bits; na coluna 4, ela é chamada de y.
Tabela 2 – O Conjunto de instruções do Mac-1.
Cinco instruções de desvio são fornecidas, um desvio incondicional (JUMP) e quatro condicionais
(JPOS, JZER, JNEG e JNZE). JUMP sempre copia seus 12 bits de baixa ordem para o contador de
programa, enquanto os outros quatro somente o fazem se a condição especificada se verificar.
LOCO carrega uma constante de 12 bits, na faixa de 0 a 4095 (inclusive), em AC. A operação inversa
é POPI, que retira uma palavra da pilha e a armazena na posição de memória endereçada por AC. PUSH e
POP são úteis na manipulação da pilha de várias maneiras. SWAP troca o conteúdo de AC com SP, o que é
útil quando SP precisa ser acrescido ou decrescido de uma quantidade não conhecida no tempo de
compilação. Ela é também útil para inicializar SP no início da execução. INSP e DESP são usados para
32
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
alterar SP de valores conhecidos em tempo de compilação. Devido à falta de espaço de codificação, as
distâncias aqui foram limitadas a 8 bits. Finalmente, CALL chama um procedimento, salvando o endereço
de retorno na pilha, e RETN retorna de um procedimento, desempilhando o endereço de retorno e
colocando-o em PC.
Até agora, nossa máquina não tem instruções de entrada/saída. Nem estamos a fim de acrescentar
alguma agora. Ela não precisa delas. Em vez disso, a máquina usará E/S mapeada em memória (veremos em
breve).
2.3
Um Exemplo de Microprograma
Tendo especificado em detalhes tanto a microarquitetura quanto a macroarquitetura, o problema
restante é a implementação: com que se parece um programa sendo executado na primeira e interpretando
a segunda, e como ele funciona? Antes que possamos responder a essas questões, devemos considerar
cuidadosamente em que linguagem queremos fazer nosso microprograma.
2.3.1.
A Microlinguagem de Montagem
Em princípio, poderíamos escrever microprogramas em binário, 32 bits por microinstrução.
Programadores masoquistas poderiam até gostar disso; certamente, ninguém mais iria. Sendo assim,
precisamos de uma linguagem simbólica na qual possamos expressar microprogramas. Uma notação possível
é fazer com que o microprogramador especifique uma microinstrução por linha, identificando cada campo
não-nulo e seu valor. Por exemplo, para somar AC e A, e armazenar o resultado em AC, poderíamos
escrever
ENC=1,C=1,B=1,A=10.
Muitas linguagens de microprogramação se parecem com isto. Entretanto, esta notação é terrível.
Uma idéia muito melhor é usar uma notação de linguagem de alto nível, mantendo o conceito básico
de uma linha de fonte por microinstrução. Conceitualmente, poder-se-iam escrever microprogramas em
uma linguagem de alto nível comum, mas como a eficiência é crucial em microprogramas, vamos nos ater à
linguagem de montagem, que definimos como uma linguagem simbólica que tem um mapeamento um-para-um
para instruções de máquina. Lembre-se de que uma ineficiência de 25% num microprograma torna toda a
máquina 25% mais lenta. Vamos chamar nossa microlinguagem de montagem de alto nível de "MAL" (Micro
Assembly Language), que, em português, pode significar "doente", como você poderá ficar se forçado a
escrever muitos microprogramas complexos para máquinas idiossincráticas. Em MAL, armazenamentos nos
16 registradores de rascunho, MAR ou MIR são representados por comandos de assinalamento. Assim, o
exemplo acima, em MAL, ficaria ac := a + ac. Para indicar o uso das funções 0, 1, 2 e 3 da ALU, podemos
escrever, por exemplo,
ac := a + ac, a := band(ir, smask), ac := a, e a := inv(a)
respectivamente, onde band significa "AND booleano" e inv significa inverso. Deslocamentos podem ser
representados pelas funções lshift, para deslocamentos para a esquerda, e rshift, para deslocamentos à
direita, como em
tir := lshift(tir + tir)
que coloca tir em ambos os barramentos A e B, realiza a adição e desloca a soma 1 bit para a esquerda
antes de armazená-la de volta em tir.
Desvios incondicionais podem ser manipulados com comandos goto; desvios condicionais podem
testar n ou z, por exemplo:
if n then goto 27
Assinalamentos e desvios podem ser combinados na mesma linha. Entretanto, um pequeno problema
aparece se desejarmos testar um registrador, mas não fazer um armazenamento. Como especificamos qual
registrador deve ser testado? Para resolver este problema, introduzimos a pseudovariável alu, à qual pode
ser assinalado um valor apenas para indicar o conteúdo da ALU. Por exemplo,
Alu := tir; if n then goto 27
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
33
Curso de Microprocessadores
0 Mar :=que
pc;rd;
{loop(código
principal}
40= 2),
Tirde
:= modo
lshift(tir);
n then
goto
ou 111x?}
significa
tir deve passar pela ALU
da ALU
que oifseu
bit de
alta{110x
ordem
possa ser
46;
testado. Note que o uso de alu significa que ENC = 0.
1 pc := pc + 1; rd;
{incremente pc}
41 Alu := tir; if n then goto 44;
{1100 ou 1101?}
Para indicar leituras e escritas à memória, vamos apenas colocar rd e wr no programa fonte. A
2 Ir := mbr; if n then goto 28
{salva, decodifica 42 Alu := ac; if n then goto 22;
{1100 = JNEG}
ordem das várias partes do comando fonte é, em princípio, arbitrária, mas, para melhorar sua legibilidade,
mbr}
vamos
arranja-lasifnan ordem
3 Tirtentar
:= lshift(ir+ir);
then em que são executadas.
43 Goto 0;
Neste
goto
19 ponto, quero reafirmar que a microlinguagem é utilizada apenas pelo projetista para criar um
interpretador
para as
sempre 44
programaremos
Por isso,
4 Tir := lshift(tir);
if nmacroinstruções.
then goto {000x Nós
ou 001x?}
Alu := ac; if z utilizando
then goto 0;macroinstruções.
{1101 = JNZE}
11
um único
parâmetro é levado em consideração na hora de criar as microinstruções: a performance da CPU.
5 Alu := tir; if n then goto 9;
{0000 ou 0001?}
45 Pc := band(ir, amask); goto 0;
46 Tir := lshift(tir); if n then goto
50;
Chegamos finalmente ao ponto em que podemos juntar todos os pedaços. A figura da próxima página
7 rd;
47 Sp := sp + (-1);
{1110 = CALL}
é um microprograma que roda no Mic-1 e interpreta Mac-1. É um programa surpreendentemente curto 8 Ac := mbr; goto 0;
48 Mar := sp; mbr := pc; wr;
apenas
79 linhas. Agora a escolha dos
nomes para os49registradores
de rascunho na Figura 13 é óbvia: PC,
9 Mar := ir; mbr := ac; wr;
{0001 = STOP}
Pc := band(ir, amask); wr; goto 0;
AC
SPgoto
são 0;usados para armazenar os três registradores
dolshift(tir);
Mic-1. IRifénothen
registrador
de instrução
10 eWr;
50 Tir :=
goto {1111,
examine e
contém a macroinstrução que está sendo correntemente65;
executada. TIR é uma cópia temporária
endereço} de IR,
usada
código {0010
de operação
três registradores
seguintes contém as
11 Alupara
:= tir;decodificar
if n then gotoo15;
ou 0011?} (opcode).
51 Tir Os
:= lshift(tir);
if n then goto
constantes indicadas. AMASK é a máscara de endereços, 59;
0FFFh, e é usado para separar opcode de bits de
12 Mar := ir;
rd;
= ADDD}
Alu :=nas
tir; if
n then gotoINSP
56; e DESP para isolar a
endereço.
SMASK
é a máscara de{0010
pilha,
00FFh, e 52
é usado
instruções
13
Rd;
53
Mar
:=
ac;
rd;
{1111000
= PSHI}
distância de 8 bits. Os seis registradores restantes não têm função assinalada e podem ser
usados
como o
14
Ac
:=
mbr
+
ac;
goto
0;
54
Sp
:=
sp
+
(-1);rd;
microprogramador quiser.
15 Mar := ir; rd;
{0011 = SUBD}
55 Mar := sp; wr; goto 10;
Como todo interpretador, o nosso microprograma tem um loop principal que busca, decodifica e
16 Ac := ac + 1; rd;
{x-y = x+1 + not y} 56 Mar := sp; sp := sp + 1; rd;
{1111001 = POPI}
executa instruções do programa que está sendo interpretado, neste caso, instruções de nível 2. Seu loop
17 A := inv(mbr);
57 Rd;
principal
na 0;
linha 0, onde ele inicia buscando58
a macroinstrução
apontada
por PC. Enquanto espera
18 Ac := começa
ac + a; goto
Mar := ac; wr; goto
10;
que
a instrução
chegue,
o microprograma
incrementa
e :=
continua
a ativar
o sinal de barramento RD.
19 Tir
:= lshift(tir);
if n then
goto {010x ou 011x?}
59 PCAlu
tir; if n then
goto 62;
Quando
25; ela chega, na linha 2, ela é armazenada em IR e, simultaneamente, o bit de alta ordem (bit 15) é
testado.
15 for
a decodificação
continua60na Sp
linha
28;
caso contrário, ela continua
linha 3.
20 Alu :=Se
tir;oifbit
n then
goto1,
23;
{0100 ou 0101?}
:= sp
+ (-1);
{1111010na
= PUSH}
21 Alu := ac;
if nenquanto
then gotoque
0; a instrução
{0100 =é JPOS}
Mar
mbr :=na
ac;linha
wr; goto
Assumindo
por
um LODD,61
o bit
14:=é sp;
testado
3, e10;
TIR é carregado com
Pc := band(ir,
amask);
goto 0; de {desvie}
62 Maruma
:= sp;vez
sp :=
sp + 1; rd;
POP}
a22instrução
original
deslocada
2 bits para a esquerda,
usando
o somador {1111011
e outra= usando
o
23
Alu
:=
ac;
if
z
then
goto
22;
{0101
=
JZER}
63
Rd;
deslocador. Note que o bit N de status da ALU é determinado pela saída da ALU, na qual o bit 14 é o de
24 Goto 0;
{desvio falhou}
64 Ac := mbr; goto 0;
mais alta ordem, pois IR + IR desloca IR 1 bit para a esquerda. A saída do deslocador não afeta os bits de
25 Alu := tir; if n then goto 27;
{0110 ou 0111?}
65 Tir := lshift(tir); if n then goto
status da ALU.
73;
Todas
as
instruções
que
têm
00
em
seus
dois
bits
de alta ordem eventualmente chegam à linha 4
26 Pc := band(ir, amask); goto 0;
{0110 = JUMP}
66 Alu := tir; if n then goto 70;
para
ter
bit 13 amask);
testado.
As0;instruções
começam
000
vãosppapa
a linha
começando
com
27 Ac
:= oband(ir,
goto
{0111 =que
LOCO}
67com
Mar
:= sp;
:= sp+1;
rd; 5, aquelas
{1111100
= RETN}
001
vão
para
a
linha
11.
A
linha
5
é
um
exemplo
de
uma
microinstrução
com
ENC
=
0;
ela
apenas
testa
TIR,
28 Tir := lshift(ir+ir); if n then {10xx ou 11xx?}
68 Rd;
mas goto
não o40;
altera. Dependendo do resultado deste teste, o código para LODD ou STOP é selecionado.
29 TirPara
:= lshift(tir);
if n then gotodeve
{100x
ou 101x?}
69a palavra
Pc := mbr;
goto 0;
LODD, o microcódigo
primeiro
buscar
endereçada
diretamente carregando os 12
35;
bits de baixa ordem de IR em MAR. Neste caso, os 4 bits de alta ordem são todos zero, mas para STOP e
30 Aluinstruções,
:= tir; if n then
33;
{1000
1001?}
7012Abits
:= ac;de largura, os bits de opcode
{1111101
SWAP} a
outras
não.goto
Entretanto,
comoouMAR
só têm
não= afetam
31
A
:=
ir
+
sp;
{1000
=
LODL}
71
Ac
:=
sp;
escolha da palavra lida. Na linha 7, o microprograma não tem nada a fazer, e portanto apenas espera.
32 Mar := a; rd; goto 7;
72 Sp := a; goto 0;
Quando a palavra chega, ela é copiada para AC e o microprograma desvia para o início do loop. STOP,
33 A := ir + sp;
{1001 = STOL}
73 Alu := tir; if n then goto 76;
ADDD e SUBD são similares. O único ponto notável relativo a elas é como a subtração é feita. Ela usa o
34 Mar := a; mbr := ac; wr; goto 10;
74 A = band(ir, smask);
{1111110 = INSP}
fato
de :=
que
35 Alu
tir; if n then goto 38;
{1010 ou 1011?}
75 Sp := sp + a; goto 0;
x
– y == x
+ (-y) = x 76
+ ( yA+1)
x + 1 +smask);
y
36 A := ir + sp;
{1010
ADDL}
:= =band(ir,
{1111111 = DESP}
37 complemento
Mar := a; rd; goto
13; A adição de 1 a AC é feita 77
A := inv(a);
em
de dois.
na linha
16, que de outra maneira seria desperdiçada
38 Aa:=linha
ir + sp;
{1011 = SUBL}
78 A := a + 1; goto 75;
como
13.
39 Mar
a; rd; goto 16;
O :=
microcódigo
para JPOS começa na linha 21. Se AC < 0, a condição de desvio falha e JPOS é
6 Mar := ir;Um
rd; Exemplo de Microprograma
{0000 = LODD}
2.3.2.
terminado imediatamente através da volta
ao 17
loop
Se, entretanto, AC ≥ 0, os 12 bits de baixa
Figura
– Oprincipal.
microprograma.
ordem de IR são extraídos, fazendo um AND deles com a máscara 0FFFh e armazenando o resultado em
PC. Não há nenhum custo extra para remover os bits de opcode aqui, e assim podemos também fazê-lo. Se
34
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
isso tivesse custado uma microinstrução extra, no entanto, teríamos que analisar cuidadosamente para ver
se a existência de lixo nos 4 bits de alta ordem de PC poderia causar problemas mais tarde.
Em certo sentido, JZER (linha 23) funciona de maneira oposta a JPOS. Com JPOS, se a condição for
verificada, o desvio falha e o controle retorna ao loop principal. Com JZER, se a condição for verificada, o
desvio é realizado. Como o código para realizar o desvio é o mesmo para todas as instruções de desvio,
podemos economizar microcódigo simplesmente indo para a linha 22 sempre que possível. Este estilo de
programação geralmente seria considerado grosseiro em outro programa de aplicação, mas num
microprograma não existem barreiras. Desempenho é tudo.
JUMP e LOCO são imediatas, de modo que a próxima rotina interessante a ser analisada é a LODL.
Primeiro, o endereço de memória absoluto a ser referenciado é calculado somando o deslocamento contido
na instrução a SP. Então, a leitura de memória é iniciada. Como o resto do código é o mesmo para LODL e
LODD, vamos apenas usar as linhas 7 e 8 para ambos. Isto não apenas economiza memória de controle sem
perda na velocidade de execução, mas também significa menos rotinas para depurar. Código análogo é
usado para STOL, AUDL e SUBL. O código para JNEG e JNZE é similar a JZER e JPOS, respectivamente
(e não ao contrário). CALL primeiro decrementa SP, então empilha o endereço de retorno, e finalmente
desvia para o procedimento. A linha 49 é quase idêntica à linha 22; se fosse exatamente a mesma,
poderíamos ter eliminado a 49 colocando um desvio incondicional para 22 em 48. Infelizmente, precisamos
continuar ativando WR por mais uma microinstrução.
Todas as macroinstruções restantes têm 1111 nos 4 bits de alta ordem, e então a decodificação dos
"bits de endereço" é necessária para distingui-las. As rotinas reais são imediatas, de modo que não
faremos mais comentários sobre elas.
2.3.2.1.
3.3.2.1.
Comentários sobre o Microprograma
Apesar de termos discutido o microprograma detalhadamente, vale a pena considerar mais alguns
pontos. Na figura da página anterior, incrementamos PC na linha 1. Isso poderia igualmente ter sido feito
na linha 0, liberando a linha 1 para qualquer outra coisa enquanto esperava. Nesta máquina não há nada mais
a fazer, mas numa máquina real o microprograma poderia usar esta oportunidade para verificar os
dispositivos de E/S esperando serviço, refrescar a RAM dinâmica, ou qualquer outra coisa.
Se deixarmos a linha 1 da maneira como está, entretanto, podemos acelerar a máquina modificando a
linha 8 para
Mar := pc; ac := mbr; rd; goto 1;
Em outras palavras, podemos iniciar a busca da próxima instrução antes de termos realmente concluído a
corrente. Esta habilidade provê uma forma primitiva de pipeline7 de instruções. O mesmo artifício pode
também ser aplicado às outras rotinas.
É claro que uma quantidade substancial do tempo de execução de cada macroinstrução é dedicada a
decodificá-la bit a bit. Esta observação sugere que poderia ser útil carregar o MPC sob o controle do
microprograma. Em muitas CPUs existentes, a microarquitetura tem suporte de hardware para extrair
opcodes de macroinstruções e coloca-los diretamente no MPC para realizar um desvio múltiplo. Se, por
exemplo, pudéssemos deslocar IR de 9 bits para a direita, zerar os 9 bits superiores e colocar o número
resultante em MPC, teríamos uma ramificação de 128 caminhos para as posições de 0 a 127. Cada uma
dessas palavras conteria a primeira microinstrução para a macroinstrução correspondente. Apesar de esta
abordagem desperdiçar memória de controle, ela acelera bastante a máquina e, na prática, quase sempre é
utilizada. (Na verdade, isto já é utilizado desde as primeiras CPUs da Intel.)
Não dissemos uma palavra sobre como a E/S é implementada. Nem temos que fazê-lo. Usando
mapeamento de memória, a CPU não sabe a diferencia entre endereços de memória verdadeira e
registradores de dispositivos de E/S. O microprograma manipula leituras e escritas nos espaços de
endereçamento de dispositivos de E/S do mesmo modo que qualquer outra leitura ou escrita.
7
Técnica que permite a execução de mais de uma instrução ao mesmo tempo. Veremos mais sobre isto em breve.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
35
Curso de Microprocessadores
2.4
Mais um Pouco Sobre Endereçamento
As instruções podem ser classificadas de acordo com o número de endereços que elas utilizam. Não
se deve esquecer que um conjunto de registradores numerados da CPU constitui, de fato, uma memória de
alta velocidade e define um espaço de endereçamento. Uma instrução que soma o registrador 1 ao
registrador 2 deve ser classificada como tendo dois endereços porque a instrução deve especificar quais
os registradores que serão adicionados, do mesmo modo que uma instrução que soma duas palavras de
memória deve especificar as palavras.
Instruções que especificam um, dois e três endereços são comuns. Em muitas máquinas que fazem
aritmética com um endereço apenas, um registrador especial denominado acumulador provê um dos
operandos. Nestas máquinas, o endereço é geralmente o endereço m de uma palavra de memória, no qual se
localiza o operando. A instrução para adição com o conteúdo do endereço m faz o seguinte:
acumulador := acumulador + memória[m]
Instruções de dois endereços de soma utilizam um dos endereços como fonte e o outro como destino. A
fonte é então somada ao destino:
destino := destino + fonte
As instruções de três endereços especificam duas fontes e um destino. As duas fontes são adicionadas e
armazenadas no destino.
Até este ponto, prestamos pouca atenção em como os bits de um campo de endereço são
interpretados para se encontrar o operando. Uma possibilidade é que eles contenham o endereço de
memória do operando. Outras possibilidades, entretanto, também existem, e nas seções seguintes
exploraremos algumas delas.
2.4.1.
Endereçamento Imediato
A maneira mais simples para uma instrução especificar um operando é a parte da instrução relativa
ao endereço conter realmente o operando em si em lugar do endereço ou outra informação que descreva
onde o operando está. Tal operando é denominado operando imediato, pois é automaticamente buscado da
memória ao mesmo tempo que a própria instrução é buscada; logo, está imediatamente disponível para uso.
O endereçamento imediato tem a virtude de não requerer uma referência extra à memória para
buscar o operando. Tem a desvantagem de restringir o operando a um número que possa caber em um
campo de endereçamento. Em uma instrução com um endereço de 3 bits (por exemplo, campo de
registradores), os operandos seriam restritos a 3 bits, o que limita a sua utilidade. As CPUs Intel não
possuem um modo de endereçamento para operandos imediatos. Ao invés disso, elas possuem uma grande
(uma enorme) coleção de instruções distintas nas quais um dos operandos é imediato.
2.4.2.
Endereçamento Direto
Um outro modo simples de especificar um operando é fornecer o endereço da palavra de memória
onde o operando está contido. Esta forma é denominada endereçamento direto. Os detalhes de como a
CPU sabe quais endereços são imediatos e quais são diretos não serão discutidos. Geralmente existem
duas abordagens: utilizar códigos de operação diferentes ou utilizar um modo de endereçamento especial
para cada tipo de operando.
2.4.3.
Endereçamento de Registrador
Endereçamento de registrador é conceitualmente a mesma coisa que endereçamento direto. Nesta
forma de endereçamento, o campo de endereço contém o número do registrador no qual o operando é
armazenado. Uma máquina com 16 registradores e 65.536 palavras de memória possuí, na realidade, dois
espaços de endereçamento. Deve-se pensar no endereço de tal máquina como tendo duas partes: (a) um bit
que diz se deseja-se um registrador ou uma palavra da memória (b) um campo de endereço que diz qual
registrador ou palavra de memória é desejado(a). Como existem menos registradores que palavras de
36
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
memória, precisa-se de um endereço menor, e assim instruções de diferentes formatos são
freqüentemente utilizadas para operandos tipo registrador e operandos tipo memória.
Se existisse uma instrução de registrador para cada instrução que endereçasse memória, a metade
dos códigos de operação seria para operandos tipo memória e a outra metade para operandos tipo
registrador. Seria necessário um bit no código de operação para designar qual o espaço de endereçamento
a ser utilizado. Se este bit fosse removido do campo código de operação e colocado no campo de
endereçamento, o fato de dois espaços de endereçamento estarem sendo utilizados ficaria mais claro. O
bit indicaria então qual o espaço de endereçamento a ser usado.
As máquinas foram projetadas com registradores por duas razões: (a) os registradores são mais
rápidos do que a memória principal e (b) como são em pequeno número, são necessários apenas alguns bits
para endereça-los. Infelizmente, ter 8 ou 16 registradores também complica muito a programação, pois
deve-se decidir quais operandos e resultados intermediários devem ser guardados no número limitado de
registradores e quais devem ser guardados na memória principal.
2.4.4.
Endereçamento Indireto
Endereçamento direto é um esquema em que o endereço especifica qual palavra de memória ou
registrador contém o operando. Endereçamento indireto é um esquema em que o endereço especifica qual
palavra de memória ou registrador contém não o operando, mas o endereço do operando. Como exemplo,
considere uma instrução para carga de um registrador (que denominaremos R1) indiretamente da posição
de memória 1000, onde a posição 1000 de memória contém 1510, como mostra a Figura 18(b).
(a)
(b)
Figura 18 – Comparações entre os endereçamentos direto e indireto. (a) Endereçamento
direto. (b) Endereçamento indireto.
Primeiramente, o conteúdo da posição 1000 é copiado para um registrador interno da CPU. Este
número de 16 bits (1.510) não é colocado em R1. Se fosse como na Figura 18(a) teríamos uma instrução de
endereçamento direto. Ao em vez disso, o conteúdo da posição 1510 de memória é buscado e colocado em
R1. O número contido na posição 1000 não é o operando, mas em vez disso "aponta" para o operando. Por
isso, é denominado apontador.
Alguns processadores, embora nenhum dos vistos durante o nosso curso, permitem endereçamento
indireto de múltiplos níveis. Neste modo de endereçamento, um apontador é utilizado para localizar uma
palavra de memória que por sua vez aponta para uma palavra de memória, e assim por diante.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
37
Curso de Microprocessadores
2.4.5.
Indexação
Muitos algoritmos necessitam da execução de alguma operação sobre uma seqüência de estruturas
de dados armazenadas em posições consecutivas de memória. Por exemplo, um bloco de n palavras de
máquina ocupando as posições.
A, A+1, A+2, ..., A+n-1
que devem ser copiadas nas posições
B, B+1, B+2, ..., B+n-1.
Este problema pode ser resolvido através de endereçamento indireto. Um registrador ou posição de
memória é carregado(a) com o endereço A; um(a) outro(a)‚ carregado(a) com o endereço B. As instruções
MOVE utilizam esses dois endereços como apontadores. Após cada palavra ter sido copiada, os
apontadores para elas são incrementados de 1. Os apontadores fazem parte dos dados e, obviamente, não
fazem parte do programa.
Uma outra solução é ter um ou mais registradores, denominados registradores de índice, que
funcionam da seguinte maneira. Os endereços possuem duas partes: o número de um registrador de índice
e uma constante. O endereço do operando é a soma da constante com o conteúdo do registrador de índice.
No exemplo acima, se ambos os endereços são indexados utilizando um registrador de índice que contém o
inteiro k, a instrução MOVE A,B copiará o conteúdo da posição de memória A + k para B + k. Inicializando o
registrador de índice com o valor 0 e incrementando-o do tamanho da palavra, após cada palavra ser
copiada, apenas um registrador é necessário para o loop de cópia. Além disso, incrementar um registrador
é mais rápido que incrementar uma posição de memória.
A indexação é também normalmente utilizada para endereçar um campo com um deslocamento
conhecido, em relação ao início de uma dada estrutura. Variáveis locais em um procedimento são acessadas
desta maneira.
2.5
Nossa Macroarquitetura Real
Neste curso, usaremos o 68HC11A8 da Motorola como exemplo de macroarquitetura real. O
68HC11A8 pertence a família de microcontroladores 68HC11. Em breve, veremos as características de
cada membro desta família. Neste capítulo, não conheceremos os periféricos extras que fazem do 68HC11
um microcontrolador. Darei enfoque apenas as características da CPU que pertencem a (quase) todos os
microcontroladores 68HC11XX.
2.5.1.
Conjunto de Registradores
O 68HC11 é uma CPU de 8 bits por isso suas instruções trabalham (quase todas) com operandos de 8
bits. Ao contrário da nossa CPU (o Mac-1), o 68HC11 possui dois acumuladores de 8 bits (A e B). Na
maioria das instruções podemos utilizar o acumulador A ou B, indiferentemente, com algumas exceções.
Por exemplo, as instruções ABX e ABY somam o conteúdo do acumulador B ao dos registradores de índice
X e Y, respectivamente, não havendo instrução que faça o mesmo com o registrador A. As instruções TAP
e TPA são usadas para transferir dados do acumulador A para o registrador de código de condição, CCR
(como veremos a seguir), ou vice-versa. Entretanto, não há instrução equivalente que use o acumulador B,
ao invés de A.
Os acumuladores A e B podem ser combinados para formar um registrador de 16 bits (D). Este
registrador é sobretudo utilizado em operações de multiplicação de dois operandos de 8 bits (para
armazenar o resultado), e de divisão de dois operandos de 16 bits (para armazenar o resto).
0 68HC11 possui ainda dois registradores de índice de 16 bits (X e Y), que são usados principalmente
com instruções que utilizam endereçamento indexado. Veremos em breve que operações que trabalham
com o indexador Y são um ciclo de máquina mais lentas, quando comparadas com as que trabalham com o
indexador X.
O PC e o SP também são de 16 bits. Neste ponto, você pode estar desconfiando que esta CPU
trabalha com endereços de 16 bits. Fique sabendo que isto está correto. Desse modo, o 68HC11A8 pode
endereçar até 64 kbytes memória. O SP pode ser localizado em qualquer lugar dentro desta faixa de
38
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
endereços. Normalmente, o apontador de pilha SP é inicializado por uma das primeiras instruções do
macroprograma.
O HC11 utiliza E/S mapeada em memória. Como já sabemos, neste caso, a CPU não destingue entre
operações na memória e em um dispositivo de E/S. Além disso, este espaço de endereçamento é dividido
entre a memória e os dispositivos de E/S do sistema, ou seja, só teremos realmente 64 kbytes de memória
se não tivermos nenhum dispositivo de E/S.
Um registrador novo para você é o CCR (Registrador de Código de Condição). Em qualquer instante
de tempo, os bits deste registrador nos dão informações importantes sobre a CPU. Na Tabela 3 é
apresentado o significado de cada um dos bits do CCR.
O bit I (se igual a 1) impede que a CPU receba pedidos de interrupção (veja a Seção 1.6) dos
dispositivos de E/S do sistema. Isto pode ser útil, por exemplo, quando a CPU está realizando operações
críticas. O bit H indica a ocorrência de vai-1 do bit 3 para o 4, após o resultado da última operação. É útil
quando se está trabalhando com valores em BCD. A função dos bits N, Z, V e C deve ser clara para você.
Estes bits (incluindo o H) são usados para os programas de nível 2 tomarem decisões, através de
instruções de desvios condicionais que testam estes bits. Os bits S e X vão ser vistos mais adiante.
Figura 19 – Conjunto de registradores do 68HC11.
Como você descobrirá, o registrador CCR provê uma maneira rápida de controlar alguns aspectos da
CPU e verificar o resultado das operações (para que decisões possam ser tomadas). Este registrador
existe na maioria das CPUs, algumas vezes com outro nome (nas CPUs da Intel ele geralmente é chamado
de FLAGS) e/ou tamanho diferente.
S Desabilita o modo STOP
N Indica se a última operação resultou em zero
X Desabilita interrupções do pino XIRQ
Z Indica se a última operação resultou em zero
H Indicador de vai-1 do nibble menos significativo
V Indica se a última operação resultou em overflow
I Desabilita todas as interrupções mascaráveis
C Indica a existência de vai-1 ou sobra-1
Tabela 3 – Significado dos bits do registrador CCR.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
39
Curso de Microprocessadores
No 68HC11, assim como na maioria das CPUs, o número de registradores é bastante reduzido. Desde
que eles são, geralmente, mais rápidos que a memória principal, a tarefa de decidir quais dados ficaram na
memória e quais ficaram nos registradores é bastante “filosófica”.
2.5.2.
Pinagem e Sinais de Barramento
O 68HC11 é geralmente encontrado em um encapsulamento PLCC de 52 pinos. A maioria desses pinos
pertencem aos seus dispositivos de E/S internos. Por enquanto, apenas os pinos de endereço, dados e
controle nos interessam.
Como na maioria das CPUs, os pinos de dados do HC11 são multiplexados com os de endereço. Mais
especificamente, os 8 pinos de dados são multiplexados com os 8 pinos que correspondem aos 8 bits menos
significativos de um endereço de 16 bits (ufa!). Para explicitar a multiplexação, este pinos são nomeados
de AD0 à AD7. Os instantes nos quais estes pinos possuem informações de endereço ou do dado, são
distintos através de um pino chamado AS (Address Strobe). Durante o período em que AD0-AD7 contêm a
parte menos significativa do endereço, AS permanece ativo. Como veremos em breve, AS pode ser
utilizado para habilitar a carga de um registrador externo à CPU (por exemplo, o 74373) que irá reter o
endereço quando AS tornar-se inativo.
Um pino chamado R/ W é utilizado para distinguir entre ciclos de leitura e ciclos de escrita. Como
você deve estar adivinhando, R/ W é colocado em nível alto durante uma leitura, e em nível baixo durante
as escritas.
Já vimos que, como todo sistema digital, uma CPU necessita de um relógio externo (uma base de
tempo). No 68HC11 esta base de tempo deve ser uma onda quadrada com freqüência de no máximo 8 MHz.
Esta base de tempo aparece dividida por 4 no pino de saída E. Este pino deve ser usado para temporizar as
operações com o barramento, ou seja, o tempo em que E está baixo é utilizado para estabilizar todos os
sinais necessários (AD0-AD7, AS, R/ W , etc), em seguida, a operação de E/S deve ser realizada enquanto
E estiver alto. Isto significa, no caso de uma base de tempo de 8 MHz, que uma operação de
leitura/escrita deve ser realizada em 0,5 µs. Como toda operação interna no 68HC11 demora também 0,5
µs para ser realizada, isto quer dizer que uma macroinstrução do 68HC11 demora, no mínimo, 1 µs para ser
executada (0,5 µs para ser buscada na memória e 0,5 µs para ser executada).
Apesar da freqüência máxima da base de tempo do HC11 ser 8 MHz, podemos utilizar uma base de
tempo menor. Contudo, qual o motivo de queremos uma base de tempo mais lenta? A tecnologia utilizada na
construção é a HCMOS (High speed Complementary Metal-Oxide, ou seja, metal, óxido e semicondutor na
configuração complementar de alta velocidade). Além de outras características, esta tecnologia apresenta
a vantagem de baixo consumo. O seu consumo é tanto maior quanto a freqüência da sua base de tempo. Por
isso, em aplicações que não necessitam de uma velocidade elevada, a base de tempo pode ser reduzida para
economizar energia. Isto é útil em sistema alimentados por bateria (como em um controle remoto ou um
telefone sem fio).
2.5.3.
Modos de Endereçamento
A CPU M68HC11 utiliza seis modos de endereçamento relacionados com a memória, são eles:
Imediato, Direto, Estendido, Indexado, Inerente e Relativo.
Cada modo de endereçamento trás informações para gerar uma palavra de dois bytes, que compõem
o chamado endereço efetivo do operando. Estas palavras resultam da declaração feita no campo do
operando, e são elas que aparecem no barramento de endereço durante a execução de uma instrução.
2.5.3.1.
Endereçamento Imediato (IMM)
No modo imediato o operando pode ser uma constante de 8 ou 16 bits, dependendo do comprimento
do registrador envolvido. Para especificar o modo imediato, o mnemônico precisa ser seguido por um
caractere ‘#’. Por exemplo, “LDAA
#256” ou “LDX
#$C000”. No exemplo anterior o símbolo
“$” foi utilizado para especificar que o operando está expresso em hexadecimal. Também podem ser
utilizados os símbolos “ ’ ”, “%” e “@”, para especificar caractere ASCII, binário e octal, respectivamente.
40
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
2.5.3.2.
Endereçamento Estendido (EXT)
É equivalente ao endereçamento direto do Mac-1. Para especificar este modo, o mnemônico da
instrução deve ser seguido por um endereço de 16 bits. Novamente, o endereço pode ser expresso em
hexadecimal, binário, octal, caractere ASCII ou decimal.
2.5.3.3.
Endereçamento Direto (DIR)
É semelhante ao endereçamento estendido, porém, o operando deve localizar-se na memória entre o
endereço 0000h e 00FFh. Por isso, o mnemônico da instrução deve ser seguido apenas pelos 8 bits menos
significativos do endereço efetivo. Deste modo, o comprimento das instruções é um byte menor, quando
comparadas com as instruções que utilizam endereçamento estendido. Isto quer dizer que as instruções
que utilizam o endereçamento direto são um ciclo mais rápidas que as que usam endereçamento estendido.
O modo Direto é, as vezes, chamado de modo de endereçamento da página zero. O comprimento da
maioria das instruções nesse modo é de 2 bytes: um para o código de operação e outro para o endereço.
Somente quatro instruções no modo direto requerem um byte extra, são aquelas que envolvem o
registrador Y.
2.5.3.4.
Endereçamento Indexado (IND)
No modo de endereçamento indexado, o registrador X ou o Y é utilizado no cálculo do endereço
efetivo, que é variável, sendo dependente do conteúdo de X ou de Y e, também, dos 8 bits de offset
contidos na instrução. Este modo de endereçamento pode ser usado para fazer referência a alguma
locação de memória dentro dos 64 Kbytes endereçáveis. Neste caso as instruções têm geralmente 2 ou 3
bytes: o código de operação e oito bits de offset, mais o prebyte ou não.
Para especificar o modo indexado, o mnemônico precisa ser seguido por “IND,X” ou “IND, Y”. Onde
“IND” é uma constante de 8 bits, X e Y são os indexadores. Por exemplo, “LDAA
$56,X”.
2.5.3.5.
Endereçamento Inerente (INH)
Uma instrução no modo de endereçamento inerente opera apenas com registradores internos de uso
geral (Figura 19), não dependendo de uma especificação de endereço. Os operandos são os próprios
registradores e assim não são procurados na memória. Isto significa que o próprio código de operação
determina o que a CPU pode fazer. Essas instruções são geralmente de um ou dois bytes.
Muitas instruções da MCU, usam um ou mais registradores como operandos. Por exemplo, a ABA
causa a soma dos conteúdos de A com B, colocando o resultado no acumulador A. A INCB promove o
incremento do conteúdo do registrador B. De modo análogo, a instrução INX incrementa o conteúdo de X.
2.5.3.6.
Endereçamento Relativo (REL)
O endereçamento relativo é usado principalmente pelas instruções branch (desvio). Estas instruções
geram 2 bytes de código de máquina: um para o código de operação e outro para o offset relativo. É
desejável que os desvios ocorram em ambas as direções, por isso o byte de offset é sinalizado em
complemento de dois, abrangendo o domínio de -128 a +127 bytes (com relação ao endereço da próxima
instrução apontada pela branch).
O offset é sempre o último byte de uma instrução branch. Se ele for zero, a execução do programa
continuará com a instrução imediatamente após a branch. Uma instrução de desvio do tipo BRA (BRanch
Always), por exemplo, com offset FEh resultaria num loop infinito sobre ela mesma. Nos modos direto ou
indexado por X (INDX), as instruções BRCLR e BRSET (Tabela 4) são de 4 bytes; então um offset $FC
causará uma repetição na execução da instrução, até que o bit de teste torne-se falso. Essas mesmas
instruções no modo indexado Y (INDY) têm 5 bytes; assim, um offset $FB causa uma repetição da
execução da instrução, até que o bit de teste torne-se falso.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
41
Curso de Microprocessadores
2.5.4.
Conjunto de Instruções
Na Tabela 4 é apresentado o conjunto de macroinstruções dos microcontroladores da família HC11.
Como você pode notar, este microcontrolador apresenta um número de instruções bem maior que o nosso
Mac-1. A Tabela 4 utiliza a notação descrita na Figura 20.
Figura 20 – Notação utilizada pela Tabela 4.
Na primeira coluna da Tabela 4 encontramos o mnemônico da instrução. Também está especificado
se a instrução necessita de operandos ou não. Na segunda e terceira colunas, existe uma breve descrição
da instrução. Os modos de endereçamento que podem ser utilizados com uma dada instrução é apresentado
na coluna quatro. Para algumas instruções, nem todos os modos de endereçamento estão disponíveis. Em
especial, algumas instruções (por exemplo, a instrução BRSET) não aceitam o modo estendido. Nestes
casos, geralmente temos que utilizar indexação. Por isto, muita atenção quando for especificar os
operandos de uma instrução. Sempre verifique se a instrução aceita o endereçamento que você deseja
utilizar.
Na quinta e sexta colunas encontramos os códigos de operação da instrução. Uma mesma instrução
pode ter vários códigos de operação (um para cada modo de endereçamento suportado pela instrução). Em
particular, para especificar a indexação por Y é utilizado um prefixo (geralmente a constante 18h). Ou
seja, todas as instruções que utilizam indexação em Y possuem um byte a mais (como pode ser comprovado
pela coluna sete). É por isto que as instruções que trabalham com o indexador Y são um ciclo de máquina
mais lentas, quando comparadas com as que trabalham com o indexador X.
A coluna sete informa quantos ciclos de instrução são utilizados para executar uma determinada
instrução. Por exemplo, instruções como INCA são executadas em apenas dois ciclos, enquanto que as de
divisão levam 41 ciclos. Isto é característico das instruções de nível 2. Pois, as instruções de nível 1 são
executadas diretamente pelo hardware em apenas um ciclo.
A coluna oito não nos interessará. Já a nove é muito importante. Ela ilustra como os bits do
registrador CCF podem ser afetados por uma determinada instrução. Isto é útil quando utilizamos
instruções de salto condicional.
Quando fiz meu primeiro curso de inglês, meu professor ensinou-me um “macete” para aprender os
verbos irregulares da língua inglesa: decorá-los. O mesmo artifício pode ser utilizado no aprendizado das
instruções do 68HC11. Felizmente, com um pouco de prática, o que poderia parecer complicado, torna-se
claro e natural. Além disso, o grande incentivo para aprendermos as instruções de uma CPU é que todas
elas, independente da família e do fabricante, possuem um conjunto de instruções muito parecido. Isto
significa que, uma fez que tenhamos entendido as instruções de uma CPU, com mais um mínimo de esforço,
poderemos programar qualquer CPU.
42
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
2.6
Comentários
Apesar de ter pouca experiência na programação de microprocessadores, acredito que agora você
possui um conhecimento bastante sólido de como uma CPU qualquer trabalha. Até o fim do curso, com a
realização de programas com o 68HC11, este conhecimento aumentará bastante.
Não fique preocupado se você não compreendeu a maioria das instruções da Tabela 4. Acredito que a
melhor forma familiarizar-se com estas instruções é praticando. Por isto, não perdi tempo explicando-as
uma por uma. De nada adiantaria a explicação teórica sem a prática. Além disso, esta explicação poderia
deixa-lo com a falsa impressão de já saber programar em assembler. Então, acredito que esta falta inicial
de respostas o levará ao laboratório e a fazer cada vez mais perguntas. E está é a melhor forma de
aprender: praticando e perguntando.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
43
Curso de Microprocessadores
Tabela 4 – Conjunto de macroinstruções do 68HC11.
44
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
Tabela 4 – Conjunto de macroinstruções do 68HC11. (Continuação)
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
45
Curso de Microprocessadores
Tabela 4 – Conjunto de macroinstruções do 68HC11. (Continuação)
46
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
Tabela 4 – Conjunto de macroinstruções do 68HC11. (Continuação)
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
47
Curso de Microprocessadores
Tabela 4 – Conjunto de macroinstruções do 68HC11. (Continuação)
48
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 2- Microprogramação
Tabela 4 – Conjunto de macroinstruções do 68HC11. (Continuação)
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
49
Curso de Microprocessadores
Capítulo 3 - Entrada e Saída
Como discutido nas Seções 1.2 e 1.6, um microprocessador sem dispositivos de E/S não é algo muito
útil. Isto acontece porque a função básica de uma CPU é processar dados. Evidentemente, ela necessita
receber os dados a serem processados de alguma fonte externa. Esta pode ser um sistema físico, um
sistema eletrônico, ou mesmo um usuário. Da mesma forma, após realizar o processamento necessário, o
microprocessador tem que enviar o resultado deste processamento ao mundo exterior. Novamente, o
destino dos dados pode ser um sistema físico, um sistema eletrônico, ou o usuário do sistema. Se nos
pensarmos um pouco na grande variedade de aplicações para microprocessadores, podemos concluir que,
quando se trabalha com microprocessadores, existem várias possibilidades de fontes e destinos de dados.
Para cada fonte de dados, devemos utilizar o dispositivo de entrada apropriado. Da mesma forma, para
cada destino devemos utilizar o dispositivo de saída mais conveniente às nossas necessidades.
Como vimos na Seção 1.6, os controladores de dispositivos tornam o “diálogo” entre a CPU e os
dispositivos de E/S bastante padronizado. De forma que, para nos tornarmos um bom projetista de
sistemas microprocessados, não precisamos realmente conhecer uma infinidade de dispositivos de E/S. De
fato, o que for visto durante este curso já será bastante abrangente.
Dependendo da complexidade, um sistema microprocessado pode possuir uma infinidade de
dispositivos E/S. Desde que estes dispositivos têm um papel fundamental no sistema, necessitamos de
técnicas que nos ajude a utiliza-los da maneira mais eficiente possível. Para isto, três técnicas são mais
populares: E/S programada, E/S por interrupção e E/S via DMA. A E/S programada é a técnica mais
simples, porém é a que mais sobrecarrega a CPU. Já a E/S via DMA, é a mais rápida, porém é a mais
complexa e não pode ser utilizada com todos os dispositivos de E/S. Essas três técnicas serão vistas em
detalhes neste capítulo e praticadas em laboratório (com exceção da E/S via DMA).
No final do capítulo, veremos em detalhes duas portas de comunicação bastante utilizadas no
projeto de sistemas: a porta serial e a porta paralela. Estas portas são bastante diferentes entre si, mas
possuem a mesma função: interligar a CPU com dispositivos de E/S (daí o nome porta). Na verdade, como
veremos, estas portas não são utilizadas apenas para conectar dispositivos de E/S, também podem
interligar sistemas entre si.
Por último, iniciaremos nosso estudo de conversores A/D e D/A. Estes dispositivos fazem a
interface entre o mundo digital dos microprocessadores e o nosso mundo analógico. Devido a complexidade
de alguns aspectos (e a importância de outros), os conversores A/D e D/A possuem um capítulo inteiro
dedicado a eles.
3.1
E/S Programada
Reporte-se à Seção 1.6 (página 16), lá está descrito como deve ser realizada a E/S com a ajuda dos
controladores de dispositivos. Mais especificamente, estamos interessados no trecho re-apresentado a
seguir:
“...devemos saber que quando utilizamos dispositivos de E/S, como regra geral, primeiro a CPU deve
acessar os registradores de controle para configurar o dispositivo de E/S. Em seguida, caso quisermos
enviar ou receber dados, a CPU precisa ler as informações contidas nos registradores de status. Só assim,
ela poderá receber ou enviar os dados desejados, através do registrador de dados.”
Na verdade, o que está descrito acima é o processo de E/S programada.
Como exemplo, observe o trecho de programa escrito em linguagem C a seguir:
key = !ESC;
do{
Faça algo
If(kbhit()) key = getch();
Faça mais alguma coisa
}while(key != ESC)
50
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
O programa anterior utiliza a função kbhit(). Esta função verifica se alguma tecla do teclado foi
pressionada. Em caso positivo, ela retorna verdadeiro, caso contrário, retorna falso. O nosso programa
exemplo fica dentro de um loop executando várias tarefas. Uma dessas tarefas verifica se uma tecla foi
pressionada. Se positivo, o programa lê o teclado e armazena a tecla pressionada na variável key. Apenas
quando a condição key != ESC não for satisfeita o programa sai do loop.
Dois aspectos importantes do programa anterior devem ser observados. Primeiro, a instrução que
verifica se alguma tecla foi digitada (instrução de E/S) deve ser incluída entre as instruções normais do
programa. Caso contrário, a tecla (o dado) jamais será recebida. Segundo, a maior parte do tempo de
processamento da E/S é gasto na verificação da existência do dado, pois a maioria das vezes que o
programa verifica se uma tecla é pressionada o resultado é negativo. Isto quer dizer que muito tempo de
processamento é desperdiçado. Em algumas aplicações, este é o maior pecado da E/S programada.
Observe agora o próximo programa exemplo. O programa precisa receber uma tecla do teclado
(logo, realizar uma operação de E/S). Contudo, a tecla é indispensável para a realização de suas tarefas.
Por isso, ele só passa para a próxima instrução quando uma tecla houver sido digitada. Neste caso, não nos
interessa se algum tempo está sendo desperdiçado. Temos todo o tempo do mundo. Por isso, esta parece
ser a técnica mais adequada neste caso.
do{
puts(“Especifique a
switch(getch()){
case 1 : faça
case 2 : faça
case 3 : faça
case 4 : faça
}while(1);
operação:”);
algo;
outra
outra
outra
break;
coisa; break;
coisa; break;
coisa;
Que fique claro que os programas em linguagem C apresentados nesta seção são apenas ilustrativos.
Na verdade, como veremos em breve, kbhit() e getch() não realizam E/S exatamente como descrito na
Seção 1.6, ou seja, através dos registradores de status e de dados do controlador de dispositivo do
teclado. Contudo, os programas ilustram bem a filosofia da E/S programada.
Vimos um caso em que a E/S programada é a mais indicada. Agora, considere um sistema
microprocessado que possua dez dispositivos de E/S. Considere também que qualquer dispositivo pode ter
um dado novo em qualquer instante de tempo. Isto significa que a CPU deve checar o registrador de status
de todos os dispositivos de E/S, o mais rápido possível. Além disso, se dois ou mais dispositivos de E/S
contiverem dados novos em um mesmo instante de tempo, existe a possibilidade de perda de dados por
parte de um dispositivo mais crítico? Se existe, posso dar prioridade a este dispositivo?
Pelo exemplo anterior, não é preciso ser nenhum gênio para descobrir que a E/S programada não é
indicada para sistemas com muitos dispositivos ou com dispositivos críticos. Neste caso, a escolha mais
indicada talvez seja E/S por interrupção.
3.2
Interrupção
A técnica de E/S por interrupção é muito importante para a operação de sistemas
microprocessados, pois ela possibilita ao microprocessador responder rapidamente aos seus dispositivos
de E/S. A importância dessa abordagem pode ser entendida comparando-a a uma campainha. Se uma porta
não tiver nenhum dispositivo para chamar a atenção (como uma campainha), talvez seja necessário irmos
até ela para verificar se existe alguém à porta. Com uma campainha, necessitamos ir até a porta apenas
quando a campainha tocar. Do mesmo modo, não é eficiente esperar que o microprocessador verifique se
seus periféricos requerem atenção (como na E/S programada). Para isto, existem as interrupções, que são
como campainhas que avisam ao microprocessador que algum dispositivo necessita dele.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
51
Curso de Microprocessadores
3.2.1.
Modo de Operação
Como visto anteriormente, durante a execução normal de um programa, as instruções são lidas da
memória e executadas de acordo com o fluxo normal do programa. O processador usa um registrador
especial chamado contador de programa, PC, para sinalizar a próxima instrução a ser executada. Um
conjunto de registradores de propósito geral são usados para manipular e armazenar temporariamente
algum dado usado pelo programa.
A maioria das CPUs possuem um pino de entrada que quando ativado, faz com que a CPU execute a
corrente instrução e salve o PC, juntamente como todos os outros registradores, na pilha. Em seguida, o
fluxo de execução do programa é desviado para uma rotina especial chamada de rotina de tratamento de
interrupção. Nesta rotina encontra-se todas as instruções necessárias para atender as necessidades do
dispositivo que requisitou a interrupção. Este processo pode envolver, por exemplo, a transferência de
dados de um dispositivo para uma região na memória. A última instrução executada pela rotina de
interrupção é uma instrução de retorno (RTI). Esta instrução força o microprocessador a restaurar o PC e
todos os demais registradores, com os valores salvos na pilha. Dessa forma, após atender à interrupção, o
microprocessador volta ao estado que estava antes da requisição de interrupção (IRQ). Por isso, talvez a
palavra que melhor defina o processo de interrupção seja “transparência”. Devido a esta característica, a
técnica de interrupção não é utilizada apenas na E/S. Ela pode ser utilizada para sincronizar eventos, ou
para responder a eventos externos. Sobre tudo, como veremos em breve, ela é bastante utilizada na
aquisição de dados.
3.2.1.1.
Vetor de Interrupção
O processo de “chamar” uma função ou uma subrotina qualquer envolve dois passos. Primeiro, o PC,
ou seja, o endereço de retorno, é salvo na pilha. Segundo, o endereço no qual se localiza a rotina ou função
é colocado dentro do PC (isto é realmente o que constitui o salto). Com uma rotina de interrupção, o
primeiro passo é substituído pelo empilhamento de não apenas o PC, mas todos os registradores da CPU. E
o segundo passo? Ou seja, de onde a CPU deve obter o endereço da rotina de interrupção para efetuar o
salto? A resposta é: do vetor de interrupção.
O vetor de interrupção é uma região de memória contínua que guarda o endereço de todas as rotinas
de interrupção de uma CPU. Por exemplo, se uma CPU suportar até dez pedidos de interrupção diferentes,
ela deve possuir em sua memória um vetor de endereços de dez posições. Caso esta mesma CPU possa
endereçar até 64 Kbytes de memória, ela deverá ter reservado 10 x 2 bytes = 20 bytes para o vetor de
interrupção.
Cada posição do vetor de interrupção está relacionado com apenas uma fonte de interrupção. Ou
seja, sempre que ocorre uma determinada interrupção, a CPU já sabe qual é a posição do vetor de
interrupção que se encontra o endereço da rotina de interrupção relacionada. Na verdade, dois
dispositivos podem compartilhar a mesma interrupção. Para isto, basta que a rotina de interrupção
verifique qual dispositivo fez a requisição. Como? Verificando o registrador de status dos dispositivos que
compartilham a interrupção. Outra maneira, bem mais explícita, é utilizando o esquema da Figura 21. Nesta
figura, uma única linha de IRQ (pino INT , Figura 21) pode ser compartilhada por até oito dispositivos. Os
pedidos de interrupção (I1 à I8), além de ativar o pino INT , habilitam a carga do 74LS374 (registrador
de 8 bits). Com isso, a rotina de interrupção pode verificar qual dispositivo requisitou ajuda.
Agora, surge outra dúvida: “Quem coloca o endereço da rotina de interrupção na posição correta do
vetor?”. Além de escrever a rotina de interrupção, somos responsáveis também por colocar o endereço
desta rotina no vetor de interrupção. Para a maioria das CPUs, o vetor de interrupção localiza-se em um
endereço fixo. Para outras, como as CPUs Intel mais avançadas, esta localização é dada por um registrador
que aponta para o vetor de interrupção. A localização exata de uma dada IRQ deve ser conseguida
consultando-se o manual da CPU.
52
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
Figura 21 – Esquema de compartilhamento de um pino de IRQ por até oito dispositivos.
Para formalizar o processo de interrupção, os passos que constituem o processo são listados a
seguir:
O dispositivo que necessita de auxílio da CPU ativa um sinal ( IRQ ) em um de seu pinos, requisitando
uma interrupção;
Ao receber o sinal, a CPU executa a corrente instrução e salva todos os seus registradores na pilha;
Neste momento, a CPU pode ativar um sinal, geralmente chamado IACK (Interrupt ACKnowledge),
avisando ao dispositivo que a interrupção já vai ser atendida;
Em seguida, a CPU localiza o endereço da rotina de interrupção no vetor de interrupção e coloca-o
no PC;
A rotina de interrupção é executada, se necessário, o dispositivo requerente,e;
Os registradores são retirados da pilha, ou seja, a CPU volta ao curso normal do programa.
3.2.1.2.
Tempo de Latência
Da Seção 3.2.1.1, podemos notar que o processo de interrupção requer um certo tempo de
processamento. Este tempo é necessário para que a CPU salve os registradores na pilha e vá para a rotina
de tratamento de interrupção. Além disso, após a rotina de interrupção ser executada, a instrução RTI
restaura o conteúdo de todos os registradores, ou seja, mais processamento é consumido. Por isso,
durante o projeto do sistema o tempo de sobre carga, conhecido também como tempo de latência, precisa
ser estimado. Se o tempo de latência for muito elevado para a aplicação, outro método tem que ser
estudado. Por exemplo, suponha que uma CPU gaste 13 µs para salvar os registradores na pilha e colocar o
endereço da rotina de interrupção no PC. Além disso, considere que sejam gastos 10 µs para restaurar os
registradores. Neste caso, o tempo de latência seria 23 µs. Isto tem duas implicações:
Toda interrupção levará 13 µs para ser atendida, e;
Toda rotina de interrupção levará mais que 23 µs para ser executada. Se, por exemplo, o código
dentro da rotina levar 10 µs para ser processado, a periodicidade da interrupção pode ser no
mínimo 33 µs. No caso de um sistema de aquisição de dados, o intervalo mínimo entre uma
aquisição e outra será 33 µs.
Caso qualquer uma das implicações anteriores seja um problema, outra técnica deverá ser utilizada.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
53
Curso de Microprocessadores
3.2.1.3.
Prioridade8
Se um sistema possui apenas um dispositivo de E/S, então as interrupções funcionam sempre como
descrevemos, e não há nada mais a dizer sobre elas. Entretanto, um sistema real pode possuir muitos
dispositivos de E/S e vários deles podem estar em atividade simultaneamente. Existe uma probabilidade
não nula de que, no momento em que uma rotina de interrupção está em execução, um segundo dispositivo
de E/S deseje gerar a interrupção dele.
Existem duas abordagens para este problema. Na primeira, todas as rotinas de interrupção inibem
interrupções subseqüentes antes de fazer qualquer coisa, mesmo antes de salvar os registradores. Esta
abordagem é muito simples, pois as interrupções são consideradas estritamente de maneira seqüencial,
mas pode causar problemas quando os dispositivos não podem tolerar muito atraso. Por exemplo, em uma
linha de comunicação de 9600 bps, os caracteres chegam a cada 1.042 µs, estando pronto para receber ou
não. Se o primeiro caractere não foi ainda processado quando o segundo chega, podem-se perder dados.
Quando um sistema possui dispositivos de E/S críticos em relação ao tempo, uma abordagem mais
adequada de projeto é atribuir diferentes prioridades para diferentes dispositivos de E/S, altas para
dispositivos muito críticos e baixas para dispositivos menos críticos. Quando um dispositivo de prioridade
n interrompe, a rotina de interrupção deve também executar com prioridade n.
Quando uma rotina de interrupção da prioridade n está em execução, qualquer tentativa de um
dispositivo com uma prioridade menor causar uma interrupção é ignorada até que a rotina de interrupção
tenha terminado e a CPU recomece a executar o programa principal (Prioridade 0). Por outro lado, deve-se
permitir que interrupções de dispositivos de prioridade mais altas aconteçam sem atraso.
Com as próprias rotinas de interrupção sujeitas a interrupção, a melhor maneira de administrá-las
corretamente é assegurar que todas as interrupções sejam transparentes. Consideremos um exemplo
simples de múltiplas interrupções. Um computador tem três dispositivos de E/S: uma impressora, um disco
e uma interface RS-232, com prioridades 2, 4 e 5, respectivamente. Inicialmente, em t = 0, o programa
principal está em execução quando, de repente, em t = 10, uma interrupção da impressora acontece. A
rotina de serviço de interrupção da impressora é iniciada, como mostra a Figura 22.
Em t = 15, a interface RS-232 requer atenção e gera uma interrupção. Como a interface RS-232
tem uma prioridade (5) maior que a da impressora (2), a interrupção acontece. O estado da máquina, que
está agora executando a rotina de serviço de interrupção da impressora, é empilhado e a rotina de serviço
de interrupção da interface RS232 iniciada.
Um pouco mais tarde, em t = 20, o disco está pronto e quer serviço. Entretanto, sua prioridade (4) é
menor do que a da rotina de interrupção (5) correntemente em execução, de forma que o hardware da CPU
não reconhece (acknowledge) a interrupção, e esta permanece pendente. Em t = 25, a rotina da RS232
termina, assim ela retorna ao estado em que estava logo antes da interrupção da RS232 ter acontecido, ou
seja, executando a rotina de serviço de interrupção da impressora em prioridade 2. Tão logo a CPU
chavear para a prioridade 2, antes mesmo de uma instrução poder ser executada, a interrupção de disco
com prioridade 4 é permitida, e a rotina de interrupção do disco inicia a sua execução. Quando ela termina,
a rotina de impressora retorna a sua execução. Finalmente, em t = 40, todas as rotinas de serviço de
interrupção terminaram e o programa principal continua a partir de onde tinha sido interrompido.
Por simplicidade, algumas CPUs possuem apenas um ou dois níveis de prioridade (como as CPUs da
Intel). Com apenas um nível de interrupção utilizável, não existe maneira de a CPU permitir que um
dispositivo de alta prioridade interrompa uma rotina de serviço de interrupção de média prioridade e ao
mesmo tempo proibir um dispositivo de baixa prioridade de fazê-lo. Para resolver este problema, estas
CPUs são normalmente utilizadas com um controlador de interrupção (ou árbitro de interrupção). Neste
caso, quando a primeira interrupção acontece, digamos com prioridade n, a CPU é interrompida. Se uma
interrupção subseqüente de maior prioridade acontecer, o árbitro interrompe pela segunda vez. Se a
segunda interrupção tiver prioridade menor, ela é suspensa até a primeira terminar. (Quando terminar, a
Todo o conteúdo desta seção foi retirado do livro Organização Estruturada de Computadores, de Tanenbaum, Ed. Prentice/Hall do
Brasil.
8
54
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
rotina de interrupção deve enviar explicitamente um comando ao árbitro, para permitir que interrupções
de prioridades mais baixas ocorram.)
Figura 22 – Seqüência temporal de um exemplo de múltiplas interrupções. (RSI = Rotina
de Serviço de Interrupção.)
3.2.1.4.
Interrupções Mascaráveis e Não-Mascaráveis
Suponha que um sistema possua um teclado alfanumérico para entrada de dados por parte do
usuário. Como o teclado será utilizado em apenas alguns poucos instantes de tempo, uma boa saída seria
utilizar interrupção para receber as teclas digitadas. Contudo, enquanto a CPU estiver ocupada, um usuário
chato poderia estar teclando o teclado insistentemente sem nenhuma necessidade (acreditem, os chatos
fazem parte de qualquer grupo de usuários). Neste caso, a tarefa da CPU estaria constantemente sendo
interrompida para nada. Pensem como seria interessante poder inibir a interrupção do teclado. Para nossa
alegria, isto é perfeitamente possível. Em qualquer sistema é possível inibir todas as interrupções ou
apenas uma em específico. Na verdade, as interrupções estão inibidas por definição. Isto significa que,
sempre que desejarmos trabalhar com interrupções, temos que habilita-las. O processo de inibir (ou
mascarar) todas as interrupções geralmente é feito através do registrador de status da CPU. Por
exemplo, como visto na Seção 2.5.1 (página 38), no 68HC11 isto é feito ligando-se o bit I do registrador
CCR. Isto pode ser executado através da instrução SEI (Tabela 4). De forma semelhante, a instrução CEI
habilita a ocorrência de interrupções desligando o bit I do registrador CCR.
Como as interrupções estão inibidas por padrão, além de habilitar o reconhecimento de interrupções
por parte da CPU, temos que habilitar a interrupção do dispositivo com o qual desejamos trabalhar. Por
padrão, esta interrupção já pode estar habilitada, porém é bom verificar.
Por último, se o sistema possui diferentes níveis de prioridades ou um árbitro de interrupção, cada
nível pode ser inibido isoladamente.
No seu computador, há duas formas de reinicia-lo: como as teclas CTRL + ALT + DEL ou com o botão
RESET. Em ambos os casos, são utilizadas interrupções. Contudo, algumas vezes as teclas CTRL + ALT +
DEL não funcionam. O mesmo não acontece com o botão RESET, ou seja, sempre podemos reiniciar o
computador por este botão. Isto significa que, em momento algum a interrupção do botão RESET é inibida.
Interrupções deste tipo são chamadas de interrupções não-mascaráveis, em oposição às interrupções que
podem ser inibidas ou mascaradas.
As interrupções não-mascaráveis têm prioridade sobre as mascaráveis. Além disso, elas são
utilizadas para sinalizar “quase catástrofes”, por exemplo, um erro de paridade na memória.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
55
Curso de Microprocessadores
3.2.2.
O Controlador 8259A
O 8259A é um árbitro de interrupções utilizado com as primeiras CPUs da Intel (do 8080 ao
80286). Na verdade, o 80186 (uma versão melhorada do 8086, anterior ao 80286) já continha um arbitro
de interrupção interno ao chip. Contudo, o 8259A continuou sendo utilizado pela Intel até o lançamento do
80386). Nos dias de hoje, o 8259A não é muito utilizado, porém ainda iremos estuda-los por dois motivos.
Primeiro, o arbitro de interrupção dos computadores atuais possui uma programação compatível com o
8259A. (O entendimento desta programação pode ser útil, sobretudo, em sistemas de tempo-real9.)
Segundo, ele irá nos ajudar a entender melhor a relação entre a CPU e os dispositivos de E/S.
O 8259A gerencia até oito níveis de IRQs e possui suporte para expandir esta capacidade para até
64 níveis (utilizando outros 8259As em cascata). Ele é programável por software como um dispositivo de
E/S qualquer. Além disso, uma seleção de modos de prioridade esta disponível ao programador, de tal
forma que as IRQs são processadas de acordo com as necessidades do sistema. Estes modos podem ser
alterados dinamicamente a qualquer instante.
Figura 23 – Diagrama de blocos do 8259A.
3.2.2.1.
Diagrama de Blocos
O diagrama de blocos do 8259A é apresentado na Figura 23. Na Tabela 5, é apresentada a descrição
de cada pino da Figura 23. Os dispositivos de E/S devem requisitar as interrupções através das entradas
IR0 à IR7. Em qualquer instante, o estado desses pinos pode ser verificado através do registrador IRR
(Interrupt Request Register, ou seja, Registrador de Requisição de Interrupção). Este registrador está
conectado diretamente ao bloco responsável pelo arbítrio das IRQs, o Analisador de Prioridade (Priority
Resolver). A IRQ de maior prioridade é selecionada e armazenada no registrador ISR (In Service
Register, ou seja, Registrador de Interrupção em Serviço). A IRQ que passar pelo analisador de
prioridade (apenas uma por vez) chega até a CPU através da saída INT. As que não passarem ficam
registradas no IRR. O sinal IACK enviado pela CPU é recebido pela entrada INTA . O dispositivo ainda
possui um registrador, o IMR (Interrupt Mask Register, ou seja, Registrador de Máscara de Interrupção),
para inibir interrupções específicas.
9
Sistemas nos quais as tarefas devem ocorrer em instantes de tempo bem determinados.
56
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
Tabela 5 – Descrição dos pinos do 8259A.
Os pinos CAS X e SP/EN são utilizados quando deseja-se expandir o número de linhas de
interrupção. Eles serão abordados em um seção específica. Já as entradas RD , WR e CS são as nossas
velhas conhecidas. A novidade é o pino A0 que, junto com RD e WR , são utilizados para enviar comandos
ao 8259A, bem como ler seus registradores. Na verdade, A0 pode ser conectado diretamente às linhas de
endereço do barramento. Finalmente, D7 – D0 são utilizadas como pinos bidirecionais para termos acesso à
todos os registradores do controlador.
3.2.2.2.
Seqüência de Interrupção
A grande vantagem do 8259A, além da possibilidade de programação, é a capacidade de endereçar
as rotinas de interrupção. Isto permite saltar para a rotina de interrupção correta sem a necessidade de
verificar todos os dispositivos de E/S do sistema. A seqüência normal de eventos durante uma interrupção
é apresentada a seguir.
No 8080/85 os passos são os seguintes:
1. Uma ou mais linhas de interrupção (IR0 – IR7) são ativadas, ligando o bit correspondente do
IRR.
2. 8259A avalia estas requisições no analisador de prioridades e envia a requisição à CPU (através
do pino INT), se for o caso.
3. A CPU responde com um pulso no pino INTA .
4. Um bit do ISR é ligado e um no IRR é desligado (indicando qual requisição está sendo atendida).
O 8259A também libera o opcode da instrução CALL (11001101b) nas linhas D7 – D0.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
57
Curso de Microprocessadores
5. Neste passo, após receber o opcode da instrução CALL, irá pulsar INTA mais duas vezes.
6. Estes dois pulsos dizem ao 8259A para colocar o endereço de 16 bits da rotina de interrupção
no barramento (primeiro o LSB, depois o MSB).
7. No modo AEOI (Automatic End of Interrupt, ou seja, Fim de Interrupção Automático), o bit do
ISR é desligado após o terceiro pulso de INTA . Caso contrário (o modo padrão), um comando
EOI (constante $20) deve ser enviado.
Os eventos que ocorrem nos sistemas baseados no 8086/88/286 são os mesmos até o passo 4.
4. Nada ocorre durante este passo.
5. Neste passo, o 8086/88/286, irá pulsar INTA uma única vez. Durante este pulso, um bit do ISR é
ligado e um no IRR é desligado. Então, o 8259A põe um inteiro no barramento de dados da CPU. A
CPU irá utilizar este inteiro para endereçar o vetor de interrupção.
3.2.2.3.
Interfaceamento
Quando utilizamos apenas um árbitro, a maneira correta de interfacear o 8259A como a CPU é
apresentada na Figura 24. Aqui, desde que o 8259A está trabalhando como mestre, SP/EN deve ser
colocado em Vcc. Fora isto, acredito que nesta altura, tudo deve parecer bastante óbvio.
Figura 24 – Interface padrão do 8259A com o barramento.
Para expandir a capacidade para 64 níveis de prioridades, o 8259A pode facilmente ser
interconectado em um sistema com um mestre e oito escravos, como é apresentado na Figura 25. Nesta
configuração, as saídas INTs dos escravos são conectadas às entradas “IR0 – IR7” do mestre. Assim,
quando um escravo ativar INT, o mestre libera o escravo correspondente, após o primeiro pulso de INTA ,
colocando seu endereço nas linhas “CAS X”. Desse modo, estas linhas atuam como pinos de seleção de chip
(chip select) durante os outros pulsos de INTA .
O endereço de cada escravo é dado durante a inicialização do sistema, através do envio de comandos
específicos à cada 8259A.
Após a interrupção ter sido atendida, necessitamos enviar dois comandos de EOI (um para o escravo
e outro para o mestre). Para seu próprio bem, não se esqueça disto, pois este é um daqueles erros que
consomem um dia inteiro para ser descoberto.
58
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
Figura 25 – O 8259A utilizado em cascata.
3.2.2.4.
Programação
O 8259A aceita dois tipos de comandos:
1. Comandos de Inicialização (Initialization Command Words, ICWs) - Antes da sua operação normal
poder ser iniciada, cada 8259A do sistema deve ser inicializado. Esta inicialização é feita enviadose uma seqüência de dois ou quatro bytes ao 8259A. Durante esta inicialização dizemos com qual
CPU ele está trabalhando (8080/85 ou 8086/88/286), se ele é um mestre ou um escravo, se for
escravo, qual o seu endereço (pinos CAS X, Seção 3.2.2.3), etc. Estes comandos devem ser
enviados uma única vez.
2. Comandos de Operação (Operation Command Words, OCWs) - Com este comandos definimos o
modo de operação dos controladores. Basicamente, existem quatro modos de operação: Fully
Nested (padrão), Rotating Priority, Special Mask e Polled. Em cada um destes modos a prioridade
dos dispositivos ligados ao 8259A pode mudar radicalmente. Só para dar uma idéia, no modo polled
o sistema funciona como na técnica de E/S programada. [Comandos de operação podem ser
enviados em qualquer instante de tempo (após a inicialização)].
Devido à grande capacidade de programação, a configuração do 8259A é um pouco complexa. Como
não iremos utiliza-los em nossas experiências, encerraremos o assunto por aqui. Contudo, caso haja
interesse (ou necessidade), aconselho os manuais 82C59A CMOS Priority Interrupt Controller e 82C59A
Priority Interrupt Controller, ambos podem ser conseguidos gratuitamente no site “Harris Semiconductor
– Search (http://www.semi.harris.com/search/index.htm)”.
3.2.3.
Interrupções no 68HC11
Uma das grandes vantagens do HC11, em relação ao BASIC Stamp II, é o suporte a técnica de E/S
por interrupção. Á primeira vista, esta técnica pode parecer um pouco confusa, porém, com um pouco de
prática, veremos que ela facilita muito as coisas (Isto ficará claro na montagem do Experimento 9).
3.2.3.1.
O vetor de interrupção
O 68HC11 possui um vetor de interrupção de 18 posições que suportam 22 fontes de interrupção
diferentes. Dessas, 15 são mascaráveis e são geradas pelos dispositivos internos ao microcontrolador. O
vetor de interrupção do 68HC11 localiza-se entre as posições de memória FFC0h e FFFFh. A Tabela 6
informa a posição do vetor de interrupção de cada fonte. Não vamos discutir agora todas as fontes de
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
59
Curso de Microprocessadores
interrupção da Tabela 6. Vamos analisar apenas as relacionadas aos pinos IRQ e XIRQ , e a do Timer
Overflow (TOI).
Tabela 6 - Fonte de interrupção, vetor de interrupção e a sua máscara.
3.2.3.2.
Interrupção IRQ e XIRQ
A interrupção XIRQ é não-mascarável. Por isso, ela deve ser utilizada apenas para sinalizar um
falha grave no sistema. Quando o sistema é inicializado [após o RESET (outra interrupção nãomascarável)], a interrupção XIRQ está desabilidade. Logo, para que ela possa ser utilizada, deve-se
limpar o bit X do registrador CCR. Contudo, uma vez habilitada, a interrupção XIRQ não pode ser inibida
(de forma alguma). Além disso, é muito importante lembrar que apenas a instrução TAP pode limpar o bi X
do registrador CCR. (Por favor, não se esqueça disso.)
É importante notar que, quando a CPU reconhece uma interrupção mascarável, o bit I do registrado
CCR é setado, ou seja, as interrupções mascaráveis são desabilitadas. Contudo, isto não afeta o bit X do
CCR, ou seja, a interrupção XIRQ continua habilitada e pode interromper qualquer interrupção
mascarável. Isto também quer dizer que, caso seja necessário uma interrupção mascarável interromper
outra mascarável (com menor prioridade), o bit I do CCR deve ser limpo no início de todas rotinas de
interrupção mascaráveis. Evidentemente, ao final do processo de interrupção (quando o registrador CCR é
desempilhado) o bit I do registrador CCR é automaticamente limpo.
O processo é ligeiramente diferente quando a CPU reconhece uma interrupção XIRQ . Neste caso,
os bits X e I do registrado CCR são setados, ou seja, as interrupções mascaráveis e a XIRQ são
desabilitadas. Como no caso anterior, ao final do processo de interrupção (quando o registrador CCR é
desempilhado) os bits X e I do registrador CCR são automaticamente limpos.
60
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
O pino IRQ da CPU 68HC11 possibilita uma maneira de periféricos externos requisitarem
interrupção à CPU. Trata-se de uma interrupção mascarável sensível a nível. Após o RESET, o pino IRQ é
configurado para ser ativo em nível baixo. Contudo, como mostra a Figura 26, isto pode ser modificado
através do bit 5 do registrador OPTION. Porém, como se trata do registrador que controla vários
aspectos importantes da CPU, o seu conteúdo só pode ser alterado nos primeiros 64 ciclos de instrução
após o RESET.
Figura 26 – Registrador OPTION.
3.2.3.3.
Interrupção do Timer Overflow (TOI)
O 68HC11, assim como a maioria dos microcontroladores, possui um timer interno. Um timer é um
registrador que simplesmente conta o tempo indefinidamente. O timer do 68HC11, chamado de TCNT
(endereço $100E), é de 16 bits. Por isso, ele consegue contar de $0000 à $FFFF. Sua contagem ocorre em
uma freqüência 4 vezes menor que a do relógio do microcontrolador. Isto quer dizer que, no 68HC11 com
clock de 8 MHz, o tempo entre uma contagem e outra é de 0,5 µs.
Um fato interessante é que, sempre que ocorre uma transição de $FFFF para $0000 (um overflow),
o bit 7 do registrador TFLG2 é setado (como mostra a Figura 27). Contudo, uma vez setado, ele só pode
ser limpo via software. Além disso, os bits do registrador TFLG2 tem a peculiaridade de só serem limpos
quando (pasmem!) tentamos seta-los. Explicando melhor, para limpar o bit 7 do TFLG2, devemos escrever o
seguinte código:
LDAA
STAA
#$80
TFLAG2
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
61
Curso de Microprocessadores
Figura 27 – Registrador TFLG2.
Podemos utilizar a indicação do bit 7 do registrador TFLG2 para saber quando ocorreu um overflow
no TCNT. Isto pode ser útil, por exemplo, quando queremos contar um tempo muito maior que 1 ms.
Caso seja necessário, pode-se habilitar uma interrupção para que ela ocorra sempre que o bit TOF
do registrador TFLG2 for setado. Esta interrupção é a interrupção do TOI (Timer Overflow Interrupt).
Ela deve ser habilitada através do bit TOI (bit 7) do registrador TMSK2 (como mostra a Figura 28).
Observe que a interrupção só ocorre no instante em que o bit TOF é setado. Isto quer dizer que, antes da
interrupção ocorrer pela primeira vez, devemos zerar o bit TOF. Além disso, caso seja necessário que a
interrupção ocorra mais de uma vez, deve-se zerar o TOF dentro da rotina de interrupção.
3.2.3.4.
Interrupções na placa EVB
Na placa EVB, todos os vetores de interrupção já estão definidos, ou seja, eles já apontam para
endereços específicos. Além disso, o vetor de interrupção está gravado em uma memória EPROM. Logo,
não pode ser alterado. Com isso, seria desejável que conseguíssemos colocar nossas rotinas de interrupção
nos endereços apontados pelo vetor de interrupção. Contudo, isto não é possível. O máximo que podemos
fazer é colocar uma instrução JMP neste endereço. Evidentemente, este JMP deve apontar para a nossa
rotina de interrupção. Conteúdo do vetor de interrupção da placa EVB é apresentado na Tabela 7.
Figura 28 – Registrador TMSK2.
62
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
Tabela 7 – Conteúdo do vetor de interrupção da placa EVB.
3.2.4.
Interrupções no IBM PC AT
A alguns anos atrás, muito projetos envolvendo microprocessadores eram baseados na CPUs Intel.
Os mais populares eram o 8085 e o 8088/86. Hoje, os microprocessadores Intel já não são tão populares
para uso em sistemas microprocessados (ao contrário dos microcontroladores, como os das famílias 8051 e
8096, ambos da Intel). Contudo, devemos estudar o processo de interrupção nestas CPUs, pois a grande
maioria dos microcomputadores existente no mercado utilizam-nas. E, como vimos nas seções anteriores,
apesar de compreensão relativamente difícil, a técnica de interrupção otimiza bastante o código em
assembler. Como veremos em breve, podemos estender esta facilidade para as linguagens de auto-nível.
3.2.4.1.
O Vetor de Interrupção do IBM PC AT
Em uma CPU da família 80x86 o vetor de interrupção está localizado nos primeiros 1.024 bytes da
memória (isto está correto paras as CPUs até o 80286, pois, a partir do 80386, a Intel utiliza um
registrador para apontar para o início do vetor de interrupção). O vetor comporta 256 endereços de 4
bytes. No IBM PC AT, algumas dessas posições são reservadas para apontar para rotinas que realizam
funções específicas, por exemplo, dar refresh na memória dinâmica. Outras posições são reservadas para
interrupções de software, e outras para interrupções de hardware, por exemplo, o disco rígido.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
63
Curso de Microprocessadores
As interrupções de hardware são controladas por dois controladores 8259A. Os sinas de IRQ0 à
IRQ7 (Figura 23) do 8259A mestre são mapeadas nas posições de 8 à 15 do vetor de interrupção. As
IRQs do segundo controlador são numeradas de IRQ8 à IR15 e são mapeados nas posições de 112 (70h) à
119 (77h) do vetor de interrupção. Estas interrupções são associadas a periféricos específicos, como
apresentado na Tabela 8. A IRQ2 de um dos 8259A foi utilizada para interfacear o segundo controlador,
como apresentado na Figura 25. Isto garante mais oito níveis de interrupção.
Em qualquer CPU, as interrupções também são utilizadas para tratar algumas eventos que possam
perturbar o sistema. Por exemplo, caso o programa do usuário tente dividir algum número por zero, a CPU
imediatamente para o processamento e provoca uma interrupção para tratar este situação. A interrupção,
por sua vez, pode, por exemplo, exibir uma mensagem rude na tela do computador ou em um display de
cristal líquido. Este tipo de interrupção, geralmente, recebe o nome de armadilhas ou traps. A principal
diferença entre armadilhas e interrupções é o fato das armadilhas ocorrerem sempre no mesmo treco de
programa (relacionadas a uma determinada instrução), porém nem todas as vezes que o trecho é executado
(como no caso da instrução de divisão). Algumas posições do vetor de interrupção do PC AT são reservadas
especificamente para tratar com este tipo de interrupção.
As posições do vetor reservadas para interrupções de software podem ser utilizadas livremente
pelo programador. Por exemplo, pode-se escrever um programa de forma que uma interrupção seja gerada
sempre que um determinado trecho do programa seja executado. Por sinal, esta é a pricipal característica
das interrupções de software, ou seja, elas ocorrem sempre no mesmo trecho do programa e todas as
vezes que este trecho é executado.
Interrupção
Posição do Vetor
Controlador
IRQ0
08h
Timer (18,2 vezes/s)
IRQ1
09h
Teclado
Segundo Controlador de
IRQ2
0Ah
Interrupções
IRQ3
0Bh
COM2/COM4
IRQ4
0Ch
COM1/COM3
Disponível (geralmente
IRQ5
0Dh
utilizada pela placa de som)
IRQ6
0Eh
Disco Flexível
IRQ7
0Fh
Porta Paralela (impressora)
IRQ8
70h
Real Time Clock
IRQ9
71h
Disponível
IRQ10
72h
Disponível
IRQ11
73h
Disponível
IRQ12
74h
Disponível
IRQ13
75h
Co-Processador Matemático
IRQ14
76h
Disco Rígido
IRQ15
77h
Disponível
Tabela 8 – Canais de interrupção dos dois controladores 8259A do PC AT e suas
posições no vetor de interrupção.
3.2.4.2.
Trabalhando com Interrupção na Linguagem C
Agora surge uma questão: “Como posso criar minhas próprias rotinas de interrupção?”. Uma rotina
de interrupção é diferente de uma rotina qualquer. Lembre-se que, ao final de uma rotina comum, apenas o
endereço de retorno da rotina (ou função) é retirado da pilha. Como na interrupção, o estado da CPU após
da interrupção tem que ser o mesmo de antes da interrupção, o programa deve salvar todos os
registradores da CPU na pilha do sistema antes de atender ao pedido de interrupção. Além disso, ao final
64
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
da rotina de interrupção, todos os registradores são restaurados da pilha. O trecho de código abaixo
ilustra como deve ser uma rotina de interrupção em Linguagem C.
Void interrupt nome_da_rotina()
{
...
// As instruções que fazem parte da sua rotina deve ser colocadas aqui
outport(0x20, 0x20);
// Envia a constante 0x20 para o dispositivo no endereço 0x20
}
Merece alguma explicação? Então vamos a ela... a palavra chave interrupt diz ao compilador C que esta
rotina salva os registradores na pilha e restaura-os antes de sair da rotina de interrupção. O código
outport(0x20, 0x20); avisa ao 8259A do computador que a requisição de interrupção já foi atendida
(Dúvidas? Consulte a Seção 3.2.2.2.). Dessa forma, outro pedido de interrupção pode, se necessário, ser
feito.
Uma vez escrita a função de tratamento de interrupção, o seu endereço deve ser posto no vetor de
interrupção. No caso da função anterior, caso desejássemos colocar o seu endereço na posição $78 do
vetor de interrupção, teríamos um código como segue:
...
disable()
velha_int78 = getvect(0x78);
setvect(0x78, nome_da_rotina);
enable();
...
// inibe todas as interrupções mascaráveis
// salva o conteúdo da posição 0x78 do vetor na variável velha_int78
// põe o endereço da função “nome_da_rotina” na posição 0x78
// libera todas as interrupções mascaráveis
Tenho certeza que o trecho de código anterior precisa de explicação. Vamos a ela... Primeiro, é
muito perigoso alterar o conteúdo do vetor de interrupção, pois, se alguma interrupção ocorrer enquanto
estamos fazendo isto, pode causar sérios problemas. Por isso, é um ótimo hábito desabilitar as
interrupções antes de mexer no vetor. Evidentemente, quando terminarmos de altera-lo podemos tornar a
habilita-las. É exatamente isto que fazem as instruções disable() e enable(). É claro que antes de
colocarmos o endereço da nossa rotina no vetor de interrupção já existe um endereço lá. Outro bom
hábito de programação é restaurar o endereço original antes de terminarmos nosso programa. Para isto,
temos que salvar o endereço existente no vetor antes de alterá-lo. Isto é feito utilizando uma variável
global. No trecho de programa anterior, utilizamos a variável velha_int78 para salvar este endereço. As
funções getvect(0x78) e setvect(0x78, nome_da_rotina) lêem e escrevem na posição $78 do vetor de
interrupção, respectivamente.
Em um programa em C, antes de uma variável ser utilizada ela deve ser declarada. Em C, a forma de
declarar uma variável que recebe um endereço de uma rotina de interrupção é muito interessante. A forma
de declarar a variável anterior, velha_int78, é
void interrupt (*velha_int78)();
// deve ser colocada no início do programa, fora da função main
Como disse, ao final do programa deve-se restaurar o vetor de interrupção com o endereço salvo.
(No caso anterior, salvo na variável velha_int78.) O Trecho do programa que faz esta tarefa é exibido a
seguir.
// o trecho de código a seguir deve ser colocado no fim da função main
disable();
setvect(78, velha_int78);
enable();
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
65
Curso de Microprocessadores
Algumas vezes desejamos roubar uma rotina de interrupção pré-existente. Por exemplo, quando
digitamos uma tecla no computador, provocamos uma interrupção. Se desejarmos, podemos substituir a
rotina que trata esta interrupção esta interrupção por uma nossa. Até aqui, não há nada demais. Usamos o
procedimento visto até aqui. Contudo, vale a pena lembrar que toda rotina de interrupção executa um
conjunto de passos indispensáveis para o funcionamento de computador. Por exemplo, a rotina de
tratamento de interrupção do teclada realiza os seguites passos quando solicitada:
1. Recebe a tecla digitada pelo usuário;
2. Armazena o código da tecla no buffer do teclado;
3. Avisa ao controlador do teclado que a tecla já foi salva no bufffer, e;
4. Avisa ao 8259A que a interrupção do teclado já foi atendida.
Caso qualquer um dos passos anteriores não seja executado, nosso computador corre perigo. Isto
seguinifica que temos que garantir que os passos anteriores sejam realizados. Uma forma de garantir isto
é chamando a rotina de interrupção original. Desde que tenhamos salvado o endereço da rotina original,
está é uma tarefa fácil. Para o caso de estarmos trabalhando, por exemplo, com a interrupção de hardware
$08, nossa função de interrupção poderia ser com segue.
Void interrupt nova_int08()
{
...
// As instruções que fazem parte da sua rotina deve ser colocadas aqui
velha_int08();
// chama rotina de interrupção 08 original
}
Note que agora não executamos a instrução outport(0x20, 0x20). Pois, isto é feito pela rotina original
da interrupção $08.
Por último, segue o corpo completo de um programa que trabalha com rotinas de interrupção em C.
#include <dos.h>
#include <conio.h>
#include <stdio.h>
void interrupt nova_int (); // Declara a rotina de interrupção
void interrupt (*velha_int)();
// Declara a variável que guarda o endereço da rotina original
void interrupt nova_int () // A sua rotina de interrupção
{
…
// Aqui vão as suas instruções
(velha_int)();
// Chama a interrupção original
}
void main(void)
{
clrscr();
disable();
velha_int = getvect(??); // escolha a posição do vetor de interrupção
setvect(??, nova_int);
// escolha a posição do vetor de interrupção
enable();
…
// coloque aqui o corpo do seu programa
disable();
setvect(??, velha_int);
enable();
// escolha a posição do vetor de interrupção
}
66
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
Para facilitar a escrita de futuros programas, na Tabela 9 é apresentado o conteúdo de cada posição
do vetor de interrupção. Faça bom proveito!
Posição do Vetor
Interrupção
Controlador
Armadilhas
00 - 01
(Traps)
Interrupção de
02
Erro de Paridade
Hardware
Armadilhas
03 - 07
(Traps)
08h
IRQ0
Timer (18,2 vezes/s)
09h
IRQ1
Teclado
Segundo Controlador de
0Ah
IRQ2
Interrupções
0Bh
IRQ3
COM2/COM4
0Ch
IRQ4
COM1/COM3
Disponível (geralmente
0Dh
IRQ5
utilizada pela placa de som)
0Eh
IRQ6
Disco Flexível
0Fh
IRQ7
Porta Paralela (impressora)
Interrupções de
10 – 6F
Software
70h
IRQ8
Real Time Clock
71h
IRQ9
Disponível
72h
IRQ10
Disponível
73h
IRQ11
Disponível
74h
IRQ12
Disponível
75h
IRQ13
Co-Processador Matemático
76h
IRQ14
Disco Rígido
77h
IRQ15
Disponível
Interrupções de
78 - FF
Software
Tabela 9 – Descrição de cada uma das posições do vetor de interrupção do PC AT.
3.3
E/S via DMA
O controlador de DMA (Acesso Direto à Memória) é um dispositivo útil e poderoso para transferir
dados entre dispositivos de E/S, ou entre dispositivo de E/S e a memória. Esta transferência ocorre
muito rapidamente porque uma peça de hardware dedicada transfere dados de uma parte do computador
para outra em apenas um ou dois ciclos de E/S por dado transferido. O DMA também minimiza a latência
em atender um dispositivo de E/S, pois um hardware dedicado responde mais rapidamente que
interrupções, e o tempo de transferência é curto. Logo, a quantidade de memória temporária necessária
nos dispositivos de E/S é reduzida (Por que?). Além disso, o DMA também diminui a carga da CPU, pois ela
não tem que executar instrução alguma para transferir dados. Portanto, o processador não é usado para
gerenciar a transmissão e fica disponível para outras atividades. Isto é ainda mais importante em sistemas
nos quais o microprocessador opera primariamente na sua memória cache. Neste caso, a transferência
ocorre em paralelo, logo a performance geral do sistema é melhorada.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
67
Curso de Microprocessadores
3.3.1.
Como o DMA funciona
Um controlador de DMA gerencia vários canais de DMA. Cada canal pode ser programado para
realizar uma seqüência de transferências. Dispositivos, normalmente periféricos de E/S que necessitam
enviar ou receber dados, sinalizam para o controlador de DMA enviando um sinal de requisição de DMA
(DRQX, com X igual ao número do canal). Um sinal de DRQX para cada canal é roteado para o controlador.
Este sinal é monitorado e respondido da mesma forma que o processador gerencia interrupções. Quando o
controlador de DMA recebe o sinal de requisição de DMA (DRQX), o controlador responde realizando uma
ou mais transferências do dispositivo de E/S para a memória ou vice versa.
Os canais do DMA precisam ser habilitados pelo processador para que o controlador de DMA
responda aos sinais de DRQX. O número de operações efetuadas, modos de transferências usados, e
locações de memória possíveis dependem de como os canais de DMA são programados.
Um controlador de DMA, tipicamente, compartilha a memória do sistema com a CPU e pode operar
como mestre ou escravo. Operando como mestre, o controlador assume o comando do barramento do
sistema (linhas de endereço, dados e controle) para realizar as transferências. Operando como escravo, o
controlador de DMA é acessado pela CPU, que programa os registradores internos ao controlador para
configurar a transferência. Estes registradores consistem de registradores de endereço fonte e
destino e contador de transferências, para cada canal de DMA. Além de um registrador de status para
configuração e monitoramento da operação do controlador.
3.3.2.
Tipos e modos de transferências
Controladores de DMA variam de acordo com os tipos de transferências e modo suportados. Os dois
tipos de transferência são o flyby e o fetch-and-deposit. Os três modos mais comuns são o sigle, block, e
demand. Todos esses tipos e modos são descritos a seguir.
O tipo de transferência mais rápida é o flyby. Nesta, uma única operação de barramento é usada
para a transferência. Os dados são lidos da fonte e escritos no destino simultaneamente. Durante a
transferência, o dispositivo envia um sinal de DRQX para o canal apropriado. Em seguida, o controlador
toma o controle do barramento e envia um sinal para o dispositivo (sinal DACKX, com X igual ao número do
canal). Este sinal avisa ao dispositivo para ler o dado do barramento ou coloca-lo no barramento,
dependendo da direção da transferência. Em outras palavras, este tipo de transferência ocorre como uma
operação de Leitura/Escrita na memória, apenas um ciclo de memória é utilizado. Apesar de muito
eficiente, este tipo de operação não pode transferir dados da memória para a memória.
O segundo tipo de transferência é chamado de fetch-and-deposit. Neste, são envolvidos dois ciclos
de memória ou de E/S. Os dados são inicialmente lidos do dispositivo ou da memória e são armazenados em
registradores internos ao controlador de DMA. Os dados são então escritos na memória ou no dispositivo
de E/S no próximo ciclo. Apesar de ineficiente, pois utilizada dois ciclos de memória, este tipo de
transferência é útil para transferir-se dados entre dispositivos incompatíveis. Por exemplo, um
controlador de DMA pode efetuar duas leituras de 16 bits em um local, seguida de uma escrita de 32 bits.
Diferente do tipo flyby, o fetch-and-deposit pode ser usado para operações entre a memória e a memória.
Além dos tipos de transferência, um controlador de DMA pode suportar um ou mais modos de
transferência. Os mais comuns são o sigle, block, e demand. O modo sigle é o mais lento, pois, neste tipo, o
DMA transfere um único dado para cada sinal de DRQX. Isto pode não ser problema para sistema com
pouca demanda de barramento, porém pode causar sérios problemas de latência quando múltiplos
dispositivos tentam acessar o barramento. Os modos block e demand podem ser mais eficientes, pois
permitem realizar várias transferências quando o DMA ganha o controle do barramento. No modo block,
em resposta a um único sinal de DRQ, o DMA realiza múltiplas transferências de acordo com seu
registrador contador. No modo demand, o DMA realiza transferências enquanto o dispositivo sustentar o
sinal de DRQ.
68
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
3.3.3.
Operação do controlador
Para cada canal, o controlador de DMA armazena os endereços dos dispositivos (ou posições de
memória) envolvidos na transferência, além do número de transferências a serem realizadas (o contador).
Esses dados são armazenados em registradores chamados “registradores de base”. Uma cópia dos
contadores de base é armazenada nos registradores de endereço corrente e de contador corrente.
Cada canal é habilitado ou inibido através de um registrador de máscara. Um canal de DMA é iniciado
escrevendo-se nos registradores de base e habilitando-se o canal. A cada transferência, o valor no
registrador de endereço corrente é colocado no barramento. Em seguida, o registrador é incrementado ou
decrementado. O contador corrente determina o número de transferências remanescentes e é
automaticamente decrementado a cada transferência. Quando o valor deste registrador passa de 0 (zero)
para –1 (menos um), um sinal chamado terminal count (TC) é gerado. Isto significa que o DMA completou a
seqüência de transferências. Este sinal pode ser monitorado pelos dispositivos de E/S que participam da
transferência.
O controlador de DMA necessita de programação a cada sinal TC. Quando este sinal ocorre, a CPU
precisa programar o DMA para uma nova transferência. Para isto, alguns controladores de DMA
interrompem a CPU à cada fim de transferência. Logo, o controlador consome algum tempo da CPU, mas
muito menos que o consumido por serviços de E/S baseados em interrupções. Alguns controladores
possuem mecanismos de auto-configuração. Geralmente, quanto mais sofisticado for o controlador,
menos tempo da CPU ele vai consumir para realizar esta configuração.
Um controlador de DMA também tem um ou mais registradores de status que são lidos pela CPU
para determinar o estado de cada canal. Este registrador geralmente indica quando um canal foi
requisitado e quando o canal envia um TC. Contudo, ler um registrador de status sempre elimina a
informação do TC do registrador, o que pode provocar problemas se múltiplos dispositivos estão tentando
usar canais diferentes.
3.3.4.
Implementação de DMA no IBM PC e no PC/XT
O controlador de DMA usado no IBM PC, PC/XT e na maioria dos microcomputadores é o 8237A, da
Intel. Este controlador tem quatro canais, cada um dos quais possui um registrador de endereço e um
registrador contador (ambos de 16 bits). O 8237A implementa os modos sigle, block e demand.
O PC utiliza dois canais de DMA, um para transferir dados da unidade de discos flexíveis (canal 2) e
outro para efetuar refresh na memória. (canal 0). Os canais remanescentes estão disponíveis para cartões
de E/S. O 8237A do PC realiza transferência do tipo flyby de 8 bits, pois o barramento do PC é de 8 bits,
além de um tipo especial de transferência de uma locação de memória para a outra.
No PC, o 8237A opera a 4,77 MHz e pode transferir dados acima de 900 kbytes/s no modo demand.
3.3.5.
Implementação de DMA no PC AT
O PC AT aumentou o número de canais de DMA disponíveis para sete. Dois 8237A são usados em
cascata. O controlador 1 possui os canais de 0 a 3 e implementa transferência do tipo flyby entre
dispositivos de E/S de 8 bits e locações de 8 ou 16 bits da memória do sistema. O controlador 2 possui os
canais de 4 a 7. O canal 4 é usado para interligar as operações dos dois controladores e portanto não está
disponível para uso. Os canais 5, 6 e 7 implementam transferências flyby de 16 bits entre dispositivos de
16 bits e locações de memória de 16 bits. O registrador contador deste controlador é de 16 bits. As linhas
de endereço A1 até A16 são armazenadas nos registradores de endereço, um registrador de página retém
os sete bits mais significativos do endereço de 24 bits, enquanto que A0 é suposto ser 0. Logo, para
transferências de 16 bits, o comprimento máximo da seqüência de transmissão é 128 kbytes e o
registrador de página não é incrementado automaticamente.
No AT, o 8237A opera a 4 MHz (seu limite máximo é de 5 MHZ) que permite, no modo demand, uma
taxa de 800 kbytes/s para 8 bits e 1,6 Mbytes/s para 16 bits.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
69
Curso de Microprocessadores
Tanto no PC original como no AT, o limite de transferência via DMA é limitado pelas necessidades e
refresh de memória. Um ciclo de refresh é executado a cada 15 µs. Por isso, um dispositivo que utilize o
modo demand tem de interromper o sinal de DRQ e liberar o barramento a cada 15 µs. Além disso, o modo
block não é muito viável neste tipo de sistema, pois apenas 24 transferências podem ser efetuadas em 15
µs.
3.3.6.
Gerenciando o controlador de DMA
O DMA é um recurso compartilhado e pode ser usado por aplicações completamente diferentes, logo
precisa ser propriamente gerenciado. As maiores preocupações são manter as informações de status
coerentes e controlar a transferência dos dados, visto que não existe suporte por parte do sistema
operacional para operações com DMA.
O 8237A possui registradores de programação de 16 bits, porém são programados através de uma
porta de 8 bits. Para isto, existe um registrador apontador que define quais das duas posições receberá
cada operações de 8 bits de leitura ou escrita. Evidentemente, para evitar conflitos, o registrador
apontador tem que ser limpo e as interrupções têm que ser interrompidas antes de cada operação de
leitura ou escrita.
Outro problema envolve a determinação de fim de transferência do DMA. Cada canal de DMA tem
um bit de TC no registrador de status, infelizmente uma leitura neste registrador limpa o bit de TC de
todos os canais. Logo, o dispositivo de E/S tem que achar outra forma de saber o fim de transferência de
DMA. No caso do PC e do AT, isto é feito através de um dispositivo de E/S que trabalha como um “DMA
slave” e gera uma IRQ para cada canal de DMA.
3.4
Interface de Comunicação Serial
Devido à simplicidade do hardware, a comunicação serial é muito utilizada dentro da indústria
eletro-eletrônica. Hoje, o padrão de comunicação mais utilizado é o EIA/TIA – 232 ou, simplesmente, RS232 (Recommended Standard).
3.4.1.
Especificações
RS-232 é um padrão completo, ou seja, ele especifica 1) características elétricas, 2) sinais de
controle e handshake, e 3) características mecânicas. Cada uma dessas três características são discutidas
a seguir.
3.4.1.1.
Características Elétricas
As especificações elétricas do padrão definem características como: níveis de tensão, slew rate e
impedância da linha de transmissão. Desses, o mais importante para nós é a especificação dos níveis de
tensão. Esta especificação foi definida antes da popularização da família TTL. Por isso, o padrão define
níveis de tensão incompatíveis com esta família. O nível alto na transmissão foi definido de +5 a +15 volts.
Já o nível baixo foi definido de –5 a –15 volts. Na recepção, o nível alto foi definido de +3 a +15 volts e o
nível baixo de –3 a –15 volts. A Figura ??? ilustra estes níveis de tensão. Como última informação, saiba
que, na comunicação RS-232, o nível baixo é definido como nível lógico 1 e o nível alto como nível lógico 0.
3.4.1.2.
Sinais de Controle e Handshake
O padrão RS-232 definiu a função de cada um dos sinais envolvidos na sua interface. Estes sinais
são divididos em 4 categorias: comum, dados, controle, e temporização. A Tabela ??? apresenta todos os
sinais definidos pelo padrão. Como se vê, existe um número exagerado de sinais. Felizmente, nenhuma
aplicação utiliza todos os sinais. Por exemplo, um dos dispositivos que utilizam o padrão RS-232 é o
modem. Este dispositivo utiliza tipicamente apenas oito sinais. Uma aplicação padrão pode funcionar
basicamente com cinco desses sinais (1 comum, 2 de dados, e 2 de handshake). Em alguns casos, apenas
três sinais podem ser utilizados (1 comum e 2 de dados).
70
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 3- Entrada e Saída
3.4.1.3.
Características Mecânicas
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
71
Curso de Microprocessadores
Capítulo 4 - Conversores A/D e D/A
Conversão digital para analógico (D/A) é o processo de converter códigos digitais em uma faixa
contínua de níveis de sinal analógico. Conversão analógico para digital (A/D) é o processo de converter uma
faixa contínua de níveis de sinal analógico em códigos digitais. Tais processos de conversão são
necessários para conectar os sistemas da natureza, que são tipicamente expressos por sinais analógicos
contínuos variantes no tempo, com os sistemas digitais que processam, armazenam, interpretam, e
manipulam as grandezas analógicos.
O avanço na tecnologia de conversores A/D e D/A, assim como a popularização dos
microcomputadores, fez com que muitos sistemas implementados de maneira analógica fossem convertidos
para circuitos digitais. Pois, além de ter um custo reduzido (quando comparado à circuitos analógicos)
estes sistemas apresentam a vantagem de serem programáveis. Além disso, alguns algoritmos são
simplesmente irrealizáveis na forma analógica.
Com o aumento da popularização dos algoritmos digitais, surge uma necessidade de conhecer-se a
base teórica necessária à interface desses sistemas discretos com o nosso mundo analógico. Este capítulo
tenta suprir um pouco desta necessidade apresentado conceitos como “Aliasing”, “Teorema da
Amostragem”, e “Freqüência de Nyquist”, de uma forma, esperançosamente, fácil de entender.
4.1
Discretização
Sabemos que em um intervalo de tempo de 1 µs não ocorre variação de temperatura significativa.
Por isso, não adianta observar a temperatura durante este período. Neste caso, poderíamos definir um
intervalo de tempo mínimo durante o qual não observaríamos a variação na temperatura. Dependendo da
aplicação, o intervalo poderia ser escolhido como sendo 1 min. Dessa forma, a temperatura seria
considerada constante (ou mesmo inexistente) durante todo o período de 1 min após a última observação.
Desta forma, a temperatura seria considerada uma grandeza discreta no tempo, ou seja, existiria apenas
para períodos de tempo específicos.
Na Figura 29 é apresentado (a) representação gráfica de um discretizador que transforma a
grandeza analógica f(t) em um sinal discreto no tempo, (b) a representação matemática de um
discretizador e (c) o gráfico da grandeza analógica (linha contínua) e do sinal discreto (pontos grossos).
4.2
Teorema da Amostragem
O teorema da amostragem foi introduzido por Shannon em 1949, e impõe restrições em termos de
componentes de freqüência de um sinal, f(t), a ser discretizado. Este teorema pode ser resumido como:
Para representar de forma unívoca um sinal f(t), é necessário amostrar-se (discretizarse) este sinal a uma freqüência superior ao dobro da maior componente de freqüência de f(t).
Ou seja, para amostrar-se um sinal cuja maior componente de freqüência é fC é necessário uma
freqüência de amostragem de pelo menos 2fC. Esta freqüência, 2fC, também é conhecida como freqüência
de Nyquist.
O teorema de Shannon (ou teorema da Amostragem) pode ser aceito observando-se o processo de
digitalização no domínio da freqüência (Figura 30).
Considere o sinal analógico f(t) representado na Figura 30(a). Assuma que este sinal tenha a
Transformada de Fourier, F(ω), esboçado na Figura 30(b). Baseado na Figura 29(b) e no teorema de
Shannon, um discretizador de Nyquist (observe o intervalo de amostragem igual a 1 2 f c ) para o sinal f(t)
seria como ilustrado na Figura 30(c) e teria uma Transformada de Fourier como apresentado na Figura
30(d). Com isto, para obter o sinal discretizado da Figura 30(e), teríamos que multiplicar o gráfico da
Figura 30(a) pelo da Figura 30(c), ou seja, convoluir a transformada da Figura 30(b) com a da Figura 30(d),
72
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
para obter o trasformada da Figura 30(f). Desse modo, a Figura 30(e) representa do sinal f(t)
discretizado e a Figura 30(f) a Transformada de Fourier do mesmo sinal após a discretização.
Figura 29 - (a) representação de um discretizador, (b) representação gráfica de um
discretizador e (c) sinal analógico (linha contínua) e sinal discreto (pontos grossos) .
Agora, se necessário, pode-se recuperar o sinal analógico f(t) [Figura 31(e)] a partir do sinal
discreto f(n) [Figura 31(a)]. Para saber como, precisa-se observar a Transformada de Fourier de f(n),
Fp(ω) [Figura 31(b)]. Da Figura 31(b), vê-se que para obter-se a transformada da Figura 31(f) (que
corresponde ao sinal f(t)) precisa-se multiplicar a transformada da Figura 31(b) pela da Figura 31(d), ou
seja, convoluir a função da Figura 31(a) com a da função sinc [Figura 31(c)], cuja transformada de Fourier
é apresentada na Figura 31(d).
Como exposto nos parágrafos anteriores, comprova-se graficamente que um sinal amostrado com a
freqüência de Nyquist pode ser recuperado. Falta provar que o sinal amostrado a uma freqüência menor
que a de Nyquist não pode ser mais recuperado. Isto pode ser feito observando-se a Figura 32. Nesta
figura apresenta-se vários exemplos de Transformadas de Fourier de sinais discretos amostrados a
freqüências menores que a de Nyquist. Comparando-se estes exemplos com o da Figura 30(f), vê-se que é
impossível encontra-se uma Transformada de Fourier que, multiplicada por qualquer uma das
transformadas da Figura 32, gere a transformada da Figura 31(e). Neste caso, diz-se que ocorreu o
Fenômeno de Aliasing.
Observando-se mais uma vez a Figura 31, nota-se que a Transformada da Figura 31(d) é na verdade a
função de transferência de um filtro passa-baixas ideal. Contudo, na prática, é impossível obter-se um
filtro com esta função de transferência. Pois, neste caso, teríamos um sistema não-causal. Na Figura 33,
apresenta-se a função de transferência de um filtro real. Desta figura, vê-se que, caso efetue-se a
digitalização a uma freqüência muito próxima a de Nyquist, ainda obtem-se o fenômeno de aliasing, ou seja,
na prática, tem-se que utilizar uma freqüência um pouco maior que a de Nyquist para separar ainda mais os
espectros da Figura 30(f). Neste caso, com um filtro real (com a função de transferência da Figura 33)
pode extrair as componentes de freqüências mais altas, para obter-se o espectro da Figura 31(f).
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
73
Curso de Microprocessadores
Figura 30 – (a) sinal analógico f(t), (b) Transformada de Fourier de f(t), F(ω), (c)
representação gráfica de um discretizador de Nyquist, (d) Transformada de Fourier do
discretizador de Nyquist, (e) sinal discreto no tempo e em amplitude e (f)
Transformada de Fourier do sinal discreto no tempo e em amplitude.
74
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
Figura 31 – (a) sinal discretizado, f(n), (b) Transformada de Fourier de f(n), (c) gráfico
da função sinc, (d) Transformada de Fourier da função sinc, (e) sinal analógico f(t) e (f)
Transformada de f(t).
O fenômeno de aliasing pode ainda ocorrer durante a amostragem de sinais com largura de faixa
infinita, ou seja, sinais cuja Transformada de Fourier ocupa toda a faixa de freqüência (todo o espectro).
Neste caso, o problema não é a função de transferência do filtro passa-baixas, mas sim a largura de faixa
infinita do sinal. Pois, segundo o Teorema de Shannon, seria necessário uma freqüência de amostragem
infinita para digitalizar o sinal. Para contornar este problema, tem-se que efetuar um estudo no sinal que
pretende-se digitalizar para descobrir qual a faixa de freqüência que realmente contribui para a sua
forma (diz-se que encontra-se a faixa de freqüência na qual concentra-se a maior quantidade de energia
do sinal). Quando a faixa de freqüência mais significante do sinal é encontrada, tem-se que aplicar um
filtro passa-baixas (algumas vezes passa-faixa), cuja freqüência de corte é igual à largura de faixa
encontrada, ao sinal antes de digitaliza-lo. Desse modo, a freqüência de Nyquist de um sinal com largura de
faixa infinita é duas vezes a maior componente de freqüência do sinal que contribui de forma significativa
pa a sua forma.
4.3
Quantização
Como visto na Seção 4.1, o processo de discretização (ou amostragem) transforma o sinal analógico
f(t) em um sinal discreto no tempo. Contudo, f(t) continua sendo contínuo em amplitude. Por exemplo, a
temperatura, assim como a maioria das grandezas existentes na natureza, é analógica. Desta forma, para a
temperatura variar de 29 para 30 OC, ela tem que passar por todos os valores intermediários. Porém,
provavelmente não é interessante saber que a temperatura variou de 29,0000000000 para
29,0000000001 OC. Pois os reflexos dessa mudança são desprezíveis. Neste caso, dependendo da
aplicação, podemos escolher a menor variação de temperatura relevante. Este valor, por exemplo, pode ser
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
75
Curso de Microprocessadores
0,5 OC. Dessa forma, seria relevante saber se a temperatura variou, como exemplo, de 29,0 para 29,5 OC.
Contudo, qualquer valor entre estes dois extremos seria considerada uma variação desprezível e poderia
ser considerada zero, ou seja, 29,1 OC ou mesmo 29,4 OC poderia ser considerado 29,0 OC. Isto quer dizer
que estaríamos transformando a temperatura em uma grandeza discreta em amplitude, ou seja, uma
grandeza que pode assumir apenas uma quantidade finita de valores entre dois valores quaisquer. Para o
nosso exemplo, dentro do intervalo 25 OC e 30 OC a temperatura poderia assumir os valores 25,0; 25,5;
26,0; 26,5; 27,0; 27,5; 28,0; 28,5; 29,0; 29,5 e 30 OC. O processo descrito anteriormente chama-se
quantização.
Figura 32 – Diversos exemplos da Transformada de Fourier de um sinal amostrado a uma
freqüência inferior a de Nyquist.
Figura 33 – Esboço da função de transferência de um filtro passa-baixas real (apenas as
componentes de freqüência positivas).
Para entender o processo de quantização, observe o gráfico da Figura 34(a). Nesta figura,
apresenta-se graficamente o processo de quantização da grandeza temperatura utilizando-se um
quantizador de 7 níveis (incluindo o zero). Como apresentado no gráfico, para valores de temperatura
entre 0 e 1 OC, considera-se a temperatura como sendo 0. De forma semelhante, para valores entre 1 e 2
76
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
C, considera-se a temperatura como sendo 1 OC. O mesmo raciocínio pode ser aplicado a todos os outros
níveis de quantização.Em particular, para valores de temperatura maiores que 7 OC, considera-se a
temperatura como sendo 6 OC. Assim, o sinal discretizado no tempo está agora discretizado também em
amplitude.
Em todo processo de quantização comete-se um erro. Este erro diminui à medida que o número de
níveis de quantização aumenta. Isto é bastante intuitivo, pois, à medida que aumenta-se o número de níveis
de quantização, diminui-se o tamanho dos degraus da Figura 34(a). Fazendo com que a escada Figura 34(a)
aproxime-se de uma rampa perfeita.
6
5
4
3
1
2
Níveis de Quantização
5
4
3
2
1
Níveis de Quantização
6
O
1
2
3
4
5
6
7
Temperatura em graus celsius
(a)
O
C
1
2
3
4
5
6
7
Temperatura em graus celsius
O
C
(b)
Figura 34 – Quantização da temperatura em sete níveis de quantização.
Observando-se novamente a Figura 34(a), nota-se que, quando o valor de temperatura aproxima-se
da ponta de um degrau, por exemplo, em T um pouco menor que 3 OC, o erro de quantização é máximo e é
igual a 1 OC. Deslocando-se os degraus da Figura 34(a) um pouco para a esquerda (exatamente 0,5 OC),
tem-se o gráfico da Figura 34(b). Neste gráfico, o erro máximo cometido é de 0,5 OC. Por isso, no
processo de quantização, o esquema da Figura 34(b) é mais utilizado, pois reduz o erro máximo pela
metade.
Generalizando, pode-se afirmar que o processo de quantização pode ser representado pela Figura
35. Nesta figura o processo de quantização é apresentado em termos do nível de quantização q. (Para o
exemplo anterior, q seria igual a 1 OC.) Além disso, o erro máximo cometido no processo de quantização é
0,5q. Lembrando que a precisão do quantizador é dada em função do número de níveis de quantização.
4.4
Codificação
Entendido o processo de quantização, torna-se fácil o conceito de codificação. Pois, o processo de
codificação consiste em atribuir-se um número binário a cada um dos níveis de quantização. Assim, o
número de bits utilizado na representação de cada nível de quantização depende do número de níveis. Por
isso, o número de bits do codificador também é uma maneira de expressar a precisão do codificador e,
conseqüentemente, do sinal digitalizado.
O processo de codificação é ilustrado na Figura 36.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
77
Curso de Microprocessadores
Figura 35 – Processo de quantização e o erro intrínseco ao processo.
Figura 36 – Processo de quantização e codificação.
4.5
Recuperação do Sinal Codificado
Caso seja necessário recuperar o sinal analógico codificados na forma de números binários, deve-se
usar um conversor D/A. Este processo é realizado fazendo-se o processo inverso da codificação, ou seja,
de acordo com a Figura 36, para um dado número binário, obtem-se um sinal de tensão igual ao nível de
quantização correspondente.
O sinal amostrado é discreto no tempo e em amplitude. Ele é algum como o sinal da Figura 37(a). Na
recuperação do sinal original, não se tem informação sobre o sinal entre os instantes de tempo de duas
aquisições. Por isso, o primeiro passo da recuperação deve ser tornar o sinal contínuo no tempo. Isto pode
ser conseguindo mantendo-se na saída do conversor D/A o nível de quantização correspondente ao código
binário da entrada do mesmo, durante o período que não se tem informação sobre o valor do sinal. Por isso,
na saída do conversor D/A o sinal é parecido com o da Figura 37(b). Evidentemente, quanto maior for o
número de bits utilizado na codificação do sinal, melhor será o sinal recuperado.
78
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
Figura 37 – (a) sinal digitalizado, quantizado e codificado, (b) sinal na saída do conversor
D/A e (c) sinal na saída do filtro "suavizador".
Neste ponto, falta ainda transformar o sinal na saída do converosr D/A discreto em aplitude.
Observando novamente a Figura 31, vê-se que os degraus da Figura 37(b) são causados por componentes
de alta freqüência contidas no sinal digitalizado. Dessa forma, para obter-se o sinal original, tem-se que
aplicar o sinal da Figura 37(b) ao filtro passa-baixas da Figura 31(b). Este filtro algumas vezes é chamado
de Filtro "Suavizador" (Smoothing Filter). Finalmente, após o Smoothing Filter, o sinal f(t) é (quase)
completamente recuperado.
4.6
Critérios de Performance
Os fatores que mais contribuem para a performance dos conversores A/D e D/A são: resolução,
velocidade e linearidade.
4.6.1.
Resolução
A resolução de um D/A é a menor variação de tensão possível sua na saída (analógica). No A/D, a
resolução é a menor variação de voltagem que pode ser detectada pelo sistema e que produz uma variação
no código digital. A resolução determina o número total de códigos digitais, ou níveis de quantização, que
são reconhecidos ou produzidos pelo circuito conversor.
A resolução de um D/A ou A/D é geralmente especificada em termos de bits no código digital. Um
código de n bits permite 2n níveis de quantização, ou 2n-1 degraus dentro da faixa dinâmica10 do
conversor, como é apresentado na Figura 38. Quando o número de bits aumenta, o tamanho dos degraus de
quantização (Seção 4.3) diminui, logo a exatidão do sistema aumenta. A resolução do sistema pode ser
especificada também em termos do "tamanho" dos degraus de quantização (Figura 35). Contudo, neste
caso, a resolução deve ser especificada em termos da faixa dinâmica do conversor. Por exemplo, resolução
de 5 mV para uma faixa dinâmica de 5 V.
4.6.2.
Velocidade
A velocidade de um conversor A/D ou D/A é determinada pelo tempo que ele leva para realizar a
conversão. Para os conversores D/A, a velocidade é especificada em termos de tempo de ajuste (o tempo
necessário para que a tensão na saída do D/A torne-se estável). Já para os conversores A/D, ela é
especificada em termos de tempo de conversão (tempo necessário para que o A/D realize a conversão).
Nos conversores D/A, o tempo de ajuste depende da faixa dinâmica do conversor e da transição do código
binário, ou seja, leva mais tempo para obter-se uma saída estável em uma transição de 0000 para 1111, do
que em uma de 1110 para 1111. Por isso, o tempo de ajuste é especificado nas condições apropriadas.
Os conversores A/D têm um tempo de conversão mínimo que limita a velocidade na qual eles podem
realizar conversões contínuas. A taxa de amostragem é o número de vezes por segundo que o sinal
analógico pode ser convertido no código digital. Logo, um conversor com tempo de conversão de 1 µs pode
10
A grosso modo, a faixa dinâmica de um conversor pode ser entendida como a faixa de tensão que pode ser aplicada a entrada (A/D)
ou gerada na saída (D/A) do mesmo.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
79
Curso de Microprocessadores
converter um sinal a uma taxa de amostragem máxima de 1 MHz. Por isso, devido ao teorema de Shannon,
a velocidade de um conversor A/D é um critério importantíssimo na escolha do tipo de conversor.
Figura 38 – Conversão A/D com 4 bits de resolução.
4.6.3.
Linearidade
Em termos de conversores A/D e D/A, existem dois tipos de linearidades: linearidade integral e
linearidade diferencial. A linearidade integral é definida em termos do desvio de uma linha reta da origem
ao final da faixa dinâmica do conversor. Esta linearidade pode ser conhecida aplicando-se valores da linha
reta em questão na entrada do conversor e observando a sua saída. Na Figura 39 é apresentado o
resultado da conversão de uma linha reta por um conversor A/D e o desvio dos pontos amostrados em
relação aos pontos da linha reta aplicada a sua entrada. A linearidade integral deve ser considerada o
maior desvio encontrado, neste caso, 0,5 LSB (Figura 39).
A linearidade diferencial é a linearidade entre transições de código. Ela pode ser entendida como a
medida da monotonicidade do conversor. Um conversor é dito monotônico se um aumento nos seus valores
de entrada resulta em um aumento correspondente na sua saída. A Figura 40 mostra a característica de
um conversor A/D ideal e a de um A/D com um código faltando (linearidade diferencial de 1 LSB).
4.7
Tipos de Conversores D/A
A grande maioria dos conversores D/A realiza a conversão atribuindo pesos de tensão (ou de
corrente) a cada um dos dígitos do código binário. Dessa forma, a sua saída analógica é produzida
somando-se a contribuição de tensão de todos os dígitos que compõem a palavra à sua entrada. Para
ilustrar este fato, são analisados dois tipos muito comuns de conversores D/A.
4.7.1.
Conversor D/A à Resistores Ponderados
Baseado no que foi apresentado no parágrafo anterior, a configuração mais intuitiva de um
conversor D/A é a apresentada na Figura 41. Neste figura, as entradas b0, b1 e b2 são os dígitos binários
do código digital e podem assumir os valores Vr (nível lógico um) ou GND (nível lógico zero), dependendo
das posições das chaves analógicas. Baseado no fato da soma das correntes que entram no nó N ser igual a
soma das correntes que saem deste mesmo nó, a equação de V0 em função dos outros parâmetros do
circuito pode ser conseguida como apresentado na (Eq. 1).
80
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
Figura 39 – Linha reta aparente adquirida com um conversor A/D e o gráfico do desvio
dos postos digitalizados em relação a linha reta real.
Figura 40 – Característica ideal de um conversor A/D e característica de um A/D com
uma linearidade diferencial pobre (com um código faltando em 120 µs).
Vrbo − Vo 2(Vrb1 − Vo ) 4(Vrb2 − Vo ) Vo
+
+
=
R
R
R
RL
Vrbo 2Vrb1 4Vrb2 Vo 2Vo 4Vo Vo
+
+
−
−
−
=
R
R
R
R
R
R
RL
Vr
(b0 + 2b1 + 4b2) = Vo + 7Vo = Vo R + 7 RL 
R
RL
R
 RL × R 
VrRL
(bo + 2b1 + 4b2)
Vo =
R + 7 RL
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
(Eq. 1)
81
Curso de Microprocessadores
Vr
R
b0
b1 R/2
N
+
RL Vo
-
R/4
b2
Figura 41 – Conversor D/A à resistores ponderados.
Da (Eq. 1), vemos que as entradas b0, b1 e b2 contribuem com pesos diferentes (em potência de dois)
para a saída V0. Exatamente como deve ser para um conversor D/A.
Generalizando o circuito da Figura 41, chegamos a (Eq. 2). Desta equação vemos que a saída V0
sempre será atenuada. Contudo, isto pode ser facilmente contornado usando-se qualquer circuito para
amplificar V0. A maior desvantagem deste circuito pode ser a grande variedade de valores de resistores.
Por exemplo, para um D/A de 12 bits, teríamos deste o valor R até R/2.048. Isto tem dois inconvenientes:
a) é muito difícil conseguir 12 resistores que satisfaçam exatamente a todos os valores necessários ao
circuito (R, R/2, R/4, R/8, ..., R/2.048), e; b) o circuito apresenta valores de resistores bastante
diferentes, por exemplo, para R = 204,8 kΩ (valor inexistente comercialmente), R/2.048 = 100 Ω. Esta
grande faixa de valores torna o circuito muito susceptível a ruídos. Por estas duas razões, o conversor
D/A a resistores ponderados não é muito utilizado.
Vo =
4.7.2.
(
RLVr
bo + 2b1 + ... + 2 n−1 bn −=1
2 − 1 RL + R
(
)
n
)
(Eq. 2)
Conversor D/A à Rede R-2R
Todos os problemas do conversor D/A à resistores ponderados são solucionados com o conversor
rede R-2R. Pois, este tipo de conversor utiliza apenas dois valores de resistores e sua configuração é
extremamente simétrica. Na Figura 42a é apresentado um circuito conversor R-2R. Para calcular a saída
V0 em função dos outros parâmetros do circuito pode-se usar o teorema da superposição (somar a
contribuição individual de cada entrada b? na saída V0). Feito isto, encontramos
 bo b1 b2 
Vr
Vo = Vr  + +  ou Vo = (bo + 2b1 + 4b2) ,
12
 12 6 3 
que é muito parecida com a (Eq. 2).
(a)
2R
2R
I1
2R
b0
R
(a)
R 2
2
R
)
(b
R 2
2
R
R
R
R
2
R 2
2
R
1
b
2
b
2R
b0
R I2
+
R
2
R 2 V
2
R o
I 1
b
0
1
b
2
b
0
b
2R
R 2
1
R
2R
2R
+
Vo
-
b2
b1
R
R
(b)
I2
R
R
2R
b1
Vo
2R
2R
b2
R2
R1
Figura 42 – (a) Conversor R-2R de 3 bits e (b) conversor R-2R com saída amplificada.
Novamente, uma configuração como a da Figura 42b pode ser utilizada para eliminar o termo 1/12.
Generalizando, podemos escrever para um circuito semelhante ao da Figura 42a, mas com n entradas
82
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
V0 =
(
)
1
b0 + 2b1 + ... + 2 n−1 bn−1 .
( n −1)
3× 2
Finalizando, pode-se dizer que, por razões óbvias, este tipo de conversor D/A é o mais utilizado.
Observe que o tempo de ajuste do circuito da Figura 42b depende apenas do tempo que as entradas b0, b1,
etc, tornam-se estáveis e, como explicado anteriormente, da faixa dinâmica do conversor e da transição
do código binário. Isto quer dizer que não é muito difícil fabricar-se conversores D/A extremamente
rápidos.
4.8
Tipos de Conversores A/D
Sinais analógicos podem ser convertidos para códigos digitais por vários métodos, incluindo
integração, aproximações sucessivas, conversão paralela (ou flash), modulação delta, sigma-delta, etc.
Duas das técnicas mais comuns são o processo de aproximações sucessivas e o tipo flash. Sistemas de
áudio ou vídeo digitais de alta resolução requerem técnicas de conversão especiais. Exemplos dessas
técnicas são PCM (Pulse Code Modulation), e conversão sigma-delta. PCM é uma técnica de codificação de
voz usada não apenas por sistemas de áudio e vídeo, mas também por sistemas de comunicações. A técnica
sigma-delta envolve conceitos complexos da área de processamento digital de sinais e processos
estocásticos e está fora do escopo de um curso de graduação.
4.8.1.
Paralelo ou Flash
A Figura 43 apresenta o diagrama de blocos de um conversor A/D paralelo. O circuito consiste de
uma rede de resistores de precisão, 2n-1 comparadores e um codificador de prioridade digital. A rede de
resistores estabelece tenções de referência para cada um dos níveis de quantização. Cada um dos
comparadores indica quando a tensão de entrada está acima ou abaixo da tensão threshold (limite) de cada
um dos níveis de quantização do circuito. As saídas dos comparadores são as entradas do codificador de
prioridade. Este codificador produz a saída do código digital que pode ser armazenada em um registrador.
Este tipo de conversor é utilizado em aplicações que exigem altas velocidades, tais como
processamento de vídeo e imagem. Conversores paralelos de oito bits tipicamente operam na faixa dos 100
MHz. Contudo, esta velocidade tem um preço. Um conversor de 8 bits deste tipo necessita de 255
comparadores. Isto torna conversores flash de 10 bits ou mais extremamente caros. Para contornar este
problema alguns fabricantes utilizam a topologia de um conversor flash modificado. Na Figura 44 é
apresentado um conversor flash modificado de 16 bits baseado em dois conversores flash de 8 bits. Na
figura, é aplicado ao conversor uma tensão analógica de 1.000 mV. Como o primeiro conversor é de 8 bits e
tem faixa dinâmica de 4.096 mV (assim como todos os outros conversores do circuito, Figura 44), ele
produz o código binário correspondente ao número 62. Este número é aplicado a um conversor D/A que
produz uma saída analógica de 992 mV, ou seja, um erro de 8 mV. Este erro é amplificado 28 vezes e
aplicado ao segundo conversor A/D que produz o código binário correspondente ao número 128. Então, o
código binário de 16 bits é formado através dos 8 bits do primeiro conversor A/D (MSB) e dos 8 bits do
último conversor (LSB). Evidentemente, desprezando-se o tempo de ajuste do conversor D/A, o conversor
de 16 bits é duas vezes mais lento que os de 8 bits.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
83
Curso de Microprocessadores
Figura 43 – Diagrama de blocos de um conversor A/D Flash.
4.096 mV
A/D
8 bits
1.000 mV
4.096 mV
+
+ -
992 mV
1.000 mV/16 mV=62
MSB
00111110
D/A
8 bits
2.048 mV/16 mV=128
4.096 mV
8 mV
G=2
8
2.048 mV
A/D
8 bits
LSB
10000000
Figura 44 - Conversor A/D de 16 bits baseado em dois conversores de 8 bits.
4.8.2.
Aproximações Sucessivas
Conversores A/D baseado em aproximações sucessivas é o que apresenta melhor relação custo
benefício, pois requerem um mínimo de componentes e são muito rápidos (tipicamente, possuem tempo de
conversão de 10 µs). Por isso, é um dos mais utilizados. (Por exemplo, no conversor A/D do 68HC11.)
84
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 4- Conversores A/D e D/A
Na Figura 45 é apresentado o diagrama de blocos de um conversor A/D de aproximações sucessivas
de n bits. Este conversor gera o código digital de n bits em n passos. O coração deste tipo de conversor é
o bloco denominado SAR (Successive Approximation Register, ou seja, Registrador de Aproximações
Sucessivas). Este bloco individualmente compara a tensão de entrada (Vi) com o ponto central de cada um
dos n níveis de quantização, para determinar os n bits do código binário. Esta comparação é feita como
segue: o bloco SAR determina se a entrada analógica está acima ou abaixo do ponto central e seta o bit do
código digital de acordo, ou seja, se estiver acima o bit é ligado, caso contrário, o bit é desligado. O bloco
SAR então passa para o próximo bit e compara a entrada com o próximo ponto central. Como o bloco SAR
precisa realizar uma aproximação para cada bit do código digital, um código de n bits requer n
aproximações.
Figura 45 – Diagrama de blocos de um conversor A/D baseado em aproximações
sucessivas.
Para esclarecer melhor o funcionamento do bloco SAR, vamos ao seguinte exemplo. Suponha um
conversor A/D de aproximações sucessivas de 8 bits. Neste caso, tanto o bloco SAR quanto o conversor
D/A são de 8 bits. Além disso, considere que todo o circuito é alimentado com 5,12 V, ou seja, cada nível
de quantização é de 20 mV. No início do processo, quando o SAR é resetado, a sua saída vai para 128 (ou
256 mV). Suponha ainda que Vi seja feito igual a 121,6 mV. Neste caso, como 256 mV é maior que 121,6
mV, o bit mais significativo (bit 7) é considerado 0 e o bloco SAR muda sua saída para o ponto central da
faixa inferior (128 mV). Como 128 mV é maior 121,6, o bit 6 do valor convertido é considerado 0 e a saída
do SAR muda para 64 mV (00100000b ou 32d). Agora, 64 mV é menor que 121,6 (tensão Vi). Por isso, o bit
5 é considerado 1 e a próximo ponto é o centro da faixa superior, ou seja, 96 mV. Com isso, o bit 4 é
considerado 1 e o SAR muda para 112 mV. Nos três passos restantes a saída do SAR assume os valores
120, 124 e 122 mV. Fazendo b3=1, b2=1, b1=0 e b0=1. Logo, o resultado da conversão é 00111101b ou 61d ou
ainda 122 mV.
Note que, no exemplo anterior, o erro máximo que pode ser cometido é de 20 mV (ou 1 LSB). O que
não está de acordo com o que foi discutido na Seção 4.3. Isto ocorre pelo fato do SAR não está
comparando Vi com o centro de cada nível de quantização, mas sim com o extremo. Este fato é facilmente
corrigido adicionando 1 mV (ou 0,5 LSB) à saída do conversor D/A. Ou ainda, subtraindo 1 mV (ou 0,5 LSB)
da tensão de entrada (Vi) do conversor A/D. Este mesmo raciocínio pode ser aplicado ao conversor Flash.
Intuitivamente, podemos fazer uma comparação entre a velocidade dos conversores D/A com a dos
conversores A/D. Nos conversores D/A a conversão é feita quase que imediatamente. No entanto, nos
conversores A/D o processo envolve vários estágios. Em particular, como dito anteriormente, um
conversor de aproximações sucessivas de n bits realiza sua conversão em n estágios. Isto demonstra como
é bem mais difícil construir-se um conversor A/D rápido que um D/A veloz.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
85
Curso de Microprocessadores
Capítulo 5 - Projeto de Sistemas
Microcontrolados
Neste ponto do curso, você já entende a CPU por dentro e conhece os principais componentes de um
sistema microcontrolado. Além disso, já está apto a desenvolver programas em assembler (relativamente)
complexos. Por último, com o que foi apresentada no Capítulo 3, você já tem um bom entendimento de como
a CPU “conversa” com o mundo exterior, através dos dispositivos de E/S. Neste capítulo, simplesmente,
você vai ter mais detalhas de como esta “conversa” é realizada. Mais especificamente, você verá como
conectar a CPU e os dispositivos de E/S fisicamente. Novamente, nosso alvo principal será o 68HC11.
Contudo, como sempre, o que for aprendido aqui será facilmente adaptável à outros microcontroladores.
Isto será demonstrado na Seção ???, quando fizermos um projeto com o microcontrolador 80C31 da Intel.
5.1
Principais Componentes de um Sistema Microprocessado
Na Figura 3 (Página 11) é apresentado o diagrama de blocos de um sistema microprocessado. Desta
figura vê-se que os principais componentes de um sistema microprocessado são: CPU, memória e
dispositivos de E/S. Basicamente, o modo como a CPU é “interfaceada” com uma memória é muito parecido
com a maneira de se conectar uma CPU a dispositivos de E/S. Por isso, para iniciar o estudo de projetos de
sistemas microprocessados, inicialmente veremos como podemos conectar uma CPU e algumas pastilhas de
memória.
5.1.1.
Memória RAM
Evidentemente, existe uma infinidade de tipos memória que podem ser conectadas a uma CPU.
Contudo, na maioria das aplicações, a memória estática é mais utilizada. Por isso, nosso estudo irá começar
por ela. Na Figura 46 é apresentada a pinagem física de uma pastilha de memória estática de 8kx8. Este
tipo de memória é referenciada pelo número 6264. O prefixo “62” informa que o chip 6264 é uma memória
RAM estática (as RAM’s dinâmicas possuem o prefixo “61”). E ainda, o sufixo “64” informa que a memória
possui 8.192 posições de memória de 8 bits (8.192x8 = 8kx8 = 64k). Contudo, você pode encontrar
memórias estáticas que tenham uma numeração diferente.
Figura 46 – Pinagem física de uma chip de memória 6264.
Acredito que a pinagem de um chip de memória não é novidade para você. Por isso, vou me ater
apenas a alguns detalhes. Por exemplo, da Figura 46, vê-se que o chip possui dois pinos Chip Enable (pinos
20 e 26). Se desejado, pode-se deixar um desses pinos sempre ativos e utilizar-se apenas um deles como
86
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
seleção do chip, por exemplo, o E1 . Outro pino interessante é o G . Este pino, quando desativado, coloca
os pinos de dados da memória em alta impedância. Por isso, sempre que desejarmos realizar alguma
operação com a memória (uma leitura ou escrita), é necessário ativar este pino. Novamente, uma outra
forma de se “trabalhar” é garantir que este pino esteja sempre ativo e colocar-se as linhas de dados em
alta impedância com o um dos pinos Chip Enable.
Preste atenção! O que eu disse no parágrafo anterior não é regra. Apenas pode ser utilizado na
maioria dos projetos. Contudo, você pode se deparar com uma aplicação na qual você precise usar todos os
pinos de controle da memória 6264. Isto também á válido para todos os outros chips discutidos neste
capítulo.
5.1.2.
Memória EPROM
Você sempre precisará de uma memória ROM. Assim que o seu sistema é ligado, ele precisa de um
programa para executar. Este programa é quem determina o que o seu sistema vai fazer. Por isso, ele
precisa ser gravado em uma memória ROM. Alguns microcontroladores possuem ROM interna. Neste caso,
o microcontrolador deve ser colocado em um gravador especial para que o programa seja gravado em sua
ROM interna. Na Figura 47 é apresentado o gravador utilizado para programar os microcontroladores da
família PIC da Microchip. Este gravador é conectado à porta serial de um microcomputador. Dessa forma,
o programa pode ser transferido para um microcontrolador que esteja no soquete do gravador.
Figura 47 – Gravador para a família de microcontroladores da Microchip.
Muitos outros microcontroladores, como o 68HC11, não possuem ROM interna. Neste caso, um chip
de memória ROM deve ser incluído no sistema para armazenar o programa. Qualquer tipo de ROM pode ser
utilizado. Contudo, o uso de uma memória ROM re-gravável facilita a atualização do sistema. Em nossos
exemplos será utilizada uma memória EPROM 2764. O prefixo “27” informa que o chip 2764 é uma
memória EPROM. E ainda, o sufixo “64” tem a mesma origem do sufixo da 6264. Novamente, você pode
encontrar memórias estáticas que tenham uma numeração diferente. Na Figura 48 é apresentado a
pinagem física da EPROM 2764. Como pode-se ver, a pinagem é muito parecida com a da 6264. A entrada
OE tem a mesma função do pino G da 6264. Novamente, ele pode ser deixado sempre ativo. Os pinos
PGM e Vpp são utilizados apenas durante a gravação e podem ser deixados ambos em 5 V. Todos os
outros pinos devem ser conhecidos para você.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
87
Curso de Microprocessadores
Figura 48 – Pinagem do EPROM 2764.
5.1.3.
Microcontrolador 68HC11
Na Figura 49(a) é apresentada a pinagem do 68HC11. Como o 68HC11 possui diversos dispositivos
encapsulados em seu chip (conversor A/D, temporizador, comunicação serial, etc) ele possui uma
quantidade elevada de pinos (52 no total). Contudo, para conectarmos memórias RAM ou EPROM e
dispositivos de E/S, apenas os pinos da Figura 49(b) são relevantes. Dentre esses, os mais importantes são
os pinos de dados e de endereço. É por esses pinos, que trafegam todas as informações do sistema
microprocessado. No caso do 68HC11, ele é uma CPU de 8 bits que pode endereçar até 64 Kbytes de
memória (incluindo memória RAM, ROM e dispositivos de E/S). Por isso, ele deve possuir oito pinos de
dados e dezesseis pinos de endereços.
Como dito anteriormente, na maioria dos microcontroladores, os pinos de dados e os pinos de
endereços são multiplexados. O 68HC11 não é uma exceção à regra, pois os seus oito pinos de endereço
menos significativos (A0-A7) são multiplexados com os seus oito pinos de dados (D0-D7). Para explicitar
isto, esses oito pinos são numerados de AD0 à AD7. Os oito pinos de endereço mais significantes são
numerados de A8-A15.
Para entender como esta multiplexação é possível, basta observar os diagramas de tempo da Figura
50. Desta figura, fica claro que, tanto no ciclo de leitura como no ciclo de escrita, as linhas (pinos) de
endereço são necessárias logo no início do ciclo, mas as linhas de dados são necessárias apenas um pouco
depois. Por isso, no 68HC11 (e nas outras CPUs também ocorre algo semelhante), os pinos de AD0 à AD7
são pinos de endereço no início do ciclo e tornam-se pinos de dados um pouco depois. Com isso, é
necessário encontrar uma forma de manter um endereço válido durante todo o ciclo de leitura/escrita.
Para isto, normalmente, utiliza-se o esquema da Figura 51. Neste esquema, no início do ciclo, o 74HC373 é
carregado com os oito bits de endereço menos significativos. Dessa forma, esses oito bits ficam
acessíveis durante todo o ciclo. A carga do 74HC373 é controlada pelo pino AS (Figura 51). Da Figura 50,
vê-se que este pino só é ativado, como desejado, no início do ciclo. De uma forma ou de outra, toda CPU
provê um pino que tem um nome diferente, mas que possui a mesma função do AS.
O uso do 74HC373 faz com que o sistema apresente três tipos de linhas: endereço, dados e
controle. Como será visto mais adiante, todos os outros dispositivos do sistema são conectados nessas
linhas.
As seções seguintes, é apresentada a função de cada um dos pinos da Figura 49(b).
5.2
Interface entre o 68HC11 com Outros Dispositivos
Fazer o 68HC11 “conversar” com outros dispositivos de entrada e saída não é uma tarefa difícil.
Pare isto, basta ter em mente a Figura 51. Como dito na seção anterior, o esquema da Figura 51 deixa
todos os sinais (endereço, dados e controle) do 68HC11 bem acessíveis. Dessa forma, basta conectar cada
88
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
um dos pinos do dispositivo que deseja-se “interfacear” com o 68HC11 aos barramentos da Figura 51. A
Figura 52 apresenta as ligações necessárias para conectar uma memória 6264 com o 68HC11.
(a)
(b)
(c)
Figura 49 –(a) Todos os 52 pinos do 68HC11, (b) Os pinos mais importantes quando
deseja-se interfacea-lo com dispositivos externos, e (c) Configuração sugerida para
alguns desses pinos.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
89
Curso de Microprocessadores
Endereço
Endereço
Dado
Dado
Escrita
Leitura
E
AS
E
AS
(a)
(b)
Figura 50 – (a) Diagrama de tempo de um ciclo de escrita típico no 68HC11; (b) Diagrama
de tempo de um ciclo de leitura típico no 68HC11
Figura 51 – Barramento de um sistema baseado no 68HC11. O 74HC373 é utilizado para
“separar” as linhas de endereço das linhas de dados.
A Figura 52 não apresenta muita informação nova. Como dito, apenas conectou-se os pinos da 6264
aos barramentos do 68HC11. Contudo, algumas ligações valem à pena serem comentadas. Por exemplo, a
6264 é uma memória de 8 kbytes. Por isso, possui apenas treze linhas de endereço. Isto faz com que
algumas linhas (A13, A14 e A15) do barramento de endereço do 68HC11 não sejam conectadas a nenhum
pino da memória. Com isso, surge uma pergunta: “Qual é o endereço da primeira posição da memória
6264?”. Evidentemente, a primeira posição de memória é acessada quando todos os pinos de endereço da
6264 são zero. No circuito da Figura 52, isto acontece quando as linhas de A0 à A12 são zero, ou seja,
90
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
para acessar a primeira posição da memória (o seu endereço base) os pinos A13, A14 e A15 não são
relevantes. Dessa forma, o endereço base da memória será acessado quando a constante $0000 (16 bits),
$2000, $4000, $6000, $8000, $A000, $C000 ou $E000, for colocado nas linhas de endereço do 68HC11.
Contudo, o endereço base não é acessado quando, por exemplo, se a constante $B000 é posta nas linhas de
endereço, pois, neste caso, A12 é igual à “1”. Com isso, a posição acessada é a de número 2.048.
74HC373
30
29
XT
EX
AD0
AD1
AD2
AD3
AD4
AD5
AD6
AD7
AS
39
RESET
A8
A9
A10
A11
A12
A13
A14
A15
E
41
40
IRQ
R/W
31
32
33
34
35
36
37
38
3
4
7
8
13
14
17
18
26
11
16
15
14
13
12
11
10
9
27
1D
2D
3D
4D
5D
6D
7D
8D
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
2
5
6
9
12
15
16
19
1
10
9
8
7
6
5
4
3
25
24
21
23
2
26
27
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
CS2
WE
D0
D1
D2
D3
D4
D5
D6
D7
CS1
OE
11
12
13
15
16
17
18
19
20
22
MCM6264
28
XIRQ
MODA
MODB
25
24
68HC11A8
Figura 52 – Interface entre o 68HC11 e uma memória 6264.
O fato de um dispositivo possuir mais de um endereço base não causa problema algum. Contudo, caso
seja desejado que o dispositivo possua apenas um único endereço base, deve-se usar na seleção do mesmo
todos os pinos que compõem o barramento de endereço. Explicando melhor, a memória 6264 possui dois
pinos de seleção ( CS1 e CS2). Se for utilizada lógica adicional para fazer com que a memória 6264 seja
accessível apenas quando, por exemplo, os pinos A13, A14 e A15 forem todos zero, o seu endereço base só
poderá ser acessado quando a constante $0000 for colocada no barramento de endereço do 68HC11. Na
Figura 53 é apresentada um esquema onde a memória 6264 possui endereço base $0000. Na figura, foram
utilizadas duas portas lógicas OU para incluir os pinos A13, A14 e A15 na seleção do chip (pino CS1 ).
Outro fato importante a ser observado quando se projeta sistemas microprocessados é que nem
sempre a CPU quer acessar seus dispositivos externos. Por isso, o 68HC11 possui um pino de seleção
externa (pino E). Enquanto este pino está desativado o 68HC11 faz alguma operação interna. Quando ele
deseja acessar um de seus dispositivos externos, o pino E é ativado. Observando novamente os diagramas
de tempo do 68HC11 (Figura 50), nota-se que o pino E só é ativado quando todos os outros sinais já estão
estáveis.
Para que o 68HC11 possa selecionar os dispositivos apenas quando desejar, o seu pino E deve ser
conectado (de alguma forma) ao pino de seleção do dispositivo. Isto foi feito na Figura 52 e na Figura 53.
Novamente, de uma forma ou de outra, outros microcontroladores têm pinos de nomes diferentes que
desempenham a mesma função do pino E do 68HC11.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
91
Curso de Microprocessadores
74HC373
30
29
AD0
AD1
AD2
AD3
AD4
AD5
AD6
AD7
XT
EX
AS
39
A8
A9
A10
A11
A12
A13
A14
A15
RESET
E
41
40
IRQ
R/W
31
32
33
34
35
36
37
38
3
4
7
8
13
14
17
18
26
11
16
15
14
13
12
11
10
9
1D
2D
3D
4D
5D
6D
7D
8D
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
2
5
6
9
12
15
16
19
10
9
8
7
6
5
4
3
25
24
21
23
2
1
20
26
1
3
2
1
3
2
27
27
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
CS1
CS2
WE
D0
D1
D2
D3
D4
D5
D6
D7
OE
11
12
13
15
16
17
18
19
22
MCM6264
28
XIRQ
MODA
MODB
25
24
68HC11A8
Figura 53 - Interface entre o 68HC11 e uma memória 6264. Neste caso, a memória
possui endereço base $0000.
E se desejarmos acrescentar outro dispositivo ao sistema? Da mesma forma, basta conectar os
pinos do novo dispositivo aos barramentos do 68HC11. Contudo, deve-se tomar o cuidado de fazer com que
NUNCA os dois dispositivos sejam acessíveis ao mesmo tempo. Isto é possível se cada dispositivo contiver
o seu próprio endereço base. Na Figura 54 é apresentado o mesmo sistema da Figura 53 acrescido de uma
memória EPROM 2764. Foi utilizada uma porta lógica NAND de três entradas para fornecer o endereço
base $E000 à memória EPROM. Com isso, os chips nunca são acessados ao mesmo tempo.
29
XT
EX
AS
39
A8
A9
A10
A11
A12
A13
A14
A15
RESET
E
41
40
R/W
IRQ
3
4
7
8
13
14
17
18
26
11
16
15
14
13
12
11
10
9
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
10
9
8
7
6
5
4
3
25
24
21
23
2
1
3
2
1
3
2
27
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
CS1
CS2
WE
MCM6264
D0
D1
D2
D3
D4
D5
D6
D7
OE
11
12
13
15
16
17
18
19
22
10
9
8
7
6
5
4
3
25
24
21
23
2
20
22
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
27
U3
2
5
6
9
12
15
16
19
20
26
1
27
O0
O1
O2
O3
O4
O5
O6
O7
11
12
13
15
16
17
18
19
CE
OE
27C64
28
XIRQ
MODA
MODB
1D
2D
3D
4D
5D
6D
7D
8D
VPP
30
31
32
33
34
35
36
37
38
PGM
74HC373
AD0
AD1
AD2
AD3
AD4
AD5
AD6
AD7
1
5V
25
24
1
2
13
12
68HC11A8
Figura 54 – Interface entre o 68HC11 e uma memória 6264 (base $0000) e uma
memória EPROM 2764 ($E000).
Evidentemente, à medida que a quantidade de dispositivos existentes no sistema aumenta, o uso de
lógica adicional para fornecer endereços base únicos à cada dispositivo do sistema torna-se muito
92
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
complexa, cansativa e cara. Por isso, o mais eficiente é utilizar o decodificador 74HC138 para selecionar
cada chip individualmente.
Na Figura 55 é apresenta da um sistema que possui uma memória 6264 (endereço base $4000) e
uma memória EPROM 2764 ($E000). Neste caso, foi utilizado o 74HC138 para atribuir os endereços base.
Observa-se que os dispositivos conectados ao 74HC138 podem possuir apenas os seguintes endereços
base: $0000, $2000, $4000, $6000, $8000, $A000, $C000 ou $E000. Cada dispositivo irá ocupar uma
faixa de 8 kbytes de memória (independente de quantas posições de memória ou registradores ele
possuir). Isto é ruim, sobretudo para dispositivos de E/S. Por exemplo, um dispositivo que possua três
registradores internos (configuração, status e dados) tem apenas duas linhas de endereço. Neste caso,
como ele possui apenas três posições de memória endereçáveis, estariam sendo desperdiçados 8.192 – 3 =
8.189 endereços. Contudo, como um pouco de lógica adicional, pode-se fazer com que dois (ou mais)
dispositivos de E/S compartilhem o mesmo espaço de endereçamento de 8 kbytes. Desta forma, reduz-se
o desperdício de espaços de endereçamento. No entanto, tenha em mente que, caso o seu sistema não
precise de muitos espaços de endereçamento, ou seja, não possua muito dispositivos, você não precisa
preocupar-se com os endereços desperdiçados.
29
AD0
AD1
AD2
AD3
AD4
AD5
AD6
AD7
XT
EX
AS
39
A8
A9
A10
A11
A12
A13
A14
A15
RESET
E
41
40
R/W
IRQ
26
11
16
15
14
13
12
11
10
9
27
28
XIRQ
MODA
MODB
1D
2D
3D
4D
5D
6D
7D
8D
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
1
10
9
8
7
6
5
4
3
25
24
21
23
2
20
27
74HC138
1
2
3
6
5
4
A
B
C
Y0
Y1
Y2
Y3
G1 Y4
Y5
G2BY6
G2AY7
15
14
13
12
11
10
9
7
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
CS1
WE
MCM6264
D0
D1
D2
D3
D4
D5
D6
D7
CS2
OE
11
12
13
15
16
17
18
19
26
22
5V
10
9
8
7
6
5
4
3
25
24
21
23
2
20
22
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
27
U3
2
5
6
9
12
15
16
19
PGM
30
3
4
7
8
13
14
17
18
VPP
74HC373
31
32
33
34
35
36
37
38
1
5V
O0
O1
O2
O3
O4
O5
O6
O7
11
12
13
15
16
17
18
19
CE
OE
27C64
25
24
68HC11A8
Figura 55 - Interface entre o 68HC11 e uma memória 6264 (base $4000) e uma
memória EPROM 2764 ($E000). Neste caso, foi utilizado o 74HC138 para atribuir os
endereços base.
Apesar do 74HC138 facilitar a definição dos endereços bases dos diferentes dispositivos do
sistema, geralmente, os endereços dos dispositivos internos do microcontrolador não devem conflitar com
os endereços dados aos dispositivos externos. Para evitar isto, o mapa de memória do microcontrolador
deve ser utilizado. Na Figura 56 é apresentado o mapa de memória do 68HC11. Na figura, as áreas escuras
são áreas ocupadas por dispositivos internos. Por exemplo, o endereço $0000 à $03FFF é ocupado com a
memória RAM interna ao microcontrolador. Por isso, nenhum dispositivo externo pode ocupar esta faixa de
memória. Em vista disso, os circuitos da Figura 52 e da Figura 53 estão errados, pois um dispositivo
externo está ocupando esta faixa de memória.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
93
Curso de Microprocessadores
5.3
Cristal Oscilador
Todas as CPUs necessitam de um relógio para funcionar. Como você sabe, diversas operações
precisam ocorrer para que uma simples instrução seja executada. A seqüência dessas operações é
comandada pelo relógio da CPU. Para fornecer este relógio, alguns projetistas utilizam um circuito RLC.
Pessoalmente, não gosto desses osciladores. Pois, sua freqüência de oscilação varia muito com os valores
dos componentes que, por sua vez, variam muito com parâmetros como, por exemplo, umidade e
temperatura. Além disso, esses osciladores não conseguem oscilar a freqüências elevadas. Contudo,
osciladores RLC são baratos. Por isso, alguns os utilizam.
Figura 56 – Mapa de memória do 68HC11.
Para obter-se precisão e freqüências elevadas, é necessário o uso de um oscilador a cristal. A Figura
57(a) apresenta o esquema de ligação de um oscilador a cristal. Como a figura mostra, além do cristal
XTAL [ver Figura 57(a)], são necessários um resistor (Rf) e dois capacitores (C1 e C2). Os valores desses
componentes dependem de variáveis como, por exemplo, freqüência do cristal, método empregado na sua
fabricação e leiaute da placa de circuito impresso. Contudo, a dependência da freqüência de oscilação com
esses parâmetros não é muito grande. Por isso, na maioria dos projetos, podem ser usados Rf = 10 MΩ e 5
pF < C1 = C2 < 30 pF.
Em alguns casos, fazer a placa de circuito impresso que comportará o oscilador a cristal é um
problema. Pois, o leiaute da placa deve evitar ao máximo as capacitâncias parasitas. Visto que, essas
capacitâncias podem fazer com que o oscilador não oscile. Na Figura 57(b) é apresentado uma sugestão de
leiaute. Na figura, a carcaça do cristal é conectada ao terra. Além disso, uma trila de GND passa entre os
pinos dos capacitores.
94
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
(a)
(b)
Figura 57 – (a) esquema de ligação do cristal oscilador no 68HC11. (b) sugestão para
confecção da placa de circuito impresso.
5.4
RESET
Em qualquer sistema microprocessado pelo menos uma interrupção é utilizada: a interrupção do
RESET. Esta interrupção deve ser ativada sempre que o sistema é ligado ou o usuário aperta um botão.
Esta ativação ocorre através de um pino do microprocessador. Este pino, dependendo do
microprocessador, pode ser ativo em nível alto ou baixo. A Figura 58 apresenta várias configurações para
RESET. A saída Vo (Figura 58) deve ser conectada ao pino de reset do microprocessador (ou
microcontrolador). Para os circuitos desta figura, os três circuitos de cima devem ser utilizados para
resets ativos em nível alto. O primeiro circuito é o mais simples de todos. Simplesmente, Vo vai para 5 V
momentaneamente quando o sistema é ligado ou quando o usuário aperta o botão da figura. O circuito do
meio acrescenta um resistor de 1 kΩ para impedir que uma corrente que surja durante a descarga do
capacitor danifique o microcontrolador. Já o circuito da direita, utiliza um inversor de histerese para
limpar o sinal gerado pelo capacitor. Os circuitos na linha de baixa são os mesmos circuitos, só que para
pinos de reset ativos em nível baixo.
5V
5V
5V
10 uF
10 uF
1k
Vo
100 k
100 k
1
100 k
5V
2
Vo
Vo
10 uF
5V
5V
100 k
100 k
10 uF
Vo
10 uF
10 uF
1k
Vo
1
2
Vo
100 k
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
95
Curso de Microprocessadores
Figura 58 – Diversas configurações para RESET.
5.5
Projetos com o 80C31.
O microcontrolador 80C51 é um dos mais populares. Assim como o 68HC11, o 80C51 é de oito bits e
pode endereçar até 64 kbytes de memória. Além disso, ele possui uma ROM interna, na qual o programa
que gerencia o sistema deve ser gravado. Uma alternativa mais barata que o 80C51 é o 80C31. O 80C31
totalmente compatível com o 80C51. A diferença é que o 80C31 não possui ROM interna. Por isso, o seu
programa deve ser gravado em uma EPROM externa. A Figura 59 mostra a pinagem do 80C31. Nesta figura
foram omitidos os pinos de comunicação serial (que não são utilizados na interface de outros dispositivos).
31
19
18
14
15
12
13
9
1
2
3
4
5
6
7
8
U1
EA/VP
P0.0
P0.1
P0.2
P0.3
P0.4
P0.5
P0.6
P0.7
ALE/P
X1
X2
T0
T1
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
INT0
INT1
RESET
P1.0
P1.1
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
RD
WR
PSEN
39
38
37
36
35
34
33
32
30
21
22
23
24
25
26
27
28
17
16
29
80C31
Figura 59 – Pinagem do microcontrolador 80C31.
Da Figura 59, é importante observar três fatos. Primeiro, o 80C31 não possui um pino E como o
68HC11. Além disso, a indicação de leitura ou gravação é indicada por pinos distintos ( W e R ). Quando a
CPU esta fazendo uma operação interna, estes dois pinos estão em “1”. Quando a CPU deseja efetuar uma
escrita ou uma leitura, o pino correspondente vai para “0”. Em nenhuma ocasião, os dois pinos vão para zero
ao mesmo tempo. Por último, note que o 80C31 possui um pino PSEN (ativo em nível baixo). Este pino é
ativado sempre que a CPU acessa a memória de programa. Por isso, ele deve ser utilizado para habilitar a
memória EPROM onde está gravado o programa que controla o sistema. Na Figura 60 é apresentado um
sistema baseado no 80C31. Como o 80C31 também possui pinos de dados e endereços multiplexados, o
sistema é muito parecido com o sistema baseado no 68HC11. Na figura, a saída da porta lógica AND tem a
mesma função do pino E do 68HC11.
19
12 MHz
Y2 18
33 pF C2
5V
C3
10 uF
SW1
RST
100 k
R1
14
15
12
13
9
1
2
3
4
5
6
7
8
X1
X2
T0
T1
INT0
INT1
RESET
P1.0
P1.1
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
80C31
P0.0
P0.1
P0.2
P0.3
P0.4
P0.5
P0.6
P0.7
ALE/P
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
RD
WR
PSEN
39
38
37
36
35
34
33
32
30
3
4
7
8
13
14
17
18
11
21
22
23
24
25
26
27
28
1D
2D
3D
4D
5D
6D
7D
8D
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
2
5
6
9
12
15
16
19
10
9
8
7
6
5
4
3
25
24
21
23
2
1
74HC373
20
U4
1
2
3
17
16
U5A
29
5V
1
3
2
6
4
5
Y0
Y1
Y2
Y3
Y4
G1 Y5
G2AY6
G2BY7
A
B
C
22
15
14
13
12
11
10
9
7
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
VPP
33 pF C1
EA/VP
27
U3
U2
U1
PGM
31
1
5V
O0
O1
O2
O3
O4
O5
O6
O7
11
12
13
15
16
17
18
19
CE
OE
27C64
10
9
8
7
6
5
4
3
25
24
21
23
2
20
26
27
22
U6
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
D0
D1
D2
D3
D4
D5
D6
D7
11
12
13
15
16
17
18
19
CS1
CS2
WE
OE
MCM6264
74HC138
74HC08
Figura 60 – Sistema microprocessado baseado no 80C31.
96
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
O fato do 80C31 possuir um pino que é ativado apenas quando o microcontrolador quer buscar
instruções tem uma implicação interessante. Como o pino PSEN, pode-se criar dois espaços de
endereçamento: uma para memória de dados e dispositivos de E/S e outro para memória de programa. Na
Figura 61 foi utilizado um outro 74HC138 para permitir que espaços de endereçamentos distintos. Com
isso, o microcontrolador pode endereçar até 64 kbytes de memória de programa e até 64 kbytes de
memória de dados.
19
12 MHz
Y2 18
33 pF C2
5V
C3
10 uF
SW1
RST
100 k
R1
14
15
12
13
9
1
2
3
4
5
6
7
8
EA/VP
X1
X2
T0
T1
INT0
INT1
RESET
P1.0
P1.1
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
P0.0
P0.1
P0.2
P0.3
P0.4
P0.5
P0.6
P0.7
ALE/P
P2.0
P2.1
P2.2
P2.3
P2.4
P2.5
P2.6
P2.7
RD
WR
PSEN
39
38
37
36
35
34
33
32
30
3
4
7
8
13
14
17
18
11
21
22
23
24
25
26
27
28
1D
2D
3D
4D
5D
6D
7D
8D
1Q
2Q
3Q
4Q
5Q
6Q
7Q
8Q
C
OC
2
5
6
9
12
15
16
19
10
9
8
7
6
5
4
3
25
24
21
23
2
1
74HC373
20
U4
1
2
3
17
16
5V
29
80C31
6
4
5
A
B
C
Y0
Y1
Y2
Y3
Y4
G1 Y5
G2AY6
G2BY7
22
15
14
13
12
11
10
9
7
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
VPP
33 pF C1
27
U2
U1
PGM
31
1
5V
U3
O0
O1
O2
O3
O4
O5
O6
O7
11
12
13
15
16
17
18
19
CE
OE
27C64
10
9
8
7
6
5
4
3
25
24
21
23
2
20
26
27
22
U6
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
D0
D1
D2
D3
D4
D5
D6
D7
11
12
13
15
16
17
18
19
CS1
CS2
WE
OE
MCM6264
74HC138
U4
1
2
3
U5A
1
5V
3
2
74HC08
6
4
5
A
B
C
Y0
Y1
Y2
Y3
Y4
G1 Y5
G2AY6
G2BY7
15
14
13
12
11
10
9
7
74HC138
Figura 61 - Sistema microprocessado baseado no 80C31 com espaços de
endereçamentos diferentes para dados e instruções.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
97
Curso de Microprocessadores
Apêndice A - BASIC Stamp II
Comentário
Este apêndice contém um breve manual do BASIC Stamp II. O texto está em inglês e sem
formatação, pois foi extraído de um arquivo texto (MANUAL.TXT) que acompanha o BS2.
Manual do BASIC Stamp II
BS2-IC
Pin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
98
TX
RX
ATN
GND
P0
P1
P2
P3
P4
P5
P6
P7
P8
P9
P10
P11
P12
P13
P14
P15
+5V *
RES
GND
Name
Serial output
Serial input
Serial attention
Serial ground
I/O pin 0
I/O pin 1
I/O pin 2
I/O pin 3
I/O pin 4
I/O pin 5
I/O pin 6
I/O pin 7
I/O pin 8
I/O pin 9
I/O pin 10
I/O pin 11
I/O pin 12
I/O pin 13
I/O pin 14
I/O pin 15
+5V supply
Reset I/O pin
System ground
Description
Connect to pin 2 of PC serial DB9 (RX)
Connect to pin 3 of PC serial DB9 (TX)
Connect to pin 4 of PC serial DB9 (DTR)
Connect to pin 5 of PC serial DB9 (GND)
Each I/O can source 20ma and sink 25ma.
P0-P7 and P8-P15, as groups, can each
source a total of 40ma and sink 50ma.
5-volt input or regulated output.
Pull low to reset; goes low in reset
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
24
PWR * Regulator input
Voltage regulator input; takes 5-15 VDC
Internal Perspective:
The BS2 has 2K bytes of EEPROM which holds the executable BASIC program and any
data. Memory not used by the BASIC program can be read and written at run-time
as a data bank, or initialized with data at download time. This memory is only
affected by downloading or run-time modification.
There are 32 bytes of RAM which serve as variable space and I/O pin interface
for the BASIC program. This memory can be accessed as words, bytes, nibbles,
or bits. Each time the BASIC program is run anew, this memory is cleared to
all zeroes.
So, the 2K byte EEPROM is for program and data, and only affected by initial
downloading or run-time modification. It survives power-down. The 32 bytes of
RAM are for run-time variables and I/O pin access. This memory is cleared each
time the BS2 is powered up, reset, or downloaded to.
The 2K-byte EEPROM is arranged as follows:
byte $000 ---+--- Data start
|
|
|
|
|
|
|
|
|
Data end
|
|
|
|
|
|
|
Program end
|
|
|
|
|
|
|
|
byte $7FF ---+--- Program start
The 32-byte RAM is arranged as follows:
WORD
$0- x x x x
$1- x x x x
$2- x x x x
$3- x x x x
$4- x x x x
BITS
xxxx xxxx
xxxx xxxx
xxxx xxxx
xxxx xxxx
xxxx xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
Description
Pin input states
Pin output latches
Pin directions
variable space
variable space
R/W
read-only
read/write
read/write
read/write
read/write
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
99
Curso de Microprocessadores
$5$6$7$8$9$A$B$C$D$E$F-
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
xxxx
variable space
variable space
variable space
variable space
variable space
variable space
variable space
variable space
variable space
variable space
variable space
read/write
read/write
read/write
read/write
read/write
read/write
read/write
read/write
read/write
read/write
read/write
Word $0 always reflects the read-state of all 16 I/O pins. Whether a pin is an
input or output, it's logical state can be read in this word. Word $0 is
accessed by the following symbolic names:
INS
INL
INH
INA
INB
INC
IND
IN0
|
|
|
IN15
the entire 16-bit word
the low byte of INS
the high byte of INS
the low nibble of INL
the high nibble of INL
the low nibble of INH
the high nibble of INH
the low bit of INS - corresponds to pin P0
the high bit of INS - corresponds to pin P15
Word $1 contains the output latches for all 16 I/O pins. If a pin is in input
mode, this data is unused, but when a pin is in output mode, its corresponding
word $1 bit sets its state. The bits are all readable and writable, regardless
of pin direction. The following symbolic names access word $1:
OUTS the entire 16-bit word
OUTL the low byte of OUTS
OUTH the high byte of OUTS
OUTA the low nibble of OUTL
OUTB the high nibble of OUTL
OUTC the low nibble of OUTH
OUTD the high nibble of OUTH
OUT0 the low bit of OUTS - corresponds to pin P0
|
|
|
OUT15 the high bit of OUTS - corresponds to pin p15
Word $2 contains the direction bits for all 16 I/O pins. To place a pin in
input mode, its corresponding word $2 bit must be cleared to 0. To put a pin
into output mode, its corresponding word $2 bit must be set to 1, at which
time its word $1 bit will determine whether it is high or low. Word $2 has
100
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
these symbolic names:
DIRS
DIRL
DIRH
DIRA
DIRB
DIRC
DIRD
DIR0
|
|
|
DIR15
the entire 16-bit word
the low byte of DIRS
the high byte of DIRS
the low nibble of DIRL
the high nibble of DIRL
the low nibble of DIRH
the high nibble of DIRH
the low bit of DIRS - corresponds to pin P0
the high bit of DIRS - corresponds to pin p15
Words $3-$F are for general purpose variable use and have no pre-assigned
symbolic names. The VAR statement is used to allocate this memory.
The above text has introduced the physical pin-out of the BS2 as well as
the internal EEPROM, RAM, and I/O structure.
Programming the BASIC Stamp II
In the BASIC Stamp II, there are two general categories of BASIC statements:
compile-time and run-time. Compile-time statements are resolved when you
compile the program (Alt-R or Alt-M) and do not generate any executable code.
Run-time statements, on the other hand, generate code and are executed at runtime.
There are three compile-time statements. They are used for declaring
variables, constants, and data. They are:
VAR
CON
and
DATA
The VAR statement - for defining variables
Your program should begin with a declaration of all of its variables. VAR
statements assign symbolic names to variable RAM (RAM not used by I/O - words
$3-$F). This is done as follows:
'Declare the variables
cat
mouse
dog
rhino
snake
var
var
var
var
var
nib
bit
byte
word
bit(10)
'make "cat" a nibble variable
'make "mouse" a bit variable
'make "dog" a byte variable
'make "rhino" a word variable
'make "snake" a 10-piece bit variable
The compiler will group all words, bytes, nibs, and bits, and respectively
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
101
Curso de Microprocessadores
arrange them into unused RAM. By pressing Alt-M, you can see a picture of
the RAM allocation. First, the three I/O words are shown, then all words,
bytes, nibs, and finally, bits, are seen. Empty RAM follows. Alt-M is a quick
way to assess how much RAM you've used.
The VAR usage options are as follows:
'define unique variables
sym1
sym2
sym3
sym4
VAR
VAR
VAR
VAR
bit
nib
byte
word
'make a bit variable
'make a nibble variable
'make a byte variable
'make a word variable
'After bit/nib/byte/word a value may be placed
'within parentheses to declare an array size:
sym5
VAR
nib (10) 'make a 10 nibble array
'define variables-within-variables or alias variables
sym6
sym7
sym8
VAR
VAR
VAR
sym4.highbit
sym4.lowbit
sym2
'make a bit variable of sym4's highbit
'make a bit variable of sym4's lowbit
'make an alternate name for sym2
'When using VAR to assign non-unique variables (a variable
'name is used in lieu of bit/nib/byte/word(size)), a period may
'be placed after the variable name and followed by modifiers.
'Modifiers are used to identify sub-pieces of the initially'mentioned variable.
sym9
VAR
sym4.highbyte.lownib.bit2
'picky, picky...
Here are all the variable modifiers:
102
LOWBYTE
HIGHBYTE
BYTE0
BYTE1
'low byte of a word
'high byte of a word
'byte0 (low byte) of a word
'byte1 (high byte) of a word
LOWNIB
HIGHNIB
NIB0
NIB1
NIB2
NIB3
LOWBIT
HIGHBIT
BIT0
BIT1
'low nibble of a word or byte
'high nibble of a word or byte
'nib0 of a word or byte
'nib1 of a word or byte
'nib2 of a word
'nib3 of a word
'low bit of a word, byte, or nibble
'high bit of a word, byte, or nibble
'bit0 of a word, byte, or nibble
'bit1 of a word, byte, or nibble
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
BIT2
BIT3
BIT4
BIT5
BIT6
BIT7
BIT8
BIT9
BIT10
BIT11
BIT12
BIT13
BIT14
BIT15
'bit2 of a word, byte, or nibble
'bit3 of a word, byte, or nibble
'bit4 of a word or byte
'bit5 of a word or byte
'bit6 of a word or byte
'bit7 of a word or byte
'bit8 of a word
'bit9 of a word
'bit10 of a word
'bit11 of a word
'bit12 of a word
'bit13 of a word
'bit14 of a word
'bit15 of a word
In summary, to declare variables, VAR statements are used. VAR statements
either declare unique variables or variables-within-variables/alias-variables.
For defining unique variables:
symbol VAR
size (array)
- symbol is a unique name for a variable
- size is either WORD, BYTE, NIB, or BIT
- (array) is an optional expression which declares an array size
For defining variables-within-variables or alias-variables
symbol VAR
variable.modifiers
- symbol is a unique name for a variable
- variable is a defined variable name
- .modifiers are optional and used to define variables-within-variables
The compiler will group all declarations by size (in the case of unique
variables) and assign them to unused RAM. Alt-M lets you see the result of
this process. Non-unique variables are in-whole or in-part derived from unique
variables and get assigned within the unique-variable memory.
Keep in mind that you may make alias names for the pin variables:
keyin
var
in5
'make "keyin" a way to read P5's state.
The CON statment - for defining constants
The CON statement is similar to the VAR statement, except that it is for
defining constant values and assigning them to symbolic names. This is
handy for having a single declaration which gets accessed throughout your
program. The CON syntax is as follows:
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
103
Curso de Microprocessadores
symbol CON
expression
'assign expression to "symbol"
- symbol is a unique symbolic name for a constant
- expression is a compile-time-resolvable constant
level
limit
CON
CON
10
10*4<<2
'"level" is same as 10 in program
'"limit" is 160
expressions after CON can contain the following binary operators and are
resolved left-to-right:
+
*
/
<<
>>
&
|
^
add
subtract
multiply
divide
shift left
shift right
logical AND
logical OR
logical XOR
example:
growth CON
100-light/gel
'"light" and "gel" are CON's, too
The DATA statment - for defining data
EEPROM memory not used by your BASIC program can be used for data storage.
Keep in mind that your BASIC program builds from the end of memory towards
the start of memory. This allocation is automatic. Your data, on the other
hand, builds from the start of memory towards the end. The sum of program and
data memory cannot exceed the 2K byte limit. The compiler will always tell you
when you have a conflict.
DATA statements are used to build data into unused memory. Initially, the DATA
location is set to 0. It is advanced by 1 for each byte declared. Here is an
example DATA statement:
table
DATA "Here is a string..."
Usually, you will want to precede DATA statements with a unique symbol name.
The symbol name will be assigned a constant value (as if via CON) which is the
current data pointer. The text following 'DATA' is usually a list of bytes
which can be constant expressions. In the above example (assuming this was
the first DATA statement in the program), "table" becomes a constant symbol of
value 0; "Here is a string..." is broken into individual bytes and placed
into EEPROM memory sequentially. Alt-M and two <SPACE>s will show you the
result of this line.
The DATA pointer may be altered at any time by an @ sign followed by a new
104
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
pointer value:
list
DATA @$100,"some data"
DATA has a few variations of use to allocate defined and undefined data.
Defined data is fully declared and known at compile time. Undefined data
is the mere allocation of data space, while not assigning values into the bytes
of EEPROM (to be done at run-time, instead). Defined and undefined data are
declared as follows:
for defined data:
fee
fie
foe
DATA 0,1,2,3,4,5,6,7,8,9
DATA word 1000
DATA 0 (256)
'actual bytes
'make two bytes: $E8 and $03
'256 bytes initialized as 0
for undefined data:
fum
DATA (1024)
scratch DATA word (16)
Important concept:
'reserved 1K byte of undefined data
'reserve 16 words of undefined data
Defined DATA and BASIC program memory are always
downloaded to the BS2. Undefined data and unused
EEPROM memory are not downloaded. This allows you
to change programs while keeping data, assuming both
programs defined the same stretch of memory as
undefined DATA. Alt-M will show you maps of EEPROM
allocation. This download/don't-download rule is
applied to 16-byte blocks. If any byte within a 16byte block is defined DATA or BASIC program, that
whole block is downloaded. Use Alt-M to see this.
In summary, DATA is used to define EEPROM byte usage that doesn't conflict
with the BASIC program storage:
- DATA can be preceeded by a symbol which will be assigned the constant value
of the current DATA pointer.
- Byte-size data is assumed, but 'word' can be used to break a word into two
bytes of storage.
- The @ sign is used to redirect the DATA pointer. If a symbol preceeds a
DATA statement and the first thing after DATA is @, the new pointer value
is assigned to the symbol.
- Defined data is spelled out, so to speak, with numbers and letters.
- Defined data may be repeated at the byte or word level using (array).
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
105
Curso de Microprocessadores
- Undefined data may be reserved by using (array) unpreeceded by a value.
Note: DATA can contain references to DATA symbols:
t1
t2
t3
t4
DATA
DATA
DATA
DATA
"Here's
"Here's
"Here's
"Here's
table 1...",0
table 2...",0
table 3...",0
table 4...",0
t_starts
DATA word t1, word t2, word t3, word t4
Run-Time Expressions
---------------------------------------------------Run-time expressions can contain constants, variables, operators, and
parentheses. They are resolved using 16-bit math.
Constants can be in several forms:
label
$BA1F
%111001111
99
"A"
- a label may be assigned a constant via CON
- Hex
- Binary
- Decimal
- ASCII
Note: When more than one character is within quotes, they are
separated by the compiler as such: "DOG" becomes "D","O","G".
"String"+$80 becomes: "S","t","r","i","n","g"+$80.
Variables can be accessed a number of ways:
somevar
wordvar.highbit
nibarray(index)
word.bit0(bitoffset)
- Some variable
- Use modifiers to access sub-variables
- A variable followed by an expression in
quotes is indexed as an array (0=1st element)
- Scan a word, one bit at a time
Say a variable were defined as such:
string var byte (10)
It could be accessed as:
string
- the 1st byte
string (0)
- the 1st byte
string (1)
- the 2nd byte
string (9)
- the 10th (last) byte
string.lownib(nibindex) - nibindex could be 0-19
string.lowbit(bitindex) - bitindex could be 0-79
106
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
There are binary, unary, and conditional expression operators.
Unary operators preceed a variable or constant or (expression) and have
highest priority. They are as follows:
SQR
ABS
~
DCD
NCD
COS
SIN
- Square root of unsigned 16-bit value
- Absolute of signed 16-bit value
- One's complement of 16-bit value (bitwise not)
- Two's complement of 16-bit value (negation)
- 2^n decoder of 4-bit value (0...15 -> 1,2,4,8,16,...32768)
- Priority encoder of 16-bit value
(=>32768,=>16384,=>8192,...=1 -> 15,14,13,...1 ; 0 -> $FFFF)
- Cosine of 8-bit value. Result is in the range of +-127,
unit circle is 0-255 radial units.
- Sine of 8-bit value. Result is in the range of +-127,
unit circle is 0-255 radial units.
Examples:
sin bytevar
sqr 50000
~ in0
Binary operators take two terms and go between variables, constants, or
expressions. They are as follows:
&
|
^
MIN
MAX
+
*
**
*/
/
//
DIG
<<
>>
REV
- Bitwise AND
- Bitwise OR
- Bitwise XOR
- limit value to minimum
- limit value to maximum
- addition
- subtraction
- multiply
- multiply and return high 16-bits of result
- multiply and return middle 16-bits of result
(use to simultaneously multiply by a whole and a part;
ie. 'value */ $0180' multiplies by 1 and a half)
- divide
- divide and return remainder
- return decimal digit; '12345 dig 3' returns 2
- shift left
- shift right
- reverse order of bits, lsb-justified; '%100110 rev 6'
yields %011001
Examples:
ypos * xsize + xpos
randword // 20
countacc min 200 - 200 / 200
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
107
Curso de Microprocessadores
Parentheses can be placed to special-order the pattern of expression
resolution. Though unary operators have highest priority and binary operators
have secondary priority, and with those rules expressions are resolved left-toright, parentheses can override priority:
X+1*Y-1
(X+1)*(Y-1)
'something's wrong here if we need (X+1)*(Y-1)
'do it right
Up to 8 levels of parentheses can be used.
For use within conditional expressions (IF), there is a special unary operator
and several binary operators. These conditional operators have highest
priority of all.
NOT
- highest priority unary
AND, OR, XOR - highest priority binaries
Note: These are arithmetically identical to expression operators:
~
&
|
^
though they differ in application.
Lower-priority conditional binary operators (still higher than expression ops):
<
<=
=
=>
>
<>
- less than
- less than or equal to
- equal to
- equal to or greater than
- greater than
- not equal
Note: These comparison operators return 0 for false and $FFFF for true.
Combined with NOT, AND, OR, and XOR, complex tests can be done.
To summarize, here are some examples:
outs = ~ dcd nibarray(index) 'lookup a nibble, decode it, not it
IF x<1 or not y>3 and (z=0 xor r=3) then loopback
Run-Time Instructions
---------------------------------------------------Anywhere a value is requested, an expression may be placed
===============================================================================
DEBUG outputdata
===============================================================================
Show variables and messages for debugging purposes.
usage: DEBUG "Here we are!" 'show message when executed
108
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
When executed, the data after DEBUG will be sent to the PC for
display. DEBUG data can be displayed in several modes. Straight
data can be relayed to the PC, or you can have values printed in decimal,
hex, binary, or ascii. In the number-printing modes, the result of an
expression can be printed or a complete relation can be shown between the
expression and its result. For example:
DEBUG dec? X
'show variable X in decimal
will yield (if x=1):
X=1
DEBUG dec X
'show variable X in decimal
yields:
1
To print numbers, there are several words which can preceed expressions:
ASC?
'show ascii value w/relation
STR bytevar
'output string from byte array - until 0
STR bytevar\length 'output string from byte array - length bytes
REP value\count
'output value count times
DEC value
'print value in decimal
DEC1-DEC5 value
'print value in decimal - 1-5 digits
SDEC value
'print value in signed decimal
SDEC1-SDEC5 value
'print value in signed decimal - 1-5 digits
HEX value
'print value in hex
HEX1-HEX4 value
'print value in hex - 1-4 digits
SHEX value
'print value in signed hex
SHEX1-SHEX4 value
'print value in signed hex - 1-4 digits
IHEX value
'print value in hex w/'$'
IHEX1-IHEX4 value
'print value in hex w/'$' - 1-4 digits
ISHEX value
'print value in signed hex w/'$'
ISHEX1-ISHEX4 value
'print value in signed hex w/'$' - 1-4 digits
BIN value
'print value in binary
BIN1-BIN4 value
'print value in binary - 1-4 digits
SBIN value
'print value in signed binary
SBIN1-SBIN16 value
'print value in signed binary - 1-4 digits
IBIN value
'print value in binary w/'%'
IBIN1-IBIN16 value
'print value in binary w/'%' - 1-4 digits
ISBIN value
'print value in signed binary w/'%'
ISBIN1-ISBIN16 value
'print value in signed binary w/'%' -1-4 digits
To print the literal text expression along with the result, follow any of the
words with a '?'. A lone '?' is the same as 'DEC?'. REP cannot be followed
by a '?', but ASC needs one.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
109
Curso de Microprocessadores
DEBUG statements can contain many strings and numbers, separated by commas. In
addition, there are several special control characters which are interpreted by
the DEBUG screen:
name value effect
-----------------------------------------------------CLS
0
clears the screen and homes the cursor
HOME 1
homes the cursor
BELL 7
beep the PC speaker
BKSP 8
backspace - backs up the cursor
TAB
9
advances to the next 8th column
CR
13
carriage return - down to next line
DEBUG cls,dec ina," " 'cls, print ina in decimal, spaces too
Example program using DEBUG:
count
var
byte
loop:
debug sdec? sin count 'show the signed-decimal sine of count
count = count + 1
'increment count
if count <> 0 then loop 'loop until count rolls over
===============================================================================
FOR...NEXT
===============================================================================
The FOR...NEXT loop.
usage: FOR variable = start TO end {STEP stepval}
{some code}
NEXT
STEP is for specifying a step value other than the default of 1; if specified,
stepval must be positive since whether to add or subtract stepval from variable
is determined dynamically at run-time (this allows '10 TO 0' without specifying
a negative STEP value.).
FOR...NEXT loops can be nested up to 16 deep.
Note: NEXT is stand-alone and implies the variable from the last FOR statement.
===============================================================================
BRANCH
===============================================================================
Branch according to an index.
usage: BRANCH
index,[label0,label1,label2,...labelN]
If index=0, a GOTO label0 will be executed. If index=1, a GOTO label1 will be
110
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
executed. If the index exceeds the number of label entries, no branch will
occur and execution will proceed at the next instruction.
===============================================================================
IF
===============================================================================
Branch conditionally.
usage: IF conditionalexpression THEN label
ie. IF x=1 then redoit
If the result of conditionalexpression is not 0, execution will be continued
at label. Else, execution continues at the next instruction.
===============================================================================
GOTO
===============================================================================
Go to a new point in the program.
usage: GOTO joe
A branch to joe will occur, rather than execution continuing at the next
instruction.
===============================================================================
GOSUB
===============================================================================
Go to a subroutine (and then RETURN later).
usage: GOSUB ledset
The execution point is stored and then a branch to ledset occurs. When
a RETURN is encountered (in ledset), execution continues at the instruction
following the GOSUB.
GOSUB's may be nested up to 4 deep and you are allowed 255 of them in your
program.
===============================================================================
RETURN
===============================================================================
Return from a subroutine.
usage: RETURN
The execution point is set to the instruction after the GOSUB that got into
the subroutine executing the RETURN.
If a RETURN is executed without a corresponding GOSUB, execution begins anew
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
111
Curso de Microprocessadores
at the start of the program.
===============================================================================
Variable Assignment
===============================================================================
assign a value to a variable.
usage: variable = value
Value is an expression which gets written to variable.
===============================================================================
LOOKUP
===============================================================================
Lookup a variable according to an index.
usage: LOOKUP
index,[value0,value1,value2,...valueN],variable
If index=0, value0 will be written to variable. If index=1, value1 will be
written to variable. If the index exceeds the number of value entries, the
variable will not be affected.
===============================================================================
LOOKDOWN
===============================================================================
Lookdown a value and return an index.
usage: LOOKDOWN value,??[value0,value1,value2,...valueN],variable
?? is a comparison operator: =,<>,>,<,<=,=> (= is the default). A comparison
is made between value and value0; if the result is true, 0 is written into
variable. If that comparison was false, another comparison is made between
value and value1; if the result is true, 1 is written into variable. This
process continues until a true is yielded, at which time the index is written
into variable, or until all entries are exhausted in which case variable is
unaffected.
===============================================================================
RANDOM
===============================================================================
Pseudo-randomly iterate a word variable.
usage: RANDOM
wordvariable
wordvariable will be iterated 16 times to potentially change every bit.
===============================================================================
SEROUT tpin,baudmode,{pace,}[outputdata]
SEROUT tpin\fpin,baudmode,{timeout,tlabel,}[outputdata]
===============================================================================
112
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
Output data serially.
usage: SEROUT 3,6+$4000,["The temperature is ",dec temp," degrees.",cr]
Tpin is 0-15 for an I/O pin, or 16 for the internal serial port. Fpin is an
option to specify a flow-control pin. Baudmode is a composite value which
specifies baud rate, parity mode, true/inverted output, and open/driven output.
If no fpin was specified, an optional pace in milliseconds may be declared to
pace characters by a number of milliseconds. If an fpin was specified, an
optional timeout (in milliseconds) and timeout label may be specified to enable
timeout and branching for flow-control.
Baudmode is the bit period expressed in microseconds-20 (ie 300 baud is 3313).
An easy formula for computing the baud rate (baudmode bits 0-12) is:
int (1,000,000/baud) - 20
baudmode's bit 15 ($8000) is 0 for driven, 1 for open-drain/source (SEROUT)
baudmode's bit 14 ($4000) is 0 for true, 1 for inverted.
baudmode's bit 13 ($2000) is 0 for 8-bit no parity, 1 for 7-bit parity
outputdata follows the DEBUG conventions
note:
If tpin=16 (internal port), baudmode's bits 14 and 15 are ignored.
However, they will affect operation of fpin.
===============================================================================
SERIN rpin{\fpin},baudmode,{plabel,}{timeout,tlabel,}[inputdata]
===============================================================================
Input data serially.
usage: SERIN 16,32+$2000,60000,nothingcame,[WAIT (","),STR bytearray\16\","]
Rpin is 0-15 for an I/O pin, or 16 for the internal serial port. Fpin is an
optional flow-control pin. Baudmode is described in SEROUT. Plabel is a an
option to specify a where to branch in the event of a parity error (parity mode
must be enabled). Timeout is an optional value to specify how long to wait in
milliseconds before giving up and branching to tlabel. Inputdata follows the
conventions below:
variable
'input a byte and store into variable
STR bytearray\L{\E} 'input a string into bytearray of
'length L with optional end-character
'of E (0's will fill remaining bytes)
SKIP L
'Input and ignore L bytes
WAITSTR bytearray 'Wait for bytearray string (bytearray
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
113
Curso de Microprocessadores
'is 0-terminated)
WAITSTR bytearray\L
'Wait for bytearray string of length L
WAIT (value,value,...) 'Wait for up to a six-byte sequence
DEC variable 'input decimal value
DEC1-DEC5 variable
'input decimal value of fixed length
SDEC variable
'input signed decimal value
SDEC1-SDEC5 variable
'" of fixed length
HEX variable
'input hex value
HEX1-HEX4 variable
'" of fixed length
SHEX variable
'input signed hex value
SHEX1-SHEX4 variable
'" of fixed length
IHEX variable
'input indicated ($) hex value
IHEX1-IHEX4 variable
'" of fixed length
ISHEX variable
'input signed inidicated ($) hex value
ISHEX1-ISHEX4 variable
'" of fixed length
BIN variable 'input binary value
BIN1-BIN16 variable
'" of fixed length
SBIN variable
'input signed binary value
SBIN1-SBIN16 variable
'" of fixed length
IBIN variable
'input indicated (%) binary value
IBIN1-IBIN16 variable
'" of fixed length
ISBIN variable
'input signed indicated (%) bin value
ISBIN1-ISBIN16 variable
'" of fixed length
note:
If rpin=16 (internal port), baudmode's bits 14 and 15 are ignored.
However, they will affect operation of fpin.
===============================================================================
READ
===============================================================================
Read a byte from the EEPROM.
usage: READ location,variable
Location is 0-2047. Variable will receive the byte read from location.
===============================================================================
WRITE
===============================================================================
Write a byte into the EEPROM.
usage: WRITE location,byte
Location is 0-2047. Byte is 0-255. Byte will be written into location.
===============================================================================
XOUT
114
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
===============================================================================
Output X-10 codes to a TW523 or TW513 module (by X-10 Powerhouse).
usage: XOUT mpin,zpin,[house\keyorcommand{\cycles,...]
Mpin will be made a low output and is the modulation control. Zpin will be
made an input and is the zero-crossing detect. House is the house code (0-15
is 'A'-'P'). Keyorcommand is a key (0-15 is '1'-'16') or command (see table
below). Cycles is an optional number which overrides the default of two; this
should only be used with 'dim' and 'bright' commands.
command symbol
UNITON
UNITOFF
UNITSOFF
LIGHTSON
DIM
BRIGHT
value
%10010
%11010
%11100
%10100
%11110
%10110
TW513/TW523-to-BS2 connections: 1-to-zpin, 2-to-VSS, 3-to-VSS, 4-to-mpin
(also zpin to VDD via 10K resistor)
===============================================================================
SHIFTOUT
===============================================================================
Shift bits out synchronously.
usage: SHIFTOUT dpin,cpin,mode,[data{\bits},...]
Dpin is the data output, cpin is the clock output. Mode is 0 for lsb-first or
1 for msb-first. Data is a value to be shifted out. Bits is an optional bit
count (8 is the default).
The following symbols are defined for use with SHIFTOUT:
symbol
value
--------------------LSBFIRST
0
MSBFIRST
1
===============================================================================
SHIFTIN
===============================================================================
Shift bits in synchronously.
usage: SHIFTIN dpin,cpin,mode,[variable{\bits},...]
Dpin is the data input, cpin is the clock output. Mode is 0 for msb-first/
pre-clock, 1 for lsb-first/pre-clock, 2 for msb-first/post-clock, or 3 for
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
115
Curso de Microprocessadores
lsb-first/post-clock. Variable receives the shifted-in data. Bits is an
optional bit count (8 is the default).
The following symbols are defined for use with SHIFTIN:
symbol
value
--------------------MSBPRE
LSBPRE
MSBPOST
LSBPOST
0
1
2
3
===============================================================================
COUNT
===============================================================================
Count cycles on a pin for some milliseconds.
usage: COUNT
pin,period,variable
Pin will be placed in input mode. For 'period' milliseconds, cycles will be
counted on pin. Both sides of the waveform must be at least 4us in duration,
limiting the input frequency to 125KHz (assuming 50/50 duty cycle). The result
(0-65535) will be written into variable.
===============================================================================
PULSOUT
===============================================================================
Output a timed pulse.
usage: PULSOUT
pin,period
Pin will be made an output opposite of it's OUTx value for period*2us. Pin
will be left in output mode with OUTx state.
===============================================================================
PULSIN
===============================================================================
Input a timed pulse.
usage: PULSIN
pin,state,variable
Pin will be placed in input mode. A pulse of 'state' will be waited for and
measured with 2us resolution and the result will be written into variable. If
an overflow occurs while waiting for any edge, (>65535*2us or >131ms), 0 will
be written into variable.
===============================================================================
BUTTON
===============================================================================
Debounce button, auto-repeat, and branch if button is in target state.
116
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
usage: BUTTON pin,downstate,delay,rate,bytevariable,targetstate,label
Pin will be placed in input mode. Downstate is the state which is read when
the button is pressed. Delay specifies down-time before auto-repeat in BUTTON
cycles. Rate specifies the auto-repeat rate in BUTTON cycles. Bytevariable is
the workspace. It must be cleared to 0 before being used by BUTTON for the
first time. Targetstate specifies what state (0=not pressed, 1=pressed) the
button should be in for a branch to occur. Label specifies where to go if the
button is in the target state.
===============================================================================
INPUT, OUTPUT, LOW, HIGH, TOGGLE, REVERSE
===============================================================================
Modify a pin's input/output high/low state.
usage: INPUT pin
Pin is 0-15.
modified:
OUTx DIRx
---------------------------INPUT
same 0
OUTPUT
same
LOW
0
1
HIGH
1
1
TOGGLE
flip
REVERSE
same
1
1
flip
===============================================================================
FREQOUT
===============================================================================
Output a sine-wave(s) for some time.
usage: FREQOUT
pin,milliseconds,freq1{,freq2}
Pin will be temporarily placed in output mode for modulation. Milliseconds
specifies how long to output the frequency(s). Freq1 specifies the (first)
frequency in 1Hz units (0-32768Hz). Freq2 is optional and specifies a second
frequency.
The pin may be filtered by an RC circuit to achieve a clean sine-wave(s).
High-Z speakers may be driven with a coupling cap and a filter cap.
===============================================================================
DTMFOUT
===============================================================================
Output DTMF tones.
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
117
Curso de Microprocessadores
usage: DTMFOUT
pin,{ontime,offtime,}[key,key,key,...]
Pin will be temporarily placed in output mode for modulation. The default
on and off times are 200ms and 50ms. ontime and offtime are optional overrides
which specify milliseconds. Key(s) are 0-15; 0-9 are the digits '0'-'9'; 10 is
'*'; 11 is '#'; 12-15 are 'A'-'D' which are fourth-column codes unavailable on
normal phones.
The pin may be filtered by an RC circuit to achieve a clean sine-waves.
High-Z speakers may be driven with a coupling cap and a filter cap.
===============================================================================
PWM
===============================================================================
Pulse-width modulate a pin for some time.
usage: PWM
pin,duty,cycles
Pin will be temporarily made an output while it is modulated. Duty is an 8-bit
value (0-255) which specifies the duty-cycle. Cycles is the number of 256
pin update periods which take ~1ms. When done, pin will be placed in input
mode to allow the voltage to remain until another PWM is executed.
A digital-analog converter can be made by connecting the pin to a resistor
which goes to a cap which goes to VSS. The resistor-cap junction will reflect
the duty (0-5V) during and after PWM.
===============================================================================
RCTIME
===============================================================================
Measure an R-C charge/discharge time.
usage: RCTIME
pin,state,variable
Pin will be placed in input mode and time will be measure in 2us units while
pin is in 'state'. The result will be written into variable. If an overflow
occurs (>131ms), 0 will be written.
This is useful for measuring resistor-capacitor charge/discharge times. Since
the logic threshold of a pin is ~1.4 volts, it is best to have the RC voltage
go from the 5V supply towards ground, yielding a span of ~3.6 volts. For
example, to convert a potentiometer setting to a number: connect a .1uf cap
to VDD (5V); the other side of the cap goes to both the pin and the center-tap
of the pot; the side-tap of the pot goes to VSS (ground); make the pin high
for 1ms, then do RCTIME; the resistor-cap junction will start at 5V and fall
towards ground. When ~1.4 is reached, the counting will terminate and the
result will be returned to variable. Adjusting the pot causes the returned
value to go up or down. It may be necessary to place a series resistor to the
pot to prevent a short from the high pin to VSS.
118
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Capítulo 5- Projeto de Sistemas Microcontrolados
===============================================================================
NAP
===============================================================================
Nap for a short period.
usage: NAP x
Enter low-power mode for a short period. When the period is over, the I/O's
will go high-z for ~18ms and execution will continue at the next instruction.
The x values for NAP are as follows:
x
~seconds
---------------0
.018
1
.036
2
.072
3
.14
4
.29
5
.58
6
1.2
7
2.3
===============================================================================
SLEEP
===============================================================================
Sleep for x seconds (x=0 to 65535).
usage: SLEEP x
Enter low-power mode and keep I/O's updated. Every ~2.3 seconds the I/O's
will go high-z for ~18ms. Approximately 50ua average current will be consumed.
When x seconds have been accrued in SLEEP mode, execution continues at the next
instruction. Though the granularity of SLEEP is ~2.3 seconds, the error is
within 1% over extended periods of time.
===============================================================================
END
===============================================================================
End program.
usage: END
Enter low-power mode and keep I/O's updated. Every ~2.3 seconds the I/O's
will go high-z for ~18ms. Approximately 50ua average current will be consumed.
END is terminated only by a hardware reset.
===============================================================================
PAUSE
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
119
Curso de Microprocessadores
===============================================================================
Pause for x milliseconds (x=0 to 65535).
usage: PAUSE x
A delay of x milliseconds will occur.
===============================================================================
STOP
===============================================================================
Stop execution.
usage: STOP
Execution is frozen, but low-power mode is not entered. This is like
END, except that the I/O's never go high-z; they remain driven. Reset
will end STOP.
120
Universidade Estadual de Londrina – Professor José Alexandre de França - http://www.josealexandre.rg3.net/
Download