Página 1 de 1

display 7 segmentos multiplexado

MensagemEnviado: 18 Set 2009 14:10
por r.bertini
Olá pessoal!

Estou lendo o livro do Wagner Zanco - Tecnicas de Soft. e Hard. para projetos de ckt eletronicos - PIC16F877A e programando em C com o MikroC (seguindo o material da microgenios) e simulando no proteus.
Pesquisei bastante aqui no fórum sobre programação para display 7seg multiplexado, e até entendi um pouco.

O que eu não consigo é programar o timer pra estouro entre 4 ms e 8 ms.

Alguém pode me mostar onde estou errando? O código é esse aqui:
Código: Selecionar todos
unsigned int disp;
unsigned short i;
unsigned short mask(unsigned short num)
{
      switch(num)
      {
      case 0 : return 0x3f;
      break;
      case 1 : return 0x06;
      break;
      case 2 : return 0x5b;
      break;
      case 3 : return 0x4f;
      break;
      case 4 : return 0x66;
      break;
      case 5 : return 0x6d;
      break;
      case 6 : return 0x7d;
      break;
      case 7 : return 0x07;
      break;
      case 8 : return 0x7f;
      break;
      case 9 : return 0x6f;
      break;
      }
}
void interrup(void)
{
if(intcon.tmr0if==1)
{
disp ++;
portb=0x01;
TMR0L=250;
intcon.tmr0if=0;
intcon.giel=0;
portb=0x00;
}
}
void main()
{
T0CON=0xc0;
TMR0L=250;
intcon=0x20;
intcon.tmr0if=0;
adcon1=0x00;
intcon=0x00;
portc=0x00;
trisc=0x00;
trisa=0x00;
trisb=0x00;


do
{
for(i=0; i<=9; i++)
{
portc = mask(i);
delay_ms(500);
if(disp==1) porta=0x01;
if(disp==2) porta=0x02;
if(disp==3) porta=0x04;
if(disp==4)
{
porta=0x08;
disp=0;
}
}}while(1);
}


e o ckt do proteus é esse:
http://rapidshare.com/files/281849048/7seg.rar

O programa é um contador de 0 a 9 que deve mostrar a contagem em todos os displays ao mesmo tempo.

Valeu.

MensagemEnviado: 18 Set 2009 15:41
por Fabio777
Olá amigo, os transistors (segundo o proteus) estão fracos para o display. Subistitua os BC548 por BD911.

Abraços

MensagemEnviado: 18 Set 2009 17:54
por r.bertini
Fabio777 escreveu:Olá amigo, os transistors (segundo o proteus) estão fracos para o display. Subistitua os BC548 por BD911.

Abraços


Fábio777, valeu pela dica, subistitui o BC548 pelo BD911 e funcionou porém só 2 displays.

Como que você viu pelo proteus que o transistor estava fraco?

Abraços

MensagemEnviado: 18 Set 2009 20:22
por Fabio777
Eu percebi que apenas os digitos "1" e "7" estavam funcionando (digitos que consomem menor corrente), então conclui que se precisava de mais corrente :D

Já ao fato de apenas dois displays funcionarem vc precisa olhar com mais atenção o seu programa:

void interrup(void) -------> void interrupt(void)

intcon=0x00; (por que está desligando as interrupções ?)


Abraços

MensagemEnviado: 19 Set 2009 11:17
por r.bertini
Valeu Fabio, arrumei os erros que você apontou.

Mas mesmo assim só acende dois displays, no material da microgênios que estou pesquisando tem a fórmula pra cálculo do valor de contagem:

Tempo de estouro=ciclo de maq x prescaler(limite de contagem - valor da contagem)
estou fazendo assim:

8ms=0,5usx1(255-vc)

Vou tentar aqui e depois posto o resultado.

Acabei de testar e configurei o TMR0 para 1s e coloquei pra mostrar o valor de disp nos displays e funcionou a cada 1s ele me mostra em um display o valor de disp, mas depois de um tempo ele para no display 3 e conta até 9.
segue o programa de teste:
Código: Selecionar todos
unsigned int disp;
unsigned short i;
unsigned short mask(unsigned short num)
{
      switch(num)
      {
      case 0 : return 0x3f;
      break;
      case 1 : return 0x06;
      break;
      case 2 : return 0x5b;
      break;
      case 3 : return 0x4f;
      break;
      case 4 : return 0x66;
      break;
      case 5 : return 0x6d;
      break;
      case 6 : return 0x7d;
      break;
      case 7 : return 0x07;
      break;
      case 8 : return 0x7f;
      break;
      case 9 : return 0x6f;
      break;
      }
}
void interrupt(void)
{
if(intcon.tmr0if==1)
{
disp ++;
portb=0x01;
TMR0L=0xf6;
TMR0H=0xc2;
intcon.tmr0if=0;
}
else if(intcon.tmr0if==0){
//intcon.giel=0;
portb=0x00;
}
}
void displays()
{
if(disp==1)
{
 porta=0x01;
 }
if(disp==2)
{
 porta=0x02;
 }
if(disp==3)
{
 porta=0x04;
 }
if(disp==4)
{
porta=0x08;
disp=0;
}}
void main()
{
T0CON=0x86;
TMR0L=0xf6;
TMR0H=0xc2;
intcon=0xE0;
intcon.tmr0if=0;
adcon1=0x06;
portc=0x00;
trisc=0x00;
trisa=0x00;
trisb=0x00;

do
{
//for(i=0; i<=9; i++)
//{
portc = mask(disp);
delay_ms(1000);
displays();
//}
}while(1);
}

