Escolar Documentos
Profissional Documentos
Cultura Documentos
Como Usar Displays de Leds Multiplexados PDF
Como Usar Displays de Leds Multiplexados PDF
TENSO DIRETA
1,7 Volts
2,1 Volts
3,5 Volts
3,4 Volts
Desta maneira, para calcular o valor do resistor a ser posto em srie com o Led, basta
fazer a seguinte conta:
Aqui, vemos que o microcontrolador suporta tanto a corrente em cada pino (40 mA)
como a corrente total ( 200 mA ). Podemos prosseguir sem nenhum problema.
Antes de montar nosso circuito, vou explicar uma outra maneira de se utilizar os Leds,
que se chama Modo Pulsado.
Repare que at agora estamos falando de manter uma corrente constante, todo o tempo
em que o Led estiver aceso. Isso no obrigatrio, podemos sim variar a corrente nele!
E desta maneira podemos fazer uma corrente maior passar por ele, desde que seja por
pouco tempo.
Vamos ver um datasheet de um display Led para vermos quais informaes o fabricante
fornece:
Assim, criaremos uma tabela na memria, informando quais os bits que precisam ser
ligados para acender o nmero que quisermos! Onde o bit tiver o valor binrio 1
significa que o segmento correspondente vai estar aceso ! uma idia bem simples.
DIGITO Seg A
Seg B
Seg C
Seg D
Seg E
Seg F
Seg G
Binrio
0
1
2
3
4
5
6
7
8
9
1
1
1
1
1
0
0
1
1
1
1
1
0
1
1
1
1
1
1
1
1
0
1
1
0
1
1
0
1
0
1
0
1
0
0
0
1
0
1
0
1
0
0
0
1
1
1
0
1
1
0
0
1
1
1
1
1
0
1
1
00111111
00000110
01011011
01001111
01100110
01101101
01111101
00000111
01111111
01100111
1
0
1
1
0
1
1
1
1
1
Do
' vamos fazer um loop todo o tempo
For I = 0 To 9
Saida = Lookup(i , Tabela)
' procura o valor correspondente ao display na tabela
' e armazena na varivel SAIDA
Portb = Saida
' coloca os segmentos correspondentes ao nmero em I na sada
Wait 1
' espera 1 segundo antes de trocar
Next I
Loop
'volta ao incio do programa
End
Tabela:
' aqui est a tabela com a correspondencia dos segmentos a acender
Data &H3F , &H06 , &H5B , &H4F , &H66
Data &H6D , &H7D , &H07 , &H7F , &H67
Este programa, depois de compilado, tem o tamanho enorme de 370 bytes apenas.
Basta compilar, gerar o .hex e gravar no seu microcontrolador Atmega328P.
Quando energizar, o programa vai comear a mostrar os dgitos de 0 a 9, trocando a
cada 1 segundo.
O que o programa faz criar um contador, que vai de 0 at 9, e consulta uma tabela de
equivalncia, que vai retornar o valor necessrio para acender o display e formar o
nmero que desejamos mostrar.
Devido a isto ser muito simples, vamos passar para o prximo tpico, que a
Multiplexao.
Repare que aqui utilizamos um port inteiro para os 8 segmentos, e mais 4 pinos de outro
port para selecionar qual dgito ir acender. Usamos novamente uma rede de resistores,
que parece um Circuito integrado de 16 pinos, mas que contm dentro 8 resistores
apenas. Facilita muito o desenho do circuito!
Agora, repare bem, quando um determinado dgito estiver selecionado, suponha que
vamos acender o numero 8 mais o ponto decimal. So 9 pinos do Port B fornecendo a
corrente, e do jeito que est o esquema, existe um pino do outro Port C que recebe toda
essa corrente somada ! Mas....
E agora ???? No existe a informao que queremos para 40 mA. Qual o motivo? O
fabricante no quer que usemos essa corrente, pois isso vai diminuir muito a vida til do
componente!
Vamos fazer um exemplo terico apenas. Extrapolando o grfico, veremos que para 40
mA teremos uma tenso em torno de 0,9 Volts.
Agora, para calcular o resistor, temos de levar em considerao a queda de tenso do
pino que fornece a corrente e do pino que recebe a corrente!
Vamos pesquisar a queda para um pino que em nvel alto fornece 4,5 mA . Este grfico
j foi apresentado antes, e fazendo a consulta nele, teremos uma tenso de 4,9 Volts.
A tenso sobre o resistor seria de 4,9 0,9 1,7 = 2,3 / 0,0045 = 511 ohms. Usaremos o
valor comercial mais prximo acima, que de 560 ohms.
Na teoria, nosso circuito vai funcionar, dentro dos limites, mas temos um problema:
como abaixamos muito a corrente de cada segmento, ele vai ficar com um brilho bem
fraco.
Existem modelos especiais de displays de alto brilho, que mesmo com baixa corrente
permite um brilho bem razovel, mas estes modelos so caros.
Ainda nem levamos em conta um dos efeitos da Multiplexao: o brilho aparente,
para quatro displays, ser dividido por 4, o que tornar ainda mais fraco o brilho de
cada dgito.
Qual a soluo para aumentarmos essa corrente atravs dos Leds do Display?
Em vez de ligarmos direto o terminal comum do display em um microcontrolador,
vamos utilizar um transistor para receber essa corrente, pois ele suporta muito mais
corrente!
Desta maneira, poderemos ainda fornecer o limite de corrente em cada um dos 8 pinos,
o que vai permitir um brilho bem maior !
Agora, nossa nica limitao ser o total da corrente que o microcontrolador consegue
fornecer no total. Se quisermos fornecer ainda mais corrente para o display, ser
necessrio utilizar um CI tipo Source de corrente, como o UDN2981A, entre o
microcontrolador e o Display. E nesse caso, lembre-se de levar em conta a tenso
VceSat em vez da tenso de sada no pino do microcontrolador quando voc for calcular
o resistor limitador.
No nosso programa, a diferena ser a de que antes, para se acender o display,
teramos de levar esse pino por onde passa toda a corrente ao nvel 0 , e agora, teremos
de levar ao nvel 1, para que o transistor possa conduzir.
Quando chegarmos ao ultimo dos 4 dgitos, fazemos tudo de novo a partir do primeiro.
Segue a sequncia abaixo, onde cada display aceso sequencialmente (programa foi
compilado com freqncia de Multiplex de 4 hertz para as capturas), e por fim o uma
captura feita em velocidade real. Repare que as cores vermelhas nos terminais dos
componentes significam que existe nvel 1, e as azuis que a tenso nvel 0. Assim fica
fcil verificar todos os nveis em cada passo do programa. Apenas um aviso sobre os
resistores R1 at R4 : Eles no so necessrios no circuito real ! Mas so necessrios
para o correto funcionamento do simulador Isis do Proteus.
Simples, no ?
Esse processo possui um pequeno inconveniente. Imagine que o seu programa principal
calculou o numero a ser mostrado no display. Agora, imagine que j atualizou 3 dos 4
dgitos, e nesse momento acontece uma interrupo do timer, e vai justamente mostrar
um dos novos dgitos j atualizados. Na prtica, voc perceberia que de vez em quando
acontece algo esquisito, alguns erros piscam muito rpido no numero mostrado.
Para evitar isto, eu sugiro sempre o seguinte procedimento:
Creio que agora voc j sabe tudo para fazer o seu prprio projeto com displays
multiplexados.
Embora este pequeno tutorial foi baseado no Atmega328P, pode ser aplicado em
qualquer microprocessador. O uso da Linguagem Basic do Bascom torna bem simples a
compreenso e a migrao para outras linguagens.
Um ultimo comentrio sobre o delay necessrio no programa. O delay pode ser maio ou
menos, conforme a velocidade de processamento de seu programa. Nos exemplos aqui
da apostila, usamos um AVR com 8 MHz. Se usarmos a velocidade interna de 1 MHz,
temos de eliminar o comando de delay, pois j vai demorar bastante para executar a
rotina de interrupo, em torno de 150 microsegundos. E se o clock for de 16 MHz,
temos de aumentar o comando de delay para 24 microsegundos.
E se utilizar um Pic tipo 16f ou 18F ? s lembrar que o processamento dele 4 vezes
menor que o de um AVR no mesmo clock.
PROGRAMAS EM BASCOM
Todos os programas apresentados aqui compilam com sobras na verso Demo do
Bascom. Disponibilizarei tambm os arquivos para a simulao no ISIS para cada um
deles.
Apresentarei trs programas, sendo o primeiro um mostrador que mostra uma contagem
que vai de 0000 at 9999 e volta para 0000.
O segundo uma verso mais elaborada do primeiro, pois ele oculta os zeros esquerda
(no significativos) da contagem.
O terceiro e ltimo mostra como obter um voltmetro de 0 a 5 volts Dc.
$crystal =
$regfile =
$hwstack =
$swstack =
$framesize
Dim
Dim
Dim
Dim
Dim
8000000
"m328pdef.dat"
40
16
= 32
Digitos(4) As Byte
Disp_index As Byte
Disp_aux As Byte
Disp_flag As Bit
Dp_position As Byte
Digitos(1) = 11
Digitos(2) = 11
Digitos(3) = 11
Digitos(4) = 11
Disp_index = 0
Dp_position = 0
Incr Digitos(3)
End If
If Digitos(3) > 9 Then
Digitos(3) = 0
Incr Digitos(2)
End If
If Digitos(2) > 9 Then
Digitos(2) = 0
Incr Digitos(1)
End If
If Digitos(1) > 9 Then
Digitos(1) = 0
End If
Dp_position = 4
Loop
End
= 0
= 0
= 0
= 0
todos os dgitos
'0,1,2,3
'4,5,6,7
'8,9,NADA,TUDO
'PONTO
Portc.0
Portc.1
Portc.2
Portc.3
=
=
=
=
Output
Output
Output
Output
' portc comanda qual display ser aceso. usamos os bits PortC.0 at PortC.3
' assim configuramos apenas os 4 bits como sada.
Digitos(1) = 11
Digitos(2) = 11
Digitos(3) = 11
Digitos(4) = 11
' com o valor 11, vamos acender todos os segmentos
Disp_index = 0
Dp_position = 0
Loop
'---- sub-rotina acerta -----------------------------------------------' esta rotina faz com que os zeros esquerda do nmero sejam apagados
' a apresentao do nmero fica muito melhor.
'
Acerta:
Str_valor = Str(numero)
' vamos converter o numero desejado em uma string de caracteres
Str2digits Str_valor , Digit_temp(1)
'esta funo transforma os dgitos dentro da string em nmeros, onde cada um
'dos dgitos ser armazenado em uma posio de uma matriz numrica.
' muito poderosa e facilita bastante nosso trabalho
Ndigit = Digit_temp(1)
'agora Sabemos Quantos Dgitos Possui O Nmero
'e s precisamos recolocar na ordem que o nosso programa vai apresentar
'pois na converso a matriz foi criada com os os numeros de maior grandeza
'no inicio da matriz e da em diante conforme abaixa a grandeza
'sugiro examinar o help do Bascom para entender o funcionamento.
Stop Timer1
' Vamos parar a contagem do timer1, para evitar que hava alguma interrupo
' enquanto preparamos todos os novos digitospois poderia haver alguma
' mudana doida n odisplay, entao paramos a contagem
' e no teremos a interrupo do timer1 !
For I = 1 To 4
Digitos(i) = 10
Next I
' j colocamos o caractere que vai apagar todos os 4 dgitos
' agora s reordenar conforme a quantidade de dgitos presente
' no nosso nmero a ser mostrado.
If Ndigit = 4 Then
Digitos(1) = Digit_temp(5)
Digitos(2) = Digit_temp(4)
Digitos(3) = Digit_temp(3)
Digitos(4) = Digit_temp(2)
Elseif Ndigit = 3 Then
Digitos(2) = Digit_temp(4)
Digitos(3) = Digit_temp(3)
Digitos(4) = Digit_temp(2)
Elseif Ndigit = 2 Then
Digitos(3) = Digit_temp(3)
Digitos(4) = Digit_temp(2)
Else
Digitos(4) = Digit_temp(2)
End If
Start Timer1
' pronto, vamos liberar o timer1 novamente pois tudo j est pronto !
' este trecho todo acaba atrasando apenas 18 microsegundos, que no chega
'a ser 3% do tempo normal de cada interrupo, portanto imperceptivel.
Return
End
= 0
= 0
= 0
= 0
todos os dgitos
'0,1,2,3
'4,5,6,7
'8,9,NADA,TUDO
'PONTO
Portc.0
Portc.1
Portc.2
Portc.3
=
=
=
=
Output
Output
Output
Output
' portc comanda qual display ser aceso. usamos os bits PortC.0 at PortC.3
' assim configuramos apenas os 4 bits como sada.
Digitos(1) = 11
Digitos(2) = 11
Digitos(3) = 11
Digitos(4) = 11
' com o valor 11, vamos acender todos os segmentos
Disp_index = 0
Dp_position = 0
Enable Interrupts
' aqui habilitamos as interrupes definidas no programa
Wait 1
' todos os segmentos vao ficar acesos por 1 segundo
' util para ver se algum foi danificado!
Digitos(1) = 0
Digitos(2) = 0
Digitos(3) = 0
Digitos(4) = 0
Dp_position = 1
' ponto decimal sempre no primeiro dgito
Do
Waitms 100
Numero = 0
For I = 1 To 32
Numero = Numero + Getadc(5)
Next I
Shift Numero , Right , 5
'fizemos a soma de 32 leituras consecutivas, e calculamos
'a mdia para ter uma melhor estabilidade
Numero = Numero * 5
Resultado = Numero / 1023
' aqui fizemos o chamado fator de escala, pois o fundo de escala
' 5 volts e nesse caso obteremos leitura de 1023, ento
' basta multiplicar por 5 e dividir por 1023, e j teremos o
' valor em volts.
Str_valor = Fusing(resultado , "#.###")
End
= 0
= 0
= 0
= 0
todos os dgitos
'0,1,2,3
'4,5,6,7
'8,9,NADA,TUDO
'PONTO
FORMATO DE COMUNICAO:
DIAGRAMA DE TEMPOS:
Pronto, tudo o que precisamos saber est colocado nas pginas anteriores.
Quando enviarmos os dados seriais, enviaremos primeiro o bit D15, depois o D14, e
assim at o ultimo bit, que o D0. Ou seja, sempre ser no formato do MSB at o LSB.
Usamos trs sinais para transmitirmos os dados. Temos dois sinais usados em
comunicao serial, que so o CLOCK e o DATA . E o ltimo o CS, ou Chip Select,
que tem de ser colocado em nvel 0 quando desejamos que o chip aceite conversar
conosco.
Const
Const
Const
Const
Reg_decode_mode = &B1111100111111111
Reg_scan_limit = &B1111101111111011
Reg_intensity = &B1111101011111111
Reg_shutdown = &B1111110011111111
=
=
=
=
1
0
0
0
0
Enable Interrupts
' aqui habilitamos as interrupes definidas no programa
Dp_position = 4
' ponto decimal sempre no primeiro dgito
'vamos agora inicializar o MAX7219
Numero = Reg_shutdown
Gosub Sai_max
Numero = Reg_decode_mode
Gosub Sai_max
Numero = Reg_intensity
Gosub Sai_max
Numero = Reg_scan_limit
Gosub Sai_max
'j configurado !
Do
Waitms 100
Numero = 0
For I = 1 To 32
'data
'load
'clock
If Digit_temp(1) = 3 Then
' o valor a mostrar zero
Digitos(1) = 0
Digitos(2) = 0
Digitos(3) = 0
Digitos(4) = 0
Else
' temos de ordenar os digitos, agora com uma novidade, pois
' digit_temp(5) tem o ponto decimal, ento pularemos
Digitos(4) = Digit_temp(6)
Digitos(3) = Digit_temp(4)
Digitos(2) = Digit_temp(3)
Digitos(1) = Digit_temp(2)
End If
For I = 4 To 1 Step -1
Numero = Digitos(i)
If Dp_position = I Then
Numero = Numero Or &B1111000010000000
End If
Select Case I
Case 1
Numero = Numero Or &B1111010000000000
Case 2
Numero = Numero Or &B1111001100000000
Case 3
Numero = Numero Or &B1111001000000000
Case 4
Numero = Numero Or &B1111000100000000
End Select
Gosub Sai_max
Next I
Loop
Sai_max:
Max_data = 0
Max_clock = 0
Max_load = 0
Shiftout Max_data , Max_clock , Numero , 1
Max_load = 1
Return
End
!!!!!
Reg_decode_mode = &B1111100111111111
Reg_scan_limit = &B1111101111111011
Reg_intensity = &B1111101011111111
Reg_shutdown = &B1111110011111111
=
=
=
=
1
0
0
0
0
Enable Interrupts
' aqui habilitamos as interrupes definidas no programa
'data
'load
'clock
Dp_position = 4
' ponto decimal sempre no primeiro dgito
'vamos agora inicializar o MAX7219
Numero = Reg_shutdown
Gosub Sai_max
Numero = Reg_decode_mode
Gosub Sai_max
Numero = Reg_intensity
Gosub Sai_max
Numero = Reg_scan_limit
Gosub Sai_max
'j configurado !
Do
Waitms 100
Numero = 0
For I = 1 To 49
Numero = Numero + Getadc(5)
Next I
' vamos calcular a media, somando 49 ezes a leitura. Porque 49 ?
' se multiplicarmos 49 x 1023, teremos 50.127, que ultrapassa em pouco 50.000
' SE DIVIDIRMOS 50127/50.000 = 1,00254, que 2,54% maior do que queremos,
' agora, temos um valor que ultrapassa 50.000 em 0,254% . Vamos portanto
subtrair
' esses 0,254% !
Resultado1 = Numero
Resultado1 = Resultado1 / 500
Numero = Numero - Resultado1
Resultado1 = Numero
Resultado1 = Numero / 2000
Numero = Numero - Resultado1
Resultado1 = Numero
Resultado1 = Resultado1 / 25000
Numero = Numero - Resultado1
' 0,2%
'0,05 %
' 0,004 %
Resultado = Digitos(2) * 10
Numero = Numero - Resultado
Digitos(1) = Low(numero)
' prontinho... no precisamos utilizar matemtica de ponto flutuante, que
' sempre faz o programa ficar bem maior. Veremos no final a reduo do
programa.
For I = 4 To 1 Step -1
Numero = Digitos(i)
If Dp_position = I Then
Numero = Numero Or &B1111000010000000
End If
Select Case I
Case 1
Numero = Numero Or &B1111010000000000
Case 2
Numero = Numero Or &B1111001100000000
Case 3
Numero = Numero Or &B1111001000000000
Case 4
Numero = Numero Or &B1111000100000000
End Select
Gosub Sai_max
Next I
Loop
Sai_max:
Max_data = 0
Max_clock = 0
Max_load = 0
Shiftout Max_data , Max_clock , Numero , 1
Max_load = 1
Return
End
Este programa compilado tem 1.474 bytes. Se comparar com o anterior, que utiliza
ponto flutuante, vemos que a reduo no tamanho enorme, cerca de 35% menor !!!
Repare que fizemos a separao dos 4 dgitos da maneira mais simples possvel, sem
utilizar nenhum funo de alto nvel do Bascom. Fiz isto apenas para que voc aprenda
esta maneira simples de se separar os dgitos individuais de um nmero.
Repare que os catodos dos Leds so interligados 8 a 8. No exemplo acima, para acender
o primeiro Led da esquerda, parte superior, temos de colocar uma tenso positiva na
primeira coluna pino 13, e colocar nvel 0 na primeira linha, que o pino 1.
Repare a dificuldade que acender vrios Leds.... s possvel acender ao mesmo
tempo os Leds pertencentes a uma mesma linha !
Se quisermos acender vrios, temos de recorrer Multiplexao, onde iremos acionar os
Leds da primeira linha, em seguida os da segunda linha, e assim at a ltima linha. Se
fizermos isto com uma boa velocidade, nosso olho vai fazer a famosa integrao, e
veremos como se todos estivessem acesos ao mesmo instante.
Como fazemos isto?
A primeira maneira a mais simples, usamos uma porta inteira de um microcontrolador
para fazer as linhas, e outra porta inteira para fazer as colunas. Perderemos 16 pinos do
nosso microcontrolador para fazer isto.
Veja o esquema abaixo:
Aqui, usamos o Port B para comutar as colunas, e o Port D para comutar as linhas.
Repare que temos os mesmos problemas de corrente que tivemos acima, usando os
displays de 7 segmentos diretamente. A corrente em cada coluna limitada corrente
mxima da de um pino, portanto a corrente de cada Led das linhas tem de ser no
mximo a da coluna / 8. Isto limita bastante o brilho, quando usamos o princpio do
Multiplex.
Vamos ilustrar aqui, como seria um programa para acender um enorme X na matriz.
Imagine que iremos utilizar 8 bytes de memria, totalizando 8 x 8 = 64 bits, portanto
uma representao perfeita da matriz.
Vamos apresentar os 8 bytes da seguinte maneira : o primeiro byte representa os Leds
da primeira linha; o prximo byte representa a segunda linha, e assim por diante.
Dentro de cada byte, o MSB representa o Led mais esquerda, e o LSB representa o
Led mais direita.
Agora, vamos supor que o bit em 1 representa o Led aceso, e 0 representa o Led
apagado.
Veja como ficam os nossos 8 bytes para acender o X:
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
Byte8
Col1
1
0
0
0
0
0
1
0
Col2
0
1
0
0
0
1
0
0
Col3
0
0
1
0
1
0
0
0
Col4
0
0
0
1
0
0
0
0
Col5
0
0
1
0
1
0
0
0
Col6
0
1
0
0
0
1
0
0
Col7
1
0
0
0
0
0
1
0
Col8
0
0
0
0
0
0
0
0
Reparou que tem uma coisa esquisita.. no usamos todas as 8 linhas e as 8 colunas, mas
sim 7 linhas e 7 colunas ?
Se voc pretende escrever um texto na matriz, recomendado sempre que o tamanho da
matriz seja de nmeros IMPARES, ou seja, 7x7 , 7x5 . Seno, se fosse usado um
nmero par, nunca teria uma posio central, aquela bem no meio da matriz, que no
nosso caso exatamente o meio do X, que est na Col4 e Byte4.
Nesta representao que adotei, no importa a letra a ser mostrada, sempre teremos o
Byte8 igual a 0 e a Col8 igual a 0.
Nosso programa far o Multiplex como se fossem 8 dgitos , fazendo acender uma
coluna a cada vez, como se fosse um display do tipo CATODO COMUM, igual ao
nosso exemplo l no comeinho ....
Assim, selecionamos a coluna 1 fazendo sair no PortB o valor 01111111b.
A seguir, colocamos no PortD o valor 10000010b , e isto far acender os dois Leds.
Na prxima vez, faremos PortB = 10111111b e PortD = 01000100b
E assim por diante. Repararam que exatamente o mesmo princpio que usamos l em
cima para fazer o Multiplex do display com 4 dgitos ? S que aqui so 8 dgitos !
A situao muito parecida com a que j vimos antes, porm tratamos agora as 8
colunas da mesma maneira com que tratamos os 4 dgitos. Tivemos de aumentar a
freqncia do Multiplex para 240 Hz, para manter a mesma taxa de acender cada coluna
pelo menos 30 vezes por segundo.
Veja dois instantes seguidos da Multiplexao, e o efeito total captado pelo nosso olho:
$crystal =
$regfile =
$hwstack =
$swstack =
$framesize
8000000
"m328def.dat"
40
16
= 32
Do
Waitms 100
Loop
End
Agora, evoluindo novamente nosso circuito, imagine que vamos usar DUAS
MATRIZES em vez de uma. Como fazer a ligao, se no temos mais uma porta com 8
bits livres ?
Aqui entra um velho amigo, o 74HCT595. Ele um Ci que integra um Shift-Register e
um Latch de sada, permitindo que enviemos os dados para ele usando apenas 3 pinos
de I/O, usando o formato serial ! E, o melhor de tudo, pode ligar vrios em cascata, um
atrs do outro!
Usaremos novamente um nico CI UDN2981A, o qual vai fornecer corrente de sobra
para todas as matrizes (afinal, apenas uma vai acender de cada vez), e iremos adicionar
um ULN1803A em conjunto com um 74HCT595 para cada matriz adicional.
USANDO 74HCT595 PARA INTERLIGAR VRIAS MATRIZES
A seguir, veremos como utilizar este maravilhoso CI de baixo custo.
Para simplificar a simulao, este circuito no apresenta nem o UDN2981A que teria de
estar ligado na sada do Port D do microcontrolador, nem os resistores que teriam de
estar entre as sadas do UDN2981A e as matrizes, e nem os dois ULN2803A que
deveriam estar presentes em cada um dos 74HCT595. Devido ao fato de a presena do
ULN2803A faz a inverso da sada, teremos de modificar o programa quando ele for
utilizado. Esta modificao ser tambm apresentada.
Da maneira mostrada no esquema, nossas duas matrizes equivalem a uma nica matriz,
como o formato de 8 linhas por 16 colunas. Para representar esta coluna, usaremos 16
bytes, sendo que o primeiro byte contem os 8 Leds mais esquerda, respectivamente o
LSB em cima e o MSB em baixo; da sucessivamente at o ltimo byte, que representa
os 8 Leds mais direita.
Vamos dimensionar uma matriz de 16 bytes para isso, onde os bytes sero acessados
desde coluna(1) at coluna(16).
A nossa rotina de Multiplex ser bem simples, ela ir a cada vez inibir a sada fazendo
/OE = 1 , e ento pega os Leds que tem de acender na prxima coluna, coloca na sada
do Port D, faz DS=0, gera um clock no shift para avanar para a prxima coluna a
mostrar, armazena fazendo STCP=1, e ento faz novamente /OE=0 , o que ir acender a
coluna desejada.
A cada vez ela seleciona a prxima coluna, tendo o cuidado de voltar ao incio quando
estivermos na ltima posio.
Simples e efetivo, no ?
A seguir, o programa que ilustra essa tcnica, e que ir apresentar o mesmo X do
programa anterior na primeira matriz, e o inverso do X na segunda matriz.
'---------------------------------------------------------------------' PROGRAMA MULTIPLEX MATRIX2 - Implementa o Multiplex Basico para
' fazer acender um X normal na primeira matriz e o inverso desse X na
' segunda matriz. Usamos agora o 74HCT595 para controlar as matrizes
' Usaremos uma Matriz de 16 bytes para armazenar os Leds das duas matrizes.
'
' Este programa utiliza o Timer0 de 8 bits para a base de tempo
' e implementa um refresh de 480 Hertz aproximado.
'----------------------------------------------------------------------
$crystal =
$regfile =
$hwstack =
$swstack =
$framesize
Dim
Dim
Dim
Dim
Dim
8000000
"m328def.dat"
40
16
= 32
Disp_index As Byte
Disp_aux As Byte
Coluna(16) As Byte
Nada As Word
Flag As Bit
End
' eu deixo DS=0 para que um nivel zero seja introduzido no shift
' register, assim vai fazer acender uma coluna. A seguir, fao DS=1
' e todos os outros shifts vo apenas propagar uma s coluna com
' nivel 0.
Shcp = 1
NOP
Shcp = 0
Stcp = 1
NOP
Stcp = 0
Ds = 1
Incr Disp_index
' aqui j apontamos para a coluna
' Se no zeramos os shifts, temos de ter um delay
If Flag = 0 Then
Waitus 30
Else
Flag = 0
End If
' pegamos os Leds que queremos mostrar nesta coluna
' dentro da nossa matriz coluna()
Portd = Coluna(disp_index)
, &B00101000 , &B00010000
, &B10000010 , &B00000000
, &B11010111 , &B11101111
, &B01111101 , &B11111111
Como prometi antes, segue o mesmo programa modificado para o caso de usar os
drivers UDN e ULN para aumentar bastante o brilho de nossas matrizes.
'---------------------------------------------------------------------' PROGRAMA MULTIPLEX MATRIX3 - Implementa o Multiplex Basico para
' fazer acender um X normal na primeira matriz e o inverso desse X na
' segunda matriz. Usamos agora o 74HCT595 para controlar as matrizes
' Usaremos uma Matriz de 16 bytes para armazenar os Leds das duas matrizes.
'
' Este programa utiliza o Timer0 de 8 bits para a base de tempo
' e implementa um refresh de 480 Hertz aproximado.
' Verso modificada para o uso de drivers UDN e ULN
'----------------------------------------------------------------------
$crystal =
$regfile =
$hwstack =
$swstack =
$framesize
Dim
Dim
Dim
Dim
Dim
8000000
"m328def.dat"
40
16
= 32
Disp_index As Byte
Disp_aux As Byte
Coluna(16) As Byte
Nada As Word
Flag As Bit
Enable Interrupts
Nada = 0
' apenas um padro de 16 bits 0 , que vamos usar para no
' selecionar nenhuma coluna para iniciar o processo !
Oe = 0
End
Shcp
Stcp
NOP
Stcp
Ds =
= 0
= 1
= 0
0
Incr Disp_index
' aqui j apontamos para a coluna
' Se no zeramos os shifts, temos de ter um delay
If Flag = 0 Then
Waitus 30
Else
Flag = 0
End If
' Acendemos a coluna
' pegamos os Leds que queremos mostrar nesta coluna
' dentro da nossa matriz coluna()
Portd = Coluna(disp_index)
Return
, &B00101000 , &B00010000
, &B10000010 , &B00000000
, &B11010111 , &B11101111
, &B01111101 , &B11111111
Por ultimo, apresento uma restrio ao uso desta tcnica para uma grande quantidade de
matrizes.
Neste ultimo programa feito para o uso de drivers ULN e UDN, dentro da rotina de
interrupo, toda vez que vamos iniciar para fazer a primeira coluna, fazemos 16 shifts
com o valor 0 para poder apresentar zero em todas as sadas dos 74hct595 .
Isto demora cerca de 40 micro segundos, e portanto bem rpido. Imagine se voc
resolve usar 10 matrizes, ao invs de 2, mesmo adequando o programa, perderemos
mais de 300 micro segundos s para zerar os 10 shifts. Isto j pode se tornar bastante
demorado, pois se vamos utilizar 10 matrizes, nossa freqncia de Multiplex ser de
2400 hertz, com um tempo entre as interrupes de 416 micro segundos.
Repare que quase no temos folga de tempo para algum processamento adicional.
Imagine se voc quiser utilizar 12 ou mais matrizes, este programa no vai funcionar
mais.
Para se evitar isto, ao invs de controlarmos o pino do /OE, podemos ligar esse sinal
diretamente ao terra, e controlar o pino /MR , onde com um simples pulso j fazemos o
Segue o esquema :
Repare que no esquema, usamos dois MAX7219, sendo que cada um controla uma
matriz.
Os dados so enviados a partir do pino Portc.0 do microprocessador, e chega entrada
Din do Max7219 mais direita. Dele, sai um sinal, atravs do pino Dout, que vai ligado
entrada Din do Max7219 mais esquerda.
Primeiro, para armazenas os valores que queremos mostrar, criamos em nosso programa
uma matriz chamada Dgitos(), cujo tamanho equivalente ao numero de colunas que
queremos mostrar no total.
Com 2 matrizes, temos 2x8 = 16 colunas.
Assim, a nossa primeira coluna, que a que est mais esquerda, vai mostrar o valor
armazenado na posio Dgitos(1) de nossa matriz.
E a ultima coluna, que a que est mais direita, vai mostrar o numero armazenado na
ultima posio, que a Dgitos(16).
curioso que para mostrar os valores corretamente, temos de entrar com os dados a
partir do ltimo MAX7219, e no a partir do primeiro! Por qu ?
Os dados so enviados serialmente. Assim, enviamos 16 bits de dados, que fazem o
endereamento da coluna correspondente e tambm j informam o valor a ser mostrado,
e a seguir enviamos mais 16 bits serialmente, para o segundo display. Desta maneira, os
16 bits enviados primeiro vo acabar ficando dentro do MAX7219 esquerda, e os
ltimos 16 bits ficam dentro do MAX7219 direita! A seguir, damos o comando de
Armazenar.
Fazemos isso para todas as 8 colunas dos dois Max7219.
O programa para isso muito simples, escrito tambm com o Bascom. E o melhor que
voc pode adequar o mesmo programa para mostrar at 31 matrizes!
Segue o mesmo :
Const N1 =(n) * 8
Const N2 =(n) - 1
Dim
Dim
Dim
Dim
Dim
Dim
Dim
X As Byte
Y As Byte
Z As Byte
Base As Byte
Numero As Word
I As Byte
Digitos(n1) As Byte
' Esta matriz Digitos() vai conter todos os valores a serem mostrados
' desde a primeira coluna ( digitos(1) ) at a ultima coluna
' ( digitos(8Xnumero de matrizes) )
Const
Const
Const
Const
Const
Reg_decode_mode = &B1111100100000000
Reg_scan_limit = &B1111101111111111
Reg_intensity = &B1111101011111111
Reg_shutdown_off = &B1111110011111111
Reg_shutdown_on = &B1111110011111110
'data
'load
'clock
Next I
Enable Interrupts
'vamos agora inicializar os MAX7219
Numero = Reg_shutdown_off
Gosub Init_max
Numero = Reg_decode_mode
Gosub Init_max
Numero = Reg_intensity
Gosub Init_max
Numero = Reg_scan_limit
Gosub Init_max
'j tudo configurado !
Init_max:
For X = 1 To N
Shiftout Max_data , Max_clock , Numero , 1
Next X
Max_load = 1
Max_load = 0
Return
End
Creio que ao chegar at aqui voc j sabe tudo o que precisa saber para trabalhar com
qualquer tipo de display de Leds.
Boas Montagens !