Descrição
Biblioteca em C compilada com PCW da CCS para decodificar sinais provenientes do chip HT6P20 da Holtek. Usando um PIC (12F629) e um módulo receptor de RF 433MHz, irei demonstrar seu funcionamento.
Funcionamento
O encoder HT6P20 é um chip amplamente utilizado principalmente em controles remotos de RF na frequência de 433MHz. Isso porque, além de não precisar de 'jumpers' em seus pinos para configuração de seu segredo, ele também conta com 24 bits em seu código. Segue tais detalhes:
Com esse módulo RX, iremos receber os dados e entregar para alguma porta do PIC:
Esquema
Código
////////////////////////////////////////////////////////////////////////////////
/// HT6P20.C ///
/// Driver para receptores Learning Code ///
/// ///
/// As seguintes variáveis devem ser definidas como byte no código main: ///
/// ///
/// dado_H - armazenará a parte mais significativa do encoder ///
/// dado_M - armazenará a parte intermediária do encoder ///
/// dado_L - armazenará a parte menos significativa do encoder ///
/// ///
/// A função principal é a 'decoder()'. Ela irá retornar um booleano ///
/// Se retornar um 'verdadeiro' indica que foi decodificado um sinal ///
/// válido no receptor. Nas variáveis 'dado_X' estarão os valores recebidos ///
/// ///
/// autor: Valdir Santos valdir.st@gmail.com ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//configuraçoes do pino de entrada
#define entrada PIN_A2
//******************************************************************************
// Definir essas 3 variáveis no código principal
extern byte dado_H; // Dado alto. MSB
extern byte dado_M; // Dado médio.
extern byte dado_L; // Dado baixo. LSB
int16 tempo;
int16 largura_pulso;
//******************************************************************************
// Decodifica 1/3 do pacote de dados. Se essa rotina retornar 0xFF, indica
// que não é o sinal com protocolo HT6P20.
byte decoder_1byte()
{
int n_bits;
byte dado = 0;
for(n_bits = 8; n_bits > 0; n_bits--)
{
// verifica a 1ª parte do bit. Tem que ser nível '0'
delay_us(largura_pulso/2);
if(input(entrada)) return(0xFF); // houver erro
// Marca valor do bit
delay_us((largura_pulso));
rotate_left(&dado, 1);
if(input(entrada)) bit_set(dado, 0);
// verifica a 3ª parte do bit. Tem que ser nível '1'
delay_us((largura_pulso));
if(!input(entrada)) return(0xFF); // houver erro
// aguarda descida
tempo = largura_pulso/2;
while(input(entrada) && tempo>0)
tempo--;
if(tempo==0) return(0xFF); // houve erro
}
return(dado);
}
//******************************************************************************
// Decodifica os 24 bits identificando o inicio de cada word
// Se essa função retornar um verdadeiro, indica que os 24 bits foram recebidos
boolean decoder()
{
// Verifica se está no inicio do código. Aguarda transação de descida por 3mS
tempo = 1000;
while(input(entrada) && tempo > 0) // cada cilco desse laço, demora 3uS
tempo--;
if(tempo==0) return(0);
// testa os 23 clocks. Esse período pode variar de 7.6mS (para osciladores
// de 3KHz) a 12mS (para osciladores de 2KHz). Testa zero por 5mS
tempo = 1666;
while(!input(entrada) && tempo > 0) // cada ciclo desse laço, dura 3uS (@ 20MHz)
tempo--;
if(input(entrada)) return(0);
// aguarda nivel 1 por 10mS (start bit)
tempo = 3333;
while(!input(entrada) && tempo > 0)
tempo--;
if(tempo==0) return(0);
// ajusta largura do pulso de acordo com o start bit com limite de 600uS (1.5KHz)
largura_pulso = 0;
while(input(entrada)) // cada ciclo desse laço, dura 4uS (@ 20MHz)
{
delay_us(1);
largura_pulso++;
if(largura_pulso == 150) break; // limita largura do pulso em 600uS (1.5KHz)
}
if(largura_pulso==150) return(0);
// Corrige o valor da largura de pulso
largura_pulso *= 4;
// Decodifica os próximos 24 bits
dado_H = decoder_1byte();
dado_M = decoder_1byte();
dado_L = decoder_1byte();
// Rejeita se no pacote houver 0xFF
if(dado_H == 0xFF || dado_M == 0xFF || dado_L == 0xFF) return(0);
// aguarda o tempo dos ultimos 4 bits do anti-código
delay_us(largura_pulso * 12);
return(true);
}
////////////////////////////////////////////////////////////////////////////////
Programa Demo
Para fins didáticos, iremos demonstrar um simples programa que acende um led por 1 segundo quando receber um sinal válido (com protocolo HT6P20) através do receptor.
//##############################################################################
#include <C:\Program Files (x86)\PICC\Devices\12F629.h>
#fuses HS, NOWDT, NOPROTECT, NOMCLR, NOBROWNOUT, PUT
#use delay(clock=20000000)
#include "HT6P20.c"
#use fast_io(A)
//*****************************************************************************
// Definições de Hardware
#define led PIN_A0
//*****************************************************************************
// Variáveis
// Nessas 3 variáveis, serão armazenadas os dados recebidos do rádio
byte dado_H; // Dado alto. MSB
byte dado_M; // Dado médio.
byte dado_L; // Dado baixo. LSB
//##############################################################################
//Inicialização
void main()
{
{
set_tris_a(0b00001110);
output_low(led);
}
//##############################################################################
// Laço principal
while(true)
{
// Verifica se está recebendo dados do rádio
if(decoder())
{
output_high(led);
delay_ms(1000);
output_low(led);
}
}
}
//##############################################################################
//##############################################################################
#include <C:\Program Files (x86)\PICC\Devices\12F629.h>
#fuses HS, NOWDT, NOPROTECT, NOMCLR, NOBROWNOUT, PUT
#use delay(clock=20000000)
#include "HT6P20.c"
#use fast_io(A)
//*****************************************************************************
// Definições de Hardware
#define led PIN_A0
//*****************************************************************************
// Variáveis
// Nessas 3 variáveis, serão armazenadas os dados recebidos do rádio
byte dado_H; // Dado alto. MSB
byte dado_M; // Dado médio.
byte dado_L; // Dado baixo. LSB
//##############################################################################
//Inicialização
void main()
{
{
set_tris_a(0b00001110);
output_low(led);
}
//##############################################################################
// Laço principal
while(true)
{
// Verifica se está recebendo dados do rádio
if(decoder())
{
output_high(led);
delay_ms(1000);
output_low(led);
}
}
}
//##############################################################################
Claro que é apenas uma pequena demonstração da biblioteca para decodificar o sinal de um controle. Mas a partir daqui, poderá ser adicionados vários recursos.
Um incremento de um botão para gravar em memória o código recebido.
Usar mais de um pino como saída, expandido, assim, diversos canais para controle.
Enfim, são diversas possibilidades.
Imagine.
Acredite em você.
E crie com eletrônica.
Abraços!