Expansão de I/O - 74HC595
Autor: Jean Carlos | Publicado: 2012-10-27T17:02:00-07:00

Pessoal, continuando com os posts relacionados aos CI’s de expansão de I/O, apresento a vocês o CI 74HC595, tal como o CI 74LS164, consiste em um conversor serial paralelo de 8 bits (Shift Register) porém com características que ao meu ver o tornam muito mais interessante que o 74164.  Uma das características que o tornam tão especial é o fato de possuir dois registradores para manuseio dos dados, sendo:   Shift RegisterArmazena as informações transferidas serialmente como registrador temporário, a cada pulso de clock no pino SRCLK este registrador é carregado bit a bit conforme o nível lógico disponível no pino SER (Entrada Serial).   Storage RegisterEste registrador é carregado com as informações disponíveis no registrador&nbsp; Shift Register quando o pino RCLK é pulsado com um nível lógico alto (Latch), ou seja, podemos manusear o envio dos bits um a um e ao término habilitamos o latch. Isto nos trás uma vantagem enorme na simplificação do hardware, pois no caso do uso do 74164 teríamos que providenciar um mecanismo eletrônico que durante a atualização dos dados apagasse o display para evitar que a serialização fosse percebida. Além desses dois registradores, o 74595 possui um pino que habilita a operação do mesmo (OE), sendo que quando garantimos um nível alto neste pino temos todas as saídas configuradas como tri-state, ou seja, não drena e nem fornece corrente alguma ao circuito, portando fica configurada como alta impedância. Outra característica importante é que este CI é capaz de trabalhar com cargas de +- 6ma sendo suficiente para por exemplo, alimentarmos pequenos leds para uso em painéis de IHMs diretamente pelos I/Os do CI. Lógica de operação:  Aqui podemos observar o funcionamento deste CI passo a passo!    Exemplo de uso  Para exemplificar o uso deste componente, vamos criar uma aplicação junto a PK2Lab, que consiste num contador de 0 à 99 com o uso de dois displays de sete segmentos conectados aos shift registers 74595 em cascata (Daisy Chain), assim podemos criar posteriormente projetos maiores como por exemplo um relógio com horas, minutos e segundos… tendo apenas como limite a sua imaginação! Esquema:  Podemos observar que além dos pinos de alimentação, são utilizados apenas 3 pinos de I/O para controlar os dois displays, e mesmo aumentando a quantidade de CIs, continuamos utilizando apenas 3 pinos, esta é a grande vantagem de se utilizar a comunicação serial para transferência de dados.  Poderíamos ainda ter utilizado os pinos de Reset e Operational Enable para controlar mais algumas funcionalidades, porém no exemplo não foram implementadas ficando estas a cargo do leitor caso queira implementar.    Software A parte de software deste exemplo já foi explorado anteriormente nos outros posts, apenas temos o acréscimo de um pino de latch que fará com que os dados previamente setados no Shift Register sejam transferidos para os pinos do CI acionando os segmentos dos displays. Uma prática interessante que podemos adotar ao construir software é o cuidado utilizado ao criar nomes de variáveis dentro de funções, por exemplo, podemos criar uma função chamada Display() e utiliza-lá em muitos projetos com grande facilidade, basta apenas que as variáveis internas desta função utilizem características próprias da função de origem, neste exemplo podemos observar que foi criada a função SN74HC595() e todas as variáveis internas desta função começam com SN74HC595_ seguido do nome da variável propriamente dito, a primeira vista temos a impressão de que o programa fica carregado, porém, facilita muito o inter-relacionamento das variáveis como um todo. Outro ponto interessante é a chamada recorrente de funções, na linha abaixo podemos ver que chamamos a função display() duas vezes dentro da função SN74HC595(). SN74HC595(Display(Unidade), Display(Dezena)); Com esta única linha de comando montamos os dois bytes referentes aos dígitos de dezena e unidade e enviamos serialmente essas informações. /****************************************************************************** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JL Audio Manutenção Eletrônica Data: 10/2012Autor: Jean CarlosProjeto: Registrador de deslocamento SN74HC595Microprocessador: PIC18F4520Clock do processador: 8MHzEstação de desenvolvimento: PK2Lab V 1.1Compilador: MikroC PRO V 4.60.0.0Versão atual: 1.0Descrição: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Demonstração do uso de shift register para expansão de I/O *******************************************************************************/// Inicializações do programa // Configuração do LCD da placa PK2Lab V.1.1 sbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit; sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit; //******************************************************************************// Variáveis Globais short Contador = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Variável para contagem de 0 a 99.short Dezena&nbsp;&nbsp; = 0, Unidade = 0; #define Latch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTC.B0#define Clock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTC.B1#define Ser_Out&nbsp; PORTC.B2 //******************************************************************************// Rotinas Auxiliares//******************************************************************************// Driver de display de 7 segmentos, número a ser impresso é passado como// argumento da função. unsigned char Display(unsigned char no){&nbsp;&nbsp;&nbsp; unsigned char Pattern;&nbsp;&nbsp;&nbsp; unsigned char SEGMENT[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x7D,0x07,0x7F,0x6F}; &nbsp;&nbsp;&nbsp; Pattern = SEGMENT[no];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Segmento a retornar&nbsp;&nbsp;&nbsp; return (Pattern);} void SN74HC595(char SN74HC595_Display1, char SN74HC595_Display2){ short SN74HC595_Aux;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Variável local de controle do laço for for(SN74HC595_Aux = 0; SN74HC595_Aux &lt; 8; SN74HC595_Aux ++)&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; if( SN74HC595_Display1 &amp; 0b10000000)&nbsp; Ser_Out = 1;// Máscara o sétimo bit&nbsp;&nbsp;&nbsp;&nbsp; else Ser_Out = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // e verifica se é zero ou um.&nbsp;&nbsp;&nbsp;&nbsp; SN74HC595_Display1 = SN74HC595_Display1 &lt;&lt; 1; // Rotaciona o próximo bit&nbsp;&nbsp;&nbsp;&nbsp; Clock = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Pulsa o clock para envio do bit&nbsp;&nbsp;&nbsp;&nbsp; Delay_us(1);&nbsp;&nbsp;&nbsp;&nbsp; Clock = 0;&nbsp;&nbsp;&nbsp; } Ser_Out = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Mantém a linha de dados em nivel baixo&nbsp;&nbsp; for(SN74HC595_Aux = 0; SN74HC595_Aux &lt; 8; SN74HC595_Aux ++)&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; if( SN74HC595_Display2 &amp; 0b10000000)&nbsp; Ser_Out = 1;// Máscara o sétimo bit&nbsp;&nbsp;&nbsp;&nbsp; else Ser_Out = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // e verifica se é zero ou um.&nbsp;&nbsp;&nbsp;&nbsp; SN74HC595_Display2 = SN74HC595_Display2 &lt;&lt; 1; // Rotaciona o próximo bit&nbsp;&nbsp;&nbsp;&nbsp; Clock = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Pulsa o clock para envio do bit&nbsp;&nbsp;&nbsp;&nbsp; Delay_us(1);&nbsp;&nbsp;&nbsp;&nbsp; Clock = 0;&nbsp;&nbsp;&nbsp; } Ser_Out = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Mantém a linha de dados em nivel baixo&nbsp; Latch = 1; Delay_us(1); Latch = 0;} &nbsp; //******************************************************************************//Rotina Principal void main(){TRISA&nbsp;&nbsp;&nbsp; = 0b00000000;PORTA&nbsp; = 0b00000000;TRISB&nbsp;&nbsp;&nbsp; = 0b00000000;PORTB&nbsp; = 0b00000000;TRISC&nbsp;&nbsp;&nbsp; = 0b00000000;PORTC&nbsp; = 0b00000000;TRISD&nbsp;&nbsp;&nbsp; = 0b00000000;PORTD&nbsp; = 0b00000000;TRISE&nbsp;&nbsp;&nbsp; = 0b00000000;PORTE&nbsp; = 0b00000000;ADCON1 = 0X0F;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Entradas digitais.OSCCON.B5 = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Ajusta oscilador interno para 8MHzOSCCON.B4 = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Ajusta oscilador interno para 8MHz Lcd_Init();Lcd_Cmd(_Lcd_Cursor_Off);Lcd_Cmd(_LCD_CLEAR);Lcd_Out(1,1,"***&nbsp; PK2Lab&nbsp; ***");Lcd_Out(2,1,"Shift&nbsp; SN74HC595");Sound_Init(&amp;PORTE,0);Sound_Play(1000,200);Delay_ms(100);Sound_Play(1000,200); while(1){ Dezena&nbsp; = Contador / 10; Unidade = Contador % 10; SN74HC595(Display(Unidade), Display(Dezena)); Delay_ms(200); Contador ++; if(Contador == 100)&nbsp;&nbsp; {&nbsp;&nbsp; Contador = 0;&nbsp;&nbsp; Sound_Play(1000,200);&nbsp;&nbsp; Delay_ms(100);&nbsp;&nbsp; Sound_Play(1000,200);&nbsp;&nbsp; Delay_ms(100);&nbsp;&nbsp; Sound_Play(1000,200);&nbsp;&nbsp; while(1){};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Trava o programa até ser pressionado o reset&nbsp;&nbsp; }&nbsp;&nbsp; }//while(1)}//main   Download do código Abaixo podemos observar os sinais de controle que foram capturados no analisador lógico, o primeiro sinal é referente ao pino de DADOS, o segundo é o clock e por fim temos o pino de habilitação de transferência(Latch) que é onde efetivamente carregamos os novos valores nos displays. Analisando as informações podemos ver o número “00” no display, onde os dois pulsos baixos iniciais correspondem aos segmentos “g”&nbsp; e “.” (ponto decimal) apagados e os outros segmentos acesos.  Protótipo montado  &nbsp; Vídeo do projeto  Bom pessoal, é isso, grande abraço a todos e ótimos projetos!!!