Escolar Documentos
Profissional Documentos
Cultura Documentos
CONTADOR DE SENHAS
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.
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
Desliga Display
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.
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 ()
// 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); } }