sexta-feira, 7 de outubro de 2016

Memória - Atividade 2 - Cofre digital













   


Implementação prática



Atividade 2.1

Baixe o programa “Mem_2_1.c” (listado mais abaixo). Adapte as faixas das teclas para o seu teclado. Lembrar que as teclas estão representadas pelo seu código ASCII

Implemente o hardware mostrado na imagem acima:
  • Teclado com 16 teclas matricial por conversor A/D e interrupção
  • Sensor de porta fechada. Utilizar circuito de um botão simples simulando um sensor de contato
  • Acionamento de tranca: Saída com led indicativo e circuito para acionamento de trava elétrica. Utilizar circuito sugerido na imagem acima com acoplador ótico e acionamento por relé (permite acionamento AC ou DC).

Avaliação: Apresentar hardware e software em funcionamento

EFEITO MAGNÉTICO (TRAVA ELETROMAGNÉTICA)






   


Atividade 2.2

Modifique o programa da atividade 2.1 para:
  • Solicitar a senha para operação de trancar a porta (utilizar a mesma senha de abertura)
  • Verificar se a porta está fechada antes de acionar a tranca

Avaliação: Apresentar hardware e software em funcionamento

Fluxograma de sugestão para implementação da atividade 2.2:





Programa Mem_2_1.c
  
/*
 * File:   Mem_2_1.c
 * Author: Pilger
 *
 * Created on 4 de Outubro de 2017, 10:17
 *
 * Programa cofre digital
 * Rotina de leitura de 3 teclas para gerar um senha com valor entre 0 e 255
 * Realiza a troca de senha
 *      Solicita 2 vezes a digitação de senha e testa se menor que 255
 *      compara so 2 valores se forem iguai e menor que 255 grava no endereço 0x00 da EEPROM
 * Abertura de porta
 *      Solicita senha
 *      Senha == 255 -> troca de senha
 *      Senha <255 testa se senha é a mesma da eeprom
 *      Senha errada, mensagem de erro
 *      Senha correta
 *          destrava porta
 *          espera abrir
 *          espera fechar
 *          tranca a porta
 * 
 */


#define _XTAL_FREQ 48000000

#include <stdio.h>
#include <xc.h>
#include "C:\h\Config_PIC18F4550.h"
#include "c:\h\biblioteca_lcd_2x162_48M_XC.h"

#define tranca LATBbits.LATB7
#define sensor_porta PORTBbits.RB6

//prototipos de funções
void inicia_regs(void);
void interrupt ISR_alta_prioridade(void);
void config_int(void);
void config_int0(void);
void config_AD(void);
int conv_AD(void);
void delay_ms(int i);
int le_3_tec(unsigned char ns1);
unsigned char testa255(unsigned char ns);
void troca_senha(void);
void Eeprom_write(char addr, char data);
unsigned char Eeprom_read(unsigned char addr);


unsigned char fl_tec = 0, tec = 0;
/* fl_tec: flag que indica que chegou uma tecla
 * tec: valor asc da tecla recebida
 */



void main(void) {
    unsigned char buffer[16];
    unsigned char senha_digitada = 0, senha_eeprom = 0;
    inicia_regs();
    config_int();
    config_int0(); // configura as interrupções
    config_AD(); // configura e inicializa o conversor AD
    lcd_inicia(0x28, 0x0f, 0x06); // incializa o LCD com 4 linhas
    lcd_LD_cursor(0); // Desliga o cursor
    tranca = 1; // tranca inicialmente ativada
    while (1) {
        lcd_limpa_tela();
        lcd_posicao(1, 1);
        imprime_string_lcd(" Cofre digital ");
        delay_ms(2000);
        senha_digitada = testa255(0);
        lcd_posicao(2, 1);
        sprintf(buffer, "Senha   = %03d  ", senha_digitada);
        imprime_buffer_lcd(buffer, 15);
        if (senha_digitada == 255) {
            troca_senha();
        } else {
            senha_eeprom = Eeprom_read(0);
            if (senha_digitada == senha_eeprom) {
                tranca = 0; // abre tranca
                lcd_limpa_tela();
                lcd_posicao(1, 1);
                imprime_string_lcd("   Destravado   ");
                lcd_posicao(2, 1);
                imprime_string_lcd(" Porta Fechada ");
                while (!sensor_porta); //espera a porta abrir
                lcd_posicao(1, 1);
                imprime_string_lcd(" Porta Aberta  ");
                lcd_posicao(2, 1);
                imprime_string_lcd("Feche p/travar ");
                while (sensor_porta); // aguarda porta fechar
                tranca = 1; // fecha tranca
                lcd_posicao(1, 1);
                imprime_string_lcd(" Cofre digital ");
                lcd_posicao(2, 1);
                imprime_string_lcd(" Porta Fechada ");
                delay_ms(2000);
            } else {
                lcd_limpa_tela();
                lcd_posicao(1, 1);
                imprime_string_lcd("ERRO -   Senha ");
                lcd_posicao(2, 1);
                imprime_string_lcd("     nao confere");
                delay_ms(2000);
            }
        }
    }
}

