O código fonte:
/* * usando o modo CCP no MPlab XC8 * * Compilador : MPlabXC8 * Microcontrolador: 16F648A * Autor: aguivone * Versão: 1 * Data : 01 de março de 2013 */ #include <stdio.h> #include <stdlib.h> #include <string.h> //para usar funçoes de string deve se adicionar este header #define _XTAL_FREQ 4000000 // oscilador interno de 4 Mhz #include <xc.h> /////////////////////////////////////////////////////////configuraçôes////////////////////////////////////////////////// #define LED_STATUS RB0 #define SINAL PORTAbits.RA0 #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) ////////////////////////////////////////////////variaveis globais/////////////////////////////////////////////////////////// long anterior = 0, atual = 0,largura_pulso = 0; int primeiro_pacote = 0,valor_pulso=0; long timeout = 0; long bit_0=0,bit_1=0,start_stop=0,range_bit=150; ///////////////////////////////////////////////////interrupção////////////////////////////////////////////////////////////// void interrupt CCP1(void) { if(CCP1IF) //verifica se é interrupção de cpp {// cada incremtento do timer será a cada 1us ,pois estou usando o oscilador interno de 4mhz atual = CCPR1; CCP1IF = 0; //limpa interrupção de captura de sinal if (anterior > atual) { largura_pulso = (0XFFFF - anterior) + atual; } else { largura_pulso = atual - anterior; } anterior = atual; } } /////////////////////////////////funçoes usadas pela uart ////////////////////////////////////////////////////// void inicializa_RS232(long velocidade,int modo) {////por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada. //verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado. RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono. int valor; if(modo == 1) {//modo = 1 ,modo alta velocidade TXSTA = 0X24;//modo assincrono,trasmissao 8 bits. valor =(int)(((_XTAL_FREQ/velocidade)-16)/16);//calculo do valor do gerador de baud rate } else {//modo = 0 ,modo baixa velocidade TXSTA = 0X20;//modo assincrono,trasmissao 8 bits. valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);//calculo do valor do gerador de baud rate } SPBRG = valor; RCIE = 0;//não vou receber nenhum dado do pc //RCIE = 1;//habilita interrupção de recepção TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo) } void escreve(char valor) { TXIF = 0;//limpa flag que sinaliza envio completo. TXREG = valor; while(TXIF ==0);//espera enviar caracter } void imprime(const char frase[]) { char indice = 0; char tamanho = strlen(frase); while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas { escreve(frase[indice]); indice++; } } void inicializa_CCP() { //habilita captura de pulso na borda de subida (prescaler sem divisão) CCP1CON = 0X05;//modo de captura sem divisão (borda de subida) CCP1IF = 0; //limpa flag de interrupção de captura CCP1IE = 1;//habilita modo de captura de pulsos*/ } void inicializa_timer1() { TMR1IF = 0; //limpa flag de interrupção de timer // TMR1IE = 1; //habilita interrupção de estouro do timer TMR1IE = 0; //desabilita interrupção de estouro do timer T1CON = 0x81; //habilita leitura do timer 1 e o timer 1,sem prescaler } //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// void main(void) { TRISA = 0XFF;//como entrada TRISB = 0X08;//configura portB B3 (ccp1) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas inicializa_CCP(); inicializa_timer1(); inicializa_RS232(9600,1);//modo de alta velocidade imprime("controle remoto"); PEIE = 1;//habilita interrupção de perifericos do pic GIE = 1; //GIE: Global Interrupt Enable bit for(;;) { if(largura_pulso > 0)//leu pulsos { valor_pulso = largura_pulso; if(primeiro_pacote == 0) { primeiro_pacote = 1;//descarta pois virá com lixo } else { if(primeiro_pacote == 1) {//tenta localizar o protocolo primeiro_pacote = 2; escreve('\n');//pula para proxima linha escreve('\r');//coloca no inicio da linha if((valor_pulso > 2900)&&(valor_pulso < 3200)) { escreve('N'); bit_0 = 1200; bit_1 = 1800; start_stop=3000; } if(valor_pulso < 2900) { escreve('P'); bit_0 = 1800; bit_1 = 2700; start_stop=0; if(valor_pulso > (bit_0 + range_bit)) {//bit 1 escreve('1'); } else {//bit0 escreve('0'); } } if((valor_pulso > 8000)&&(valor_pulso < 10000)) { escreve('S'); bit_0 = 1100; bit_1 = 2250; start_stop=9000; } if(valor_pulso > 10000) { escreve('L'); bit_0 = 1100; bit_1 = 2250; start_stop=13500; } } else { if((valor_pulso > (start_stop - range_bit))&&(valor_pulso < (start_stop + range_bit))) {//start bit escreve('S');//pra indicar que recebeu um bit de inicio ou fim de pacote } if(valor_pulso < (bit_1 + range_bit)) { if(valor_pulso > (bit_0 + range_bit)) {//bit 1 escreve('1'); } else {//bit0 escreve('0'); } } } } largura_pulso=0; timeout = 3000;//prepara contagem }//fim do leu pulsos if(timeout>0) { timeout--; } if(timeout==1) {// tempo usado para resetar ou descartar pacotes com defeito primeiro_pacote = 0; } }//loop infinito }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Depois de montado os códigos vamos a simulação,na simulação o primeiro pacote dá um erro, mas logo em seguida tudo funciona normalmente.Veja a imagem da simulação e do esquemático no proteus :
O esquemático:
Testando com um controle remoto e com o prototipo montado numa proto-o-board recebi os seguintes códigos do controle:
Padrão samsung, 33bits + start_stop_bit:
Power = 111000001110000001000000101111110
vol+ = 111000001110000011100000000111110
vol- = 111000001110000011010000001011110
ch+ = 111000001110000001001000101101110
ch- = 111000001110000000001000111101110
Padrão LG, 32bits + start_stop_bit:
Power = 01000001101111100010000111011110
vol+ = 01000001101111101000000101111110
vol- = 01000001101111111000000001111110
ch+ = 01000001101111100000000111111110
ch- = 01000001101111110000000011111110
padrão sony, repete 3 vezes um codigo de 11 bits + start_bit
com intervalos de 27ms
Power = 10101001000
vol+ = 01001001000
vol- = 11001001000
ch+ = 00001001000
ch- = 10001001000
padrão philips envia 10 bits sem pulsos de inicio e fim
Power = 0100000101
vol+ = 0100001100
vol- = 0000001101
ch+ = 0000011000
ch- = 0100011001
Para pegar os dados eu montei na proto-o-board o esquema elétrico seguinte:
Em breve vou postar um artigo usado este projeto como base para acionar leds com diferentes controles, até a próxima!
#curtimasnãoentendi
ResponderExcluir