[Resolvido] Contador com display de 7 segmentos

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

[Resolvido] Contador com display de 7 segmentos

Mensagempor [Daniel] » 20 Dez 2010 07:50

Olá,

Estou começando a aprender C usando o compilador CCS, gostaria de uma ajuda dos colegas, é o seguinte:

Consegui fazer um contador com os displays usando apenas 1 display, minha meta é fazercom que conte de 0 até 9999, multiplexando os mesmos mas este não é o problema, isso eu já resolvi a respeito da multiplx....
Então meu problema não seria multiplexar, mas basicamente como fazer para o programa incrementar e decrementar esse valor , quais as maneiras mais recomendadas de se fazer isso..

Por exemplo, eu creio que possa usar uma int16 afim de fazer a contagem assim, mas como eu faço as demais partes? Dividir o numero em milhar centena dezena e unidade, como posso criar uma sub-rotina pra isso em CCS por exemplo...

Eis meu codigo:
Código: Selecionar todos
#include <16f628a.h>
#use delay(clock=4000000)
#FUSES NOWDT, INTRC_IO, PUT, NOPROTECT, NOBROWNOUT, NOMCLR, NOLVP, NOCPD

int8 valor=0;           //variáveis globais
int8 valor_2=0;
int8 contador=0;

//tabela de converção de números
 byte const tabela[]= {0b00000000,//0
                       0b00010000,//1
                       0b00100000,//2
                       0b00110000,//3
                       0b01000000,//4
                       0b01010000,//5
                       0b01100000,//6
                       0b01110000,//7
                       0b10000000,//8
                       0b10010000,//9
                       0b00000000};

//interrupção do timer 0
#int_timer0
void trata_t0()
{
   switch(contador)
   {
   case 0:                 //contador=0, mostra display unidades
   output_b(tabela[valor]);
   output_low(pin_b2);
   contador=1;
   break;
   case 1:                 //contador=1, mostra display de dezenas
   output_b(tabela[valor_2]);
   output_high(pin_b2);
   contador=0;
   break;
   }
}

//programa principal
main()
{
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   enable_interrupts(global|int_timer0); //ativa a interrupção do tmr0
   while(true)
   {
      if (input(pin_a4)==0)         //se pino ra4=0:
      {
         valor++;                   //incrementa  valor
         if (valor>9) valor=9;      //se >9 será =9 (trava incr.)
         delay_ms(100);             //debounce para o botão
      }
      else if (input(pin_a7)==0)    //se ñ, veja se pino ra7=0:
      {
         if (valor==0) valor=1;     //se valor=0, valor será 1
         valor--;                   //então decr. e torna-se 0 novamente
         delay_ms(100);             //debounce para o botão
      }
   }
}


Ele já multiplexa unidade e dezena mas so mexe nas unidades...
Eu uso uma placa lab de teste, pelo que podem ver tenho um 4511 ligado nos pinos RB4 a RB7.

Obrigado pela colaboração.
Editado pela última vez por [Daniel] em 21 Dez 2010 10:50, em um total de 2 vezes.
Avatar do usuário
[Daniel]
Byte
 
Mensagens: 106
Registrado em: 18 Nov 2009 09:14

Mensagempor ze » 20 Dez 2010 10:34

isso é +- fácil. mas é o difícil mesmo é não dizer algo sobre sua ferramenta de começo. mas enfim...consigo.
vamos criar uma variável int que vai ser exposta no display 7seg 4 digitos
Código: Selecionar todos
unsigned int v;