// função de configuração do conversor A/D

void config_AD(void) {
    ADCON0 = 0b00000001; /* canal AN0 selecionado <5:2> 0000
                                   Flag GO - /DONE desligado <1> 0
   Módulo conversor ligado <0> 1 */
    ADCON1 = 0b00111110; /* Vref- = GND <5> 0 RA2 <5> 1
   Vref+ = VDD <4> 0
   pino RA0/AN0 analógico e demais digitais <3:0> 1110 */
    ADCON2 = 0b10110110; /* Resultado justificado a direita <7> 1
* Tempo de Aquisição de 16 TDA <5:3> 110
* TDA = 1,33us <2:0> 110
                                 * 48MHz/64 = 750kHz = 1,33us */
}


// função que efeuta uma conversão A/D e retorna um inteiro com o valor convertido

int conv_AD(void) {
    int result_AD; // Variável local para armazenar o resultado da conv
    ADCON0bits.GO = 1; // inicia a conversão
    while (ADCON0bits.GO); // Aguarda a o fim da conversão
    result_AD = (((int) ADRESH) << 8) | (ADRESL);
    return result_AD;
}

// função que inicia os registradores I/O

void inicia_regs(void) {
    // Configura todas as portas multiplexadas com o módulo conversor A/D, como I/O digital. (cap13)
    ADCON1 = 0x0F;
    TRISA = 0b00001101;
    TRISB = 0b01000001; // define a B0 como entrada (INT0)  e B6 sensor da porta
    TRISD = 0x00; // define a porta D como saída      - onde está o LCD
    TRISE = 0x00; // define a porta E como saída      - onde está o Led que indica que passou pela interrupção
    PORTA = 0;
    PORTB = 0;
    PORTC = 0;
    PORTD = 0;
    PORTE = 0; // zeroa todos os pinos
}

// função de interrupção de alta prioridade

void interrupt ISR_alta_prioridade(void) {
    delay_ms(100); // atraso de 0,1s
    // este atraso é importante para evitar pulos do teclado, pois o up roda muito rápido 48MHz
    int vc;
    //    unsigned char buffer[16];
    fl_tec = 1;
    tec = 0;
    vc = conv_AD();
    lcd_posicao(2, 1);
    if (vc > 965 && vc < 1003) tec = 47;
    else if (vc > 929 && vc < 965) tec = 57;
    else if (vc > 899 && vc < 929) tec = 56;
    else if (vc > 865 && vc < 899) tec = 55;
    else if (vc > 821 && vc < 865) tec = 120;
    else if (vc > 755 && vc < 821) tec = 54;
    else if (vc > 737 && vc < 775) tec = 53;
    else if (vc > 665 && vc < 737) tec = 52;
    else if (vc > 575 && vc < 665) tec = 45;
    else if (vc > 509 && vc < 575) tec = 51;
    else if (vc > 453 && vc < 509) tec = 50;
    else if (vc > 369 && vc < 453) tec = 49;
    else if (vc > 260 && vc < 369) tec = 43;
    else if (vc > 163 && vc < 260) tec = 35;
    else if (vc > 70 && vc < 163) tec = 48;
    else if (vc > 20 && vc < 70) tec = 42;
    //    sprintf(buffer, "  Conv= %04d", vc);
    //    imprime_buffer_lcd(buffer, 15);
    INTCONbits.INT0IF = 0; // Limpa o flag de ativação da interrupção
}


