084060 085778 ProjetoFinal

De DCA-Wiki

EA 870 - Laboratório de computação Grupo 10 Renato Aranha 084060 Bruno Vargas 085778

Projeto Final

Objetivos: Implementar um cronômetro com precisão de até décimos de segundos que seja visualizado simultaneamente no hyperterminal e no visor LCD. Implementar no mínimo a função de parar, reiniciar e acertar o cronômetro. Para os acertos podem ser usados indistintamente tanto as teclas do teclado (hyperterminal) como o teclado matricial da placa auxiliar.

Código:

em exceptions.c alterar:

1)depois de todas as definições , adicionar:

void interrupcao_pit0(); void interrupcao();

2) asm_exception_handler, /* 67 (0x10C) Device-specific interrupts */ interrupcao, /* 68 (0x110) Device-specific interrupts */

asm_exception_handler,           /*  69 (0x114) Device-specific interrupts */

3) asm_exception_handler, /* 118 (0x___) Reserved */

interrupcao_pit0,                       /* 119 (0x___) Reserved                   */
asm_exception_handler,           /* 120 (0x___) Reserved                   */

em main.c :

  1. include "support_common.h" /* include peripheral declarations and more */
  2. include "uart_support.h"
  3. include <stdio.h>
  1. define DDRAS 0x40100023
  2. define PORTAS 0x4010000B
  3. define PASPAR 0x4010006B
  4. define CLRAS 0x40100053
  5. define SETAS 0x4010003B
  6. define IPSBAR 0x40000000
  7. define PORTTC 0x4010000F //Porta TC
  8. define DDRTC 0x40100027
  9. define PORTAN 0x4010000A//Porta AN
  10. define DDRAN 0x4010002
  11. define PUBPAR 0x40100072
  12. define DDRUB 0x4010002A
  13. define IPSBAR 0x40000000
  14. define EPPAR IPSBAR + 0x00130000 // configuraçoes gerais
  15. define EPIER IPSBAR + 0x00130003
  16. define EPFR IPSBAR + 0x00130006
  17. define IMRL IPSBAR + 0x00000C0C
  18. define EPDR IPSBAR + 0x00000004
  19. define PORTUBP 0x40100042

uint8 * RTCCTL = (uint8 *)IPSBAR + 0x03D3; // controlador do RTC uint8 * SECONDS = (uint8 *)IPSBAR + 0x03C7; // registrador dos segundos uint8 * HOUR = (uint8 *)IPSBAR + 0x03C2; // registrador de horas uint8 * MINUTES = (uint8 *)IPSBAR + 0x03C3; // registrador de minutos uint8 *ddrtc = (uint8 *)DDRTC; uint8 *porttc = (uint8 *)PORTTC; uint8 *ddran = (uint8 *)DDRAN; uint8 *portan = (uint8 *)PORTAN; uint8 *ddrub = (uint8 *)DDRUB; uint8 *pubpar = (uint8 *)PUBPAR; uint8 *ddras = (uint8 *)DDRAS; uint8 *portas = (uint8 *)PORTAS; uint8 *paspar = (uint8 *)PASPAR; uint8 *clras = (uint8 *)CLRAS; uint8 *epfr = (uint8*) EPFR; uint16 *eppar = (uint16*) EPPAR; uint8 *epier = (uint8*) EPIER; uint32 *imrl = (uint32*) IMRL; uint8 *epdr = (uint8*) EPDR; uint8 *portubp = (uint8 *)PORTUBP;

int teclado[12]={0,0,0,0,0,0,0,0,0,0,0,0};

__declspec(interrupt) void interrupcao();

__declspec(interrupt) void interrupcao_pit0();

int modulus=0,prescaler=0,flag=0,k=99,parado=0,hp1=0,hp2=0,mp1=0,mp2=0,sp1=0,sp2=0,decimop=0,h1=0,h2=0,m1=0,m2=0,s1=0,s2=0,decimo=0,ha1=99,ha2=99,ma1=99,ma2=99,sa1=99,sa2=99,decimoa=99,cr=0; char msg1[7]={'\n','\r','H','o','r','a',':'},msg2[9]={'\n','\r','M','i','n','u','t','o',':'},msg3[10]={'\n','\r','S','e','g','u','n','d','o',':'},msg4[8]={'\n','\r','A','l','a','r','m','e'},msg5[7]={'\n','\r','D','e','c','s',':'},msg6[5]={'\n','\r','F','i','m'}; //////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////

//Função que gera um delay suficiente para o LCD funcionar/processar void delay() { int i,j;

