sexta-feira, 9 de junho de 2017

Lista de materiais para o módulo 3



   





   

  • Microcontrolador PIC18F4550 DIP
  • Módulo LCD 2 x 16
  • Placa para o hardaware básico de desenvolvimento (opcional)


   
Lista de peças para o hardware de desenvolvimento




   
Lista de peças para práticas



   


RS 232 - Atividades 1 e 2

Abaixo o esquemático para simulação e montagem do hardware para comunicação RS232 utilizando o PIC18F4550
  • ·        Microcontrolador PIC18F4550
  • ·        Módulo LCD 2 x 16
  • ·        Modelo de interface serial





Atividade 1

O programa main39.c foi desenvolvido para um PIC 18F4520 rodando a 8MHz e uma comunicação serial a 2.400bps
  • ·        Montar um projeto no MPLABX utilizando como base o programa “main39.c”
  • ·        Adaptar o código para o microcontrolador PIC 18F4550
  • ·        Adaptar o código para a biblioteca de LCD
  • ·        Utilizar um software para criação de uma porta serial virtual
  • ·        Utilizar um terminal – Windmil ComDebug Serial Intrument Set Up Utility”
  • ·        Configure as portas seriais (qual porta) e a velocidade de comunicação


Avaliação: Apresentar a comunicação no simulador com o terminal COMDEBUG






Atividade 2

·        Modificar o software da atividade 1 para trabalhar com o clock de 48MHz no microcontrolador alterando o “boud rate”
·        Montar o circuito de interface para comunicação com a porta de um computador utilizando o MAX232.

Avaliação: Apresentar a comunicação no PIC18F4550 com o terminal COMDEBUG em um PC







programa main_39.c

 


/*********************************************************************
Nome do arquivo: main_39.c            
Data:     17 de maio de 2010          
Versao: 1.0                              
MPLAB IDE: v8.20a 
Autor: Wagner Zanco              
*********************************************************************/
#include <p18f4520.h> //diretiva de compilação
#include "Lcd_8bits.h" //diretiva de compilação
//********************************************************************
//protótipos de funções
void Inic_Regs (void);
void Atual_LCD (char dado);
void Configura_UART (void);
void Transmite_UART (char dado);
//********************************************************************
//variáveis globais
char count=0;
//********************************************************************
void main(void) //função main
{
float x=0; //declaração  de variável local inicializada
int dly=0; //declaração  de variável local inicializada
char DADO; //declaração  de variável local inicializada
//**********************************
Inic_Regs (); //configurar SFRs
//**********************************
IniciaLCD (2); //inicializar LCD controller HD44780
TestPixelsLCD(); //teste no LCD - acende todos os pixels.

EscInstLCD(0x0C); //desativa cursor
while(TesteBusyFlag()); //espera LCD controller terminar de executar instrução
//**********************************
//delay de 3 segundos
for(dly=0;dly<600;dly++) //comando de iteração
{
_Delay5ms(); //delay de 5ms
}
//**********************************
EscInstLCD(0x01); //desativa cursor
while(TesteBusyFlag()); //espera LCD controller terminar de executar instrução
//**********************************/
Configura_UART(); //configura UART com taxa de 2400bps
//**********************************/
//rotina principal
while(1)
{
while(!PIR1bits.RCIF); //aguarda chegar um novo byte
if (RCSTAbits.FERR) //houve erro de transmissão?
{
RCSTAbits.CREN = 0; //sim, desabilita recepção
RCSTAbits.CREN = 1; //habilita recepção
}
else //não houve erro de transmissão, transmite dado recebido
{
DADO = RCREG; //obtém caractere
Transmite_UART (DADO); //transmite DADO
Atual_LCD(DADO); //atualiza LCD
}
}
}//******************************************************************
// funções
//*******************************************************************
/*Esta funcao inicializa os resgistradores SFRs.*/
 void Inic_Regs (void)
{
TRISA = 0x00; //PORTA saída
TRISB = 0x00; //PORTB saída
TRISC = 0x00; //PORTC saída
TRISD = 0x00; //PORTD saída
TRISE = 0x00; //PORTE saída
ADCON1 = 0x0F; //configura pinos dos PORTA e PORTE como digitais
PORTA = 0; //limpa PORTA
PORTB = 0; //limpa PORTB
PORTC = 0; //limpa PORTC
PORTD = 0x00; //apaga displays
PORTE = 0; //limpa PORTE
}//********************************************************************
//inicializa USART
void Configura_UART (void)
{
TRISCbits.TRISC7 = 1; //configura pino RX como entrada
TRISCbits.TRISC6 = 1; //configura pino TX como entrada
TXSTA = 0b00100100; //transmissão habilitada<5>
//transmissão assíncrona<4>
//transmissão em alta velocidade<2>
RCSTA = 0b10010000; //porta serial habilitada<7>
//recepção contínua habilitada<4>
BAUDCON = 0b00000000; //TX ocioso em nível alto<4>
//gerador de baud rate de 8 bits<3>
SPBRG = 207; //2400bps
}//*********************************
//transmite o caractere
void Transmite_UART (char dado)
{
TXREG = dado; //inicia a transmissão
while(!TXSTAbits.TRMT); //aguarda transmissão terminar
}//***************************************************************************
//função  que  atualiza o LCD. 
void Atual_LCD (char dado)
{
if(count==16) //se cursor chegou no final da primeira linha
{
EscInstLCD(0xC0); //move cursor para a primeira posição da segunda linha
while(TesteBusyFlag()); //espera LCD controller terminar de executar instrução
}
else if(count==32) //se cursor chegou no final da segunda linha
{
EscInstLCD(0x01); //limpa display e mostra cursor piscando na primeira posição da primmeira linha
while(TesteBusyFlag()); //espera LCD controller terminar de executar instrução
}
EscDataLCD(dado); //escreve caractere no LCD na posição apontada pelo cursor
while(TesteBusyFlag()); //espera LCD controller terminar de executar instrução
count+=1; //incrementa count
//*******************************************************************
}


 