// função de configuração geral de interrupções

void config_int(void) { // configurações gerais a todas as interrupçãoes
    RCONbits.IPEN = 1; // Habilita interrupção com nível de prioridade. End 0x08 - alta e 0x18 - baixo
    INTCONbits.GIEH = 1; // Habilita todas as interrupções de alta prioridade
    INTCONbits.GIEL = 0; // Desabilita todas as interrupções de baixa prioridade
}

// função de configuração da Interrupção externa 0

void config_int0(void) { // configurações específicas a INT0
    INTCONbits.INT0IE = 1; // Ativa a inerrupção externa INT0 (RB0)
    INTCON2bits.INTEDG0 = 0; // Interrupção externa INT0 na borda de descida
    INTCONbits.INT0IF = 0; // Limpa o flag bit da interrupção externa INT0
}

// função que gera atraso em mlisegundos
void delay_ms(int i){
    for ( int x = 0; x < i; x++ )     { 
    __delay_ms(1); 
    }
}

unsigned char testa255(unsigned char ns) {
    // ns = 0 escreve "senha"
    // ns = 1 escreve "senha 1" ou 2 escreve "senha 2"
    int pass = 999;
    unsigned char fl_testa = 1;
    while (fl_testa) {
        pass = le_3_tec(ns);
        if (pass > 255) {
            lcd_limpa_tela();
            lcd_posicao(1, 1);
            imprime_string_lcd("ERRO");
            lcd_posicao(2, 1);
            imprime_string_lcd("Senha > 255");
            delay_ms(2000);
        } else fl_testa = 0;
    }
    return (char) pass;
}

/*
 * Função que lê 3 num do teclado de 0 a 9
 * Backspace tecla *
 * OK tecla # Saída da função e retorna um num de 0 a 999
 */
int le_3_tec(unsigned char ns1) {
    // ns1 = 0 escreve "senha"
    // ns1 = 1 escreve "senha 1" ou 2 escreve "senha 2"
    unsigned char i = 0, fl_3 = 1, num_asc[4] = {48, 48, 48, 48};
    int num = 0;
    unsigned char buffer[16];
    lcd_posicao(1, 1);
    if (ns1 != 0) sprintf(buffer, "Digite senha %d ", ns1);
    else sprintf(buffer, "Digite senha   ");
    imprime_buffer_lcd(buffer, 15);
    //    imprime_string_lcd("Digite senha   ");
    lcd_posicao(2, 1);
    imprime_string_lcd("      * <- # OK ");
    imprime_buffer_lcd(buffer, 3);
    while (fl_3) {
        if (fl_tec) {
            fl_tec = 0; // desliga flag que avisa que tecla chegou
            //            lcd_posicao(1, 14);
            //            sprintf(buffer, "%d", i+1);
            //            imprime_buffer_lcd(buffer, 1);
            if (tec == 35) { // tec # OK
                if (i == 1) {
                    num_asc[0] = num_asc[2];
                    num_asc[2] = 48; //num_asc[1]=48;
                } else if (i == 2) {
                    num_asc[0] = num_asc[1];
                    num_asc[1] = num_asc[2];
                    num_asc[2] = 48;
                }
                if (i < 4) i = 4;
            } else if (tec == 42) { // tec * Backspace
                if (i == 1) num_asc[2] = 48;
                if (i == 2) num_asc[1] = 48;
                if (i == 3) num_asc[0] = 48;
                if (i > 0) i--;
                else i = 0;
            } else if (i < 3) {
                if (tec < 58 && tec > 47) { // garante que só vale teclas de 0 a 9 para registrar
                    num_asc[2 - i] = tec;
                    i++;
                }
            }
            if (i == 4) { //se # - OK foi pressionado
                fl_3 = 0;
                num = (num_asc[2] - 48)*100 + (num_asc[1] - 48)*10 + (num_asc[0] - 48); // converte asc para num
            }
            lcd_posicao(2, 1);
            if (i == 0) sprintf(buffer, "   ");
            if (i == 1) sprintf(buffer, "%d  ", num_asc[2] - 48);
            if (i == 2) sprintf(buffer, "%d%d ", num_asc[2] - 48, num_asc[1] - 48);
            if (i == 3) sprintf(buffer, "%d%d%d", num_asc[2] - 48, num_asc[1] - 48, num_asc[0] - 48);
            imprime_buffer_lcd(buffer, 3);
        }
    }
    return num;
}