for(i=0;i<40;i++) { for(j=0;j<1000;j++) {

} }

}

//////////////////////////////////////////////////////////////////////////////////////////////////////

//FUNÇÃO DE TRANSMISSÃO QSPI void envia_spi(uint8 sinal) { MCF_QSPI_QAR = 0x0000; //Registrador de endereço aponta para área de transmissão MCF_QSPI_QDR = sinal; //É armazenado o dado a ser transmitido MCF_QSPI_QDLYR |= 0x8000; //Dá início à transmissão }

//////////////////////////////////////////////////////////////////////////////////////////////////////

//CONFIGURAÇÃO DO PERIFERICO QSPI void configura_spi() { MCF_GPIO_PQSPAR |= 0x1555; //A porta porta QS exerce função QSPI (Configura PQSPAR)

//Configuração do registrador "Mode" MCF_QSPI_QMR &= ~(MCF_QSPI_QMR_CPHA); //Dados mudam na borda de subida do clk MCF_QSPI_QMR |= MCF_QSPI_QMR_MSTR; //Modo MASTER (Obrigatorio) MCF_QSPI_QMR |= MCF_QSPI_QMR_BITS(0x8); //8bits por transmissão MCF_QSPI_QMR |= MCF_QSPI_QMR_BAUD(0x2); //Baud Rate 10Mhz

MCF_QSPI_QDLYR = 0x0000; //Delay register = 0 Delays são todos zero MCF_QSPI_QWR = 0x1000; //Abaixa nível de CS0 e informa transmisão única

                                           //Lembrando-se que o HLT pára transmissão

MCF_QSPI_QIR |= MCF_QSPI_QIR_SPIF; //Garante que o "finish flag" é alto nível

//Programa a transmissão MCF_QSPI_QAR = 0x0020; //Registrador de endereço aponta para área de comandos MCF_QSPI_QDR = 0x7E00; //Programa a transmissão (nº de bits...) }

void init() {


      // Prioridade da int = 0
      MCF_INTC0_ICR55 = 0 | MCF_INTC_ICR_IP(0) | MCF_INTC_ICR_IL(1);
      //Permite interrupção
      MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASKALL;
      MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_INT_MASK55;
      // divide o clock em 2
      prescaler = 0x7;
      modulus = 31250; 
      // interrupções a cada 100 ms


      MCF_PIT0_PMR = modulus;
       
      

// Configuração de PIT0

      MCF_PIT0_PCSR = (uint16)
       ( MCF_PIT_PCSR_PRE(prescaler) 

         | MCF_PIT_PCSR_PIE          // Permite interrupção
         | MCF_PIT_PCSR_RLD          
         | MCF_PIT_PCSR_PIF          // Zera flag de interrupção
         | MCF_PIT_PCSR_EN           // Habilita o contador
      ); 
      
      //Prioridade do microprocessador 
      asm 
      {
               move.w #0x2000, sr
      }       
      // Configura Porta B como GPIO e porta de entrada
      *pubpar = 0;
  		*ddrub  = 0;        

}

void tecl_checkchar()//funçao que verifica qual botao foi apertado , modficando o vetor teclado { int i,j, mask; int aterra[4] = {0x0E,0x0D,0x0B,0x07}; /*Sequencia de saidas para as portas*/ int io[4] = {0x01,0x02,0x04,0x08}; /*Sequencia de configuracao de porta*/ int indice=0;

for (i=0; i<4; i++) //Rotina para varrer teclado { *ddrtc = io[i]; *porttc = aterra[i];

mask = 0x01;

for (j=0;j<3;j++) { if(mask & *portubp) { teclado[indice] = 0; } else { teclado[indice] = 1;/*um elemento dentro do vetor teclado (antes definido como 0) é setado*/ }

       	mask = mask <<1;//Verifica bit seguido (colula j)
   		indice++; //Passa para próximo digito no vetor teclado

} } }

void tecl_init() // função para iniciar o teclado deixando-o pronto para receber a interrupção { *ddrtc = 0xFF; *porttc = 0x00; *pubpar = 0x00;//Configura porta UB para trabalhar como porta comum *ddrub = 0x00;//Configura UB como ENTRADA

*epfr = 0x10; // reseta flag de IRQ4 *epier = 0x10;// habilita interrupções de IRQ4 *eppar = 0x0200;//configura interrupção para ser percebida na borda de descida *epdr = 0x10;// configura IRQ4 como input *imrl = 0xFFFFFFEF;// habilita o tratamento de interrupção }

void zeracronometro() { h2=0; h1=0; m2=0; m1=0; s2=0; s1=0; k=99; }

