083405 082921 Rel11

De DCA-Wiki

Relatório 11 - Versão 0.1 BETA

Nomes:

Danilo A. Berbert
Thiago L. C. Kurovski
RA: 083405
RA: 082921

Parte I - Perguntas

1. Ligação do Teclado na interrupção IRQ4.
Explique como a solicitação de interrupção IRQ4 é acionada pelas teclas do teclado da montagem auxiliar. O que é necessário fazer para que o IRQ4 seja acionado? Veja o esquemático da placa auxiliar.

Resposta: A porta IRQ4 está ligada, através de um resistor de pull-up de 10K, a fonte de alimentação da placa que a mantém em nível alto por padrão. Caso uma tecla do teclado esteja ativada, esta irá conectar a PTC correspondente a sua linha a PUBP correspondente a sua coluna. As colunas estão conectadas através de diodos, com os lados N ligados a PUBP correspondente, que formam uma porta AND. Assim, se qualquer tecla estiver ativada e sua linha estiver em nível zero, o diodo irá polarizar reversamente e baixar o nível do sinal IRQ4, sinalizando uma interrupção.

2. Explique como funciona o EPORT (Edge Port Module) do coldfire (capítulo 14 do manual de referência.

Resposta: O Edge Port Module contém 7 pinos de interrupção externa (IRQ1-IRQ7). Esses pinos podem ser configurados tanto como pinos de GPIO comuns como como fontes de interrupção, através do registrador PNQPAR. Cada pino também pode ser configurado como uma fonte de interrupção sensível a nível, borda de subida, borda de descida, ou ambas, através do registrador EPPAR. Se o bit de EPIER correspondente estiver habilitado, a condição de interrupção acionará a interrupção correspondente (IRQn, no nosso caso IRQ4), acionando a função correspondente no vetor de interrupção (64+n) e o bit correspondente no registrador de flags de interrupção (EPFR), até que a flag de interrupção seja manualmente limpa com uma escrita em EPFR.

3. Como se faz para configurar a solicitação IRQ4 para solicitar interrupção por nível ou por borda (subida, descida ou ambas)?

Resposta: Muda-se o valor do registrador EPPAR. Cada conjunto de 2 bits controla a configuração de uma das fontes de interrupção. No caso de IRQ4 controlamos os bits 8 e 9:
  • 00 => Sensível a nível baixo
  • 01 => Sensível a borda de subida
  • 10 => Sensível a borda de descida
  • 11 => Sensível a borda de subida e descida

4. Qual é o número do vetor de interrupção associado ao IRQ4?

Resposta: É o vetor 64 + 4 = 68 = 0x44 = 0b1000100.



Parte II – Código

Atenção! Código ainda não foi projetado, versão preliminar apenas para testes.

Em exceptions.c, após todos as definições, colocamos:

declspec (interrupt) void interrupcao_teclado();

E substituímos a linha /* 68 por:

interrupcao_teclado, /* 68 (0x___) Reserved */

Código:

#include "support_common.h" /* include peripheral declarations and more */
#include <stdio.h>
#include "exceptions.h"

#define MINTIME 3
#define MAXTIME 300 

#define IPSBAR 0x40000000
//Porta TC
#define PORTTC	0x4010000F
#define DDRTC	0x40100027
#define PORTUBP 0x40100042
#define DDRUB   0x4010002A
#define PUBPAR  0x40100072
//#define PNQPAR IPSBAR + 0x00100068
//Edge Port Module
#define EPFR  IPSBAR + 0x00130006
#define EPPAR IPSBAR + 0x00130000
#define EPIER IPSBAR + 0x00130003
#define EPDR IPSBAR + 0x00130004
#define EPDDR IPSBAR + 0x00130002

unsigned char *UMR10 = (unsigned char*)0x40000200;
unsigned char *UCSR0 = (unsigned char*)0x40000204;
unsigned char *UISR0 = (unsigned char*)0x40000214;
unsigned char *UBG10 = (unsigned char*)0x40000218;
unsigned char *UBG20 = (unsigned char*)0x4000021C;
unsigned char *UCR0 = (unsigned char*)0x40000208;
unsigned char *UTB0 = (unsigned char*)0x4000020C;
unsigned char *URB0 = (unsigned char*)0x4000020C;

uint8 *epfr = (uint8*) EPFR;
uint16 *eppar = (uint16*) EPPAR;	
uint8 *epier = (uint8*) EPIER;
uint8 *epdr = (uint8*) EPDR;
uint8 *epddr = (uint8*) EPDDR;

//uint16 *pnqpar = (uint16*) PNQPAR;

int teclado=12;
int RXRDYteclado=0;
int repet=0;
int situacaoant;
int situacaoatual=12;

void tecl_init();
void escrita(char code);
int soma(int N[], int numeros);
int tecl_checkchar();
char tecl_getchar();
int converte(int code[3], int digit);
__declspec(interrupt) void interrupcao_teclado();  //Declara a função como uma função de interrupção

void init(void)
{
	*UCR0 = 0x30; 
	*UCR0 = 0x20; 
	*UCR0 = 0x10; 
	*UMR10 = 0x13; 
	*UMR10 = 0x07; 
	*UCSR0 = 0%11011101; 
	*UISR0 = 0x0; 
	*UBG10 = 0x1; 
	*UBG20 = 0x04; 
	*UCR0 = 0x05;          
}

void printString(char *vetor)
{	
	int i=0;
	
	for(i=0;vetor[i]!=0;i++)
              escrita(vetor[i]);
}

void putDec(unsigned int a)
{
	int i, j;
	char hex[20];
	
	i = 0;
	while(a > 0)
	{
		hex[i] = a % 10;
		hex[i] = hex[i] + 48;
		a = a / 10;
		i++;
	}
	for(j = i - 1; j >= 0; j--)
		escrita(hex[j]);
		
	escrita(0x0A);
	escrita(0x0D);
}

void putBin(unsigned int a)
{
	int i, j;
	char hex[32];
	
	i = 0;
	while(a > 0)
	{
		hex[i] = a % 2;
		hex[i] = hex[i] + 48;
		a = a / 2;
		i++;
	}
	for(j=(i - 1); j >= 0; j--)
		escrita(hex[j]);
		
	escrita(0x0A);
	escrita(0x0D);
}

void putHex(unsigned int a)
{
	int i, j;
	char hex[16];
	
	i = 0;
	while(a > 0)
	{
		hex[i] = a % 16;
		if(hex[i] >= 10)
			hex[i] = hex[i] + 55;
		else
			hex[i] = hex[i] + 48;
		
		a = a / 16;
		i++;
	}
	for(j = i - 1; j >= 0; j--)
		escrita(hex[j]);
		
	escrita(0x0A);
	escrita(0x0D);	
}

void tecl_init()
{
       uint8 *ddrub   = (uint8 *)DDRUB;
       uint8 *pubpar  = (uint8 *)PUBPAR;
       uint8 *ddrtc = (uint8*) DDRTC;
       uint8 *porttc = (uint8*) PORTTC;
	
       //Configuração das interrupções gerais
       //Queremos liberar apenas para a interrupçao de numero 68

       MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASKALL;	// Não mascara as interrupções (master)
       MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_INT_MASK4;	// Desmascara a interrupção do IRQ4 (4) (enable)
       
       *epfr = 0x10; //Reseta Flag de IRQ4       
       *epier = 0x10; //Ativa IRQ4
       //*eppar = 0x0000; //Configura IRQ4 para sensível a nível baixo
       //*eppar = 0x0100; //Configura IRQ4 para sensível a borda de subida
       *eppar = 0x0100; //Configura IRQ4 para sensível a borda de descida
       //*eppar = 0x0100; //Configura IRQ4 para sensível a borda de subida e descida
       *epdr = 0x10; //Aciona IRQ4
       
       //Definição de prioridade do microprocessador (Nivel 0 como o INT0)
       asm 
       {
               move.w #0x2000, sr
       }

	
    	*pubpar = 0x00;	/*Configura porta UB para trabalhar como porta comum*/
   	*ddrub = 0x00;	//Configura UB como entrada
   	*ddrtc = 0x0F; //TC Saída
   	*porttc = 0x00; //TC zerada
}

int tecl_checkchar()
{
	if (RXRDYteclado == 0) return 0;
	else return 1;
}
 
char tecl_getchar()
{
       char tabela[]={'1','2','3','4','5','6','7','8','9','#','0','*',0};
       while ((tecl_checkchar())==0);
       RXRDYteclado = 0;
       return (tabela[teclado]);
}

int converte(int code[3], int digit)// Pega o número a partir do vetor num
{
       int i, num = 0;
       for (i=0; i<digit; i++)
               num = 10*num + code[i];

       return num;
}

int soma(int N[], int numeros)		// Soma todos os números do vetor N
{
	int i, total=0;
	for(i = 0; i<numeros; i++)
		total += N[i];
		
	return total;
}

//Função quando ocorre quando há interrupção
__declspec (interrupt) void interrupcao_teclado()
{
	int i,j,tecla=0;
	uint8 mask;
	uint8 io[4] = {0x01,0x02,0x04,0x08}; /*Sequencia de configuracao de porta*/
	uint8 aterra;
	uint8 *porttc  = (uint8 *)PORTTC;
	uint8 *ddrtc   = (uint8 *)DDRTC;
	uint8 *portubp = (uint8 *)PORTUBP;
	uint8 *ddrub   = (uint8 *)DDRUB;
	uint8 *pubpar  = (uint8 *)PUBPAR;
	uint8 leitura;
      
   situacaoant=situacaoatual;
	situacaoatual=12;

	/*Rotina para varrer teclado. Previne contra curto quando mais teclas estao apertadas ao mesmo tempo*/
	for (i=0; i<4; i++)
	{  
		/*Faz a leitura da linha i*/
		*ddrtc = io[i]; 				//Coloca coluna em questão como saída
		aterra = !io[i];
		aterra = aterra & 0x0f;				//Dá NOT em io e joga em aterra, só com primeiros bits,
		*porttc= aterra;			//Aterra coluna a aterrar
		mask = 0x01; 				/*Configura mascara para detectar botao apertado ou nao*/
		leitura = *portubp;

		for (j=0;j<3;j++)
		{
			/*Caso o botao esteja apertado, o bit i do registrador PORTUBP estara em ZERO*/
			if(!(mask & leitura))
				situacaoatual=tecla;
			        
        	        mask = mask <<1; 		/*Verifica bit seguido (colula j)*/
        	        tecla++;
		}
	}

      if (situacaoatual == situacaoant) repet++;
      else repet=0;
      
      if ((repet == MINTIME) && (situacaoatual != 12))
      {
          teclado = situacaoatual;
          RXRDYteclado = 1;
      }

      if (((repet % MAXTIME) == 0) && (repet != 0) && (situacaoatual != 12))
      {
          RXRDYteclado = 1;
      }
      
      *ddrtc = 0x0F;
      *epfr = 0x10; // reseta flag de IRQ4                      
}
 
void clearScr()
{
	escrita(0x1B);	// 
	escrita(0x5B);	// ClearScr
	escrita(0x32);	//
	escrita(0x4A);	//	
}

void escrita(char code)
{
	while (!((*UCSR0) & 0x4));
	*UTB0 = code;
}

int main(void)
{
       int num[3], N[15], digit=0, numeros=0, total;
       char caracter;
       char msg3[] = "SOMA EM HEXADECIMAL: ";
       char msg4[] = "SOMA EM DECIMAL: ";
       char msg5[] = "SOMA EM BINARIO: ";
	
       init();
       tecl_init();
       clearScr();

       //Apartir daqui, o contador já foi liberado e entrará na função caso estoure a contagem
       //Podemos executar qualquer código aqui, e será interrompido
       while (1)
       {
               caracter = tecl_getchar();
               if (caracter == '*') break;
               if (caracter == '#')
               {
                       N[numeros++] = converte(num, digit);	// Vetor N contém os números a serem somados
                       digit = 0;
                       escrita(0x0A);	// ENTER
                       escrita(0x0D);	//
               }
               else
               {
                       num[digit++] = caracter - 0x30;
                       escrita(caracter);
               }
       }

       total = soma(N, numeros);

       printString(msg3);
       putHex(total);
	
       printString(msg4);
       putDec(total);
	
       printString(msg5);
       putBin(total);

       return 0;
}

Ferramentas pessoais