MensagemEnviado: 19 Set 2009 18:51
por Fabio777
Olá bertini

Está bem legal o código, ele só está travando porque em certo momento a variável "disp" está sendo incrementada duas vezes antes de ser testada e ao não passar pelo valor 4 ela não é resetada. Você pode diminuir o delay e por segurança adicionar:
if(disp > 4) disp = 0;

Abraços

MensagemEnviado: 21 Set 2009 14:28
por barboza
Código: Selecionar todos

const byte mask[10] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6d, 0x7D, 0x07, 0x7F, 0x6F };

do
{
   for(i=0; i<=9; i++)
   {
      portc = mask(i);
      delay_ms(500);
      porta &= 0xF0;
      porta |= (1<<disp);
      disp++;
      disp &= 0x03;
   }
}while(1);

MensagemEnviado: 21 Set 2009 17:28
por fabim
...............[i];

MensagemEnviado: 21 Set 2009 19:43
por r.bertini
barboza, testei esse programa e não funcionou.

fabim, ajuda ieu mizifio


Abraços

MensagemEnviado: 22 Set 2009 09:16
por barboza
r.bertini escreveu:barboza, testei esse programa e não funcionou.

fabim, ajuda ieu mizifio


Abraços



Este ai é só uma idéia básica.
Poste o código completo que testou.

O certo é colocar o conteúdo dos display em um buffer em RAM e deixar a interrupção atualizando fazendo a varredura e atualização no display.

MensagemEnviado: 22 Set 2009 10:27
por fabim
r.bertini escreveu:barboza, testei esse programa e não funcionou.

fabim, ajuda ieu mizifio


Abraços


é posso ajudar sim, só preciso saber o que você quer.
não entendi bulhufas..

o zói humano acima de 25 piscadas dentro de um segundo não consegue perceber, ele simplesmente acha que a luz esta mais fraca ou mais forte.
São 4trus displays.
1segundo / 25frames = 40mS por frame.
Sabendo o comprimento do frame, e quantos mostradores ten-se que são 4, fica 10mS por display.

fica +/- assim.
interrupt pelo timer, estouro 10mS+/-.
mostra disp 1;
proximo estouro
mostra disp 2;
proximo estouro
mostra disp 3;
proximo estouro
mostra disp 4
proximo estouro
vorta pro disp1........

E fica em um looping infinito.

Tu ja tem a tabela de amostragem de converção de binario para BCD7S.
Sendo assim, tu tambem ja sabe quais são os pinos para setar o determinado display.
o seu contador "int" é incrementado a cada 1S na interrupt...

No main,
wordtostr(contador, array);
array_dos_displays[0] = mask(array[0]-'0');
array_dos_displays[1] = mask(array[1]-'0');
array_dos_displays[2] = mask(array[2]-'0');
array_dos_displays[3] = mask(array[3]-'0');

10mS da pra fazer isso e ainda sobra tempo pra ir tomar um cafézinho..

Entendeu ?

porque eu não tendi nada..

MensagemEnviado: 22 Set 2009 10:53
por barboza
Se não sair agora, sei não hein..........



Código: Selecionar todos
int main (void)
{
   // Config hardware


   // Loop Infinito
   while (1)
   {
      // Conte de 0 a 9 em loop
      for (i = 0; i < 10; i++)
      {
         // Escreva o mesmo valor em todos os displays
         for (d = 0; d < 4; d++)
         {
            // Copia o valor em decimal para a RAM interna do display
            array_dos_displays[d] = i;
         }
         // Delay para testes - Odeio esta função.
         delay_ms(xxxxx);
      }
   }
}


// Timer de 5ms = 200Hz = 50Hz por display
void interrupt (void)
{
   // Desliga todos os displays ligados ao nibble baixo da porta x
   port_comun &= 0xF0;

   // Converte do decimal para o mapa do display atual
   port_seg = mask(array_dos_displays[display]);

   // Ligue somente o display atual, 0..3 = 0x1, 0x2, 0x4, 0x8
   port_comun |= (1<<display);

   // Incremente o display para a proxima int
   display++;

   // Limite ao range de 0..3 = display 1 a 4
   display &= 0x03;
}