display 7 segmentos multiplexado

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

display 7 segmentos multiplexado

Mensagempor r.bertini » 18 Set 2009 14:10

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.
R.Bertini
__________________________________
#include<stdio.h>
main()
{
printf("\n R.Bertini");
}
r.bertini
Bit
 
Mensagens: 28
Registrado em: 30 Ago 2008 01:43

Mensagempor Fabio777 » 18 Set 2009 15:41

Olá amigo, os transistors (segundo o proteus) estão fracos para o display. Subistitua os BC548 por BD911.

Abraços
Fabio777
Nibble
 
Mensagens: 62
Registrado em: 19 Fev 2008 11:26

Mensagempor r.bertini » 18 Set 2009 17:54

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
R.Bertini
__________________________________
#include<stdio.h>
main()
{
printf("\n R.Bertini");
}
r.bertini
Bit
 
Mensagens: 28
Registrado em: 30 Ago 2008 01:43

Mensagempor Fabio777 » 18 Set 2009 20:22

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
Fabio777
Nibble
 
Mensagens: 62
Registrado em: 19 Fev 2008 11:26

Mensagempor r.bertini » 19 Set 2009 11:17

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);
}
R.Bertini
__________________________________
#include<stdio.h>
main()
{
printf("\n R.Bertini");
}
r.bertini
Bit
 
Mensagens: 28
Registrado em: 30 Ago 2008 01:43

Mensagempor Fabio777 » 19 Set 2009 18:51

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
Fabio777
Nibble
 
Mensagens: 62
Registrado em: 19 Fev 2008 11:26

Mensagempor barboza » 21 Set 2009 14:28

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);
Os homens mentiriam muito menos se as mulheres fizessem menos perguntas.
Avatar do usuário
barboza
Word
 
Mensagens: 948
Registrado em: 17 Out 2006 13:42
Localização: Longe de onde gostaria de estar

Mensagempor fabim » 21 Set 2009 17:28

...............[i];
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor r.bertini » 21 Set 2009 19:43

barboza, testei esse programa e não funcionou.

fabim, ajuda ieu mizifio


Abraços
R.Bertini
__________________________________
#include<stdio.h>
main()
{
printf("\n R.Bertini");
}
r.bertini
Bit
 
Mensagens: 28
Registrado em: 30 Ago 2008 01:43

Mensagempor barboza » 22 Set 2009 09:16

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.
Os homens mentiriam muito menos se as mulheres fizessem menos perguntas.
Avatar do usuário
barboza
Word
 
Mensagens: 948
Registrado em: 17 Out 2006 13:42
Localização: Longe de onde gostaria de estar

Mensagempor fabim » 22 Set 2009 10:27

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..
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor barboza » 22 Set 2009 10:53

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;
}
Os homens mentiriam muito menos se as mulheres fizessem menos perguntas.
Avatar do usuário
barboza
Word
 
Mensagens: 948
Registrado em: 17 Out 2006 13:42
Localização: Longe de onde gostaria de estar


Voltar para PIC

Quem está online

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

x