A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 1 Folhas de Apoio à Disciplina de Introdução aos Microprocessadores.

Apresentações semelhantes


Apresentação em tema: "ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 1 Folhas de Apoio à Disciplina de Introdução aos Microprocessadores."— Transcrição da apresentação:

1 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 1 Folhas de Apoio à Disciplina de Introdução aos Microprocessadores Versão 1.4 © Jorge Pais Instituto Superior de Engenharia de Lisboa Departamento de Eng. Electrónica e Telecomunicações e de Computadores Secção de Sistemas Digitais

2 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 2 Objectivo O principal objectivo destas folhas de apoio à disciplina de Introdução aos Microprocessadores é dar ao aluno um texto de apoio sintético mas que foque os aspectos considerados importantes e essenciais sobre cada um dos tópicos do programa da disciplina. De modo, a que o aluno se sinta apoiado nas aulas teóricas e na realização dos trabalhos práticos. Este texto não pretende substituir de forma alguma a bibliografia recomendada para a disciplina. E, deve ser entendido como um texto de apoio à matéria leccionada nas aulas teóricas da disciplina, como tal, o aluno deverá sempre ser assíduo e estudar continuamente a matéria leccionada para concretizar com êxito a realização da disciplina. Nota ao aluno: Como este conjunto de folhas encontra-se ainda numa fase embrionária é natural que contenha alguns erros ortográficos e também técnicos. Portanto, agradece-se a colaboração activa de todos os alunos interessados que ao detectarem qualquer erro, ou ao lerem certo tópico do texto acharem-no menos esclarecedor que contactem o autor via com as vossas criticas e sugestões. Muito obrigado. J.Pais Pré-requisitos: Sistemas Digitais e Programação.

3 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 3 Memória de Acesso Aleatório - RAM (random access memory) Para se compreender o funcionamento de uma memória de acesso aleatório, nada melhor que projectar em primeiro lugar a estrutura interna de um dispositivo destes recorrendo aos dispositivos digitais registo bidireccional e demultiplexer. No entanto, algumas considerações devem ser feitas sobre a sua estrutura interna. A RAM é constituída por um conjunto de registos de n bits cada e sendo cada registo identificado internamente através de um endereço personalizado. Assim, o número de bits de cada registo define a dimensão do conjunto de sinais por onde flui a informação de e para a RAM, este conjunto de sinais é designado por barramento de dados (data bus). A quantidade de registos internos define o número de bits necessários para o endereço de modo a que cada registo tenha um endereço distinto dos outros. Este conjunto de bits é designado por barramento de endereços (address bus). Existem ainda sinais de controlo que definem o fluxo de informação de e para a RAM que se designam respectivamente por OE/ (output enable) ou WE/ (write enable), ambos activos a zero. Também deve ser disponibilizado um sinal de controlo CE/ (chip enable) que função do seu nível lógico deve permitir realizar ou não operações sobre a RAM consoante esteja ou não activo. Por exemplo, a seguinte figura ilustra a arquitectura interna de uma RAM 4x8, ou seja, um dispositivo com 4 registos de 8 bits cada. E/ OE/ E/ EN/ CE/ S0S0 S1S1 A0A0 A1A YYYY OE/ WE/ Reg. 8 D 0-7 RAM 4x8 8

4 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 4 Depois de se compreender o modo de funcionamento e a estrutura interna de uma RAM pode-se então proceder ao projecto de um sistema simples que permita ler e escrever dados de uma RAM 16x8. No sistema sugerido existem dois registos com os seguintes objectivos: Sistema de acesso à memória Memory Address Register (MAR) define um endereço a 4 bits seleccionando a posição de memória a aceder. O seu conteúdo pode ser estabelecido muito simplesmente através de um thumbweel switch hexadecimal quando o sinal Address/Data/ está a 1 e houver a transição ascendente do sinal Strobe, ou então, por acção do sinal Next quando se pretenda aceder ao endereço seguinte; Memory Buffer Register (MBR) contém os 8 bits de dados a escrever na RAM. O seu conteúdo pode ser definido através de dois thumbweel switch quando o sinal Address/Data/ está a 0 e houver a transição ascendente do sinal Strobe.

5 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 5 As ligações sugeridas na figura seguinte ilustram o funcionamento descrito anteriormente. Exercício: Projecte o circuito combinatório (C.C.) da figura de modo a que o circuito anterior opere correctamente sobre a RAM.

6 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 6 Exercício: Pretende-se desenhar a estrutura interna do CPU especificado bem como a sua interligação à memória. Para a realização do exercício vamos fazer uma breve revisão do formalismo gráfico Basic Schemata que nos vai servir como ferramenta para o projecto de hardware complexo. Também vamos rever o conceito de instrução e a sua decomposição/composição em subcampos como auxiliar importante para a codificação em binário. Considere uma unidade de processamento central (CPU – Central Processing Unit) como uma arquitectura de Von Newman, na qual os dados e o código são acedidos através dos mesmos barramentos de endereço e dados. Os barramentos têm ambos 8 bits. O CPU suporta o seguinte conjunto de instruções: Projecto da Estrutura Interna de um CPU e sua Interligação à Memória

7 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 7 Esquema de fluência de informação - EFI Este esquema disponibiliza dois mecanismos. Um mecanismo chamado registo que serve para armazenar informação e que é representado por um rectângulo, tal e qual o ilustrado na seguinte figura: Um outro mecanismo é designado acção e representa operações sobre um ou mais registos, sejam elas de transferência de informação, aritméticas ou lógicas. Este mecanismo gráfico tem a sintaxe ilustrada na seguinte figura: Esquema de Sequência de Acções – ESA Este esquema é composto por quatro mecanismos. O mecanismo acção onde se evoca o nome de uma acção existente no EFI e que obedece à seguinte sintaxe gráfica: Nome da acção Operação ou Nome da acção Operação - símbolo de acção. Nome da acção Nome Nº bits - símbolo de registo. Basic Schemata O basic schemata é um formalismo gráfico constituído por dois esquemas.

8 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 8 No exemplo da figura anterior, quando a avaliação da expressão lógica for verdadeira (V) o conjunto de acções a executar é o referido por acções1, caso contrário são executadas as acções identificadas por acções2. Quando terminado um conjunto de acções o fluxo de acções continua pelo ramo central. Um outro mecanismo é designado decisão simples e representa um teste sobre uma expressão lógica englobando uma ou mais entidades existentes no EFI e cujo resultado define o conjunto de acções a executar. O seu grafismo é: acções1 acções2 V F E.L. Expressão Lógica O terceiro mecanismo é designado por repetição e consiste na avaliação de uma expressão lógica cujo resultado pode originar a execução de um conjunto de acções de um modo repetitivo. O grafismo inerente ao mecanismo de repetição é: Acções a repetir E.L. Expressão Lógica - decisão simples. - repetição. F Vf v

9 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 9 O último mecanismo é designado por decisão múltipla e consiste na avaliação de uma expressão cujo resultado pode originar múltiplos valores e no qual cada valor conduz à execução de um conjunto exclusivo de acções. A sintaxe gráfica é representada na seguinte figura: Expressão a avaliar valor1valor3valor2valorN Acções 1Acções 2Acções 3Acções N - decisão múltipla Instruções As instruções são em geral agrupadas em classes ou famílias. As classes mais relevantes de instruções são as designadas por transferência de informação, aritméticas, lógicas e de controlo. As instruções de transferência de informação são responsáveis pelas as acções de leitura ou escrita em registos, contadores e flags da estrutura interna do CPU bem como pela a alteração ou leitura de valores em dispositivos externos ao CPU mas que partilhem todos os seus barramentos.

10 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 10 As instruções aritméticas são aquelas que desempenham operações aritméticas e em geral são realizadas por uma máquina designada por unidade aritmética e lógica (ALU – arithmetic logic unit) e que é parte integrante da estrutura interna do CPU. As instruções lógicas implementam as funções lógicas comuns e em geral são realizadas na ALU. As instruções de controlo são todas as que podem alterar, de alguma forma, a execução sequencial de instruções. Depois de uma breve revisão dos tipos de instruções vamos de seguida analisar o problema da codificação das instruções tendo como exemplo o exercício proposto. De uma forma pragmática podemos dizer que o CPU a projectar tem dez instruções logo necessito de pelo menos 4 bits para a sua codificação. O modo de codificar as instruções pode ser realizado utilizando 2 abordagens completamente distintas que conduzem a complexidades de hardware e de estruturação muito diversas. A primeira abordagem pode ser designada como força bruta e consiste em atribuir um código binário distinto a cada instrução sem qualquer tipo de critério. Por exemplo, se o CPU tem 10 instruções então uma possível codificação a 4 bits é atribuir valores entre 0000B e 1001B a cada uma das instruções, resolvendo-se este problema.

11 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 11 A segunda abordagem é uma abordagem estruturada onde os critérios são perfeitamente bem definidos quanto à funcionalidade de cada um dos bits da codificação. A figura seguinte ilustra esta abordagem para o exercício proposto. Código da instrução DC1C1 C0C0 T D – Dimensão 0 1 byte 1 2 bytes C 1 C 0 – Classe 0 0 Transf. de Informação 0 1 Aritmética 1 X Controlo T – Tipo Exemplo para C 1 = 0 e C 0 =1: 0 ADDC 1 SUBB Portanto, estamos a assumir que as instruções do nosso CPU têm duas dimensões possíveis, de 1 ou 2 bytes. Então, de seguida vamos esclarecer como se calcula a dimensão de cada uma das instruções. Basicamente a dimensão depende do número de bits do código de identificação e do número de bits dos operandos da instrução.

12 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 12 CJNC A, end8, rel4 2 bytes CJZ SJMP rel4 1 byte MOV A, end8 2 bytes 4 bits8 bits + códigoendereço MOV end8, A 2 bytes 4 bits8 bits + códigoendereço 4 bits + códigovalor relativo LJMP end8 2 bytes 4 bits8 bits + códigoendereço ADDC A, end8 2 bytes 4 bits8 bits + códigoendereço SUBB A, end8 2 bytes 4 bits8 bits + códigoendereço 4 bits8 bits + códigoendereço + 4 bits relativo SETB C 1 byte CLR C 4 bits código e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 r 3 r 2 r 1 r e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 r 3 r 2 r 1 r 0 e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e0 e7e6e5e4e3e2e1e0e7e6e5e4e3e2e1e byte

13 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 13 A 8 EFI MBR 8 IR 4 MAR 8 Memória 256x8 I PC 8 I I WRM RDM I I RDA WRA II RDPC WRPC +1 IMAR 4 WRIR Inst. + 4 ADDREL Flag Cy AU 1 01 CLRCSETC 0 RESET(ext.) TMP 8 I I WRTMP RDTMP REL 4 1 I WRMAR 1 I WRREL Flag TCy I I RDTCY WRTCY

14 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 14 0 ESA ADDREL WRPCRDM AU (IR0=1 - ) AU( IR 0 =0 +) RDPCWRIRIMARWRREL IR 3 1(1 byte)(2 bytes) RDM WRMAR Fase de Preparação case instrução MOV A,end 8 MOV end 8, ASJMP rel 4 LJMP end 8 RDMWRARDAWRMWRPC ADDC A, end 8 SUBB A, end 8 Fase de execução RDM IMARWRPC

15 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 15 RDTMPWRTMP CJNC A, end 8, rel 4 AU (IR0=1 - ) 1 Cy ADDREL 0 CJZ A, end 8, rel 4 SETC CLRC SETB C CLR C RDMWRTCYCLRCRDTCYRDTMPWRTMP AU (IR0=1 - ) 0 A=0 ADDREL 1 RDMWRTCYCLRCRDTCY

16 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 16 Depois de termos projectado o CPU, utilizando o formalismo basic schemata, precisamos de verificar a correcção do desenho. Para isso, precisa-se de realizar um programa de prova de correcção numa qualquer linguagem de alto nível (C, C++, Java, etc). De seguida, apresenta-se o programa de prova da correcção nas linguagens C, C++ e JAVA. Um aspecto importante, é que o programa não tem interface com o utilizador, sendo esta realizada utilizando a opção watch dos ambientes de desenvolvimento utilizados. Programa em C /////////////////////////// Inicio do programa em C ////////////////////////////// // definir tipo byte e word #define byte unsigned char #define word unsigned int // definição da sintaxe das instruções para introdução do programa #define MOVA0x08 #define MOVM0x09 #define _SJMP0x04 #define SJMP(R)(_SJMP | (R << 4)) #define LJMP0x0C #define ADDC0x0A

17 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 17 #define SUBB0x0B #define _CJNC0x0D #define CJNC(R)(_CJNC | (R << 4)) #define _CJZ0x0F #define CJZ(R)(_CJZ | (R << 4)) #define SETBC0x00 #define CLRBC0x01 // definição dos operadores simples #define RDPC cpu.mar= cpu.pc #define RDM cpu.mbr= RAM[cpu.mar] #define IMAR ++cpu.mar #define WRIR cpu.ir= cpu.mbr & 0x0F #define WRRELcpu.rel= cpu.mbr >> 4 #define WRMAR cpu.mar= cpu.mbr #define WRPC cpu.pc= cpu.mar #define WRA cpu.a= cpu.mbr #define RDA cpu.mbr= cpu.a #define WRM RAM[cpu.mar]= cpu.mbr #define ADDREL cpu.pc += (cpu.rel & 0x08)? cpu.rel | 0xF0 : cpu.rel #define SETC cpu.cy= true #define CLRC cpu.cy=false #define WRTMP cpu.tmp= cpu.a #define RDTMP cpu.a= cpu.tmp #define WRTCY cpu.tcy= cpu.cy #define RDTCYcpu.cy= cpu.tcy #define AU au() #define IR3 (cpu.ir & 0x08)

18 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 18 // memória byte RAM[256]; // registos do CPU struct t_cpu { byte pc, mar, mbr, rel, ir, tmp, a; bool cy, tcy; } cpu; // definição do macro-operador au void au() { word aux; if (IR3) { aux= cpu.a - cpu.mbr - cpu.cy; cpu.cy= cpu.a < cpu.mbr+cpu.cy; } else { aux= cpu.a + cpu.mbr + cpu.cy; cpu.cy= aux > 0xFF; } cpu.a= aux; } void ResetCPU() { cpu.pc= 0; }