void paracronometro() { if(parado==0){ hp1=h1; hp2=h2; mp1=m1; mp2=m2; sp1=s1; sp2=s2; decimop=decimo; parado=1; k=99; } }


void recomecacronometro() { parado=0; k=99; } void entrada() { int i;

for(i=0;i<7;i++){ uart_putchar(0,msg1[i]); } delay(); h2=uart_getchar(0); uart_putchar(0,h2); h2=h2-'0'; delay(); h1=uart_getchar(0); uart_putchar(0,h1); h1=h1-'0'; delay();

for(i=0;i<9;i++){ uart_putchar(0,msg2[i]); } m2=uart_getchar(0); uart_putchar(0,m2); m2=m2-'0'; delay(); m1=uart_getchar(0); uart_putchar(0,m1); m1=m1-'0'; delay();

for(i=0;i<10;i++){ uart_putchar(0,msg3[i]); } s2=uart_getchar(0); uart_putchar(0,s2); s2=s2-'0'; delay(); s1=uart_getchar(0); uart_putchar(0,s1); s1=s1-'0';

for(i=0;i<7;i++){ uart_putchar(0,msg5[i]); } decimo=uart_getchar(0); uart_putchar(0,decimo); decimo=decimo-'0';

}

void ajustacronometro() { entrada(); k=99; }


void imprimir(){ int i; char mensagem[] = "TIME: "; *portas = 0x03; //Seleciona o LCD com escrita de CARACTER

//Envia os caracteres para o LCD for (i=0; i<5; i++) { envia_spi(mensagem[i]); //Envia o caracter delay(); }

s1= s1+'0'; s2= s2+'0'; m1= m1+'0'; m2= m2+'0'; h1= h1+'0'; h2= h2+'0'; decimo= decimo +'0';


uart_putchar(0,'\r'); *portas = 0x03; envia_spi(h2); uart_putchar(0,h2); delay(); envia_spi(h1); uart_putchar(0,h1); delay(); envia_spi(':'); uart_putchar(0,':'); delay(); envia_spi(m2); uart_putchar(0,m2); delay(); envia_spi(m1); uart_putchar(0,m1); delay(); envia_spi(':'); uart_putchar(0,':'); delay(); envia_spi(s2); uart_putchar(0,s2); delay(); envia_spi(s1); uart_putchar(0,s1); delay(); envia_spi(':'); uart_putchar(0,':'); delay(); envia_spi(decimo); uart_putchar(0,decimo); delay();

uart_putchar(0,'\r'); *portas = 0x02; envia_spi(0x80);

delay();

s1= s1-'0'; s2= s2-'0'; m1= m1-'0'; m2= m2-'0'; h1= h1-'0'; h2= h2-'0'; decimo= decimo -'0';

delay(); }


void converte() {

if(decimo>9) { s1++; decimo=0; } if(s1>9) { s2++; s1=0;

} if(s2>5) {

m1++; s2=0; } if(m1>9) {

m2++; m1=0; } if(m2>5) {

h1++; m2=0; } if(h1>9) { h2++; h1=0;

} if((h2>2)||(h1>4)) { h2=0; h1=0; } }

void principal() { converte();

if (parado==1){ h1=hp1; h2=hp2; m1=mp1; m2=mp2; s1=sp1; s2=sp2; decimo=decimop; } imprimir();

}

void ajustaalarme() { int i;

for(i=0;i<8;i++){ uart_putchar(0,msg4[i]); }


for(i=0;i<7;i++){ uart_putchar(0,msg1[i]); } delay(); ha2=uart_getchar(0); uart_putchar(0,ha2); ha2=ha2-'0'; delay(); ha1=uart_getchar(0); uart_putchar(0,ha1); ha1=ha1-'0'; delay();

for(i=0;i<9;i++){ uart_putchar(0,msg2[i]); } ma2=uart_getchar(0); uart_putchar(0,ma2); ma2=ma2-'0'; delay(); ma1=uart_getchar(0); uart_putchar(0,ma1); ma1=ma1-'0'; delay();

for(i=0;i<10;i++){ uart_putchar(0,msg3[i]); } sa2=uart_getchar(0); uart_putchar(0,sa2); sa2=sa2-'0'; delay(); sa1=uart_getchar(0); uart_putchar(0,sa1); sa1=sa1-'0'; delay();

for(i=0;i<7;i++){ uart_putchar(0,msg5[i]); } decimoa=uart_getchar(0); uart_putchar(0,decimoa); decimoa=decimoa-'0'; if(decimo>10)decimo=0; delay();

k=99; }


