Você está na página 1de 8

PROJETO DE SISTEMAS DIGITAIS, 2013-2

CONTADOR DE SENHAS

FILIPE DIAS PEREIRA

INTRODUO
Ao longo do segundo semestre de 2013, fomos apresentados aos assuntos da disciplina de Sistemas Digitais. Aps aprendermos conceitos importantes que abrangeram os conhecimentos de sistemas de numerao e cdigo, portas lgicas, lgica booleana, circuitos lgicos combinacionais, Flip-Flops e dispositivos correlatos, partimos para o enfrentamento prtico em aulas laboratoriais. Neste momento tivemos a oportunidade de aplicarmos os conhecimentos tericos previamente adquiridos, em aulas laboratoriais com experincias que faziam uso do microcontrolador PIC da Microchip. Vistas as funes existentes no microcontrolador, foi proposto pelo professor um trabalho prtico que consistia na programao do PIC para a exibio de senhas de chamada para atendimento (painel de senha), em quatro displays de sete segmentos.

Figura 1 - Diagrama de blocos Painel de Senhas.

O funcionamento do equipamento bem simples. Ao pressionar o boto prximo, um contador incrementado e o painel passa a exibir a prxima senha. O boto anterior tem a funo de decrementar o contador, fazendo exibir a senha imediatamente anterior a que est sendo exibida.

IMPLEMENTAO
Para desenvolver o projeto deveramos usar o kit Minipa SD-1700 e um PIC 16F877A. O kit Minipa j se encontra montado. Assim sendo, foi necessrio seguir as configuraes prestabelecidas. Os displays que representam o milhar, centena, dezena e unidade so ligados quando recebem nvel alto respectivamente nos pinos Rb4, Rb5, Rb6 e Rb7. O pino Rb4 tambm responsvel por mandar nvel lgico alto nos botes, que repassaro o nvel lgico para os pinos Rb2 e Rb1, conforme forem pressionados.

Assim sendo, os pinos Rb1 e Rb2 foram configuradas como entrada e os pinos Rb4 at Rb7 foram configuradas como sada. Alm deles, toda a Porta D foi configurada como sada, inclusive o pino Rd7, que ligaria o Dp (decimal point) no display. Como somente a Porta D ser usada para transmitir as informaes sobre quais segmentos do Display devem estar ou no acesos, a soluo encontrada foi usar os pinos Rb4~Rb7 para fazer a multiplexao dos displays. Desta maneira, em questo de milissegundos, ligaremos um display, mostraremos o nmero que desejamos, desligaremos o display e passaremos para o prximo display para exibir um novo algarismo. Resumidamente:

Liga Display

Repete o processo para os outros 3 Displays.

Transmite informao do algarismo (PortD).

Desliga Display

Aguarda alguns instantes

Figura 2 - Ciclo de acionamento dos displays

Para identificarmos se um dos botes foi pressionado, faremos a leitura dos pinos sempre que houver um estouro do TIMER 0. Como o pino Rb4 ser usado simultaneamente para ativar o display do milhar e tambm para alimentar os botes, ele ser tratado de forma especial no momento da interrupo do TIMER0. Assim que a rotina de interrupo for chamada, o valor que a porta D estiver recebendo no momento, ser copiado para uma varivel temporria. A porta D ento receber o valor que deveria estar sendo mostrado no display dos milhares. Desta maneira podemos colocar o pino RB4 em nvel lgico alto para leitura dos botes pelos pinos Rb1 e Rb2, e ainda garantiremos que o display dos milhares no exibir um nmero errado. Ao final da rotina de interrupo, desligamos o pino Rb4 e fazemos com que a porta D receba o valor da varivel temporria de quando a rotina foi iniciada.

FLUXOGRAMA
O fluxograma a seguir demonstra o funcionamento do contador de senha e a lgica implementada no firmware. Ao entrar no looping principal (P1) a rotina verifica se algum boto foi pressionado. Caso algum dos botes (prximo ou anterior) tenha sido pressionado, o programa partir para rotina de converso e alerta. Nesta rotina, o nmero atual convertido para o formato do display e um contador faz com que os quatro displays pisquem simultaneamente e o buzzer ligado ao pino Re2 emita um som, alertando que a vez do prximo atendimento. Caso nenhum boto tenha sido pressionado, a rotina principal permanece no looping exibindo o nmero atual no display. A rotina da interrupo do timer ser executada sempre que o contador do Timer 0 passar do valor de 255 para 0. O prescaler foi configurado para 256, assim sendo, teremos uma interrupo aproximadamente a cada 65 milissegundos. Nesta interrupo saberemos se algum dos botes foi pressionado e em caso positivo mudaremos o valor da varivel Numero.

