Neste sketch serão trabalhadas a questão da multiplexação de 4 displays de 7 segmentos conectados em paralelo e com seus pinos comuns decidindo qual deles estará ligado em cada momento, fazendo com que a quantidade de portas digitais seja reduzida, já que as mesmas portas estão conectadas a todos os displays, e também a utilização de um circuito integrado registrador de deslocamento com o intuito de reduzir ainda mais a quantidade de saídas digitais necessárias, pois com apenas 3 portas é possível controlar as 8 saídas deste componente.
Link para a simulação aqui.
Neste sketch foram utilizados displays cátodo comum, sendo assim, os LEDs são ligados com nível lógico alto.
Os segmentos dos 4 displays foram interconectados e conectados às saídas do registrador de deslocamento, sendo “a” ligado à saída Q7, “b” ligado à saída Q6, até “h” ligado à saída Q0. O pino comum de cada display foi conectado a um transistor NPN de modo que cada display seja ligado de maneira semelhante ao buzzer. Assim que aplicada uma corrente na base do transistor por meio de uma porta digital, ele se comporta como uma chave fechada, conectando o pino comum ao terra do circuito, ativando, assim, o display.
Para configurar o registrador de deslocamento é necessário antes entender o que significa cada porta do circuito integrado.
As portas Q0 até Q7 são as saídas, VCC 5V, GND 0V, DS é a entrada de dados, OE habilita a saída dos dados (ativo em nível baixo), ST_CP habilita a passagem dos dados adquiridos para as saídas, SH_CP é a entrada para o clock de deslocamento, MR é o máster reset (ativo em nível baixo) e Q7’ é a saída para conectar a um próximo registrador de deslocamento.
Para o funcionamento desejado, o pino OE deve estar em nível baixo para habilitar as saídas e o MR em nível alto para evitar o reset, e os pinos DS, ST_CP e SH_CP conectados a 3 portas digitais do microcontrolador.
Código
Como as bibliotecas padrão do Tinkercad não utilizam o registrador de deslocamento, será necessário criar nossas próprias funções.
Para manusear as saídas do registrador de deslocamento serão utilizadas as seguintes funções:
#define DS 8 //DS
#define EN 10 //SH_CP
#define CLK 11 //ST_CP
void serialInit(){
pinMode(DS, OUTPUT); //Configura os pinos como saída
pinMode(EN, OUTPUT);
pinMode(CLK, OUTPUT);
digitalWrite(DS, LOW); //Inicializa com nível baixo
digitalWrite(EN, LOW);
digitalWrite(CLK, LOW);
}
void serialWrite(unsigned char data){
digitalWrite(EN, LOW); //Desabilita a transferência de dados para a saída
for (char i = 0; i < 8; i++){
digitalWrite(CLK, LOW);
if (data & 0x80>>i){ //0x80 = 0b1000 0000
digitalWrite(DS, HIGH);
}
else{
digitalWrite(DS, LOW);
}
digitalWrite(CLK, HIGH);
}
digitalWrite(EN, HIGH); //Habilita a transferência de dados para a saída
digitalWrite(DS, LOW); //Mantém o restante com nível baixo
digitalWrite(CLK, LOW);
}
A função serialInit() é responsável por inicializar os pinos que irão realizar a comunicação com o 74HC595.
A função serialWrite(unsigned char data) é responsável por escrever os 8 bits (data), que são passados como parâmetro, nas saídas do registrador de deslocamento. É importante notar que o primeiro bit a ser passado pelo pino DS é o bit que se encontrará na última posição (Q7), então a transmissão deve começar do bit mais significativo até o menos significativo. É isso que acontece no loop for, em que a cada if é verificado se o dado passado tem nível alto no bit mais significativo, finalizando, na oitava iteração, com o bit menos significativo através do shift do valor 0x80 e um and lógico.
Tabela 1: Exemplo de shift.
|
0x80 >> 0 = 0b1000 0000 |
0x80 >> 1 = 0b0100 0000 |
0x80 >> 2 = 0b0010 0000 |
|
0x80 >> 3 = 0b0001 0000 |
… |
0x80 >> 7 = 0b0000 0001 |
O dado é então colocado na entrada DS, dá-se um pulso de clock e, ao final das 8 iterações, habilita que esses dados sejam transmitidos às saídas.
Já que o método de comunicação foi definido, serão agora apresentadas as funções que são responsáveis pelo funcionamento e pela multiplexação dos displays, são elas:
#define D0 5
#define D1 4
#define D2 3
#define D3 2
char disp[4]; // Valor a ser escrito em cada display
char atual = 0; // Display a ser atualizado
void ssdInit(){
pinMode(D0, OUTPUT); //Configura os pinos que controlarão os displays que estão ligados como saída
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
digitalWrite(D0, LOW); //Inicializa todos os displays desligados
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW);
}
void ssdDigit(unsigned char pin, unsigned char data){
static const char valor [] = {0xFC , 0x60 , 0xDA , 0xF2 , 0x66 , 0xB6 , 0xBE , 0xE0 , 0xFE , 0xF6 , 0xEE , 0x3E , 0x9C , 0x7A ,0x9E , 0x8E};
disp[pin] = valor[data]; // Atualiza a posição referente ao display com o valor referente do número desejado
}
void ssdUpdate(){
digitalWrite(D0, LOW);
digitalWrite(D1, LOW);
digitalWrite(D2, LOW);
digitalWrite(D3, LOW); // Desliga todos os displays
// A cada chamada da função é escrito na saída do registrador o valor correspondente a um display
// A variável atual é atualizada de forma que na próxima chamada da função o próximo display seja atualizado
switch (atual){
case 0:
serialWrite(disp[0]);
digitalWrite(D0, HIGH);
atual = 1;
break;
case 1:
serialWrite(disp[1]);
digitalWrite(D1, HIGH);
atual = 2;
break;
case 2:
serialWrite(disp[2]);
digitalWrite(D2, HIGH);
atual = 3;
break;
case 3:
serialWrite(disp[3]);
digitalWrite(D3, HIGH);
atual = 0;
break;
default:
atual = 0;
break;
}
}
A função ssdInit() é responsável por inicializar as portas digitais do microcontrolador que serão responsáveis por polarizar o transistor presente no pino comum de cada display, que posteriormente controlarão qual deles estará ativo em cada momento.
A função ssdDigit(unsigned char pin, unsigned char data) é responsável por atualizar o vetor global char disp[] com o valor que traduz um número de 0 a 15 passado como parâmetro (data) em sua representação gráfica e inserir na posição referente a cada display (pin).
Os valores a serem salvos no vetor char disp[] foram obtidos da seguinte maneira:
A função ssdUpdate() é responsável pela atualização e multiplexação do display e deve ser colocada no loop do programa. A cada chamada da função todos os displays são desligados, escrevendo no registrador de deslocamento o valor a ser exibido em certo display. Ele é, então, ligado e a variável “atual” alterada de forma que na próxima chamada da função o próximo display seja ligado.
O código implementado nas funções principais tem o objetivo de escrever nos displays a quantidade de segundos que se passaram desde que o sistema foi ligado.
void setup(){
ssdInit();
serialInit();
ssdDigit(0, 0); // Escreve 0 no display 0
ssdDigit(1, 0); // Escreve 0 no display 1
ssdDigit(2, 0); // Escreve 0 no display 2
ssdDigit(3, 0); // Escreve 0 no display 3
}
void loop(){
ssdUpdate();
ssdDigit(0, millis()/1000%10); // unidades de segundo
ssdDigit(1, (millis()/10000)%10); // dezenas de segundo
ssdDigit(2, (millis()/100000)%10); // centenas de segundo
ssdDigit(3, (millis()/1000000)%10); // milhares de segundo
}
Conclusão
Neste artigo foi apresentada a maneira de realizar conversão de dados seriais em paralelos por meio do circuito integrado HC74595, a multiplexação de displays de 7 segmentos, seus circuitos e a programação utilizando o Arduino UNO simulado pelo Tinkercad.
Nos próximos artigos serão apresentados a varredura do teclado matricial e a utilização do display LCD 16×2, ambos conectados ainda ao mesmo circuito integrado registrador de deslocamento utilizado até agora (HC74595).
Todos os códigos podem ser acessados em meu GitHub.
Saiba mais
Displays de LED de 7 segmentos
Curso de C com microcontoladores MCF51QE128 e MC9S08QE128 – Display HD44780 – Parte 8
Raspberry Pi – Display LCD com Python
Aprenda a usar o CD4511: Circuito decodificador para Display de 7 Segmentos





Você teria explicando o display 7 segmentos no arduino com botão? Desde já agradeço