sábado, 3 de junho de 2017

RS 232 - Atividades 3 e 4

Atividade 3 – TX e RX com PC

  • Microcontrolador PIC18F4550
  • Módulo LCD 2 x 16
  • Hardware do teclado
  • Circuito de interface com MAX232
  • PC com terminal (Windmil-Comdebug)





Baseado na solução encontrada na Atividade 2 (Recepção de dados USART com ECO) mofificar o programa para:
  • 1ª linha do LCD mostrar os caracteres recebidos
  • 2ª linha do LCD mostrar os caracteres enviados

Dicas de implementação

  • Utilizar como base o programa desenvolvido na Atividade 2
  •  Importar as rotinas utilizadas nos programas anteriores para funcionamento do teclado
    • Configuração do Conversor A/D
    • Função de conversão A/D
    • Função de configuração geral de interrupções
    • Função de configuração da interrupção externa utilizada
    • Função de interrupção que lê o teclado
  • Modificar o “while (1)” para não fazer mais o “ECO”
  • Na função de interrupção após identificação da tecla, enviar o código ASC pela USART
  • Modificar a função atualiza LCD para duas funções
    •  Atualiza LCD RX: imprimir na 1ª linha “RX:” e na sequência os caracteres recebidos, com controle de fim de linha (coluna 16
    •  Atualiza LCD TX¨: imprimir na 2ª linha “TX:” e na sequência os caracteres recebidos, com controle de fim de linha (coluna 16)

Avaliação: Apresentar a comunicação do PIC com o PC


Atividade 4 – TX e RX com PIC a PIC

Utilizar 2 conjuntos:
·        Microcontrolador PIC18F4550
·        Módulo LCD 2 x 16
·        Hardware do teclado
Utilizar o software desenvolvido na Atividade 3

Dicas de implementação

  • Alimentar com fonte externa ou USB apenas 1 dos conjuntos (módulo 1, por exemplo)
  • Alimentar o outro módulo (módulo 2 por exemplo) com os terminais VCC e GND
  • Ligar TX do módulo 1 com RX do módulo 2
  • Ligar RX do módulo 1 com TX do módulo 2


Avaliação: Apresentar a comunicação de duas PIC





Programa Relógio com ajuste RTC

Sugestão de implementação

Tecla # Entra e sai do ajuste do relogio
Tecla 2 (^) rola o menu de opções para cima
 Tecla 8 (v) rola o menu de opções para baixo
 Tecla 4 (<) Ajusta a opção corrente do menu por decremento
 Tecla 6 (>) Ajusta a opção corrente do menu por incremento

 Opções do menu e ajustes possíveis:
 1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
 2 - Data (1 a 31)
 3 - Mês (1 a 12)
 4 - Ano (2000 a 2099)
 5 - Hora (0 a 23)
 6 - Minutos (0 a 59)



Sugestão de variáveis a ser utilizadas

Leitura, gravação e apresentação do lcd

  • sec
  • min
  • hour
  • day
  • date
  • month
  • year

Ajuste dos parâmetros


  • min_aj
  • hour_aj
  • day_aj
  • date_aj
  • month_aj
  • year_aj

Controle e fluxo de programa

tec            // valor do código ASCII da tecla pressionada
fl_tec        // flag que indica que uma tecla foi pressionada, valores 1 (uma tecla foi pressionada) ou 0
menu        //  indica a opção corrente que será mostrada no LCD e pode ser alterada
fl_menu    //  indica que está no modo de ajuste, valores 0 ou 1, serve para manter um while () que
                     executa o ajuste do menu



Funções para modificar os dados RTC - > ajuste


// devolve a dezena em decimal do numero
unsigned char UpperCh(unsigned char ch)
{
unsigned char temp;
  temp = ch >> 4;
  return(temp);
}
// devolve a unidade em decimal do numero
unsigned char LowerCh(unsigned char ch)
{
unsigned char temp;
  temp = ch & 0x0F; //Making the Upper 4-bits
  return(temp);
}


Exemplo de uso:

unsignde char min;        // variável usada para ler os minutos do RTC
unsigned char min_aj;   // variável para fazer o ajuste dos minutos

min_aj = UpperCh(min)*10 + LowerCh(min);




Funções para modificar os dados Ajuste -> RTC


// converte para o formato RTC
unsigned char ch_to_rtc (unsigned char ch){
    unsigned char dezena,unidade,saida;
    dezena = ch/10; // dezena
    unidade= ch - dezena*10; // unidade
    saida = (dezena<<4)|(unidade);
    // temp = ((ch/10)<<4) && (ch - (ch/10)); // não sei se funciona de uma vez só???
    return saida;
}

Exemplo de uso:

unsignde char min;        // variável usada para ler os minutos do RTC
unsigned char min_aj;   // variável para fazer o ajuste dos minutos

min = ch_to_rtc(min_aj);



Programa com funções a completar

/*
 *
 * Programa que mostra caledário e relógio no LCD
 * Teclado matricila por conversor AD com Interrupção
 * Programa de ajuste do relógio
 *
 * Tecla # Entra e sai do ajuste do relogio
 * Tecla 8 (^) rola o menu de opções para cima
 * Tecla 2 (v) rola o menu de opções para baixo
 * Tecla 4 (<) Ajusta a opção corrente do menu por decremento
 * Tecla 6 (>) Ajusta a opção corrente do menu por incremento
 *
 * Opções do menu e ajustes possíveis:
 * 1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
 * 2 - Data (1 a 31)
 * 3 - Mes (1 a 12)
 * 4 - Ano (2000 a 2099)
 * 5 - Hora (0 a 23)
 * 6 - Minutos (0 a 59)
 *
 */


#define _XTAL_FREQ 48000000

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

// prototipos de funções para leitura e escrita do rtc i2c
void i2c_init();
void i2c_start(void);
void i2c_restart(void);
void i2c_stop(void);
void i2c_wait(void);
void i2c_send(unsigned char dat);
unsigned char i2c_read(void);
unsigned char rtc1307_read(unsigned char address); //RTC DS1307 Read Function

// protipos de funções para o main e funcionamento do teclado matriacial
void inicia_regs(void);
void interrupt ISR_alta_prioridade(void);
void config_int(void);
void config_int2 (void);
void config_AD(void);
int conv_AD(void);
void delay_ms(int i);
void atraso_meios(unsigned char meio_segundos);
unsigned char UpperCh(unsigned char ch);
unsigned char LowerCh(unsigned char ch);
unsigned char ch_to_rtc (unsigned char ch);
void grava_rtc (void);
void mostra_rtc_lcd(void);
void mostra_menu(void);

void trata_tecla_4(void);
void trata_tecla_6(void);
void trata_tecla_8(void);
void trata_tecla_2(void);

unsigned char fl_tec = 0, tec = 0;
/* fl_tec: flag que indica que chegou uma tecla
 * tec: valor asc da tecla recebida
 */
unsigned char sec,min,hour,day,date,month,year, menu=1;
unsigned char min_aj,hour_aj,day_aj,date_aj,month_aj,year_aj;
unsigned char buffer[17];

void main(void) {
    unsigned char fl_menu = 0;
    inicia_regs();
    config_int();
    config_int2(); // configura as interrupções
    config_AD(); // configura e inicializa o conversor AD
    i2c_init(); //To Generate the Clock of 100Khz
    // trata o LCD
    lcd_inicia(0x28, 0x0f, 0x06); // incializa o LCD com 4 linhas
    lcd_LD_cursor(0); // Desliga o cursor
    lcd_posicao(1, 1);
    imprime_string_lcd("   Calendario   ");
    lcd_posicao(2, 1);
    imprime_string_lcd("  Relogio - RTC ");
    atraso_meios(2);
    while (1) {
        lcd_posicao(2, 1);
        imprime_string_lcd("Set-RTC press #");
        mostra_rtc_lcd();
        if (fl_tec) {
            fl_tec = 0;
            if (tec == 35) {// tecla # entra no mneu
                fl_menu = 1;
             
                // converte os dados para numero para ajuste
                //                sec_aj = UpperCh(sec)*10 + LowerCh(sec);
                min_aj = UpperCh(min)*10 + LowerCh(min);
                hour_aj = UpperCh(hour)*10 + LowerCh(hour);
                day_aj = day;
                date_aj = UpperCh(date)*10 + LowerCh(date);
                month_aj = UpperCh(month)*10 + LowerCh(month);
                year_aj = UpperCh(year)*10 + LowerCh(year);
                mostra_menu();
                // fim da conversão
            }
        }
        while (fl_menu) {
            if (fl_tec) {
                fl_tec = 0;
                if (tec == 35) { // tecla # sai do menu
                    fl_menu = 0;
                    tec = 0; // destrava o while do menu
                    grava_rtc(); // grava os dados no rtc
                }
                trata_tecla_8();
                trata_tecla_2();
                trata_tecla_4();
                trata_tecla_6();
                mostra_menu();
            }
        }
    }
}


// funções para leitura e escrita do rtc i2c
// copiar as funções do programa de exemplo
// void i2c_init(){}
// void i2c_start(void){}
// void i2c_restart(void){}
// void i2c_stop(void){}
// void i2c_wait(void){}
// void i2c_send(unsigned char dat){}
//unsigned char i2c_read(void){}

unsigned char rtc1307_read(unsigned char address)
{
unsigned char temp;
i2c_start();
i2c_send(0xD0);
i2c_send(address);
i2c_restart();
i2c_send(0xD1);
temp = i2c_read();
//i2c_stop(); this line is Removed Because it is already included in i2c_read function
return temp;
}
// fim das funções para leitura e escrita do rtc i2c


// funções para o main e funcionamento do teclado materiacial
// função de configuração do conversor A/D
// void config_AD(void) {}
// função que efeuta uma conversão A/D e retorna um inteiro com o valor convertido
// int conv_AD(void) {}
// função que inicia os registradores I/O
// void inicia_regs(void) {} 
// função de interrupção de alta prioridade
// função que lê o teclado na INT2 - Ver prog cofre
// void interrupt ISR_alta_prioridade(void) {}
// função de configuração geral de interrupções
// void config_int(void) {}
// configura a interrupção exarna INT2
// void config_int2(void) {}
// função que gera atraso em mlisegundos
// void delay_ms(int i){}
//função de atraso de multiplos de 0,5s
// void atraso_meios(unsigned char meio_segundos)
// devolve a dezena em decimal do numero
unsigned char UpperCh(unsigned char ch)
{
unsigned char temp;
  temp = ch >> 4;
  return(temp);
}
// devolve a unidade em decimal do numero
unsigned char LowerCh(unsigned char ch)
{
unsigned char temp;
  temp = ch & 0x0F; //Making the Upper 4-bits
  return(temp);
}
// converte para o formato RTC
unsigned char ch_to_rtc (unsigned char ch){
    unsigned char dezena,unidade,saida;
    dezena = ch/10; // dezena
    unidade= ch - dezena*10; // unidade
    saida = (dezena<<4)|(unidade);
    // temp = ((ch/10)<<4) && (ch - (ch/10)); // não sei se funciona de uma vez só???
    return saida;
}
// grava os dados no RTC

/* void grava_rtc(void) {
    // retorna os alores para gravação
    min = ch_to_rtc(min_aj);
    // fazer para hour, day, date, month, year
    // rotina de gravação

    // exemplo para gravação de um valor fixo
    // data quarta 31/dez/2014 23h 59min e 45 seg
 
//    i2c_start();
//    i2c_send(0xD0);
//    i2c_send(0x00);
//    i2c_send(0x45 | 0x80); //CH = 1 Stop oscillator
//    i2c_send(0x59); //Minute
//    i2c_send(0x23); //Hour
//    i2c_send(0x04); //4 - quarta
//    i2c_send(0x31); //31 data
//    i2c_send(0x12); //12 Dez
//    i2c_send(0x14); //2014
//    i2c_stop(); //Stop the I2C Protocol

    //Have to start the Clock again
//    i2c_start();
//    i2c_send(0xD0);
//    i2c_send(0x00);
//    i2c_send(0x00); //start Clock and set the second hand to Zero
//    i2c_stop();
    // fim do start
}

// mostra caledario - hora alternados na linha 1
void mostra_rtc_lcd(void){
    sec = rtc1307_read(0x00);
// ler min, hour, day, date, month, year
    lcd_posicao(1, 1);
    switch (day) {
        case 1: sprintf(buffer, "SUN %02x/%02x/20%02x", date, month, year);
            break;
        // fazer para os outros 6 dias da semana
    }
    imprime_buffer_lcd(buffer, 15);
    atraso_meios(1);
    // mostra a hora na na linha 1 e espera 1/2 segundo
}

void mostra_menu(void) {
    /*1 - Dia corrente (SUN, MON, TUE, WED, THU, FRI, SAT)
     * 2 - Data (1 a 31)
     * 3 - Mes (1 a 12)
     * 4 - Ano (2000 a 2099)
     * 5 - Hora (0 a 23)
     * 6 - Minutos (0 a 59) */
    //    lcd_limpa_tela();
 
    switch (menu) {
        case 1:
            switch (day_aj) {
                case 1: sprintf(buffer, "dia = SUNDAY   ");
                    break;
                // fazer os outros dias
            }
            break;
        case 2:
            sprintf(buffer, " Data = %2d    ", date_aj);
            break;
        // fazer para Mes, Ano, Hora, Minutos
    }
    lcd_posicao(1, 1);
    imprime_buffer_lcd(buffer, 15);
    lcd_posicao(2, 1);
    imprime_string_lcd("set < >  ch ^ v ");
}