sua tabela tem 10 posições, portanto ela pode ser acessada de 0 a 9
vamos criar índices com 4 variáveis char globais uma pra cada dígito do display:
Código: Selecionar todos
unsigned char q[4];
//q[0]=unidade
//q[1]=dezena
//q[2]=centena
//q[3]=milhar
agora vamos quebrar a variável v nestas 4
Código: Selecionar todos
void quebra(unsigned int dd)
{
unsigned char j;
for(j=0;j<4;j++) //4 dígitos
      {
      while(TMR1H);//aguade, a interrupt confunde o display
   q[j]=dd%10; //só o resto interessa
      dd/=10; //quebrando.
   }
}
no main()
Código: Selecionar todos
...
if (...) v++;
if (...) v--;// etc
quebra(v);
...
o que tiver em v vai pro display. para multiplexar na sua int:
Código: Selecionar todos
unsigned char i; //global
void tim1(void) __interrupt 0 //sintaxe do sdcc
{
PORTB=tabela[q[i]] | 1<<i; //coloca o padrão da tabela na posição correta
i++; if (i>3) i=0; //só 4 dígitos
}
este princípio vale também pra quando não for usar 4511 desde que modifique a tabela, óbvio. A propósito pro 4511 não precisa de tabela, sabia? claro.
digitei isso aqui sem testar e sem pensar [muito], portanto perdoe-me por algum erro. corrijo depois se for o caso.

editei: alguma correção bem como fiz um exemplo com sdcc pra verfificar. 1/2 que funcionou com alguma peculiaridade. amanhã posto (ou não) o fonte e simulação do proteus.

hoje é o amanhã de ontem. editei de novo pra não criar outro irritante post sequencial. veja o anexo
Imagem
salve a figura no seu pc e abra com o 7zip. (o windows não abre como zip) mude a extensão para .zip ou .7z e veja o conteúdo oculto. aí tem os fontes sdcc e simulação proteus. pode ser que não lhe seja 100% inútil. se um dia fizer em ccs algo similar, gentileza comparar os tamanhos dos cod gerados. a qualquer momento vou compilar isso no hitech pra comparar. ou não.

abç & sucessos de novo mais uma vez
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor [Daniel] » 21 Dez 2010 11:07

lellis

Abri o arquivo que colocasse na foto muito bacana, inclusive funciona bem legal era isso que eu queria, porém o jeito que você escreve é diferente do que estou aprendendo... Não entendi por exemplo as expressões:

q[4]...
PORTB=tabela[q[i]] | 1<<i;...

Me esforcei mais um pouco e tentei escrever como eu faria em asm e ficou assim, (usando unidade e dezena) e também funcionou:

Código: Selecionar todos
#include <16f628a.h>
#use delay(clock=4000000)
#FUSES NOWDT, INTRC_IO, PUT, NOPROTECT, NOBROWNOUT, NOMCLR, NOLVP, NOCPD

int8 valor=0;           //variáveis globais
int8 unidade=0;
int8 dezena=0;
int8 contador=0;

//tabela de converção de números
 byte const tabela[]= {0b00000000,//0
                       0b00010000,//1
                       0b00100000,//2
                       0b00110000,//3
                       0b01000000,//4
                       0b01010000,//5
                       0b01100000,//6
                       0b01110000,//7
                       0b10000000,//8
                       0b10010000,//9
                       0b00000000};

//interrupção do timer 0
#int_timer0
void trata_t0()
{
   switch(contador)
   {
   case 0:                 //contador=0, mostra display unidades
   output_b(tabela[unidade]);
   output_low(pin_b2);
   contador=1;
   break;
   case 1:                 //contador=1, mostra display de dezenas
   output_b(tabela[dezena]);
   output_high(pin_b2);
   contador=0;
   break;
   }
}

void converte()
{
   dezena=valor/10;
   unidade=valor%10;
}
//programa principal
main()
{
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   enable_interrupts(global|int_timer0); //ativa a interrupção do tmr0
   while(true)
   {
      if (input(pin_a4)==0)         //se pino ra4=0:
      {
         valor++;                   //incrementa  valor
         if (valor>99) valor=99;    //se >9 será =9 (trava incr.)
         converte();
         delay_ms(80);
      }
      else if (input(pin_a7)==0)    //se ñ, veja se pino ra7=0:
      {
         if (valor==0) valor=1;     //se valor=0, valor será 1
         valor--;                   //então decr. e torna-se 0 novamente
         converte();
         delay_ms(80);
      }
   }
}


O arquivo compilado para asm deu 281linhas...

Po cara valeuzão pela ajuda de novo!
Avatar do usuário
[Daniel]
Byte
 
Mensagens: 106
Registrado em: 18 Nov 2009 09:14


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x