19 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 19 void InitRam() {// Exemplo: Colocar na posição de memória com o endereço 12H // o maior valor das posições de memória 10H e 11H // código em 0 RAM[0x00]= MOVA; RAM[0x01]= 0x10; RAM[0x02]= CJNC(+2); RAM[0x03]= 0x11; RAM[0x04]= MOVA; RAM[0x05]= 0x11; RAM[0x06]= MOVM; RAM[0x07]= 0x12; RAM[0x08]= SJMP(-1); // dados inicializados em 0x10 RAM[0x10]= 0xFF; RAM[0x11]= 0x01; // variável de saída RAM[0x12]= 0; } void FasePreparacao() { RDPC; RDM; IMAR; WRIR; WRREL; if (IR3) { // 2 bytes RDM; IMAR; WRPC; WRMAR; } else WRPC; // 1 byte }

20 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 20 void FaseExecucao() { switch (cpu.ir) { case MOVA: RDM; WRA; break; case MOVM:RDA; WRM; break; case _SJMP: ADDREL;break; case LJMP: WRPC;break; case ADDC: case SUBB: RDM; AU; break; case _CJNC: RDM; WRTMP; WRTCY; CLRC; AU; if (!cpu.cy) ADDREL; RDTMP; RDTCY; break; case _CJZ:RDM;WRTMP; WRTCY; CLRC; AU; if (cpu.a) ADDREL; RDTMP; RDTCY; break; case SETBC:SETC; break; case CLRBC:CLRC;break; default:break; }

21 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 21 void CpuRun() { for(;;) { FasePreparacao(); FaseExecucao(); } void main() { InitRam(); // faz load do programa em RAM ResetCPU(); // simula a activação do reset do CPU CpuRun(); // run ao CPU } ///////////////////// FIM do programa em C ///////////////////////// Programa em C++ ///////////////////////////////////////////////////// ficheiro CPU.H //////////////////////////////////////////// // tipo byte e word #define byte unsigned char #define word unsigned int // definição da sintaxe das instruções para introdução do programa #define MOVA0x08 #define MOVM0x09 #define _SJMP0x04 #define SJMP(R)(_SJMP | ((R & 0x0F) << 4)) #define LJMP0x0C #define ADDC0x0A #define SUBB0x0B #define _CJNC0x0D

22 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 22 #define CJNC(R)(_CJNC | ((R & 0x0F) << 4)) #define _CJZ0x0F #define CJZ(R)(_CJZ | ((R & 0x0F) << 4)) #define SETBC0x00 #define CLRBC0x01 class Registo { protected: byte r; public: byte OE() { return r; } void PL(const byte d) { r= d; } }; class Contador : public Registo { public: void CLR() { r= 0; } void UP() { ++r; } void DWN() { --r; } }; class RAM { Registo ram[256]; void LoadPrograma(); public: RAM () { LoadPrograma(); } byte Read(const byte end) { return ram[end].OE(); } void Write(const byte end, const byte dados) { ram[end].PL(dados); } }; class ALU { word aux; public: void run(Registo&, Registo&, Registo&, bool&); };

23 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 23 class CPU { Registo mbr, rel, ir, tmp, a; Contador mar, pc; bool cy, tcy; RAM& mem; ALU au; // definição dos operadores simples void RDPC() { mar.PL(pc.OE()); } void RDM() { mbr.PL(mem.Read(mar.OE())); } void IMAR() { mar.UP(); } void WRIR() { ir.PL(mbr.OE() & 0x0F); } void WRREL() { rel.PL(mbr.OE() >> 4); } void WRMAR() { mar.PL(mbr.OE()); } void WRPC() { pc.PL(mar.OE()); } void WRA() { a.PL(mbr.OE()); } void RDA() { mbr.PL(a.OE()); } void WRM() { mem.Write(mar.OE(), mbr.OE()); } void ADDREL() { pc.PL(pc.OE() + ((rel.OE() & 0x08)? rel.OE() | 0xF0 : rel.OE())); } void SETC() { cy= true; } void CLRC() { cy=false; } void WRTMP() { tmp.PL(a.OE()); } void RDTMP() { a.PL(tmp.OE()); } void WRTCY() { tcy= cy; } void RDTCY() { cy= tcy; } // as duas fases distintas de uma instrução do CPU void FasePreparacao(); void FaseExecucao(); public: CPU(RAM& m):mem(m) { pc.CLR(); } void Run(); }; /////////// fim do ficheiro CPU.H ///////////////

24 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 24 #include "CPU_cpp.h" void RAM::LoadPrograma() {// Exemplo: Colocar na posição de memória com o endereço 0CH // o maior valor das posições de memória 0AH e 0BH // código em 0 ram[0x00].PL(MOVA); ram[0x01].PL(0x10); ram[0x02].PL(CJNC(+2)); ram[0x03].PL(0x11); ram[0x04].PL(MOVA); ram[0x05].PL(0x11); ram[0x06].PL(MOVM); ram[0x07].PL(0x12); ram[0x08].PL(SJMP(-1)); // dados inicializados em 0x10 ram[0x10].PL(0xFE); ram[0x11].PL(0xFF); // variável de saída em 0x12 } void CPU::FasePreparacao() {RDPC(); RDM(); IMAR(); WRIR(); WRREL(); if (ir.OE() & 0x08) { // 2 bytes RDM(); IMAR(); WRPC(); WRMAR(); } else WRPC(); // 1 byte }

25 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 25 void ALU::run(Registo& a, Registo& mbr, Registo& ir, bool& cy) {if (ir.OE() & 0x01) { aux= a.OE() - mbr.OE() - cy; cy= a.OE() < (mbr.OE() + cy); } else { aux= a.OE() + mbr.OE() + cy; cy= aux > 0xFF; } a.PL(aux); } void CPU::FaseExecucao() { switch (ir.OE()) { case MOVA: RDM(); WRA(); break; case MOVM: RDA(); WRM(); break; case _SJMP: ADDREL(); break; case LJMP: WRPC(); break; case ADDC: case SUBB:RDM(); au.run(a, mbr, ir, cy); break;

26 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 26 case _CJNC:RDM(); WRTMP(); WRTCY(); CLRC(); au.run(a, mbr, ir, cy); if (!cy) ADDREL(); RDTMP(); RDTCY(); break; case _CJZ:RDM(); WRTMP(); WRTCY(); CLRC(); au.run(a, mbr, ir, cy); if (a.OE()==0) ADDREL(); RDTMP(); RDTCY(); break; case SETBC:SETC(); break; case CLRBC:CLRC(); break; default:break; } void CPU::Run() { for(;;) { FasePreparacao(); FaseExecucao(); } void main() {RAM m;// criação da memória CPU x(m);// criação do CPU associando-lhe uma memória x.Run(); // run ao CPU } //////////////// fim do ficheiro CPU.CPP ////////////////////

27 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 27 Programa em JAVA sem interface gráfica /// início do ficheiro Registo.java package CPUX; public class Registo { // variáveis protected int valor; // construtor public Registo() { valor= 0; } // métodos public int OE() { return valor; } public void PL(int v) { valor= v & 0xFF; } } /// fim de ficheiro /// início do ficheiro Instrucao.java package CPUX; public interface Instrucao { // definição da código das instruções para introdução do programa int MOVA= 0x08; int MOVM= 0x09; int SJMP= 0x04; int LJMP= 0x0C; int ADDC= 0x0A; int SUBB= 0x0B; int CJNC= 0x0D; int CJZ= 0x0F; int SETC= 0x00; int CLRC= 0x01; public abstract int CJZ(int op); public abstract int CJNC(int op); public abstract int SJMP(int op); } /// fim de ficheiro ///início do ficheiro Contador.java package CPUX; // import Registo.*; public class Contador extends Registo { public Contador() { valor= 0; } public void CLR() { valor= 0; } public void INC() { ++valor; } public void DEC() { --valor; } } /// fim de ficheiro /// início do ficheiro Flag.java package CPUX; public class Flag { // variáveis private boolean valor; // construtor public Flag() { valor= false; } // métodos public boolean OE() { return valor; } public void CLR() { valor= false; } public void SET() { valor= true; } public void LD(boolean v) { valor= v; } } /// fim de ficheiro

28 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 28 /// início do ficheiro ALU.java package CPUX; public class ALU { private int aux; public void run(Registo a, Registo mbr, Registo ir, Flag cy) { if ((ir.OE() & 1) == 1) { aux= a.OE() - mbr.OE() - (cy.OE()? 1 : 0); cy.LD(aux < 0); } else { aux= a.OE() + mbr.OE() + (cy.OE()? 1 : 0); cy.LD(aux > 0xFF); } a.PL(aux); } } /// fim de ficheiro /// início do ficheiro Memoria.java // classe memória de acesso aleatório package CPUX; public class Memoria { static final int DIM_MEM= 256; private Registo m[]; public Memoria() { m= new Registo[DIM_MEM]; for(int i= 0 ; i

29 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 29 /// início do ficheiro CPU.java package CPUX; import java.lang.*; // classe CPU public class CPU implements Instrucao { // implementação da interface instrucao public int CJZ(int op) { return CJZ | ((op & 0x0F) << 4); } public int CJNC(int op){ return CJNC | ((op & 0x0F) << 4); } public int SJMP(int op){ return SJMP | ((op & 0x0F) << 4); } // registos internos ao CPU private Registo mbr, rel, ir, tmp, a; private Contador mar, pc; private Flag cy, tcy; private Memoria mem; // Unidade Aritmética e Lógica do CPU private ALU au; // definição dos operadores simples privatevoid RDPC() { mar.PL(pc.OE()); } privatevoid RDM() { mbr.PL(mem.Read(mar.OE())); } privatevoid IMAR() { mar.INC(); } privatevoid WRIR() { ir.PL(mbr.OE() & 0x0F); } privatevoid WRREL() { rel.PL(mbr.OE() >> 4); } privatevoid WRMAR() { mar.PL(mbr.OE()); } privatevoid WRPC() { pc.PL(mar.OE()); } privatevoid WRA() { a.PL(mbr.OE()); } privatevoid RDA() { mbr.PL(a.OE()); } privatevoid WRM() { mem.Write(mar.OE(), mbr.OE()); } /// continua /// continuação privatevoid ADDREL() { pc.PL(pc.OE() + (((rel.OE() & 0x08)==0x08)? rel.OE() | 0xFFFFFFF0 : rel.OE())); } privatevoid SETCY() { cy.SET(); } privatevoid CLRCY() { cy.CLR(); } privatevoid WRTMP() { tmp.PL(a.OE()); } privatevoid RDTMP() { a.PL(tmp.OE()); } privatevoid WRTCY() { tcy.LD(cy.OE()); } privatevoid RDTCY() { cy.LD(tcy.OE()); } public CPU(Memoria m) { mem= m; au= new ALU(); cy= new Flag(); tcy= new Flag(); mar= new Contador(); pc= new Contador(); mbr= new Registo(); rel= new Registo(); ir= new Registo(); tmp= new Registo(); a= new Registo(); } /// continua

30 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 30 /// continuação private void FasePreparacao() { RDPC(); RDM(); IMAR(); WRIR(); WRREL(); if ((ir.OE() & 0x08)==0x08) { // 2 bytes RDM(); IMAR(); WRPC(); WRMAR(); } else WRPC(); // 1 byte } private void FaseExecucao() {switch (ir.OE()) { case MOVA: RDM(); WRA(); break; case MOVM: RDA(); WRM(); break; case SJMP: ADDREL(); break; case LJMP: WRPC(); break; /// continua /// continuação case ADDC: case SUBB: RDM(); au.run(a, mbr, ir, cy); break; case CJNC: RDM(); WRTMP(); WRTCY(); CLRCY(); au.run(a, mbr, ir, cy); if (cy.OE()==false) ADDREL(); RDTMP(); RDTCY(); break; case CJZ: RDM(); WRTMP(); WRTCY(); CLRCY(); au.run(a, mbr, ir, cy); if (a.OE()==0) ADDREL(); RDTMP(); RDTCY(); break; case SETC: SETCY(); break; case CLRC: CLRCY(); break; default: break; } } /// continua

31 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 31 /// continuação public void LoadPrograma() { // Exemplo: Colocar na posição de memória com o endereço 12H // o maior valor das posições de memória 10H e 11H // código em 0 mem.Write(0x00, MOVA); mem.Write(0x01, 0x10); mem.Write(0x02, CJNC(+2)); mem.Write(0x03, 0x11); mem.Write(0x04, MOVA); mem.Write(0x05, 0x11); mem.Write(0x06, MOVM); mem.Write(0x07, 0x12); mem.Write(0x08, SJMP(-1)); // dados inicializados em 0x10 mem.Write(0x10, 0xFE); mem.Write(0x11, 0xFF); // variável de saída em 0x12 } public void Run() { for(;;) { FasePreparacao(); FaseExecucao(); } }/// fim de ficheiro /// início do ficheiro KitXXX.java package CPUX; public class KitXXX { public static void main(String args[]) { // criação da memória Memoria m= new Memoria(); // criação do CPU associando-lhe uma memória CPU x= new CPU(m); // carregar o programa de teste na memoria do Kit x.LoadPrograma(); // run ao CPU x.Run(); } } /// fim de ficheiro

32 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 32 Simulação do CPU, DMA e RAM com interface gráfica em JAVA Algumas considerações devem ser realizadas antes da apresentação do código do programa em Java devido à simulação aqui descrita diferir nalguns conceitos e em complexidade relativamente ao anteriormente apresentado. Em primeiro lugar o que é um DMA? DMA é a sigla abreviada do termo anglo-saxónico Direct Memory Access que em português traduz um dispositivo de acesso directo a uma memória. Por outras palavras é uma máquina hardware (previamente descrita no ponto sistema de acesso a uma memória) que permite a leitura ou a escrita numa memória. A segunda questão que se coloca é: como dois dispositivos físicos podem aceder à mesma memória? O problema do acesso múltiplo de duas máquinas hardware a um mesmo dispositivo de memória consiste na partilha física dos barramentos de dados, endereço e controlo que em caso de simultaneidade temporal no acesso poria em risco a integridade física das respectivas máquinas. A solução simples deste problema passa por estabelecer um protocolo físico entre as duas máquinas designado por HOLD/HLDA (abreviatura de hold/hold acknowledge). A ideia deste protocolo é baseada no facto de existir uma máquina que por defeito acede à memória, designada por sistema Mestre (Master em inglês) e a outra máquina que pretende o acesso à memória é designada por sistema Escravo (Slave em inglês). Este protocolo estabelece uma hierarquia de acesso à memória por hardware designada por Mestre-Escravo. O sinal físico Hold é uma entrada do sistema Mestre e é uma saída do sistema Escravo, permitindo ao Escravo indicar ao Mestre que pretende aceder à memória. Existe o sinal HLDA (HoLD Acknowledge) que é uma saída do sistema Mestre e uma entrada no sistema Escravo que indica ao sistema Escravo que o Mestre libertou os barramentos e que este pode aceder aos barramentos. Quando o sistema Escravo deixa de aceder aos barramentos por ter executado todas as suas tarefas descativa o sinal Hold e o sistema Mestre ao detectar a desactivação deste sinal também desactiva o sinal HLDA passando a aceder novamente à memória.

33 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 33 Em termos gráficos pode-se descrever do seguinte modo o acesso à memória função do protocolo HOLD/HLDA: HOLD HLDA Acesso do Master Acesso do Slave Acesso do Master Master HOLD HLDA HOLD HLDA Memória AB DBCB DB AB CB Slave CPUDMA

34 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais CPU Nota: Na figura, o ESA do CPU foi redesenhado tendo em atenção que originará uma máquina de estados hardware o que faz corresponder a cada nível de acções um número que é o identificador de estado. 0 ESA AU(IR 0 =0 +) IR 3 1 (1 byte) (2 bytes) Fase de Preparação case instrução MOV A,end 8 MOV end 8, A SJMP rel 4 LJMP end 8 ADDC A, end 8 Fase de Execução RDM RDPCIMARWRREL WRIR WRPCRDMIMARWRPCWRMARWRARDAWRMADRELWRPCRDM AU(IR 0 =1 -) SUBB A, end 8 RDM CJNC A, end 8, rel 4 CJZ A, end 8, rel 4 SETB CCLR C RDMWRTMPWRTCYCLRC AU(IR 0 =1 -) RDMWRTMPWRTCYCLRC AU(IR 0 =1 -) 0 Cy 1 ADREL RDTMPRDTCY 1 A=0 0 ADREL RDTMPRDTCY CLRCSETC HOLD HOLDA

35 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 35 A 8 EFI IR 4 MAR 8 Memória 256x8 PC 8 WRM RDM RDA WRA RDPC WRPC IMAR WRIR Inst. ADDREL MBR 8 44 Flag Cy AU 1 CLRC SETC RESET(ext.) TMP 8 WRTMP RDTMP REL 4 1 WRMAR 1 WRRELFlag TCy RDTCY WRTCY Flag HoldFlag HldA 10 SETHOLDACLRHOLDA 1 0 I I I I I I I I I I I +1 I I (ext.) SETHOLD (ext.) CLRHOLD Nota: Ao EFI foi acrescentado as flags Hold e HoldA.

36 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 36 Neste ponto, apresenta-se um sistema software desenvolvido em Java que implementa a arquitectura ilustrada. A interface é gráfica e é composta por 3 janelas, cada uma das quais ilustra ao raio-x o conteúdo de cada dispositivo permitindo o utilizador interagir com o DMA e com o modo de funcionamento do CPU. O sistema é composto por três componentes Memória, DMA e CPU que são implementados utilizando os seguintes ficheiros e classes: Sistema KitXXX.java – define a classe KitXXX que tem o método main e que aglotina todos os dispositivos físicos do sistema. Memória Memoria.java - define a classe Memória e as acções de leitura e escrita sobre o dispositivo. E também inclui o suporte da interface gráfica. DMA DMA.java – define um DMA e todos os registos e sinais que o utilizador pode manipular para concretizar a escrita e a leitura da memória. CPU CPUComInterface.java – define a classe com o mesmo nome que implementa a interface gráfica do CPU. Flag.java – define a classe Flag que implementa um flip-flop e os respectivos métodos de manipulação. Registo.java – define a classe Registo bem como os métodos de operação. Contador.java – a classe Contador aumenta a operacionalidade do Registo tal como em hardware. ALU.java – define uma classe ALU que permite realizar operações aritméticas ou lógicas. InstrucaoRegistos.java – define uma interface abstracta designada InstrucaoRegistos aonde se identificam os recursos físicos do CPU, tais como flags, registos, contadores... CPU.java – define a classe CPU que contém toda a arquitectura interna do CPU definida pelo projectista em Basic Schemata e que serve para provar a sua correcção. Nota: O aluno só deve alterar ou interferir na classe CPU e na interface InstrucaoRegistos.

37 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 37 // Ficheiro KitXXX.java package CPUX; public class KitXXX { public static void main(String args[]) { // criação da memória Memoria m= new Memoria(); // criação do DMA associando-lhe uma memória DMA d= new DMA(m); // criação do CPU associando-lhe uma memória CPUComInterface x= new CPUComInterface(m); for (;;){ x.Hold(d.Hold()); // ligar o hold do DMA ao hold do CPU d.Holda(x.Holda()); // ligar o holda do CPU ao holda do DMA } // fim de ficheiro // continuação do ficheiro Memoria.java private String Int2Hex(int v){ return new String(Integer.toHexString(v)); } public Memoria() { // inicialização das posições de memória m= new Registo[DIM_MEM]; for(int i= 0 ; i

38 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 38 // ficheiro DMA.java package CPUX; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DMA { private Memoria mem; private Flag holda; int estado; // interface gráfica Frame janela; Panel quadro; Button next, strobe; Label label_mbr, label_mar, label_holda; TextField mbr, mar; Checkbox hold; // variáveis para simular o clock do DMA final static int TCLOCK= 200; // 200 mse ActionListener Lclock; Timer clock; private void Run(){ switch (estado) { case 1: if (holda.OE()) estado=2; break; case 2: mbr.setText(Integer.toHexString( String2Int(mbr.getText()))); mar.setText(Integer.toHexString( String2Int(mar.getText()))); mem.Write(String2Int(mar.getText()), String2Int(mbr.getText())); estado=0; break; default: break; } label_holda.setText("HOLDA:" + ((holda.OE())? "1" : "0")); } // continua // Continuação do ficheiro DMA.java public DMA(Memoria m) { // recursos mem= m; holda= new Flag(); // grafismos janela= new Frame(); quadro= new Panel(); janela.setBackground(Color.green); janela.add(quadro); janela.setTitle("DMA"); janela.setBounds(140, 0, 200, 120); label_mbr= new Label("MBR:"); quadro.add(label_mbr); mbr= new TextField("00"); mbr.setColumns(2); mbr.setBackground(new Color(150, 255, 0)); quadro.add(mbr); label_mar= new Label("MAR:"); quadro.add(label_mar); mar= new TextField("00"); mar.setColumns(2); mar.setBackground(new Color(200, 255, 0)); quadro.add(mar); hold= new Checkbox("HOLD"); quadro.add(hold); label_holda= new Label(""); quadro.add(label_holda); FlagsRefresh(); next= new Button("Next"); quadro.add(next); strobe= new Button("STROBE"); quadro.add(strobe); TratarEventos(); janela.show(); } public boolean Hold() { return hold.getState(); } public void Holda(boolean h) { holda.LD(h); } // continua // Continuação do ficheiro DMA.java private void FlagsRefresh(){ } private void IncMar(){ int i= String2Int(mar.getText()); mar.setText(Integer.toHexString(++i)); } private int String2Int(String s){ int i; try { i= Integer.parseInt(s, 16) & 0xff; } catch (NumberFormatException e) { return 0xff; } return i; } private void TratarEventos() { // next next.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { IncMar(); }}); // strobe strobe.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (hold.getState()) estado=1; }}); // clock DMA Lclock= new ActionListener() { public void actionPerformed(ActionEvent e) { Run(); } }; clock= new Timer(TCLOCK, Lclock); clock.start(); } // Fim de Ficheiro

39 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 39 // Ficheiro CPUComInterface.java package CPUX; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class CPUComInterface extends CPU{ Frame janela; Label display_flags[], display_contadores[], display_registos[]; Label display_estado, display_clocks, display_fase; Button next, reset, power_down; Checkbox run; Contador nclocks; int estado_execucao; // variáveis para a simulação do clock do CPU final static int TCLOCK= 1000; // 1000 mseg= 1seg ActionListener Lclock; Timer clock; public void TratarEventos() { // next next.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!run.getState()){ nclocks.INC(); Run(); VisualizarRecursos(); } }}); // power down power_down.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); // reset reset.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { nclocks.CLR(); Reset(); VisualizarRecursos(); } }); // clock CPU Lclock= new ActionListener() { public void actionPerformed(ActionEvent e) { if (run.getState()){ if (!f[HOLDA].OE()) { nclocks.INC(); Run(); VisualizarRecursos(); } else Run(); } } }; clock= new Timer(TCLOCK, Lclock); clock.start(); } // continuação de CPUComInterface.java public CPUComInterface(Memoria m) { nclocks= new Contador(); CriaRecursos(m); estado_execucao= MenorEstado(DecoderInstrucao); janela= new Frame("CPU"); janela.setBackground(new Color(100, 100, 255)); janela.setTitle("CPU: Unidade de Processamento Central"); janela.setBounds(340, 0, NREGISTOS*100, 150); Panel norte= new Panel(); display_fase= new Label(); norte.add(display_fase); display_estado= new Label(); norte.add(display_estado); display_clocks= new Label(); norte.add(display_clocks); janela.add("North", norte); next= new Button(" Next "); janela.add("East", next); reset= new Button(" RESET "); janela.add("West", reset); Panel centro= new Panel(); display_flags= new Label[NFLAGS]; for(int i= 0 ; i= estado_execucao)? "Fase de Execução " : "Fase de Preparação"; display_fase.setText(s); janela.show(); } private int MenorEstado(int di[]){ int menor= Integer.MAX_VALUE; for(int i= 0 ; i< di.length ; ++i) if ((di[i]!= 0) && (di[i]< menor)) menor= di[i]; return menor; } // continua

40 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 40 // Ficheiro Flag.java package CPUX; import java.awt.*; public class Flag { // variáveis private String nome; private Color cor; private boolean valor; // construtor public Flag() { valor= false; cor= Color.black; } public Flag(String n){ nome= new String(n); valor= false; cor= Color.black; } // métodos public String Nome() { return nome; } public void Cor(Color c) { cor= c; } public Color Cor() { return cor; } public boolean OE() { cor=Color.green; return valor; } public void CLR() { cor= Color.yellow; valor= false; } public void SET() { cor= Color.yellow; valor= true; } public void LD(boolean v) { cor= Color.red; valor= v; } } // fim de ficheiro // Ficheiro Registo.java package CPUX; import java.awt.*; public class Registo { // variáveis protected String nome; protected Color cor; protected int valor; // construtor public Registo() { valor= 0; cor=Color.black; } public Registo(String n) { nome= new String(n); valor= 0; cor= Color.black; } // métodos protected String Nome() { return nome; } protected void Cor(Color c) { cor= c; } protected Color Cor() { return cor; } public int OE() { if (cor==Color.black) cor= Color.green; return valor; } public void PL(int v) { cor=Color.red; valor= v & 0xFF; } } // fim de ficheiro // Ficheiro Contador.java package CPUX; import java.awt.*; // import Registo.*; public class Contador extends Registo { public Contador() { } public Contador(String n) { nome= new String(n); } public void CLR() { cor= Color.yellow; valor= 0; } public void INC() { cor= Color.yellow; valor= ++valor & 0xff; } public void DEC() { cor= Color.yellow; valor= --valor & 0xff; } }

41 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 41 // Ficheiro ALU.java package CPUX; public class ALU { private int aux; public void run(Registo a, Registo mbr, Registo ir, Flag cy) { if ((ir.OE() & 1) == 1) { aux= a.OE() - mbr.OE() - (cy.OE()? 1 : 0); cy.LD(aux < 0); } else { aux= a.OE() + mbr.OE() + (cy.OE()? 1 : 0); cy.LD(aux > 0xFF); } a.PL(aux); } // fim de ficheiro // ficheiro InstrucaoRegistos.java package CPUX; public interface InstrucaoRegistos { /* definição da código das instruções existentes no CPU int MOVA= 0x08; int MOVM= 0x09; int SJMP= 0x04; int LJMP= 0x0C; int ADDC= 0x0A; int SUBB= 0x0B; int CJNC= 0x0D; int CJZ= 0x0F; int SETC= 0x00; int CLRC= 0x01; */ // descodificador de instrução int [] DecoderInstrucao={27,28,0,0,13,0,0,0,9,11,15,15,14,17,0,22}; // identificação dos registos int MBR= 0; int REL= 1; int IR= 2; int TMP= 3; int A= 4; int NREGISTOS= 5; // identificação dos contadores int ESTADO= 0; int MAR= 1; int PC= 2; int NCONTADORES= 3; // identificação de flags int CY= 0; int TCY= 1; int HOLD= 2; int HOLDA= 3; int NFLAGS= 4; } // fim de ficheiro

42 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 42 // ficheiro CPU.java package CPUX; import java.lang.*; public class CPU implements InstrucaoRegistos { // registos internos ao CPU protected Registo r[]; protected Contador c[]; protected Flag f[]; protected Memoria mem; // Unidade Aritmética e Lógica do CPU private ALU au; // definição dos operadores simples private void IESTADO() { c[ESTADO].INC(); } private void CLRESTADO() { c[ESTADO].CLR(); } protected int RDESTADO() { return c[ESTADO].OE(); } private void WRESTADO(int v) { c[ESTADO].PL(v); } private void CLRPC() { c[PC].CLR(); } private void RDPC() { c[MAR].PL(c[PC].OE()); } private void RDM() { r[MBR].PL(mem.Read(c[MAR].OE())); } private void IMAR() { c[MAR].INC(); } private void WRIR() { r[IR].PL(r[MBR].OE() & 0x0F); } private int RDIR() { return r[IR].OE(); } private boolean IR3() { return (r[IR].OE() & 0x08) == 0x08;} private void WRREL() { r[REL].PL(r[MBR].OE() >> 4); } private void WRMAR() { c[MAR].PL(r[MBR].OE()); } private void WRPC() { c[PC].PL(c[MAR].OE()); } private void WRA() { r[A].PL(r[MBR].OE()); } private void RDA() { r[MBR].PL(r[A].OE()); } private boolean AZERO() { return r[A].OE()==0; } private void WRM() { mem.Write(c[MAR].OE(), r[MBR].OE()); } private void ADDREL() { c[PC].PL(c[PC].OE() + (((r[REL].OE() & 0x08)==0x08)? r[REL].OE() | 0xFFFFFFF0 : r[REL].OE())); } private void SETCY() { f[CY].SET(); } private void CLRCY() { f[CY].CLR(); } private boolean RDCY() { return f[CY].OE(); } private void WRTMP() { r[TMP].PL(r[A].OE()); } private void RDTMP() { r[A].PL(r[TMP].OE()); } private void WRTCY() { f[TCY].LD(f[CY].OE()); } // continua // continuação private void RDTCY() { f[CY].LD(f[TCY].OE()); } private void CLRHOLDA() { f[HOLDA].CLR(); } private void SETHOLDA() { f[HOLDA].SET(); } public boolean RDHOLDA(){ return f[HOLDA].OE(); } private boolean RDHOLD(){ return f[HOLD].OE(); } public void WRHOLD(boolean v){ f[HOLD].LD(v); } public CPU(){ } // continua

43 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 43 // continuação do ficheiro CPU.java protected void CriaRecursos(Memoria m) { mem= m; au= new ALU(); // criação de flags f= new Flag[NFLAGS]; f[CY]= new Flag("CY"); f[TCY]= new Flag("TCY"); f[HOLD]= new Flag("HOLD"); f[HOLDA]= new Flag("HOLDA"); // criação de contadores c= new Contador[NCONTADORES]; c[ESTADO]= new Contador("ESTADO"); c[MAR]= new Contador("MAR"); c[PC]= new Contador("PC"); // criação de registos r= new Registo[NREGISTOS]; r[MBR]= new Registo("MBR"); r[REL]= new Registo("REL"); r[IR]= new Registo("IR"); r[TMP]= new Registo("TMP"); r[A]= new Registo("A"); } public void Reset(){ CLRPC(); CLRESTADO(); } // continua // continuação de CPU.java public void Run(){ switch (RDESTADO()) { case 0: // Fase de Preparação if (RDHOLD()) SETHOLDA(); else{ CLRHOLDA(); IESTADO(); }break; case 1: RDPC(); IESTADO(); break; case 2: RDM(); IESTADO(); break; case 3: IMAR(); WRIR(); WRREL(); if (IR3()) IESTADO(); else WRESTADO(6); break; // 2 bytes case 4: RDM(); IESTADO(); break; case 5: IMAR(); IESTADO(); break; case 6: WRPC(); IESTADO(); break; case 7: WRMAR(); WRESTADO(DecoderInstrucao[RDIR()]); break; case 8: WRPC(); WRESTADO(DecoderInstrucao[RDIR()]); break; case 9: // Fase de Execução RDM(); IESTADO(); break; // MOV A, M case 10: WRA(); CLRESTADO(); break; // MOV A, M case 11: RDA(); IESTADO(); break; // MOV M, A case 12: WRM(); CLRESTADO(); break; // MOV M, A case 13: ADDREL(); CLRESTADO(); break; // SJMP rel4 case 14: WRPC(); CLRESTADO(); break; // LJMP end8 case 15: RDM(); IESTADO(); break; // ADDC A, M : SUBB A, M case 16: au.run(r[A], r[MBR], r[IR], f[CY]); CLRESTADO(); break; // ADDC A, M : SUBB A, M case 17: RDM(); WRTMP(); WRTCY(); IESTADO(); break; // CJNC A, M, rel4 case 18: CLRCY(); IESTADO(); break; // CJNC A, M, rel4 case 19: au.run(r[A], r[MBR], r[IR], f[CY]); if (RDCY()) WRESTADO(21); else IESTADO(); break; // CJNC A, M, rel4 case 20: ADDREL(); IESTADO(); break; // CJNC A, M, rel4 case 21: RDTMP(); RDTCY(); CLRESTADO(); break; // CJNC A, M, rel4 case 22: RDM(); WRTMP(); WRTCY(); IESTADO(); break; // CJZ A, M, rel4 case 23: CLRCY(); IESTADO(); break; // CJZ A, M, rel4 case 24: au.run(r[A], r[MBR], r[IR], f[CY]); IESTADO(); if (AZERO()) IESTADO(); else WRESTADO(26); break;// CJZ A, M, rel4 case 25: ADDREL(); IESTADO(); break; // CJZ A, M, rel4 case 26: RDTMP(); RDTCY(); CLRESTADO(); break; // CJZ A, M, rel4 case 27: SETCY(); CLRESTADO(); break; // SETB C case 28: CLRCY(); CLRESTADO(); break; // CLR C }}} // fim de ficheiro

44 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 44 Exercício: Acrescente ao CPU projectado as seguintes instruções. Proceda às alterações da estrutura interna do CPU projectado de modo a que este suporte todo o conjunto de instruções. No programa simulador apenas deve modificar os ficheiros CPU.java e InstrucaoRegistos.java de modo a que respeitem o projecto realizado em termos de ESA e EFI.. Exemplo de programa: Colocar como conteúdo da posição de memória de endereço 12H o maior valor existente entre os conteúdos das posições de memória com endereços 10H e 11H. endereçocódigo hexadecimalinstrução 0: 08, 10MOV A, 10H 2:2D, 11CJNC A, +2, 11H 4:08, 11MOV A, 11H 6:09, 12MOV M, 12H 8:F4SJMP -1

45 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 45 CPU Nesta secção pretende-se estudar o CPU80535 numa perspectiva de programador. Assumindo-se que este já tem ao seu dispor uma arquitectura de desenvolvimento baseada no CPU Deste modo, o programador tem de conhecer os aspectos principais da estrutura interna do CPU, tais como, a organização de memória, os modos de endereçamento e as instruções para lhe permitir o começo do desenvolvimento de programas de aplicação. De seguida vamos abordar todos estes aspectos. Organização de memória Memória Externa Memória de Código 0H FFFFH Algumas características a ter em conta: Address Bus externo – 16 bits Data Bus – 8 bits Instruções de 1, 2 ou 3 bytes de dimensão.

46 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 46 Modelo da Memória de Dados Memória Externa de dados 0H FFFFH 0H 7FH 80H FFH 128 bytes de RAM interna IDATA 128 bytes de RAM Interna IDATA 80H FFH Registos especiais Internos DATA DPTR 16 bits Ex: A End. directo Ex: MOV A, #80H End. directo End. indirecto Ri 8 bits Ex: A Port 2 8 bits Ex: A Ex: MOV Ex: MOV 1, A 128 bytes de RAM interna DATA Memória Física Partilhada pelos segmentos Data e IData XDATA Memória Interna de dados

47 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 47 00H 7FH 128 bytes de RAM interna (parte baixa) Memória de Dados Interna (endereços baixos) 30H 7FH Uso geral 2FH 20H Registos com manipulação ao bit BIT 7F 7E 7D 7C 7B 7A R0 R1 R2 R3 R4 R5 R6 R7 RB0 RB1 RB2 RB3 00H 07H 08H 0FH 10H 17H 1FH 18H

48 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 48 B – registo B Acc - Acumulator – bit ou byte P6 – Port 6 – acesso ao bit ou byte ADDAT – A/D Converter Data ADCON – A/D Converter Control – b/b PSW – Program Status Word – bit/byte TL2 – Timer 2, low byte P4 – Port 4 – acesso ao bit ou byte CRCH – Compare/Reload/Capture, high TH2 – Timer 2, high byte CRCL – Compare/Reload/Capture, low CCH3 – Compare/Capture reg3, high CCH2 – Compare/Capture reg2, high DAPR – D/A Converter Program Reg. CCL2 – Compare/Capture reg2, low P5 – Port 5 – acesso ao bit ou byte CCL1 – Compare/Capture reg. 1, low CCEN – Compare/Capture Enable IP1 – Interrupt Priority 1 IRCON – Interrupt Request Control IEN1 – Interrupt Enable 1 – bit ou byte P3 – Port 3 – acesso ao bit ou byte IP0 – Interrupt Priority 0 IEN0 – Interrupt Enable 0 – bit ou byte 80H FFH Registos especiais internos Registos especiais internos P0 – Port 0 – acesso ao bit ou byte80H SP – Stack Pointer81H DPL – Data Pointer Low82H DPH – Data Pointer High83H PCON – Power Control87H TCON – Timer Control88H TMOD –Timer Mode89H TL0 – Timer 0, low byte8AH TL1 – Timer 1, low byte8BH TH0 – Timer 0, high byte8CH TH1 – Timer 1, high byte8DH P1 – Port 1 – acesso ao bit e byte90H SCON –Serial Control- bit ou byte98H SBUF – Serial buffer99H P2 – Port 2 – acesso ao bit ou byteA0H A8H A9H B0H B8H B9H C0H C1H C2H CCH1 – Compare/Capture reg1, highC3H C4H C5H CCL3 – Compare/Capture reg3, lowC6H C7H T2CON – Timer 2 ControlC8H CAH CBH CCH CDH D0H D8H D9H DAH DBH E0H E8H F0H F8H

49 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 49 Instruções do 80535

50 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 50

51 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 51

52 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 52

53 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 53 Algumas notas: Rn – qualquer registo desde R0 até R7. Ri – registos R0 e R1. Directo, directo d, directo f – RAM interna desde 00H até 7FH, Portos 0 a 6, qualquer registo de status e control. bit – qualquer dos 128 bits da memória interna, qualquer bit dos Portos, qualquer bit de status e control. A – acumulador. MX – posição de memória externa. MC – posição de memória de código (externa ou interna). relativo8 – valor a 8 bits entendido a código de complementos. endereço16 – valor a 16 bits entendido como um endereço. endereço11 – valor a 11 bits entendido como um endereço constante8 – valor a 8 bits.

54 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 54 Conjunto de instruções do 80535

55 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 55 Programas de Aplicação Exercício 1: Faça um programa que determine o maior de 2 números do tipo byte. i. Os 2 números encontram-se respectivamente nas posições de memória externa 10H e 11H. O resultado deve ser colocado na posição de memória externa 12H. ii. Os 2 números encontram-se respectivamente nas posições de memória interna 10H e 11H. O resultado deve ser colocado na posição de memória interna 12H. Exercício 2: Faça um programa que inicializa uma tabela de 200 bytes. Cada byte da tabela deve ser inicializado com um valor igual ao do seu índice na tabela. Exercício 3: Faça um programa que simule uma Unidade Aritmética e Lógica com a funcionalidade ilustrada na seguinte tabela:

56 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 56 Resolução dos exercícios Antes de se realizar um programa numa qualquer linguagem de programação seja ela de alto nível (Pascal, C, C++, Java) ou de baixo nível (Assembly51, Assembly86, etc), em primeiro lugar deve-se sempre realizar o algoritmo utilizando uma linguagem gráfica tipo fluxograma ou program graph e depois então implementar o algoritmo na linguagem de programação pretendida. Vamos então seguir esta estratégia na resolução dos nossos exercícios utilizando em primeiro lugar a linguagem gráfica program graph para a descrição do algoritmo e em segundo lugar então proceder-se-á à codificação do algoritmo em Assembly51. Exercício 1: (10H) > (11H) (12H) = (11H) FT (12H) = (10H) Programa1_i SEGMENT CODE RSEG Programa1_i Maiorde2: MOV DPTR, #10H MOVR7, A; R7 = (10H) INCDPTR A= (11H) CLRC SUBBA, R7; A= (11H)-(10H) JNCELSE_IF THEN_IF:MOVA, R7 INCDPTR A SJMP FIM_IF ELSE_IF:ADDCA, R7; repor o valor de A INCDPTR A FIM_IF:SJMP$; forever: fim do programa

57 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 57 O programa anterior introduz algumas directivas novas do programa tradutor ASM51.EXE que passaremos a descrever. SEGMENT – define um segmento ou um troço de código ou dados consoante seja do tipo CODE ou XDATA e IDATA. A sintaxe é: NOME SEGMENT TIPO_SEGMENT No qual, NOME – identifica um conjunto de caracteres ou dígitos começados por letra. TIPO_SEGMENT – pode ser uma das seguintes palavras chave: CODE : identifica o segmento como de código. XDATA : o segmento é de dados (DATA) existentes na memória externa ao CPU. IDATA: as variáveis aqui definidas existem na memória interna do CPU. RSEG – define o segmento como relocalizavel, ou seja, o endereço do código ou das variáveis definidas num segmento com este atributo não têm um endereço absoluto. A sintaxe é: RSEG NOME Esclarecidas as directivas e analisado o programa Programa_i é fácil verificar que este poderia ser optimizado pois as instruções finais do THEN_IF e do ELSE_IF são comuns logo poderiam ser retiradas e passadas para o ramo FIM_IF. Exercício: Optimize o código do Programa1_i.

58 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 58 Programa1_ii SEGMENT CODE RSEG Programa1_ii Maiorde2: MOV A, 11H CLRC SUBBA, 10H; A= (11H)-(10H) JNCELSE_IF THEN_IF:MOV12H, 10H SJMP FIM_IF ELSE_IF:MOV12H, 11H FIM_IF:SJMP$; forever: fim do programa A solução para o exercício 1.ii é dado pelo programa Programa1_ii. O código é consideravelmente mais simples e mais fácil de perceber. Assim, sempre que se puder utiliza-se variáveis definidas na memória interna. Tendo realizado os programas anteriores,como é que se poderá testá-los no kit SAB Em primeiro lugar tem de se saber aonde está disponível a memória de desenvolvimento RAM. Sem grandes preocupações dos porquês, admita que a RAM está disponível entre os endereços 0000H e 7FFFH. Pois, em breve iremos estudar a arquitectura interna do kit SAB Em segundo lugar terá de se perceber o ambiente de desenvolvimento a utilizar, que é composto por um qualquer editor de texto e pelos programas ASM51, L51 e OH51. A seguinte figura pretende elucidar os passos requeridos até termos produzido um ficheiro com extensão.HEX que deve ser carregado na memória do kit.

59 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 59 Editor de Texto FICHEIRO.A51 A51.EXE FICHEIRO.LSTFICHEIRO.OBJ L51.EXE FICHEIRO.M51 FICHEIRO OHS51.EXE FICHEIRO.HEX Há erros FICHEIRO1.A51 FICHEIRON.A51 FICHEIRO1.OBJ FICHEIRON.OBJ Módulos Módulo Principal

60 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 60 Segue-se uma breve explicação da figura anterior. Em primeiro lugar deve-se criar um ou mais ficheiros de texto com extensão.A51 utilizando um editor. De seguida, deve-se utilizar o programa tradutor e analisador sintáctico ASM51.EXE de Assembly51 para gerar os ficheiros com extensão.OBJ e.LST, a sintaxe é: A51 FICHEIRO.A51 DEBUG Depois de gerarmos todos os ficheiros.OBJ sem erros sintácticos vamos agrupar todos os segmentos existentes nos nossos ficheiros assim como localizá-los em determinados endereços. Um exemplo possível é o seguinte comando: L51 FICHEIRO.OBJ, FICHEIRO1.OBJ,..., FICHEIRON.OBJ XDATA(2000H) IDATA(30H) CODE(4000H) DATA(60H) BIT(00H) DEBUGSYMBOLS aonde se está a agrupar todos os segmentos XDATA, IDATA e CODE existentes nos n+1 ficheiros do comando. Cada segmento tem como endereço inicial o valor hexadecimal dado como parâmetro. Assim, o segmento XDATA começa em 2000H, IDATA em 30H, CODE em 4000H, etc. De notar que este comando é apenas um exemplo possível, podendo-se variar os valores de inicio de cada segmento. Este comando gera um ficheiro sem extensão com nome igual ao do primeiro ficheiro dado como parâmetro. Por fim para gerarmos o ficheiro com extensão.HEX temos de executar o comando: OHS51 FICHEIRO terminando-se então todos os passos necessários para se obter um ficheiro que se pode carregar na memória RAM do kit

61 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 61 Voltemos aos exercícios: Exercício 2: ; tabela existente na memória externa Programa2 SEGMENT CODE RSEG Programa2 IniciarTabela: MOVDPTR, #Tabela CLRA LOOP: A INC DPTR INC A CJNE A, #DIM, LOOP SJMP$ DadosSEGMENT XDATA RSEG Dados DIMEQU 200 Tabela:DS DIM END ; tabela existente na memória interna Programa2 SEGMENT CODE RSEG Programa2 IniciarTabela: MOVR0, #Tabela CLRA LOOP: A INC R0 INC A CJNE A, #DIM, LOOP SJMP$ DadosSEGMENT IDATA RSEG Dados DIMEQU 200 Tabela:DS DIM END i= 0 i= i+1 Tabela[i]= i i DIM T F Resolução com a estrutura algorítmica DO WHILE – a tabela tem de ter pelo menos 1 elemento.

62 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 62 Exercício 2: ; tabela existente na memória externa Programa2 SEGMENT CODE RSEG Programa2 IniciarTabela: MOVDPTR, #Tabela CLRA CONDICAO; CJNE A, #DIM, DO SJMPFIM_WHILE DO: A INC DPTR INC A SJMP CONDICAO FIM_WHILE: SJMP$ DadosSEGMENT XDATA RSEG Dados DIMEQU 200 Tabela:DS DIM END ; tabela existente na memória interna Programa2 SEGMENT CODE RSEG Programa2 IniciarTabela: MOVR0, #Tabela CLRA CONDICAO: CJNE A, #DIM, DO SJMPFIM_WHILE DO: A INC R0 INC A SJMPCONDICAO FIM_WHILE: SJMP$ DadosSEGMENT IDATA RSEG Dados DIMEQU 200 Tabela:DS DIM END Resolução com a estrutura algorítmica WHILE DO – a tabela pode ter 0 ou mais elementos. i= 0 i= i+1 Tabela[i]= i i DIM T F

63 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 63 Exercício 3: Case S 2 S 1 S 0 R= Op1 + Op2 000 R= Op1 - Op2 001 R= Op1 x Op2 010 R= Op1 / Op2 011 R= R= Op1. Op2 101 R= Op1 or Op2 110 R= Op1/ 111 ; tabela existente na memória interna Programa3 SEGMENT CODE RSEG Programa3 ALU: MOVA, Operacao ANLA, #07H ; multiplicar por 2= sizeof(SJMP) RLA MOVDPTR, #TAB_JMP FIM_CASE: MOVRES, A SJMP $ TAB_JMP: SJMPSOMAR SJMPSUBTRAIR SJMPMULTIPLICAR SJMPDIVIDIR SJMPZERO SJMPINTERSECCAO SJMPUNIAO SJMP NEGACAO ; continua ; continuação SOMAR: MOVA, Op1 ADDA, Op2 SJMPFIM_CASE SUBTRAIR: MOVA, Op1 CLRC SUBBA, Op2 SJMPFIM_CASE MULTIPLICAR: MOVA, Op1 MOVB, Op2 MULAB SJMPFIM_CASE DIVIDIR: MOVA, Op1 MOVB, Op2 DIVAB SJMPFIM_CASE ZERO: MOVA, #0 SJMPFIM_CASE ; continuação INTERSECCAO: MOVA, Op1 ANLA, Op2 SJMPFIM_CASE UNIAO: MOVA, Op1 ORLA, Op2 SJMPFIM_CASE NEGACAO: MOVA, Op1 CPLA SJMPFIM_CASE DadosSEGMENT DATA RSEGDados Operacao:DS 1 Op1:DS 1 Op2:DS 1 RES:DS 1 END

64 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 64 Distinção entre o módulo principal e os restantes módulos No módulo principal deve-se colocar no início a directiva, $TITLE ( Texto do título do programa) Nos módulos secundários deve-se usar a directiva NAME para sua identificação, NAME Nome_do_Módulo Em termos práticos o módulo principal deve conter sempre o entry point ou o endereço inicial do programa. Quando se programa utilizando módulos, tem de se indicar em cada módulo as funções ou variáveis que estão definidas noutros módulos e que são utilizadas no módulo corrente. Para isso, utiliza-se a directiva EXTRN que tem a seguinte sintaxe: EXTRN segmento(lista de símbolos) Exemplo: EXTRN CODE(write_string, read_string) Estamos a indicar que no módulo corrente vamos utilizar duas funções chamadas write_string e read_string que pertencem ao segmento CODE e que estão definidas noutro módulo. Para que estas directivas não indiquem erro no processo de ligação a executar pelo programa l51.exe então deve-se nos módulos aonde estas funções estão definidas utilizando a directiva PUBLIC que tem a seguinte sintaxe, PUBLIC símbolo [, símbolo,...] No nosso exemplo teríamos que definir, PUBLIC write-string, read_string

65 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 65. Definição de stack no O segmento de stack é localizado na RAM interna. Este é usado para guardar o Program Counter (PC) durante as chamada e retorno de funções e rotinas de interrupção. As leituras e escritas no stack são controladas por um registo chamado stack pointer (SP) que faz uma gestão First In Last Out (FILO) ou Last In First Out (LIFO) do segmento de stack. O SP é um registo interno de 8 bits que contém o endereço do último byte a ser guardado no stack. É responsabilidade do programador que o SP tenha um valor válido no espaço de endereçamento do stack (menor que 80H) e que este espaço não é utilizado para outras variáveis. Um exemplo da definição do stack e correspondente inicialização do registo SP poderá ser, DSEG AT 40H ; DATA SEGMENT identifica a memória interna de 00H-7FH DIM_PILHA EQU 40H pilha: DS DIM_PILHA. codigo SEGMENT CODE RSEG codigo MOV SP, #pilha-1 ; porque o primeiro incrementa o SP e depois é que guarda De notar que após uma acção de reset ao CPU o SP fica com o valor 7 que coincide com o R7 do banco 0.

66 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 66 Convenção para Parâmetros de Entrada passados por Registo Tipo char, 1 byte pointerint, word pointerlong, floatPointer 1º parâmetro R7 R6, R7 R4-7R1, R2, R3 2º parâmetro R5 R4, R5 R1, R2, R3 3º parâmetro R3 R2, R3 Quando o nº de parâmetros excede os indicados na anterior tabela então os parâmetros são passados em posições de memória fixas. Convenção para os Parâmetros de Saída de Funções Valor devolvidoRegistoSignificado BitCarry CharR7 IntR6, R7R6 (MSB) e R7 (LSB) LongR4-7R4 (MSB) e R7 (LSB) FloatR4-7R4(MSB) e R7 (LSB) PointerR1, R2, R3R1 – Tipo de memória, R2 – High Offset, R3 – Low Offset Tipo de memória: 1 – IDATA ; 2 – XDATA ; 3 – PDATA ; 4 – DATA ; 5 – CODE Exercício i: Realize uma função que recebe como parâmetro de entrada o endereço de uma StringC residente em XDATA faça a visualização da stringC na consola. Assuma que dispõe de uma função CO com um parâmetro de entrada tipo char e que faz a visualização do carácter na consola. ii. Generalize o parâmetro de entrada de modo à stringC poder residir em qualquer memória.

67 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 67 Significado das flags CY – carry AC – auxiliary carry F0 e F1– a usar pelo utilizador OV – overflow P - paridade par RS 1 RS 0 - Bits de selecção do banco de registos R banco 0, endereços entre 00H e 07H 0 1- banco 1, endereços entre 08H e 0FH 1 0- banco 2, endereços entre 10H e 17H 1 1- banco 3, endereços entre 18H e 1FH Exercício iii : Faça uma função Read_String que tem como parâmetro de entrada o endereço da StringC a ser afectada com o conjunto de caracteres introduzidos pelo teclado. Assuma que tem uma função CI que devolve um valor tipo char correspondente ao último carácter introduzido pelo teclado. Registo de flags Este registo no chama-se Program Status Word (PSW) e pode ser acedido em termos de bits ou ao byte. A informação que contém é a seguinte: CYACF0RS 1 RS 0 OVF1PPSWD0H D7HD6HD5HD4HD3HD2HD1HD0H Endereço do acesso ao byte Endereços de acesso ao bit

68 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 68 Portos paralelo de entrada e saída O CPU disponibiliza 48 sinais digitais de entrada/saída agrupados em 6 portos bidireccionais de 8 bits cada. Os acessos de leitura ou escrita a estes 6 portos são realizados através dos registos de função especial P0 a P5. Genericamente, cada bit consiste num flip-flop tipo D, num driver de saída e num buffer tri-state de entrada, tal como se ilustra na seguinte figura: Q Q/ D Escrita driver de saída Pino do porto Ler Pino Ler flip.flop Bus Interno R N-FET Circuito genérico associado a cada bit dos portos de entrada/saída.

69 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 69 Os drivers de saída dos portos 0 e 2 são diferentes pois também são usados para acesso à memória externa tal como se exemplifica na seguinte figura: O porto 0 multiplexa no tempo a parte baixa do endereço A0-7 com o byte a ser lido ou escrito D0-7, enquanto que o porto 2 define a parte alta do endereço A8-15 sempre que o endereçamento é a 16 bits. Caso contrário, em ambos os portos aparece o conteúdo do registo correspondente. R N-FET 0 1 S Y Q bit de endereço controlo Driver de saída do porto 2. Pino do porto N-FET 0 1 S Y Q/ bit de endereço/dados controlo N-FET Pino do porto Driver de saída do porto 0. Portos 0 e 2

70 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 70 Os portos 1 e 3 são multifuncionais, ou seja, permitem implementar além da funcionalidade de entrada/saída incondicional também os seguintes sinais de entrada/saída alternativos: Porto 1PinoFunção Alternativa P1.0/INT3/CC0Entrada da interrupção 3; Entrada de captura 0; Saída de comparação 0. P1.1INT4/CC1Entrada da interrupção 4; Entrada de captura 1; Saída de comparação 1. P1.2INT5/CC2Entrada da interrupção 5; Entrada de captura 2; Saída de comparação 2. P1.3INT6/CC3Entrada da interrupção 6; Entrada de captura 3; Saída de comparação 3. P1.4/INT2Entrada da interrupção 2. P1.5T2EXEntrada de reload trigger do timer 2. P1.6CLKOUTClock de saída. P1.7T2Entrada externa de clock do contador realizado com o timer 2. Porto 3 P3.0RXDEntrada série de dados em modo assíncrono; entrada/saída série de dados em modo síncrono. P3.1TXDSaída série de dados em modo síncrono; saída de clock em modo síncrono. P3.2/INT0Entrada da interrupção 0; gate de controlo do timer 0. P3.3/INT1Entrada da interrupção 1; gate de controlo do timer 1. P3.4T0Entrada externa de clock do contador realizado com o timer 0. P3.5T1Entrada externa de clock do contador realizado com o timer 1. P3.6/WRSinal de escrita (write/) para a memória externa. P3.7/RDSinal de leitura (read/) para a memória externa. Portos 1 e 3

71 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 71 Na versão MYMOS do CPU80535 o porto 6 define uma interface analógica para o conversor analógico- digital. Na versão ACMOS além da interface analógica também se pode definir entradas digitais. Nesta versão, o porto pode ser tratado como um porto de entrada digital cujo endereço é P6 (0DBH). O circuito completo correspondente a um bit de entrada/saída dos portos 1 e 3 é mostrado na seguinte figura: Após Reset todos os flip-flops dos portos 1 a 5 ficam com o valor lógico 1. Q Q/ D Escrita driver de saída Pino do porto Ler Pino Ler flip.flop Bus Interno R N-FET Sinal de entrada alternativo Sinal de saída alternativo Portos 1 e 3 (continuação) Porto 6

72 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 72 Características Eléctricas dos Portos de Entrada/Saída Os drivers de saída dos portos 1 a 5 podem ser ligados directamente a entradas TTL pois as suas características eléctricas garantem valores lógicos correctos. Para mais informações deve consultar o data sheet do SAB80535 e verificar na secção de características DC os valores correspondentes aos parâmetros V OL e V OH. Os bits do porto 0 quando programados como saída também partilham esta característica. No entanto quando programados como entrada é necessário ligar-lhes pullups para estas não ficarem em alta impedância. A excepção é feita quando os bits do porto 0 estão sendo usados como sinais de endereço ou de dados (address/data bus). Instruções Read-Modify-Write dos portos 0 a 5 Todas as instruções, que têm como destino um porto de entrada/saída ou um bit de um porto, lêem em primeiro lugar o flip-flop de informação correspondente ao bit e não a entrada física do porto. Por exemplo, a instrução ORL P4, #99H lê a informação presente nos 8 flip-flops (latch do porto), modifica o valor e coloca o resultado no latch. Às instruções que em primeiro lugar lêem um ou mais flip-flops depois modificam o seus valores consoante a operação e finalmente actualizam os respectivos flip- flops são chamadas instruções de read-modify-write. Estas instruções são as seguintes: ANLex: ANL P4, #01H ORLex: ORL P3, A XRLex: XRL P5, #0FFH JBCex: JBC P3.1, LOOP CPLex: CPL P3 INCex: INC P5 DECex: DEC P5 DJNZex: DJNZ P4, LOOP MOV ex: MOV P3.2, C CLRex: CLR P3.1 SETBex: SETB P4.0 De salientar que este conjunto de instruções não lê os valores presentes nos pinos físicos dos portos mas sim os respectivos flip-flops.

73 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 73 Flat-Cables SD535 CPU RAMROM P P SD535 Flat-Cable P0.0 AD0 P0.1 AD1 P0.2 AD2 P0.3 AD3 P0.4 AD4 P0.5 AD5 P0.6 AD6 P0.7 AD7 NC AN6 AN7 VCC GND P4.4 P4.5 P4.6 P4.7 P5.0 P5.1 P5.2 P5.3 P5.4 TXM P5.5 RXM P5.6 SELM P5.7 AN0 AN1 AN2 AN3 AN4 AN5 VCC GND A0 A1 A2 A3 A4 A5 A6 A7 A8 P2.0 A9 P2.1 A10 P2.2 A11 P2.3 A12 P2.4 A13 P2.5 A14 P2.6 A15 P2.7 PSEN ALE P3.6 WR/ P3.7 RD/ P1.0 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7 P3.0 RxD P3.1 TxD P3.2 INT0/ P3.3 INT1/ P3.4 T0 P3.5 T1 P3.6 WR/ P3.7 RD/ P4.0 P4.1 P4.2 P4.3 Flat-Cable

74 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 74 Esta técnica de endereçamento que é talvez a mais utilizada no desenvolvimento de microsistemas consiste em dividir o espaço de endereçamento total do CPU, definido pelo seu número de bits de endereçamento externo, em blocos de endereços de semelhante dimensão que são designadas por páginas. Nas páginas inserem-se os dispositivos de memória do microsistema e a dimensão de cada página deve ser concordante com a dimensão do dispositivo de memória nela inserido. Por exemplo, num CPU que tem um barramento de endereços de 16 bits, a organização de páginas é criada pensando no endereçamento total de 64K, dividido em 2 páginas de 32K pelo bit de endereçamento externo A 15 e depois cada página de 32K pode ser dividida em 2 páginas de 16K pelo bit A 14, e assim sucessivamente até obtermos páginas com a dimensão desejada. Esta técnica pode ser ilustrada na seguinte figura: No projecto hardware de microsistemas tem particular importância a atribuição de endereços aos módulos de memória que partilham os barramentos de endereços e dados estabelecidos pelo CPU. Assim, devemos saber qual a dimensão (nº de bits) dos barramentos de endereço e de dados do CPU para depois podermos começar o projecto hardware do microsistema. Os módulos de memória são caracterizados pela dimensão (nº de palavras), pela dimensão das palavras (nº de bits) e por serem memória volátil (RAM) ou não volátil (ROM, PROM, EPROM, EEPROM). De notar que a memória não volátil de um microsistema deve incluir sempre o endereço de reset do CPU. As técnicas de descodificação de endereços num microsistema que iremos estudar são as seguintes: Técnicas para a Descodificação de Endereços num Microsistema Paginação 64K 32K 16K 8K A 15 A 14 A Dimensão das páginas Bits de endereçamento externo Bits responsáveis pela selecção de um dispositivo de memória. Paginação Atribuição contígua Selecção linear

75 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 75 Exemplo: Projecte um circuito descodificador de endereços para um microsistema baseado num CPU de 8 bits com 16 bits de endereços que contém os dispositivos de memória apresentados no seguinte mapa de memória: EPROM 8K RAM 8K Não utilizado 0000H FFFFH 2000H 6000H 4000H 1FFFH 3FFFH 5FFFH End. inicial End. final E S1 S A15 A14 A13 CSEPROM/ CSRAM#1/ CSRAM#2/ Circuito descodificador de endereços Exercício: Acrescente ao microsistema anterior 2 RAMs de 4K cada. Solução:

76 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 76 Atribuição Contígua Esta técnica utiliza-se quando se pretende introduzir um dispositivo de memória de pequena dimensão contiguamente a outros dispositivos de memória com dimensão muito superior. Por exemplo, suponha que pretende realizar o circuito de descodificação de endereços para o seguinte mapa de memória: EPROM 8K ROM 256 RAM 8K 0000H 1FFFH 20FFH 40FFH 2000H 2100H 4100H Não utilizado Solução: Os sinais de selecção da EPROM e ROM são obtidos descodificando os bits de endereçamento externo de cada dispositivo. A solução sem atribuição repetitiva de endereços (chamada tecnicamente de foldback), será: CSEPROM/= A15 + A14 + A13 CSROM/= A15 + A14 + A13/ + A12 + A11 + A10 + A9 + A8 O problema está na realização do CSRAM/ pois a RAM é um dispositivo com 8K que se encontra localizado no início de uma página de 256. Assim sendo, a única solução é relocalizar o dispositivo em termos de endereço. Como? Utilizando um subtractor que permita passar o valor do endereço inicial definido pelos 8 bits de maior peso do endereço cujo valor é 21H para o valor 00H, endereçando-se à RAM com os bits do resultado, como o apresentado na seguinte figura: X0-7 Y0-7 8 S0-7 BW A H RAM 8K A8-A12 A0-A7D0-D7 CS/ OE/ WE/ D0-D7 8 8 A0-A7 8 A A A13-15 WR/ RD/ Nota: O BW do subtractor entra na geração do CS/ da RAM e de eventuais dispositivos de memória que se venham a acrescentar ao sistema para distinguir estes dispositivos dos dispositivos que não são afectados com o problema de estarem inseridos em páginas com dimensão inferior à sua (ex: EPROM e ROM). 8

77 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 77 Selecção Linear Este método de endereçamento consiste em activar o CS/ de cada dispositivo com um bit de endereçamento externo. Este método tem como grande vantagem a simplificação do hardware para a descodificação de endereços. Embora também apresente graves desvantagens tais como: 1. A não contiguidade de endereços atribuídos a cada dispositivo; 2. Limitação no número de dispositivos a inserir que são tantos quantos os bits de endereçamento externo; 3. As instruções do CPU para acesso à memória externa ficam passíveis de seleccionar vários dispositivos simultaneamente. De referir que este tipo de endereçamento utiliza-se em sistemas vocacionados numa fase posterior ao seu desenvolvimento com o objectivo de reduzir os custos de produção. Exemplo: Suponha um microsistema baseado num CPU com 16 bits de endereço e que dispõe de dispositivos RAM e EPROM de 4K. Realize o circuito de descodificação de endereços para o microsistema inserindo o número máximo de dispositivos de memória possível utilizando a técnica de selecção linear. Bits de endereçamento interno: A0-11 Bits de endereçamento externo: A Deste modo, o número máximo de dispositivos permitido são 4. Cada um deles é seleccionado com cada um dos bits de endereço entre A12 e A15. CSRAM#1/ = A12 CSRAM#2/ = A13 CSRAM#3/ = A14 CSEPROM#1/ = A15 Para esta solução ser correcta na prática o CPU deveria de ter um endereço de reset entre 7000H e 7FFFH. Mapa de memória resultante RAM#1 4K RAM#2 4K RAM#3 4K EPROM#1 4K 7000H 7FFFH B000H BFFFH D000H DFFFH E000H EFFFH

78 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 78 Temporizações e formas de onda do Clock de saída para f XTALL =12MHz Acesso às memórias de código e dados ALE CLK out 7.T CLCL -40ns 2.T CLCL -40ns [T CLCL -40, T CLCL +40] 10.T CLCL -40ns t CLCX min=20ns t CLCH max=20ns 83,3ns t CLCL t CHCX min=20ns CLK out t CHCL max=20ns PSEN/ RD/, WR/ Acesso à memória de código Acesso à memória de dados

79 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 79 Ciclo de read sobre a memória de código ALE PSEN/ Port 0 Port 2 A0-A7 Instrução A8-A15 Ciclo de read sobre a memória de dados ALE PSEN/ Port 0 Port 2 A0-A7 de Ri ou DPL A0-A7 de PCL Dados P2.0-P2.7 ou A8-A15 de DPHA8-A15 de PCH RD/ Instrução

80 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 80 A0-A7 de PCL Ciclo de write sobre a memória de dados ALE PSEN/ Port 0 Port 2 A0-A7 de Ri ou DPL Dados P2.0-P2.7 ou A8-A15 de DPHA8-A15 de PCH WR/ Instrução Oscilador recomendado com cristal XTAL1 XTAL2 12MHz C C C= 30pF ±10pF

81 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 81 Exercício 1: Projecte um microsistema baseado no com 32Kbytes de RAM para dados e código, e com 32Kbytes de EPROM só para código. Utilize na resolução do exercício 1 RAM 62256(32Kx8) e 1 EPROM 27256(32Kx8). Exercício 2: Projecte um microsistema baseado no com 32Kbytes de RAM e 32Kbytes de EPROM mas tendo as seguintes particularidades: 1. após reset o CPU só consegue aceder à EPROM que está localizada em qualquer endereço externo para acesso a código; 2. após ter-se acedido a um qualquer endereço com o bit A15=1 o microsistema deve passar a localizar a RAM no endereço base 0000H e a EPROM no endereço base 8000H. A EPROM deve continuar a aceitar acesso só para código e a RAM deve permitir acesso tipo código e dados. Circuito de reset para o com botão reset/ + R C C= [4.7uF, 10uF] T reset = 24xT osc O conteúdo dos registos mais utilizados após e durante a acção de reset são os seguintes: PC= 0000H SP= 07H P0-P5= 0FFH DPTR= 0000H ACC= 00H B= 00H PSW= 00H

82 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 82 Resolução do exercício 1, especificando os barramentos de endereços e dados e os sinais de controlo necessários: CPU80535 RAM62256 A0-14 CS/ OE/ WE/ D0-7 EPROM27256 A0-14 CS/ OE/ D0-7 P0.0-7, AD0-7 ALE P2.0-7, A8-15 PSEN/ P3.7, RD/ P3.6, WR/ LATCH D0-7 Q0-7 EN A A DB0-7 8 A A A0-14 A15 8 8

83 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 83 Resolução do exercício 2: CPU80535 RAM62256 A0-14 CS/ OE/ WE/ D0-7 EPROM27256 A0-14 CS/ OE/ D0-7 P0.0-7, AD0-7 ALE P2.0-7, A8-15 PSEN/ P3.7, RD/ P3.6, WR/ LATCH D0-7 Q0-7 EN A A DB0-7 8 A A A0-14 A RESET/ C R Reset R/ S/

84 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 84 Temporizadores e Contadores do O tem três temporizadores/contadores (em linguagem anglo-saxónica são designados por timer/counters) de 16 bits chamados timer 0, timer 1 e timer 2. Timer 0 e 1 Estes dois dispositivos podem funcionar ou como temporizadores(timers) ou como contadores de eventos (counters). Quando em modo temporizador (timer), o registo é incrementado em todos os ciclos máquina. Cada ciclo máquina inclui 12 ciclos de clock, o que para um clock de 12MHz implica incrementar o registo em todos os 1uS. Quando em modo contador, o registo é incrementado nas transições descendentes existentes nos pinos de entrada T0(P3.4) e T1(P3.5). Neste modo a entrada externa é amostrada durante o ciclo de clock número 11 de todos os ciclos máquina. Quando os testes exibem o valor 1 num ciclo e o valor 0 no ciclo seguinte, o contador é incrementado. O novo valor aparece no registo durante o terceiro ciclo de clock do próximo ciclo máquina. Como este demora 2 ciclos máquina a reconhecer uma transição descendente então o ritmo máximo de contagem é de 1/24 a frequência do oscilador ou seja de 2uS. Cada temporizador consiste de dois registos de 8 bits cada. TH0 (parte alta) e TL0 (parte baixa) para o timer 0. TH1 e TL1 para o timer 1. As funções de cada um dos timers são controladas através dos registos TCON e TMOD como se pode constatar nas seguintes figuras e descrições: TF1TR1 TR0 TF0 TCON (88H) 8CH8DH 8EH8FH TR0 – Se a 1 permite o timer 0 contar. Caso contrário o timer está parado. TF0 – Timer 0 overflow flag. Esta flag é colocada a 1 sempre que há overflow no processo de contagem do timer, ou seja, quando o registo do temporizador passa de tudo a 1s para tudo a 0s. Esta flag é colocada a 0 por hardware quando o processador é vectorizado para a rotina de atendimento desta interrupção. TR1 – idem TR0 mas agora para o timer 1. TF1 – idem TF0 mas agora para o timer 1. Endereço ao nível do bit

85 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 85 Timer 0 e 1 (continuação) GATE C-T/M0M1 TMOD (89H) timer 1 GATEC-T/M1M0 timer 0 GATE – Quando a 1 permite contagem sempre que o pino INTX/ e o bit TRX estão ambos a 1. C-T/ – Se a 1 fica em modo contador com a entrada no pino TX. Quando a 0 funciona em modo temporizador. M1M0 00- Modo 0: temporizador/contador de 13bits. O THX funciona como contador de 8 bits de maior peso e o TLX serve como contador de 5 bits de menor peso. 01- Modo 1: temporizador/contador de 16 bits. O THX funciona como contador de 8 bits de maior peso e TLX como contador de 8 bits de menor peso. 10- Modo 2: temporizador/contador de 8 bits recarregável. THX contém um valor que é atribuído a TLX sempre que neste ocorre o overflow de contagem. 11- Modo 3: timer 0: TL0 funciona como um temporizador/contador de 8 bits controlado pelos bits de controlo destinados ao timer 0. TH0 funciona como um temporizador de 8 bits comandado pelos bits de controlo destinados ao timer Modo 3: timer 1: Não funciona.

86 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 86 Timer 0 e 1 (continuação) Modo 0 OSC ÷12 Tx 0 1 S Y C-T/ TRx GATE INTx/ TLx (5 bits) THx (8 bits) TFx Interrupção timer x Modo 1 OSC ÷12 Tx 0 1 S Y C-T/ TRx GATE INTx/ TLx (8 bits) THx (8 bits) TFx Interrupção timer x f ÷32 Prescaler Contador de 16 bits Contador de 13 bits

87 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 87 Modo 2 OSC ÷12 Tx 0 1 S Y C-T/ TRx GATE INTx/ TLx (8 bits) THx (8 bits) TFx Interrupção timer x PL Modo 3 OSC ÷12 T0 0 1 S Y C-T/ TR0 GATE INT0/ TL0 (8 bits) TH0 (8 bits) TF0 Interrupção timer 0 TF1 Interrupção timer 1 TR1

88 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 88 Comunicação Série A comunicação série consiste no envio e recepção, de forma sincronizada, de 1 bit de informação em cada intervalo temporal designado por tempo de bit (bit time). O nível lógico 1 costuma designar-se por mark e o nível lógico 0 designa-se por space. A nível físico, os dois níveis lógicos correspondem a níveis de tensão diferentes ou à existência ou não de corrente na linha. Por exemplo, apresenta-se de seguida alguns protocolos para comunicação série e os respectivos níveis de tensão: Em termos históricos, o primeiro protocolo adoptado foi o loop de corrente de 40mA que se adaptava perfeitamente às características electromecânicas dos dispositivos da época, em que os relés eram directamente excitados pela corrente de 40mA pulsando ao ritmo de mark-space dos sinais enviados. A conversão de níveis de tensão TTL para RS232 são realizados através de circuitos SSI desenvolvidos para o efeito, caso dos MC1488 e MC1489 da Motorola e os e da Texas Instruments. Usualmente costuma dizer-se que existem dois tipos de comunicação série, a comunicação síncrona e a comunicação assíncrona. Dentro da classe da comunicação síncrona englobam-se os protocolos Bisync, SDLC, HDLC, etc. Na classe da comunicação dita assíncrona temos o protocolo start-stop bit. É sobre este protocolo que vamos dirigir o nosso estudo. A comunicação designa-se assíncrona quando existe unicamente sincronismo ao nível do bit. Enquanto se houver sincronismo ao nível do carácter e da trama(conjunto de caracteres) a comunicação designa-se por síncrona.

89 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 89 D1 Protocolo start-stop bit A composição deste protocolo é ilustrada na seguinte figura: Espera(idle) Mark Space Start bit dados Bit de paridade Stop bit O bit de paridade pode ou não existir. Caso exista, a paridade designa-se por par quando o número de bits de dados mais o bit de paridade têm no conjunto um número par de 1s. O inverso designa-se por paridade ímpar. Na comunicação série assíncrona o débito da comunicação ou o número de bits por segundo designa-se por baud rate. Os valores usuais deste parâmetro são: 110, 300, 600, 1200, 2400, 4800, 9600, 14400(14K), 28800(28K), 57600(56K). D0 D2D3D4P Exercício 1: Realize uma rotina para transmissão de dados série através do bit P5.6. Esta rotina tem como parâmetro de entrada o carácter a enviar. Exercício 2: Realize uma rotina para recepção de dados série através do bit P5.7. Esta rotina tem como parâmetro de saída o carácter recebido.

90 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 90 Resolução do exercício 1: Resolução do exercício 2: ; o carácter a enviar é passado no registo R7 ; comunicação série: 1 start bit, 8 data bits, 1 Stop bit ; baud rate= 1/ Delay_1_bit_time CO:CLRP5.6; start bit LCALLDELAY_1_BIT_TIME MOVR0, #8 TX_DATA_BITS: MOVA, R7 RRCA MOVR7, A MOVP5.6, C; 8 data bits LCALLDELAY_1_BIT_TIME DJNZR0, TX_DATA_BITS SETBP5.6; stop bit LCALLDELAY_1_BIT_TIME RET ; o carácter a receber é devolvido no registo R7 ; comunicação série: 1 start bit, 8 data bits, 1 Stop bit ; baud rate= 1/ Delay_1_bit_time CI:JBP5.7, $; espera start bit LCALLDELAY_MEIO_BIT_TIME JBP5.7, CI; falso start bit MOVR0, #8 RX_DATA_BITS: LCALLDELAY_1_BIT_TIME MOVC, P5.7; 8 data bits MOVA, R7 RRCA MOVR7, A DJNZR0, RX_DATA_BITS LCALLDELAY_1_BIT_TIME JNBP5.7, CI; falso stop bit RET Só falta fazer as funções de delay referidas nas anteriores funções. Então, como se faz um delay com um mínimo de rigor temporal? Em primeiro lugar, temos de recordar que um ciclo máquina no para uma frequência de 12MHz demora 12 ciclos de clock ou seja 1uS. Em segundo lugar tem de se repetir tantos uS ou ciclos máquinas quantos os desejados. Por exemplo se quiséssemos receber e transmitir com um baud rate= 9600, isto significa que cada bit tem de permanecer durante 1/9600= 104uS, daí o bit time= 104us e meio bit time= 52uS. Assim, a estrutura das rotinas será idêntica à parte de uma valor constante que chamaremos respectivamente UM_BIT_TIME e MEIO_BIT_TIME. DELAY_1_BIT_TIME: MOVR0, #UM_BIT_TIME NOP DJNZR0, $ RET DELAY_MEIO_BIT_TIME: MOVR0, #MEIO_BIT_TIME NOP DJNZR0, $ RET Cálculo das constantes: T(LCALL) + T(MOV) + T(NOP) + UM_BIT_TIME*T(DJNZ) + T(RET) = UM_BIT_TIME*2 + 2= 104 UM_BIT_TIME= 49 MEIO_BIT_TIME 24

91 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 91 Comunicação série no Este CPU disponibiliza internamente um canal série que suporta comunicação série bidireccional em simultâneo (dita tecnicamente comunicação em full duplex). Este canal de comunicação pode funcionar em 4 modos diferentes, um modo síncrono e três modos assíncronos como se irá descrever de seguida Modo 0 – Canal Síncrono de 8 bits Neste modo de funcionamento os bits de dados são transmitidos e recebidos através do sinal RxD. O sinal TxD opera como saída, aonde é definido o clock do ritmo da transferência de informação. O campo de dados é de 8 bits e o baud rate é 1/12 da frequência do oscilador do CPU. A transmissão é iniciada sempre que uma instrução utiliza o registo SBUF(99H) como registo destino. A recepção é iniciada quando os bits de controlo REN= 0 (Receiver Enable) e RI= 0 (Receiver Interrupt). Modo 1 – Canal Assíncrono de 8 bits Neste modo de funcionamento são transmitidos e recebidos 10 bits: 1 start bit, 8 bits de dados(bit de menor peso em primeiro lugar) e 1 stop bit. Na recepção os bits de dados ficam no registo interno SBUF(99H) e o stop bit é registado no bit RB8 do registo SCON(98H). O baud rate do canal neste modo é programável através do timer 1 ou através do gerador de baud rate interno. Utilizando o timer 1 como gerador de baud rate, temos: Timer 1 em modo 1: baud rate= 2 SMOD /32 * Timer1_Overflow Timer 1 em modo 2: baud rate= 2 SMOD /32 * (f XTALL / 12*(256-TH1)) Utilizando o gerador de baud rate interno, o baud rate depende do bit SMOD(bit 7 do registo PCON(87H)) e da frequência do oscilador, através da seguinte fórmula: baud rate= 2 SMOD /2500 * f XTALL

92 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 92 Modo 2 – Canal Assíncrono de 9 bits Modo 3 – Canal Assíncrono de 9 bits Neste modo, o canal série transmite através do TxD ou recebe através do RxD 11 bits, distribuidos da seguinte forma: 1 start bit, 8 bits de dados, 1 bit de paridade e 1 stop bit. Na transmissão o bit de paridade pode ser afectado com 1 ou 0 e é o bit TB8(end. de bit 9BH) do registo SCON(98H). Na recepção o nono bit é afectado ao bit RB8(9AH) do registo SCON(98H). O baud rate é programável para 1/32 ou 1/64 de f XTALL função do valor do bit SMOD do registo PCON estar respectivamente a 1 ou a 0. Modo funcionalmente idêntico ao modo 2 com a diferença do baud rate poder ser programável através do timer 1 ou do gerador interno de baud rate. As fórmulas para o cálculo do baud rate obtido à custa do timer 1 ou do gerador de baud rate são idênticas às apresentadas na descrição do funcionamento do canal série em modo 1. Registos para parametrização do canal série do H99H9AH9BH9CH9DH9EH9FH RITIRB8TB8RENSM2SM1SM0 SCON - 98H Modo Modo Modo Modo Permite o funcionamento em modo 2 e 3, quando a 1. Em modo 1 e SM2= 1 implica RI=1 se o stop bit recebido for válido. Em modo 0, SM2 deverá estar sempre a 0. Se a 1 permite recepção. Bit 8 da transmissão. Bit 8 da recepção. Flag de interrupção da transmissão. É colocada a 1 por hardware no 8º bit time quando em modo 0, ou no início do stop bit nos outros modos. Deve ser afectado a 0 por programação. Flag de interrupção da recepção. É colocada a 1 por hardware no 8º bit time quando em modo 0, ou no início do stop bit nos outros modos. Deve ser afectado a 0 por programação.

93 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 93 Registos para parametrização do canal série do (continuação) D0D1D2D3D4D5D6D7 SBUF - 99H Registo que define a interface entre o canal de comunicação série do e o programa. Escrever no registo SBUF implica escrever no registo de transmissão correspondendo a iniciar-se o processo de transmissão. Ler o SBUF implica ler o registo de recepção do canal. SMOD PCON - 87H Bits não utilizados na comunicação série. Quando a 1, duplica o baud rate do canal série nos modos 1, 2 e 3. BD ADCON – 0D8H Bits não utilizados na comunicação série. Quando a 1, o baud rate do canal série nos modos 1 e 3 são obtidos a partir de um divisor de frequências dedicado. Valores de baud rate de 4800 e 9600 podem ser obtidos a partir de f XTALL = 12MHz.

94 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 94 NAME CI_CO ; ISEL ; ;por Jorge Pais ; ; Rotinas que usam a UART do para enviar ; e receber dados série por pooling ; PUBLIC CI, CO, INIT_SERIE ;PUBLIC CO ; TI EQU SCON.1 ; RI EQU SCON.0 ; PORTO 5 P5 EQU 0F8H ; SCON REGISTER INIT_WORD EQU B ; MODO 1, RECEIVER ENABLE, POOLING ; TI ACTIVE ; PCON REGISTER SMOD EQU 80H ; ADCON REGISTER ADCON EQU 0D8H BD EQU 80H ; continua Consultando o anteriormente descrito, estamos em condições para desenvolver um módulo para manipular o canal série do 535 composto por uma rotina de iniciação chamada INI_SERIE, uma rotina de recepção chamada CI e uma rotina de transmissão chamada CO. ; continuação PROGSEGMENT CODE RSEG PROG ; inicialização do UART do 535 INI_SERIE: CLR P5.5 ; seleccionar o UART do 535 ; seleccionar 8 bits modo MOV SCON, #INIT_WORD; MODO1, 8BITS ORL PCON, #BD ; baud rate enable ORL ADCON, #SMOD; 9600 bit/s RET ; devolve em R7 um caracter CI: JNB RI, $ MOV R7, SBUF CLR RI RET ; tem um caracter como parametro de entrada em R7 ; e transmite-lo via canal série CO: JNB TI, $ CLR TI MOV SBUF, R7 RET END

95 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 95 Interrupções no As fontes de pedido de interrupção no são as seguintes, INT0/, INT1/, INT2/, INT3/, INT4/, INT5/, INT6/ - Interrupções externas 0, 1, 2, 3, 4, 5 e 6 respectivamente. Timer0, Timer1, Timer2 – Interrupções internas geradas pelos temporizadores existentes no CPU. No caso do Timer2 existem modos de funcionamento para os quais a interrupção é gerada externamente e outros em que a interrupção é interna. Canal Série 0 – Interrupção interna gerada pelos eventos de recepção ou transmissão série de um carácter. Conversor A/D – Interrupção interna gerada pelo conversor analógico/digital aquando do fim de uma conversão. O mecanismo de controlo das interrupções no envolve variadas flags localizadas nos seguintes registos de função especial: TCON.0TCON.1TCON.2TCON.3TCON.4TCON.5TCON.6TCON.7 IT0IE0IT1IE1TF0 TCON - 88H TF1 88H89H8AH8BH8DH8FH Endereço ao nível do bit IT0 – Define a característica da entrada INT0/. Quando a 1 indica pedido de interrupção nas transições descendentes de INT0/. Se a 0 implica pedido de interrupção quando INT0/ estiver a 0. IE0 – Flag de detecção de transições na entrada INT0/. Quando a 1 indica que houve um pedido de interrupção por transição descendente na entrada INT0/. É colocada a 0 quando a interrupção é atendida. IT1 – Idem IT0 mas agora o significado é para a entrada INT1/. IE1 – Idem IE0 mas respeitante à entrada INT1/. TF0 – Flag de overflow do timer 0. Colocada a 1 por hardware quando o temporizador/contador 1 passa da configuração binária definida por tudo a 1s para tudo a 0s. Esta flag é colocada a 0 por hardware sempre que o processador atende o pedido. TF1 – Idem TF0 mas agora para o timer 1.

96 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 96 T2CON.5T2CON.6 I2FR T2CON – 0C8H I3FR C8HCDHCEHEndereço do bit I2FR – Define se a entrada INT2/ afecta na transição ascendente ou descendente a flag de pedido de interrupção IEX2. Se a 1, a entrada INT2/ afecta IEX2 quando houver uma transição ascendente. Se a 0, INT2/ afecta IEX2 quando houver uma transição descendente. I3FR – Idem I2FR mas agora respeitante à entrada INT3/. IRCON.0IRCON.1IRCON.2IRCON.3IRCON.4IRCON.5IRCON.6IRCON.7 IADCIEX2IEX3IEX4IEX6 IRCON – 0C0H EXF2 C0HC1HC2HC3HC5HC7H Endereço do bit C4HC6H TF2IEX5 IADC – Flag de pedido de interrupção do conversor analógico/digital. É colocado a 1 no fim de uma conversão e deve ser colocado a 0 por software. IEX2-6 – Flag de transição para a entrada de interrupção INTx/. Colocada a 1 por hardware quando for detectado um pedido de interrupção. Fica a zero quando é atendido o pedido de interrupção. TF2 – Flag de overflow do timer 2. Fica a 1 quando o timer 2 passa a sua configuração binária de todos os bits a 1 para todos os bits a 0. Deve ser colocada a 0 por software. EXF2 – Flag de recarregamento (reload) do timer 2. Fica a 1 quando existe uma transição descendente no sinal T2EX enquanto EXEN2= 1. Quando é permitido a interrupção do timer 2, EXF2=1 implica uma vectorização para a rotina de atendimento da interrupção timer 2. Deve ser colocado a 0 por software.

97 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 97 Cada entrada de interrupção pode ser mascarada ou desmascarada através dos seus bits de permissão, existentes nos registos IEN0 e IEN1. Existe também um bit global de permissão para todas as fontes de interrupção que quando a 0 não permite qualquer pedido de interrupção independentemente dos bits de permissão individuais. IEN0.0IEN0.1IEN0.2IEN0.3IEN0.4IEN0.5IEN0.7 EX0ET0EX1ET1ET2 IEN0 – 0A8H EAL A8HA9HAAHABHADHAFHEndereço do bitACH ES IEN1.0IEN1.1IEN1.2IEN1.3IEN1.4IEN1.5IEN1.7 EADCEX2EX3EX4EX6 IEN1 – 0B8H EXEN2 B8HB9HBAHBBHBDHBFHEndereço do bitBCH EX5 EX0 – Se a 1 permite INT0/. ET0 – Quando a 1 permite interrupção gerada pelo timer 0. EX1 – Permite INT1/ sempre que esteja este bit a 1. ET1 – Se a 1 permite interrupção gerada pelo timer 1. ES – Quando a 1 permite interrupção gerada pelo canal série, tanto na transmissão como na recepção. ET2 – Permite interrupção do timer 2 quando a 1. EAL – Permite ou não interrupções. Se a 0 este bit não permite atendimento aos pedidos de interrupção. EADC – Se a 1 permite interrupção gerada pelo conversor analógico/digital. EX2-6 – Quando a 1 permite o respectivo pedido de interrupção correspondente à entrada INTx. EXEN2 – Não permite interrupção por recarregamento automático do timer 2 enquanto este bit estiver a 0..

98 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 98 Todas as fontes de interrupção mencionadas obedecem à priori a uma hierarquia quanto às suas prioridades que podem ir do nível 0 a 3 e que são definidas através de bits dos registos IP0 e IP1. Uma rotina de atendimento de interrupção correspondente a uma entrada de interrupção de baixa prioridade só pode ser interrompida por outra interrupção de maior prioridade. Uma interrupção de nível 3 não poder ser interrompida por qualquer outra fonte de interrupção. A definição dos níveis de prioridade das várias fontes de interrupção realizam-se aos pares segundo a seguinte lista: INT0/ e Conversor A/D Timer0 e INT2/ INT1/ e INT3/ Timer1 e INT4/ Canal Série 0 e INT5/ Timer2 e INT6/ Registos para definição dos níveis de prioridade IP0, IP1 IP0.0IP0.1IP0.2IP0.3IP0.4IP0.5IP0.6IP0.7 IP1.0IP1.1IP1.2IP1.3IP1.4IP1.5IP1.6IP1.7 IE0 IADC TF0 IEX2 IE1 IEX3 TF1 IEX4 RI+TI IEX5 TF2+EXF2 IEX6 IE0 IADC TF0 IEX2 IE1 IEX3 TF1 IEX4 RI+TI IEX5 TF2+EXF2 IEX6 IP0 - 0A9H IP1- 0B9H O nível de prioridade 0 é o menor e o 3 é o maior. Quando as fontes de interrupção estão todas com a mesma prioridade e existem simultâneos pedidos de atendimento, estes pedidos são atendidos segundo um critério de prioridades pré-definidos no e ilustrados na seguinte tabela:

99 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 99 Atendimento de Interrupções As flags correspondentes às entradas de interrupção são testadas em todos os ciclos máquina no 10º ciclo de clock. Se alguma destas flags está activa existe um ciclo máquina seguinte durante o qual estas flags são obsessivamente testadas. Caso continuem activas o sistema de interrupções gerará uma instrução LCALL Endereço16, na qual o Endereço16 é um valor a 16 bits que especifica o endereço absoluto do início da respectiva rotina de atendimento de interrupção. Os valores dos endereços absolutos correspondentes às rotinas de atendimento das interrupções são ilustrados na seguinte tabela: Uma rotina de atendimento de interrupção começa no endereço especificado e termina quando é cumprida a instrução RETI. A instrução RETI indica que a rotina de atendimento terminou a execução afectando o PC com os dois bytes que se encontram no topo do stack e também informa a máquina de atendimento de interrupções do CPU que pode voltar a atender interrupções de igual ou menor prioridade. Portanto, nunca se deve terminar uma rotina de interrupção com uma instrução RET porque para o CPU a rotina de atendimento da interrupção ainda está sendo realizada nunca mais atendendo interrupções de igual ou menor prioridade. Uma característica importante das rotinas de atendimento de interrupções é que devem ser sempre invisíveis, do ponto de vista do programa que foi interrompido. Ou seja, não devem alterar o estado do CPU nem demorar demasiado tempo de execução. O estado do CPU é definido como sendo os valores dos seus registos internos e stack. O tempo de execução de uma rotina de atendimento de interrupções poderá ser definido como demasiado quando este tempo degradar substancialmente o tempo de execução dos programas interrompidos.

100 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 100 Desenho das Rotinas para Atendimento de Interrupções Para garantir a invisibilidade da rotina para atendimento da interrupção de nível 1, a sua estrutura genérica deve ser: ROTINA_DE_INTERRUPCAO: PUSHDPH ; salvar os registos que vão ser utilizados na rotina PUSHDPL ; de interrupção. Uma das condições para se garantir PUSHB ; a invisibilidade desta rotina de interrupção. PUSHACC PUSHPSW SETBRS0 ; nível 1 de interrupção implica no 535 trabalhar com o ; banco 1 de registos por convenção. Ao nível do programa ; deve-se garantir que se trabalha com o banco 0 de registos. ; Assim garante-se a não destruição dos registos R0-7. LCALLFazer_Accoes ; destrói A, B e DPTR. Acções a efectuar na rotina ; de interrupção. POPPSW ; reposição dos valores nos registos POPACC POPB POPDPL POPDPH RETI ; assinala ao processador o fim do atendimento da interrupção ; e afecta o PC com a word que se encontra no topo do stack. Fazer_Accoes: RET

101 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 101 Desenho das Rotinas para Atendimento de Interrupções (continuação) O módulo assembly535 para o atendimento de interrupções no kit didáctico SD535 deve ter a seguinte estrutura: ; entry point da interrupção do Canal Série Rx/Tx CSEG AT 23H LJMPINT_RXTX_ROT ; entry point da interrupção do Overflow do Timer 0 CSEG AT 0BH LJMPINT_T0_ROT ; rotina de tratamento da interrupção do Overflow do Timer 1 CSEG AT 1BH LJMPINT_T1_ROT ; entry point da interrupção do Overflow do Timer 2 ; ou recarregamento externo do Timer 2 CSEG AT 2BH LJMPINT_T2_ROT ; entry point da interrupção do Conversor Analogico-Digital CSEG AT 43H LJMPINT_ADC_ROT ; entry point da interrupção 0 externa CSEG AT 03H LJMPINT0_ROT ; entry point da interrupção 1 externa CSEG AT 13H LJMPINT1_ROT ; entry point da interrupção 2 externa CSEG AT 4BH LJMPINT2_ROT ; entry point da interrupção 3 externa CSEG AT 53H LJMP INT3_ROT ; entry point da interrupção 4 externa CSEG AT 5BH LJMPINT4_ROT ; entry point da interrupção 5 externa CSEG AT 63H LJMPINT5_ROT ; entry point da interrupção 6 externa CSEG AT 6BH LJMPINT6_ROT Nota importante: As chamadas às rotinas de interrupção devem ser realizadas através da instrução LJMP ROTINA_INTERRUPÇÃO porque não nos podemos esquecer que o processador chega ao endereço de entry point da rotina de atendimento da interrupção através de uma instrução LCALL ENDEREÇO16 produzida internamente pelo CPU, a qual garante a memorização do endereço de retorno em stack. Deste modo, o conjunto de instruções que compõem o atendimento da interrupção deve ser sempre terminado pela instrução RETI, como o exemplificado na página anterior.

102 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 102 Desenho das Rotinas para Atendimento de Interrupções (continuação) Exercício: Faça um programa que simule um contador crescente de 16 bits com clear assíncrono. O contador deve contar 20 unidades por segundo. O valor do contador deve ser visualizado na consola. Opções tomadas: 1. O timer 0 vai gerar o sinal de relógio (20Hz). Como trabalha a 1MHz tem de dividir-se esta frequência por O sinal de clear do contador vai ser a entrada INT3 do CPU. $TITLE('Contador crescente de 16 bits com clear') ; ****************************************** ; * feito por Jorge Pais * ; * 2001 * ; ****************************************** EXTRN CODE(INIT_INT, INIT_TIMER0) EXTRN CODE(GOTOX) EXTRN CODE(WRITE_WORD, WRITELN) BANCO0EQU B IEN0EQU0A8H EALEQUIEN0.7 ; permite ou não todas as fontes de interrupção DSEG AT 40H DIM_PILHA EQU 40H PILHA: DS DIM_PILHA ; FICA COM UM STACK DE 40H ATÉ 7FH MAINCODESEGMENT CODE RSEG MAINCODE START: MOVSP, #PILHA-1 ANLPSW,#BANCO0 ; TRABALHA COM O BANCO 0 MOVCONTADOR, #0 MOVCONTADOR+1, #0 ; inicialização do contador SETBVER_CONTADOR ; ver o valor 0 LCALL WRITELN; afixar o contador na linha seguinte ; continua ; continuação LCALLINIT_TIMER0 LCALLINIT_INT FOREVER: JNB VER_CONTADOR, FOREVER MOVR7, #0 LCALLGOTOX ; posiciona o cursor MOVR7, CONTADOR MOVR6, CONTADOR+1 LCALL WRITE_WORD CLR VER_CONTADOR SJMPFOREVER MAINDATASEGMENT DATA RSEG MAINDATA PUBLIC CONTADOR CONTADOR: DS 2 MAINBITSEGMENTBIT RSEGMAINBIT PUBLIC VER_CONTADOR VER_CONTADOR: DBIT 1 END

103 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 103 NAME INTERRUPTS ; **************************** ; * ISEL * ; * por Jorge Pais * ; *2001 * ; **************************** EXTRN DATA(CONTADOR) EXTRN BIT(VER_CONTADOR) ; **************************************************** ; * definição dos registos e bits para tratamento das interrupções * ; **************************************************** IEN0EQU0A8H IEN1EQU0B8H T2CONEQU0C8H IRCONEQU0C0H ; BITS DO IEN0 EALEQUIEN0.7 ; BITS DO IEN1 EX3EQUIEN1.2 ; BITS DO T2CON I3FREQUT2CON.6 ; BITS DO IRCON IEX3EQUIRCON.2 ; *********************************************** ; *** entry points das rotinas de interrupção *** ; *********************************************** ; entry point da interrupção do Overflow do Timer 0 CSEG AT 0BH LJMPINT_T0_ROT ; entry point da interrupção 3 externa CSEG AT 53H LJMP INT3_ROT ;continua ; continuação ; ************************************************ ; *** rotinas para tratamento das interrupções *** ; ************************************************ INTSSEGMENT CODE RSEGINTS ; rotina de tratamento da interrupção do Overflow do Timer 0 INT_T0_ROT: MOVTL0, #LOW( ) MOVTH0, #HIGH( ) ; reinicialização do Timer PUSHPSW PUSHACC INCCONTADOR MOVA, CONTADOR CJNEA, #0, IT0_FIM INCCONTADOR+1 IT0_FIM: SETBVER_CONTADOR POPACC POPPSW RETI ; rotina de atendimento da entrada de interrupção externa 3 - Clear do contador INT3_ROT:MOVCONTADOR, #0 MOVCONTADOR+1, #0 SETBVER_CONTADOR CLRIEX3 ; clear ao isr3 - para aceitar novos interrupts RETI ; rotina para inicialização das interrupções PUBLIC INIT_INT INIT_INT:CLREAL ; disable a todos os interrupts SETBET0 ; enable Timer 0 interrupt SETBEX3 ; enable IEX3 SETBI3FR ; transição ascendente IEX3 CLRIEX3 ; CLEAR FLAG INT3 SETBEAL ; enable aos interrupts permitidos RET END

104 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 104 NAME TIMERS ; **************************** ; * ISEL * ; * por Jorge Pais * ; * 2001 * ; **************************** ; ************************************************ ; * definição dos registos e bits para os timers * ; ************************************************ ; peso dos BITS DO TMOD M0_T0EQU01H M1_T0EQU02H CT_T0EQU04H GATE_T0EQU08H M0_T1EQU10H M1_T1EQU20H CT_T1EQU40H GATE_T1EQU80H ; ******************************************** ; *** rotinas para incialização do Timer 0 *** ; ******************************************** TIMERSSEGMENT CODE RSEGTIMERS ; rotina de inicialização do timer 0 que não destrói a programação do timer 1 ; Timer 0 programado em modo 1, e ; existe Timer Overflow passados 50000uS PUBLIC INIT_TIMER0 INIT_TIMER0: MOVTL0, #LOW( ) MOVTH0, #HIGH( ) ANLTMOD, #0F0H ORL TMOD, #M0_T0; modo 1-16 bits, timer, TRx SETBTR0 ; Timer0 ON RET END Algumas considerações devem ser feitas acerca da solução apresentada anteriormente. A rotina de tratamento de interrupção de Timer Overflow, chamada INT_T0_ROT, faz a reinicialização do Timer0 nas suas duas primeiras instruções para minimizar o erro temporal relativamente ao que é pedido no enunciado. E que é, passo a citar, O contador deve contar 20 unidades por segundo.. No entanto, existe um erro de tempo que é derivado do tempo que decorre entre existir Timer Overflow e a completa execução das 2 instruções de reinicialização de TL0 e TH0. Na figura seguinte, tenta-se ilustrar o erro temporal que não é exactamente quantificável, porque um pedido de interrupção é assíncrono relativamente à normal execução de instruções. Timer Overflow LJMP INT_T0-ROT MOV TL0, #LOW(-50000) MOV TH0, #HIGH(-50000) LCALL 0BH Valor variável entre [1us, 3us] 1us 2us 1us 2us Escala De Tempo

105 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 105 A questão que se coloca perante este problema é: Qual a solução para a correcta contabilização de tempo? A resposta é: não existe uma forma exacta de contabilizar este tempo. No entanto, o próprio temporizador, que estamos a utilizar, é um contador de tempo então porque não utilizá-lo para a contagem do tempo ilustrado na figura anterior. Como? Se pensarmos um pouco, o tempo de execução das várias instruções a cumprir vai fazer com que o par de registos (TH0, TL0) fique com um valor diferente de zero. Logo a operação a realizar não será: (TH0, TL0) = mas sim, (TH0, TL0)= (TH0, TL0) – De referir, que para o problema simples do contador o erro temporal é quase contabilizavel pela figura anterior, mas geralmente e pensando num problema com vários níveis de interrupção, o tempo pode-se tornar perfeitamente incontabilizavel. Considere a figura seguinte em que a interrupção do Timer Overflow 0 tem prioridade 0 e existem mais fontes de interrupção com prioridades superior, então o erro temporal é ilustrado pela figura seguinte: As setas bidireccionais da figura anterior representam a chamada e retorno das rotinas de tratamento de interrupção com prioridade crescente. A figura é confusa e esta confusão ilustra devidamente a inaptidão para se medir um tempo correcto e concreto. Timer Overflow LCALL 0BH LJMP INT_TO_ROT MOV TL0, #LOW(-50000) MOV TH0, #HIGH(-50000) Escala de Tempo Rotina_Interrupção_Nível_1 Rotina_Interrupção_Nível_2 Rotina_Interrupção_Nível_3

106 ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 106 Nota Final Espero sinceramente que esta versão, ainda em construção, das folhas de apoio lhe tenham sido particularmente úteis na concretização teórico-prática da disciplina de Introdução aos Microprocessadores. O docente Jorge Pais Bibliografia SAB80535 Quick Reference Secção de Sistemas Digitais DEETC – ISEL SAB Bit Single-Chip Microcontroller Family Users Manual Microcomputer Components Siemens SAB Bit CMOS Single-Chip Microcontroller Data Sheet Microcomputer Components Siemens Deste modo, o conjunto de instruções que devem ser realizadas no início da rotina de tratamento da interrupção Timer Overflow, (INT_T0_ROT), para uma nova inicialização do temporizador com vista a minimizar o erro temporal do à precisão do temporizador que é de 1us, será: VALOR EQU ; 20 vezes por segundo ; rotina de tratamento da interrupção gerada por ; Overflow do Timer 0 INT_T0_ROT: PUSH PSW PUSH ACC ; reinicialização do timer CLR TR0 ; pára o timer MOV A, TL0 ADD A, #LOW(-VALOR+7) ; 7 é o nº de instruções MOV TL0, A ; da reinicialização MOV A, TH0 ADDC A, #HIGH(-VALOR+7) MOV TH0 SETB TR0 ; fim da reinicialização INC CONTADOR MOV A, CONTADOR CJNE A, #0, IT0_FIM INC CONTADOR+1 IT0_FIM: SETB VER_CONTADOR POP ACC POP PSW RETI


Carregar ppt "ISEL – SSD - Folhas de Apoio à Disciplina de Introdução aos Microprocessadores© Jorge Pais 1 Folhas de Apoio à Disciplina de Introdução aos Microprocessadores."

Apresentações semelhantes


Anúncios Google