void troca_senha(void) {
    unsigned char fl_4 = 1;
    unsigned char buffer[16];
    int senha1 = 0, senha2 = 0;
    while (fl_4) {
        lcd_limpa_tela();
        lcd_posicao(1, 1);
        imprime_string_lcd("Troca de senha ");
        delay_ms(2000);
        lcd_posicao(1, 1);
        imprime_string_lcd("Digite         ");
        lcd_posicao(2, 1);
        imprime_string_lcd("Senha 1        ");
        delay_ms(1000);
        senha1 = testa255(1);
        lcd_posicao(2, 1);
        sprintf(buffer, "Senha 1 = %03d  ", senha1);
        imprime_buffer_lcd(buffer, 16);
        delay_ms(2000);
        lcd_posicao(1, 1);
        imprime_string_lcd("Digite         ");
        lcd_posicao(2, 1);
        imprime_string_lcd("Senha 2        ");
        delay_ms(1000);
        senha2 = testa255(2);
        lcd_posicao(2, 1);
        sprintf(buffer, "Senha 2 = %03d  ", senha2);
        imprime_buffer_lcd(buffer, 16);
        delay_ms(2000);
        if (senha1 == senha2) {
            if (senha1 == 255) {
                lcd_limpa_tela();
                lcd_posicao(1, 1);
                imprime_string_lcd("ERRO senha     ");
                lcd_posicao(2, 1);
                imprime_string_lcd(" Nao pode 255  ");
                delay_ms(2000);
            } else {
                lcd_limpa_tela();
                lcd_posicao(1, 1);
                imprime_string_lcd("Senha 1=Senha 2");
                lcd_posicao(2, 1);
                imprime_string_lcd("Gravando senha ");
                Eeprom_write(0, senha1);
                delay_ms(2000);
                fl_4 = 0;
            }
        } else {
            lcd_limpa_tela();
            lcd_posicao(1, 1);
            imprime_string_lcd("ERRO de senhas ");
            lcd_posicao(2, 1);
            sprintf(buffer, "  %03d <> %3d  ", senha1, senha2);
            imprime_buffer_lcd(buffer, 16);
            delay_ms(2000);
        }
    }
}

void Eeprom_write(char addr, char data) {
    char intcon_temp;
    while (EECON1bits.WR); // se uma escrita estiver em andamento, aguarda
    EEADR = addr; // configura o endereço inicial da escrita
    EECON1bits.EEPGD = 0; // Seleciona  área de mem = eeprom
    EECON1bits.CFGS = 0; // Seleciona  área de mem = eeprom   
    EECON1bits.WREN = 1; // escrita permitida (1))
    EEDATA = data; // escreve no registrador EEDATA o dado a ser gravado
    intcon_temp = INTCON; // Guarda o valor do registrador INTCON
    INTCON = 0; // Erase INTCON e disable interrups
    EECON2 = 0x55; // senha de escrita em memória
    EECON2 = 0xAA;
    EECON1bits.WR = 1; // habilita a escrita , volta a zero no fim da op
    while (EECON1bits.WR); // aguarda o fim da escrita, pois leva 4ms
    INTCON = intcon_temp; // restaura o valor do registrador INTCON
}

unsigned char Eeprom_read(unsigned char addr) {
    EEADR = addr; // EEADR recebe o endereço passado para a função
    EECON1bits.EEPGD = 0; // Seleciona  área de mem = eeprom
    EECON1bits.CFGS = 0; // Seleciona  área de mem = eeprom
    EECON1bits.FREE = 0; // modo de apagamento de flash não selecionada (0)
    EECON1bits.WREN = 0; // escrita não permitida (0))
    EECON1bits.RD = 1; // habilita opção de leitura, volta a zero no fim da op
    return (EEDATA); // retorna o conteúdo lido (de EEDATA)
}


   




Nenhum comentário:

Postar um comentário