Apesar de ser mais simples que o visto
anteriormente, o HEF4094 também é um conversor serial/paralelo de 8 bits. A
diferença é em sua ferramenta de expansão pois possui duas portas seriais
implementáveis a outros circuitos.
Nele temos quatro portas principais de controle,
entrada de Dados (D), sinal de Clock
(CP), Strobe (STR) e Enable (OE).
Em aplicação geral, as portas CP e STR são ligadas em
paralelo para entrada do Clock e caso não seja necessario o controle Enable (OE) deve ser ligado ao GND.
O Protocolo de comunicação em sua simplicidade não
foge do 74HC595 que são basicamente identicos. Abaixo temos o diagrama de
timing da comunicação SPI:
Os níveis lógicos de entrada para transição devem
ser inferior a +1,5V para 0 (baixo)
e superior a +3,5V para 1 (alto).
O que diferencia este circuito integrado também é a
voltagem de operação, que pode ser de no máximo +18V e a corrente em cada saída
Qs deve ser de no máximo 10mA
contínuo.
Na próxima imagem temos o diagrama esquemático
interno do circuito lógico empregado no HEF4094:
A imagem seguinte mostra a pinagem encontrada e
aplicada ao HEF4094 de 16 pinos:
|
Símbolo
|
Pino
|
Descrição
|
|
STR
|
1
|
Strobe
|
|
D
|
2
|
Data
|
|
CP
|
3
|
Clock
|
|
QP0 a QP7
|
4 a 7, 14 a 11
|
Saída Paralela
|
|
VSS
|
8
|
Terra (0V)
|
|
QS1
|
9
|
Saída Serial 1
|
|
QS2
|
10
|
Saída Serial 2
|
|
OE
|
15
|
Enable
|
|
VDD
|
16
|
Fonte (+V)
|
Para implementarmos este integrado serial/paralelo
em um circuito devemos prestar a atenção em na alimentação do circuito, pois os
valores de nível lógico de entrada dependem da voltagem aplicada em VDD, pois
ele é relativo. Deve ser consultada a folha de dados do componente para mais
informações.
Para implementar mais circuitos em uma mesma linha
de comunicação deve-se definir um CI como Controle Continuo e posteriormente os
outros como escravos assumindo o diagrama seguinte.
Abaixo temos o exemplo de rotina baseada em
linguagem C para microcontroladores PIC da Microchip feitos em CCS.
<main.c>
#include <18F4550.h>
#use delay(clock=20000000)
#fuses INTHS,NOWDT,NOPROTECT
#define DAT PIN_B0
#define CLK PIN_B1
unsigned int j;
unsigned int Valor;
const char Segments[1][8] = {{
0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f
}};
const
char Valores[1][7] = {{
0x01,0x02,0x03,0x04,0x05,0x06,0x07
}};
void
Escreve4094(char Dados){
for(j = 0x40; j > 0; j = j >> 1) {
if(Dados & j){
output_high(DAT);
}else{
output_low(DAT);
}
output_high(CLK);
output_low(CLK);
}
}
void main() {
setup_oscillator(OSC_8MHZ | osc_intrc);
delay_ms(1000);
while(TRUE) {
output_low(DAT);
output_low(CLK);
Valor
= 1;
Escreve4094(Segments[0][Valor]);
delay_ms(1);
}
}
Em caso de utilização de microcontroladores com
portas Open-Drain é aconselhado o uso de resistores Pull-Up para fornecer as
tensões de nível lógico alto (+V) para as linhas de Data, Clock, Strobe e Enable do HEF4094.
Seguindo com o estudo do HEF4094, podemos encontrar
diversas aplicações para ele, desde a controle de periféricos, displays,
luminosos,etc. Sua aplicação é de importante valor para microcontroladores de
baixo numero de portas I/O, onde podemos multiplicar de duas portas no micro
para oito ou mais portas dependendo de quantos HEF4094 empregarmos.
Exemplo de utilização do HEF4094 para controle de um
display LCD 16X2:
No esquema acima podemos implementar o codigo feito
em linguagem C para microcontroladores PIC desenvolvidos na plataforma CCS.
<main.c>
#include <18F4550.h>
#use delay(clock=4000000)
#fuses INTHS
#include <3wire_lcd.c>
void main(void){
lcd_initialize();
lcd_cmd(LCD_CLEAR);
delay_ms(2000);
while( true ){
lcd_cmd(LCD_CLEAR);
lcd_goto(1, 1);
printf(lcd_out, "EletroGB!");
delay_ms(1000);
}
}
<3wire_lcd.c>
#define LCD_DATA_PIN PIN_b0
#define LCD_CLOCK_PIN PIN_b1
#define LCD_EN_PIN PIN_b2
#define LCD_FIRST_ROW 0x80
#define LCD_SECOND_ROW 0xC0
#define LCD_THIRD_ROW 0x94
#define LCD_FOURTH_ROW 0xD4
#define LCD_CLEAR 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_CURSOR_OFF 0x0C
#define LCD_UNDERLINE_ON 0x0E
#define LCD_BLINK_CURSOR_ON 0x0F
#define LCD_MOVE_CURSOR_LEFT 0x10
#define LCD_MOVE_CURSOR_RIGHT 0x14
#define LCD_TURN_ON 0x0C
#define LCD_TURN_OFF 0x08
#define LCD_SHIFT_LEFT 0x18
#define LCD_SHIFT_RIGHT 0x1E
short RS;
void lcd_write_nibble(unsigned int8 n){
unsigned int8 i;
output_low(LCD_CLOCK_PIN);
output_low(LCD_EN_PIN);
for( i = 8; i > 0; i = i >> 1){
if(n & i){
output_high(LCD_DATA_PIN);
}else{
output_low(LCD_DATA_PIN); }
Delay_us(10);
output_high(LCD_clock_PIN);
Delay_us(10);
output_low(LCD_clock_PIN);
}
if(RS){
output_high(LCD_DATA_PIN);
}else{
output_low(LCD_DATA_PIN); }
for(i = 0; i < 2; i++){
Delay_us(10);
output_high(LCD_clock_PIN);
Delay_us(10);
output_low(LCD_clock_PIN);
}
output_high(LCD_EN_PIN);
delay_us(2);
output_low(LCD_EN_PIN);
}
void LCD_Cmd(unsigned int8 Command){
RS = 0;
lcd_write_nibble(Command >> 4);
lcd_write_nibble(Command & 0x0F);
if((Command == 0x0C) ||
(Command == 0x01) ||
(Command == 0x0E) ||
(Command == 0x0F) ||
(Command == 0x10) ||
(Command == 0x1E) ||
(Command == 0x18) ||
(Command == 0x08) ||
(Command == 0x14) ||
(Command == 0x02))
Delay_ms(50);
}
void LCD_GOTO(unsigned int8 col, unsigned int8 row){switch(row){
case 1: LCD_Cmd(0x80 + col-1); break;
case 2: LCD_Cmd(0xC0 + col-1); break;
case 3: LCD_Cmd(0x94 + col-1); break;
case 4: LCD_Cmd(0xD4 + col-1); break;
}
}
void LCD_Out(unsigned int8 LCD_Char){
RS = 1;
lcd_write_nibble(LCD_Char >> 4);
delay_us(10);
lcd_write_nibble(LCD_Char & 0x0F);
break;
}
void LCD_Initialize(){
RS = 0;
output_low(LCD_DATA_PIN);
output_low(LCD_CLOCK_PIN);
output_low(LCD_EN_PIN);
output_drive(LCD_DATA_PIN);
output_drive(LCD_CLOCK_PIN);
output_drive(LCD_EN_PIN);
delay_ms(40);
lcd_Cmd(3); delay_ms(5);
lcd_Cmd(3); delay_ms(5);
lcd_Cmd(3); delay_ms(5);
lcd_Cmd(2); delay_ms(5);
lcd_Cmd(0x28); delay_ms(50);
lcd_Cmd(0x0C); delay_ms(50);
lcd_Cmd(0x06); delay_ms(50);
lcd_Cmd(0x0C); delay_ms(50);
}