void checaalarme() { int i,j;

if((h2==ha2)&&(h1==ha1)&&(m2==ma2)&&(m1==ma1)&&(s2==sa2)&&(s1==sa1)&&(decimo==decimoa)) { for(j=0;j<3;j++){ for(i=0;i<8;i++){ uart_putchar(0,msg4[i]); } for (i=0; i<8; i++) { *portas = 0x03; envia_spi(msg4[i]); delay(); } *portas = 0x02; envia_spi(0x01); delay(); } } }

void tecl_getchar() // função que identifica qual tecla foi apertada { int a,i;

	for (a=0; a<12; a++)
	{
		if (teclado[a]==1)
		{
			k=a;// verifica o indice do elemento modficado no vetor teclado
		}
	}
	
	switch (k) // assimila o indice com a tecla apertada para verificar o char relacionado

{ case 0: //zera break; case 1: //para break; case 2: //volta break;

 		case 3:

//ajusta break; case 4: //ajusta alarme break; case 5: // break; case 6: // break; case 7: // break; case 8: // break; case 9: // break; case 10: // break; case 11: // break; default: // break; }

}

void interrupcao() { tecl_checkchar(); tecl_getchar();

   	tecl_init();                 

}

void funcoes() { if(k==0) { zeracronometro(); } if(k==1) { paracronometro(); } if(k==2) { recomecacronometro(); } if(k==3) { ajustacronometro(); } if(k==4) { ajustaalarme(); }

}

void interrupcao_pit0() {

//Esta função seta 1 ou 0 na porta TC0 e simultaneamente na porta AN2 //Com isso geramos uma onda quadrada de período 2* o definido pelo contador na

//Primeiro verificamos o status da porta: if (flag==0) { //Se a porta ficou abaixada, agora é levantada

  • porttc = 0x01;
  • portan = 0x04;

//Altera a flag: flag = 1; } else {

  • porttc = 0x00;
  • portan = 0x00;

flag = 0; }

MCF_PIT0_PCSR |= MCF_PIT_PCSR_PIF;


decimo++;

} ///////////////////////////////////////////////////////////////////////////////////////////


//Função Principal int main(void) {

int i; uint8 configuracao[4] = {0x38, 0x06, 0x0F, 0x01}; //Configuracao do LCD // 0x38 = habilita 8 bits, 1 linha e matriz 5x7 // 0x06 = cursor para a direita sem deslocamento da msg // 0x0F = Liga display, cursor e cursor piscante // 0x01 = Limpa todo display e move o cursor para a primeira posição


tecl_init();

uart_init(0,80000,9600);

configura_spi(); //Configura o SPI (Configuração fixa)


*paspar = 0x00; //Define a porta AS como IO comum *ddras = 0x03; //Define a porta AS como saída *clras = 0x00; //Zera a porta AS

//Lembrando que a porta AS1 escolhe para onde os dados do SPI vão: //DAC (0) ou LCD (1)

//No caso do LCD, quando desejamos mandar um COMANDO, AS0 = 0 //Para enviarmos um caracter, AS0 = 1

delay(); //Espera um tempo para o LCD inicializar

//Seleciona LCD com escrita de COMANDO *portas = 0x02; // AS1 = 1 e AS0 = 0

//Envia os comandos de configuração do LCD for (i=0; i<3; i++) { envia_spi(configuracao[i]); //Envia o comando delay(); }

init();

zeracronometro();

*portas = 0x02; envia_spi(0x01); delay();

while(1) { funcoes(); checaalarme(); principal(); } }

Funcionamento:O relógio apresenta o horário no formato HH:MM:SS:dS no hyperterminal e LCD ,simultaneamente. As funções desenvolvidas são zerar, parar, setar e alarme, sendo estas acionadas através do teclado auxiliar: 1)Zera o cronometro; 2)Para a contagem: 3)Reinicia a contagem; 4)Ajusta o horário; 5)Ajusta o alarme; Sendo que a entrada de dados é feita através do teclado principal (do computador).

Interrupções: Foram utilizadas 2 interrupções ; uma que ocorre a cada decimo de segundo para implementar a contagem do relógio e outra que faz a leitura do teclado auxiliar.

Problemas encontrados: 1)Quando o relógio é parado , os décimos de segundo ficam oscilando entre dois valores subsequentes. 2)A entrada de funções deveria ocorrer tanto no teclado principal e auxiliar ,no entanto , ocorre apenas pelo auxiliar. 3)A entrada de dados deveria ocorrer por ambos teclados , mas só ocorre pelo principal. 4)Não foi utilizada interrupção UART.

Ferramentas pessoais