Figura 3 - Fluxograma do Contador de Senhas

CDIGO FONTE
#include "16F877A.h" #fuses XT,nowdt,noprotect,put,brownout,nolvp,nocpd,nowrt #use delay(clock=4000000) #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #byte porta = 0x05 #byte portb = 0x06 #byte portc = 0x07 #byte portd = 0x08 #byte porte = 0x09 //############################ENTRADAS############################## #bit botaoProx = portb.1 #bit botaoAnte = portb.2 //#############################SAIDAS############################### #bit dispMilh = portb.4 #bit dispCent = portb.5 #bit dispDeze = portb.6 #bit dispUnid = portb.7 #bit buzzer = porte.2 //##########################VARIVEIS GLOBAIS######################## int apertou = 1; long int numero=0; char CHMilhar, CHCentena, CHDezena, CHUnidade, portTemp; //#####################FUNES############################# #int_rtcc void trataTMR0(){ int filtro =20; portTemp = portd; portd = CHMilhar; dispMilh=1; while(botaoProx && filtro>0){ filtro--; while(filtro==0){ //permanece looping enquanto boto no if (!botaoProx){ //confirma se o boto foi solto apertou=1; if(numero==9999) numero=0; //garante rotao else numero++; filtro--; } } } filtro =20; while(botaoAnte && filtro>0){ filtro--; while(filtro==0){ //permanece looping enquanto boto no if (!botaoAnte){ //confirma se o boto foi solto apertou=1; if(numero==0) numero=9999; //garante rotao else numero--;

for solto

do display

for solto

do display

filtro--; } } } dispMilh=0; portd = portTemp; } //############## DESMEMBRA O NUMERO PARA MILHAR, CENTENA, DEZENA ################# long int desmembraNum (long int num, char c){ switch(c){ case 'm': { return (num/1000); break; } case 'c': { return (num/100); break; } case 'd': { return (num/10); break; } } } //################ CONVERTE OS NUMERO DE INTEIRO PARA CHAR ###################### char convParaDisplay (long int x){ switch (x){ case 0:{ return (0b00111111); break; } case 1:{ return (0b00000110); break; } case 2:{ return (0b01011011); break; } case 3:{ return (0b01001111); break; } case 4:{ return (0b01100110); break; } case 5:{ return (0b01101101); break; } case 6:{ return (0b01111100); break;

} case 7:{ return break; } case 8:{ return break; } case 9:{ return break; } default: return break; } }

(0b00000111);

(0b01111111);

(0b01100111);

(0b11111111);

//################ IMPRIME OS NMERO ATRAVS DE MULTIPLEXAO ################### void printDisplay(char milhar, char centena, char dezena, char unidade){ portd=milhar; dispMilh=1; delay_ms(2); dispMilh=0; portd=centena; dispCent=1; delay_ms(2); dispCent=0; portd=dezena; dispDeze=1; delay_ms(2); dispDeze=0; portd=unidade; dispUnid=1; delay_ms(2); dispUnid=0; } //#################### GERA ALERTA PARA O PAINEL ############################# void alerta (char milhar, char centena, char dezena, char unidade){ long int i; int j; for (j=0; j<3;j++){ buzzer=1; for(i=0; i<500; i++){ printDisplay(milhar, centena, dezena, unidade); } buzzer=0; delay_ms(800); } }

void main ()

{ //####################variveis locais############################ long int milhar, centena, dezena, unidade, num;

// configura setup_counters(rtcc_internal , rtcc_div_256); enable_interrupts (global); enable_interrupts (int_rtcc); // configura os TRIS set_tris_a(0b00000000); set_tris_b(0b00001111); set_tris_c(0b10011001); set_tris_d(0b00000000); set_tris_e(0b00000000); // inicializa os ports porta=0x00; // limpa porta portb=0x00; // limpa portb portc=0x00; // limpa portc portd=0b00111111; // coloca 0000 nos displays porte=0x00; // limpa porte

//#####################Loop principal############################### while(TRUE){ if(apertou){ apertou=0; num = numero; milhar = desmembraNum(num, 'm'); num= num-(milhar*1000); centena = desmembraNum(num, 'c'); num = num-(centena*100); dezena = desmembraNum (num, 'd'); num = num-(dezena*10); unidade=num; CHMilhar = convParaDisplay(milhar); CHCentena = convParaDisplay(centena); CHDezena = convParaDisplay(dezena); CHUnidade = convParaDisplay(unidade); alerta (CHMilhar, CHCentena, CHDezena, CHUnidade); } printDisplay(CHMilhar, CHCentena, CHDezena, CHUnidade); } }

Você também pode gostar