void trata_tecla_4(void) {
    if (tec == 52) {// tecla 4 < decrementa a opção corrente
        switch (menu) {
            case 1: // decrementa dia
                day_aj--;
                if (day_aj == 0) {
                    day_aj = 7;
                }
                break;
            case 2: // decrementa data
                if (date_aj == 1) {
                    date_aj = 31;
                } else date_aj--;
                break;
            case 3: // decrementa  mês
                if (month_aj == 1) {
                    month_aj = 12;
                }
                month_aj--;
                break;
            case 4: // decrementa ano
                if (year_aj == 0) {
                    year_aj = 99;
                } else year_aj--;
                break;
            case 5: // decrementa hora
                if (hour_aj == 0) {
                    hour_aj = 23;
                } else hour_aj--;
                break;
            case 6: // decrementa minutos
                if (min_aj == 0) {
                    min_aj = 59;
                } else min_aj--;
                break;
        }
    }
}

void trata_tecla_6(void) {
// ver exemplo função trata_tecla_4
}

void trata_tecla_8(void) {
    if (tec == 56) {// tecla 8 ^ rola menu p/ cima
        if (menu < 6) {
            menu++;
        } else {
            menu = 1;
        }
    }
}

void trata_tecla_2(void) {
// ver exemplo função trata_tecla_8
}