Escolar Documentos
Profissional Documentos
Cultura Documentos
ALGORÍTMOS
Introdução ................................................................................................................................3
1. Diodo emissor de luz (LED) .........................................................................................4
1.1. Pisca-LED ............................................................................................................5
1.2. Contador Binário de 8 bits.....................................................................................5
2. Display de 7 Segmentos................................................................................................5
2.1. Contador Simples .................................................................................................6
2.2. Caractere Personalizada.......................................................................................7
2.3. Contador de 0 a 9999............................................................................................9
3. LCD Alfanumérico........................................................................................................10
3.1. “Hello World”........................................................................................................12
3.2. Contador .............................................................................................................13
3.3. Relógio ................................................................................................................14
4. Conversor A/D...............................................................................................................15
4.1. Conversor A/D + LED’s........................................................................................16
4.2. Conversor A/D + Display de 7 segmentos...........................................................18
4.3. Conversor A/D + LCD..........................................................................................19
4.4. Termômetro..........................................................................................................20
5. EUSART........................................................................................................................22
5.1. EUSART + LED’s.................................................................................................22
5.2. EUSART + LCD....................................................................................................23
5.3. Controle de temperatura via EUSART.................................................................24
6. PWM (Modulação por Largura de Pulso) ...................................................................27
6.1. PWM + LED, Ventoinha e LCD............................................................................28
6.2. PWM + LCD.........................................................................................................29
6.3. PWM + Buzzer.....................................................................................................30
7. Teclado Matricial...........................................................................................................32
7.1. Teclado + Display 7 segmentos...........................................................................33
7.2. Teclado + LCD.....................................................................................................34
8. Comunicação I²C...........................................................................................................37
8.1. Botão + Display 7 segmentos...............................................................................37
8.2. Botão + LCD.........................................................................................................40
8.3. PIC + RTC............................................................................................................43
8.4. Relógio Ajustável..................................................................................................46
Considerações Finais...............................................................................................................50
2
INTRODUÇÃO
Os projetos a seguir foram desenvolvidos no laboratório de Sistemas Micro Processados
alocado nas dependências do Instituto Federal do Pará, IFPA, com fins exclusivamente didáticos e
com intuito de estudar os módulos presentes no Kit de desenvolvimento da Acepic PRO V2.1 e
relacioná-los com o Microcontrolador PIC18F4550.
Todos os programas foram escritos e compilados utilizando o compilador MikroC, que se
trata de um software criado para quem almeja programar, em C, Microcontroladores em geral.
Depois de compilados, os programas foram descarregados no PIC pelo Bootloader, que tem a
função de gravar os algoritmos na memória do Microcontrolador.
3
1.1. Pisca-LED:
Um programa básico que consiste em testar a comunicação tanto entre o PC e o PIC (no ato
de upload do código do PC para a memória do Micro Controlador) quanto entre o PIC com os
periféricos do Kit, nesse caso, os LED’s.
Para isso, na função principal, o registrador onde se encontram os Leds é configurado como
saída e é iniciado com todos os seus bits em low. No Loop Infinito um bit do PORTD é colocado em
HIGH, e após 500 milissegundos ele passa para LOW.
////////////////////////////////////////////////////////////////////////////////
void main() { // Função Principal
TRISD = 0x00; // Declara todas as portas do Registrador D como SAÍDAS
PORTD = 0x00; // Passa todas os pinos de PORTD para low
while(1) { // Loop Infinito
PORTD = 0x01; // Coloca o pino RD0 em high
delay_ms(500); // Delay de 0,5s
PORTD = 0x00; // Coloca o pino RD0 em low
delay_ms(500); // Delay de 0,5s
} // end while
} // end void main
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main(){ // Função principal
TRISD = 0x00; //Declara todos pinos do registrador PORTD como saídas.
PORTD = 0x00; //Inicia todos os pinos do PORTD em low.
////////////////////////////////////////////////////////////////////////////////
2. Display de 7 Segmentos:
Além dos LED’s outros itens também estão associados ao PORTD, como os 4 displays de 7
segmentos, que serão alvos de nosso estudo a partir de agora.Os componentes em questão são de
catodo comum, considerando o fato de que um display basicamente trata-se de um conjunto de
LED’s, logo,é necessário citar o procedimento para se formar um caractere no mesmo:
O “Seven Segment Editor” do programa MikroC, pode ser usado para gerar um Hexa que será lido
pelo módulo do display, mostrado no display, como na figura abaixo:
4
Serão gerados dois números hexadecimais
um para display do tipo Catodo Comum e outro para
o tipo Anodo Comum, já que o tipo de display
presente utilizado no Kit da Acepic V2.1 é Catodo
Comum, logo, o hexadecimal equivalente ao digito
“Zero” será 0x3F.
5
RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0
h g f e d c b a
///////////////////////////////////////////////////////////////////////////////////////////////
Unsigned char cont; // variável de contagem
6
TRISD = 0x00; // Declara PORT’D’ como saída
PORTD = 0x00; // Inicia os bits do PORT’D’ em low
TRISA.RA5 = 0x00; // Declara o pino RA5 do PORT’A’ como saída
PORTA.RA5 = 0x01; // Inicia RA5 em high, ativando o display
while(1){ // Loop Infinito
PORTD = (digito[cont]); // Chama o digito correspondente a [cont]
cont = (cont + 1); // Incrementa em 1 a variável cont
delay_ms(500); // Delay de 0,5 segundo
if(cont==10){ // Se cont for igual a 10...
cont = 0; // Zera cont, e recomeça a contagem
} // end if
} //end while
} //end void main
Tarefa: gerar efeitos de iluminação nos segmentos de um display.
///////////////////////////////////////////////////////////////////////////////////////////////
O programa consiste em mostrar “IFPA” nos displays durante 4 segundos e depois exibe
letra por letra por 8 segundos e assim sucessivamente, para isso são atribuídas ás variáveis
osvalores dos dígitos em hexa, na função principal são declarados os registradores que serão
utilizados no processo, feito isso, no loop infinito habitam os dois laços “for”. O primeiro laço é
responsável por mostrar as letras nos 4 displays ao mesmo tempo, o segundo laço mostra de forma
sequencial letra por letra em um display por vez e assim ininterruptamente.
///////////////////////////////////////////////////////////////////////////////////////////////
// valor do display de 7 segmentos correspondente às letras:
unsignedchar letra_I = 0x06;
unsignedchar letra_F = 0x71;
unsignedchar letra_P = 0x73;
unsignedchar letra_A = 0x77;
7
while (1){ //Loop infinito
for(i=0;i<=199;i++){ //Executa ou mostra “IFPA” através de 200 laços por aprox. 4s
//Veja que a qualquer letra é mostrada de 20ms em 20ms no período de 4s, eliminando o efeito da cintilação.
// Apresenta a IFPA nos displays
PORTD = letra_A; // Apresenta a LETRA A
RA5_bit = 1; // Habilita RA5
delay_ms(5); // Aguarda 5ms
RA5_bit = 0; // Desabilita
8
com o intuito de habilitar e desabilitar os mesmos (através dos registradores) de uma forma
extremamente rápida, para vencer a perceptibilidade do olho humano, então assim cria-se a
ilusão de que todos os displays estão ligados de forma simultânea.
///////////////////////////////////////////////////////////////////////////////////////////////
unsignedchar digito[]= { 0x3F, // 0 Define cada segmento
0x06, // 1 dos valores mostrados
0x5B, // 2 no display de LEDs
0x4F, // 3 em Hexadecimal para ficar
0x66, // 4 mais fácil de codificar
0x6D, // 5 cada dígito dos valores
0x7D, // 6 mostrados no display.
0x07, // 7
0x7F, // 8
0x67}; // 9
char i; // variável auxiliar
int Cnt = 0; // variável de contagem
int Mil, Cen, Dez, Uni = 0; //variáveis do display
void main(){
TRISD = 0x80; //Declara RD7 como entrada e os demais pinos como saídas
PORTD = 0x00; //Inicia todos os pinos de PORTD em low
TRISE = 0x00; //Declara todos os pinos do registrador PORT'E como saídas
PORTE = 0x00; //Inicia todos os pinos de PORT'E em low
TRISA.RA5 = 0x00; //Declara o pino RA5 como saída
PORTA.RA5 = 0x00; //Inicia o pino RA5 em low
while (1){ // Loop infinito
for (i = 0; i<=1; i++){ /* controla o tempo que cada numero
é mostrado no display (aprox= 40ms) */
9
RE0_bit = 1; // Habilita RE0
delay_ms(5); // Aguarda 5ms
RE0_bit = 0; // Desabilita
}// end for
if(Cnt == 10000){ // Se Cnt for igual a 10000...
Cnt = 0; // Zera a variável de contagem, recomeça
delay_ms(1000); // Delay de 1 segundo
PORTD = 0x00; // Zera PORTD
}//end if
Cnt++; //Incrementa a variável de contagem em 1
} // end while
}// end void main
Tarefa: Temporizar em 1min, acionando buzer ou ventoinha, na contagem de 2500.
///////////////////////////////////////////////////////////////////////////////////////////////
3. LCD Alfanumérico:
Os módulos LCD são interfaces de saída muito úteis em sistemas Microprocessados, estes
módulos podem ser Gráficos ou Caractere. Os LCD comuns (tipo Caractere) são especificados em
número de linhas por colunas e no Kit Acepic em questão o LCD é 16x2, logo, tem 2 linhas e 16
colunas.
O LCD utiliza um controlador próprio, permitindo sua interligação com outras placas através de
seus pinos, onde devem ser alimentados e interligados com o barramento de dados e controle do
módulo da placa do usuário. Antes de iniciar o uso do LCD é importante notar que:
• O LCD tem conectado seus pinos de dados diretamente no “PORT D”.
• Os pinos de controle, RS(entrada de dados ou instrução) e Enable nos bits 1 e 0,
respectivamente, do “PORT E”.
• O backlight(gerado pelo conjunto de LEDs posicionados na parte de trás do display) pode ser
acionado ligando-se a chave 1 do DIP DP2, conforme esquema abaixo:
10
Antes de escrever algum programa para o uso do LCD é de suma importância ter conhecimento das
funções e comandos que o MikroC disponibiliza para facilitar a manipulação do Display de Cristal Líquido
(LCD).
Na página anterior foram declaradas as conexões e as direções dos pinos do LCD em relação ao
Micro controlador, após isso deve-se atentar para as seguintes funções e comandos que são cruciais para o
uso do LCD:
Lcd_Init(); // Inicializa o LCD
Lcd_Cmd(_LCD_CLEAR); // Limpa o conteúdo da tela
Lcd_Cmd(_LCD_CURSOR_OFF); // Desliga o cursor
Lcd_Out(2,6,texto); // Escreve o texto na linha 2, a partir da coluna 6
//////////////////////////////////////////////////////////////////////////////////////////////
// Módulo de conexões dos pinos do LCD com os do PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// Variáveis de texto
char txt1[] = "Hello World!";
char txt2[] = "^__^";
char txt3[] = "Eletronica";
char txt4[] = "IFPA";
char i; // Variável auxiliar de 'contagem'
11
delay_ms(5000); //Aguarda 5s
Lcd_Cmd(_LCD_CLEAR); //Limpa a tela do LCD
delay_ms(250); //delay de 250ms
Lcd_Out(1,4,txt3); //Escreve na linha 1, coluna 4: txt3
Lcd_Out(2,7,txt4); //Escreve na linha 2, coluna 7: txt4
delay_ms(2000); //Aguarda 2s
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// Conexões do LCD com o PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
12
sbit LCD_D7_Direction at TRISD7_bit;
///////////////////////////////////////////////////////////////////////////////////////////////
// Conexões dos pinos do LCD com os pinos do PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
13
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// Minutos,
digit[4] = (Cnt_min%10) +48; // Calcula a unidade
digit[3] = (Cnt_min%100); // Calcula a Dezena
digit[3] = ((digit[3]/10) - ((digit[3]%10)/10)) +48; // +48 (TABELA ASCII)
// Horas.
digit[1] = (Cnt_hora%10) +48; // Calcula a unidade
digit[0] = (Cnt_hora%100); // Calcula a Dezena
digit[0] = ((digit[0]/10) - ((digit[0]%10)/10)) +48; // +48 (TABELA ASCII)
} // end int digits
14
4. Conversor A/D.
O conversor analógico-digital é capaz de gerar uma representação digital a partir de uma grandeza
analógica, normalmente um sinal representado por um nível de tensão ou intensidade de corrente
elétrica. O módulo ADC presente no PIC18F4550 permite a conversão para o numero digital de até 10
bits correspondente ao sinal analógico na entrada, o micro controlador apresenta ainda 3
registradores responsáveis pela configuração do módulo ADC, são eles, ADCON1,2 e 3.
Antes da manipulação do Conversor A/D é importante lembrar que:
• Os potenciômetros podem ser conectados aos canais analógicos AN0 e AN1 através das
chaves 1 e 2, respectivamente, do DIP DP1.
• O sensor de temperatura pode ser conectado ao canal analógico AN2 acionando-se a chave
3 do DIP DP1.
• A utilização das portas analógicas deve ser configurada por software.
• A seguir tem-se o esquema dos periféricos relacionados ao ADC.
15
Na Função principal são configurados os registradores do módulo ADC, que são de crucial
importância no processo, também são configurados os PORT’s D e A, nos quais estão presentes os
LED’s e a entrada analógica, respectivamente.
No Loop Infinito a variável ‘leitura’ recebe o valor lido do módulo ADC, logo após, divide esse
valor por 127 e atribui o resultado da divisão à variável ‘led_on’. E então os Led’s referentes ao
valor da divisão serão acionados através dos laços if’s que tiverem sua condição atendida. Logo
quanto maior o valor da tensão no potenciômetro, mais LED’s serão ativados.
///////////////////////////////////////////////////////////////////////////////////////////////
//Define atalhos para os pinos:
#define D0 RD0_bit
#define D1 RD1_bit
#define D2 RD2_bit
#define D3 RD3_bit
#define D4 RD4_bit
#define D5 RD5_bit
#define D6 RD6_bit
#define D7 RD7_bit
TRISA = 0x01; // Declara apenas o bit RA0 como entrada e o resto como saída
PORTA = 0x00; // inicia PORT’A em Low
while(1){
leitura = ADC_read(0); /* Atribui a variável 'leitura' à
Função ADC_read(que lê a porta 0)*/
// 1023/8 = 127
led_on = leitura/127; // Led_on recebe o valor da divisão de 'leitura/127'
if(led_on>=2) D1 = 1;
16
if(led_on>=3) D2 = 1;
if(led_on>=4) D3 = 1;
if(led_on>=5) D4 = 1;
if(led_on>=6) D5 = 1;
if(led_on>=7) D6 = 1;
if(led_on>=8) D7 = 1;
///////////////////////////////////////////////////////////////////////////////////////////////
unsignedchar digito[]= { 0x3F, // 0 Define cada segmento
0x06, // 1 dos valores mostrados
0x5B, // 2 no display de LEDs
0x4F, // 3 em Hexadecimal para ficar
0x66, // 4 mais fácil de codificar
0x6D, // 5 cada dígito dos valores
0x7D, // 6 mostrados no display.
0x07, // 7
0x7F, // 8
0x67}; // 9
TRISD = 0x80; //Declara RD7 como entrada e os demais pinos como saídas
PORTD = 0x00; //Coloca todos os pinos de PORTD em low
TRISE = 0x00; //Declara todos os pinos do registrador PORT'E como saídas
PORTE = 0x00; //Coloca todos os pinos de PORT'E em low
TRISA.RA5 = 0; //Declara o pino RA5 como saída
PORTA.RA5 = 0; //Coloca o pino RA5 em low
17
CHS1_bit = 0;
CHS0_bit = 0;
18
Na função principal é inicializado o display LCD e também é configurado o registrador PORT’A,
onde se encontra a porta analógica que faz parte do processo. No Loop Infinito o valor lido pelo
módulo ADC é armazenado na variável ‘Cnt’ e ainda é chamada a Display para calcular os
algarismos e mostrá-los no LCD.
///////////////////////////////////////////////////////////////////////////////////////////////
// Módulo de conexões do LCD com o PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//end módulo de conexões
unsignedchar Cnt; // variável de armazenamento da leitura do ADC
char *digit = "0000";
while(1){
Cnt = ADC_read(0); /* Atribui a variável 'Cnt' à
Função ADC_read(que lê a porta 0)*/
Lcd_Out(1,4,"ADC 10bits");
Display(); // Chama a função Display
}//end while
}// end void main
///////////////////////////////////////////////////////////////////////////////////////////////
19
4.4. Termômetro (ADC + LCD).
Utilizando o módulo ADC, Display LCD e o sensor de temperatura (LM35) presentes no Kit de
desenvolvimento AcepicPro, é possível projetar um Termômetro, para isso é importante lembrar
que o LM35 se encontra na porta AN2.
No início do programa são definidos as conexões do LCD com o PIC, a seguir, são criadas as
variáveis do tipo “unsigned char” que armazenam os algarismos e “unsigned long” que armazenam
as grandezas analógicas.
O programa apresenta três funções auxiliares, a primeira (CustomChar) é gerada pelo próprio
MikroC para mostrar no LCD caracteres especiais, nesse caso, a caractere referente à graus. A
segunda função (media_temp) é responsável por calcular a média de 100 medidas de temperatura
no intervalo de 10 milissegundos, para que assim o resultado seja mais exato.
A terceira função auxiliar (Celsius) é responsável por converter os valores lidos pelo módulo ADC
para a escala Celsius de temperatura. Após as funções auxiliares, tem-se a Função Principal onde
são configurados os registradores referentes ao módulo ADC, após isso, é inicializado o LCD.
No Loop infinito é chamada a função Celsius os valores calculados pela função são mostrados no
display.
///////////////////////////////////////////////////////////////////////////////////////////////
//Comunicação entre o PIC e o LCD
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//Variáveis Globais
unsignedlong store, t_Celsius;//variáveis que armazenam as grandezas analógicas
20
constchar character[] = {6,9,6,0,0,0,0,0}; //caractere especial de "graus"
void CustomChar(char pos_row, char pos_char){ /*função gerada pelo mikroC para
Imprimir caracteres especiais*/
char i;
Lcd_Cmd(64);
for (i = 0; i<=7; i++) Lcd_Chr_CP(character[i]);
Lcd_Cmd(_LCD_RETURN_HOME);
Lcd_Chr(pos_row, pos_char, 0);
}//end CustomChar
void Celsius(){
store = media_temp(); //atribui a média de 100 medidas à variável store
t_Celsius = (store*5*100)/1023; //converte o valor para escala Celsius
ADCON1 = 0x0B; // Configura AN0, AN1, AN2, AN3 como portas ANALÓGICAS
21
Celsius(); // Chama a função
5. EUSART.
EUSART (Enhanced Universal Synchronous Assynchronous Receiver-Transmitter) é um módulo que
possibilita a transmissão e recepção serial de dados originalmente disponíveis na forma paralela.
Através do protocolo RS-232 é possível comunicar-se com outros dispositivos, por exemplo, com
outros Micro Controladores e até mesmo com o computador. As I/O’s relacionados à EUSART Tx e Rx
são localizados, respectivamente, nos pinos RC6 e RC7 do PIC18F4550.
///////////////////////////////////////////////////////////////////////////////////////////////
22
char uart_rd; // Variável de armazenamento serial
void main() { //--Função Principal
TRISD = 0x00; // Configura o PORTD como saída
PORTD = 0x00; // Inicia em low
ADCON1 = 0x0F; // Configura as portas analógicas
23
} // end main
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// Módulo de conexões do LCD com o PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//end módulo de conexões
24
}// end while
}// void main
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// Conexões dos pinos do LCD com os pinos do PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
void Celsius();
void CustomChar(char pos_row, char pos_char);
long average_temp();
25
PORTC.RC1 = 0; // RESISTOR OFF
PORTC.RC2 = 0; // COOLER OFF
UART1_Write_Text("2- AQUECEDOR");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
UART1_Write_Text("3- COOLER");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
while(1){
Celsius();
if (UART1_Data_Ready()) { // Se os dados forem recebidos...
tecla_uart = UART1_Read(); // Lê os dados e atribui à variável tecla_uart
if(lig==1 || tecla_uart=='1'){ /* Se o botão ligar tiver sido pressionado ou
se o bit lig estiver em high... */
switch(tecla_uart){
// Quando uma tecla for pressionada executa o laço referente à mesma...
case '0':
Lcd_Out(1,1," DISPOSITIVO ");
Lcd_Out(2,1," DESLIGADO ");
UART1_Write_Text("Dispositivo Desligado.");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
Res = 0; // Desliga o Resistor de Aquecimento
Cooler = 0; // Desliga o Cooler
lig = 0; // Zera o bit
break;
case '1':
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela
UART1_Write_Text("Termometro Ligado");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
26
lig = 1; // Ativa o bit
break;
case '2':
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela
Lcd_Out(2,1," AQUEC. LIGADO ");
Res = 1; // Liga o Resistor de Aquecimento
UART1_Write_Text("Aquecedor Ligado, para desligar pressione 'w'");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
break;
case '3':
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela
Cooler = 1; // Liga o Cooler
Lcd_Out(2,1," COOLER LIGADO ");
UART1_Write_Text("Cooler Ligado, para desligar pressione 'q'");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
break;
case 'w':
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela
Res = 0; // Desliga o Resistor de Aquecimento
UART1_Write_Text("Aquecedor Desligado.");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
break;
case 'q':
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela
Cooler = 0; // Desliga o Cooler
UART1_Write_Text("Cooler Desligado.");
UART1_Write(10); // line feed, alimentação de linha
UART1_Write(13); // car return, quebra de linha
break;
}//end switch
}//end if
}//end if
27
long average_temp(){ // Função que calcula a média das medições
unsignedchar i;
unsignedlong temp_store = 0;
28
6.1. PWM + LED, Ventoinha e LCD.
Através da modulação da largura de pulso é possível controlar o Duty Cicle das ondas que
mantém os componentes, citados acima, ativados. Para isso configura-se o CCP1 para o módulo
PWM e também o TIMER 2 para auxiliar no processo, lembrando que todas as informações
necessárias para tal então presentes no Datasheet.
O programa a seguir consiste em ajustar o Duty Cicle na saída RC2 através de dois botões, então,
para isso, na função principal são configurados os registradores onde se encontram os botões e
também o registrador referente a saída CCP1, feito isso, são configurados os registradores
responsáveis pelos TIMER0 e TIMER2 que são essências na operação.
O TIMER2 trabalha em conjunto com o módulo PWM e o TIMER0 é utilizado na interrupção
responsável pelo monitoramento dos botões, logo quando TIMER0 chega ao overflow e gerada a
interrupção e se o botão RB0 for pressionado aumenta a largura do pulso, se RB1 for pressionado
diminui-se a largura do pulso.
29
///////////////////////////////////////////////////////////////////////////////////////////////
void interrupt(){ //-- Interrupção
if(T0IF_bit){ // Se houve overflow do TMR0...
T0IF_bit = 0x00; // Reseta a variável que "detecta" o overflow
TMR0L = 0x6C; // Reinicia o Timer0
/*Se RB0 for pressionado... */
if(!RB0_bit) CCPR1L++; // Incrementa o Duty Cicle
///////////////////////////////////////////////////////////////////////////////////////////////
// Módulo de conexões do LCD com o PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//end módulo de conexões
char *digit = "000"; // Variável que mostra no LCD o valor de CCPR1L
30
void interrupt(){ // -- Interrupção
if(T0IF_bit){ // Se ocorreu o overflow do TMR0...
T0IF_bit = 0x00; // Zera a variável de verificação
TMR0L = 0x6C; // Reinicia o TMR0
// Mostra no display:
Lcd_Out(1,1," Duty Cicle: ");
Lcd_Out(2,5, digit);
Lcd_Out(2,9,"bits");
}//end while
}//end void main
///////////////////////////////////////////////////////////////////////////////////////////////
31
Sound_Play(), responsável por gerar as frequências e as durações das notas que serão tocadas, para
reproduzir a melodia desejada.
///////////////////////////////////////////////////////////////////////////////////////////////
// DEFINE AS FREQUÊNCIAS DAS NOTAS
#define E3 164.81
#define F3 174.61
#define Gb3 185.00
#define G3 196.00
#define Ab3 207.65
#define A3 220.00
#define Bb3 233.08
#define B3 246.94
#define C4 261.63
#define Db4 277.18
#define D4 293.66
#define Eb4 311.13
#define E4 329.63
#define F4 349.23
#define Gb4 369.99
#define G4 392.00
#define Ab4 415.30
#define A4 440.00
#define Bb4 466.16
#define B4 493.88
void melodia();
Sound_Play(A3,Q);
delay_ms(1+Q);
Sound_Play(A3,Q);
delay_ms(1+Q);
Sound_Play(A3,Q);
delay_ms(1+Q);
Sound_Play(F3,E+S);
delay_ms(1+E+S);
Sound_Play(C4,S);
delay_ms(1+S);
Sound_Play(A3,Q);
delay_ms(1+Q);
32
Sound_Play(F3,E+S);
delay_ms(1+E+S);
Sound_Play(C4,S);
delay_ms(1+S);
Sound_Play(A3,H);
delay_ms(1+H);
Sound_Play(E4,Q);
delay_ms(1+Q);
Sound_Play(E4,Q);
delay_ms(1+Q);
Sound_Play(E4,Q);
delay_ms(1+Q);
Sound_Play(F4,E+S);
delay_ms(1+E+S);
Sound_Play(C4,S);
delay_ms(1+S);
Sound_Play(Ab3,Q);
delay_ms(1+Q);
Sound_Play(F3,E+S);
delay_ms(1+E+S);
Sound_Play(C4,S);
delay_ms(1+S);
Sound_Play(A3,H);
delay_ms(1+H);
}//end melodia
///////////////////////////////////////////////////////////////////////////////////////////////
7. Teclado Matricial.
O Teclado matricial é do tipo 4x4 e está conectado ao PORT’B, conforme o esquema abaixo, logo 4
bits do registrador B serão linhas e os outros 4 serão colunas e isso deve ser levado em conta em todos
os programas que utilizam o teclado.
33
Antes de iniciar o módulo referente ao Teclado Matricial é de suma importância entender o
mecanismo das interrupções, pois são fundamentais para o funcionamento do Teclado, já que ele está
disposto na forma de Matriz.
Interrupções:
Uma interrupção é um sinal de um dispositivo que tipicamente resulta em uma troca de contextos,
isto é, o processador para de fazer o que está fazendo para atender o periférico que pediu a
interrupção. Nesse caso a interrupção será acionada pelo Overflow do Timer 0, que é configurado com
um tempo X, para verificarse houve o pressionamento das teclas, então o programa é “interrompido”
para a execução dos comandos presente na função de interrupção, e em seguida o programa retorna
ao ponto que foi obstruído. Abaixo nota-se o diagrama padrão de uma interrupção:
///////////////////////////////////////////////////////////////////////////////////////////////
//Define os pinos das colunas do Teclado
#define col_1 RB4_bit
34
#define col_2 RB5_bit
#define col_3 RB6_bit
#define col_4 RB7_bit
if(!row_A) tecla = 2;
elseif(!row_B) tecla = 5;
elseif(!row_C) tecla = 8;
elseif(!row_D) tecla = 0;
}//end else if
if(!row_A) tecla = 3;
elseif(!row_B) tecla = 6;
elseif(!row_C) tecla = 9;
}//end else if
35
}//end T0IF_bit
}//end interrupt
///////////////////////////////////////////////////////////////////////////////////////////////
// Módulo de conexões do LCD com o PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//end módulo de conexões
36
//Define os pinos do PIC das colunas do Teclado
#define col_1 RB4_bit
#define col_2 RB5_bit
#define col_3 RB6_bit
#define col_4 RB7_bit
37
col_2 = 0x01;
col_3 = 0x01;
col_4 = 0x00; //Apenas a coluna 4 em nível baixo
8. Comunicação I2C.
Para o entendimento dos algoritmos a seguir é necessário o estudo do protocolo de comunicação I2C,
e ainda modo de implementação desse protocolo no PIC18F4550, tendo isso em mente, é possível
desenvolver diversosprojetos utilizando os periféricos anexados aos Kits dos Microcontroladores.
Os algoritmos a seguir, por usarem o mesmo protocolo de comunicação, seguem um padrão nos
dispositivos Mestre e outro padrão nos dispositivos escravos. O padrão de programação nos “Mestres”
consiste em declarar os endereços dos “Escravos” que serão instruídos, após isso duas funções são
arquitetadas, uma para enviar dados para o escravo endereçado e outra para ler dados do mesmo.
Para os dispositivos “Escravos”são declaradas, no mínimo, duas variáveis que são manipuladas na
interrupção, que é gerada pelo “Mestre” com o intuito é de enviar dados, através de uma variável, ou
receber dados, através de outra variável. A partir disso foram desenvolvidos os algoritmos abaixo.
38
para o dispositivo “Escravo”, através do protocolo I2C de comunicação. O Escravo por sua vez, está
programado para receber esse byte e converter de binário para decimal e mostrar o valor convertido nos
displays de 7 segmentos.
///////////////////////////////////////////////////////////////////////////////////////////////
39
const Addy = 0xA0; // Endereço do escravo no barramento I2C
unsignedchar digito[] = { 0b10111111, // 0 Define cada segmento
0b10000110, // 1 dos valores mostrados
0b11011011, // 2 no display de LEDs
0b11001111, // 3 em binário para ficar
0b11100110, // 4 mais fácil de codificar
0b11101101, // 5 cada dígito dos valores
0b11111101, // 6 mostrados no display.
0b10000111, // 7
0b11111111, // 8
0b11100111}; // 9
40
TRISE = 0x00; //Declara todos os pinos do registrador PORT'E como saídas
PORTE = 0x00; //Coloca todos os pinos de PORT'E em low
TRISA.RA5 = 0; //Declara o pino RA5 como saída
PORTA.RA5 = 0; //Coloca o pino RA5 em low
41
///////////////////////////////////////////////////////////////////////////////////////////////
// Conexões dos pinos do LCD com os pinos do PIC
sbit LCD_RS at RE0_bit;
sbit LCD_EN at RE1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISE0_bit;
sbit LCD_EN_Direction at TRISE1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
42
/* 1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
SSPM3_bit = 1;
SSPM2_bit = 0;
SSPM1_bit = 0;
SSPM0_bit = 0;
elseif (botao_ast==0){
delay_ms(300); // anti bouncing
Lcd_Cmd(_LCD_CLEAR); // Limpa a tela do LCD
Cnt = read(); // lê o byte do escravo SPPBUF
delay_ms(50);
Display_Init(); // chama a função que mostra os dados no LCD
}// end else if
}//end while
}// end void main
///////////////////////////////////////////////////////////////////////////////////////////////
43
char *digit = "000"; // declara os dígitos
44
8.3. PIC + RTC
Para tornar possível o entendimento dos próximos algoritmos, é necessário o estudo do
módulo RTC, presente no Kit ACEPIC de desenvolvimento, feito isso, nota-se que os programas a
seguir são relativamente simples, o primeiro com intuito de escrever os valores nos registradores
do RTC e o segundo com a função de ler e mostrar no LCD os valores armazenados nos
registradores do RTC, ambas ações são realizadas através do protocolo I2C.
I2C1_Start();
I2C1_Wr(0xD0); // Endereço DS1307 + 0 = ESCRITA
I2C1_Wr(0); // Escreve no REGISTRADOR 0
I2C1_Wr(0); // Escreve 0 = (Habilita a Contagem + 0 seg)
I2C1_Stop(); // Finaliza a transmissão
// ESCRITA I2C
I2C1_Start(); // Inicia a transmissão
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x01); // Escreve no REG 01 (MINUTOS)
I2C1_Wr(Dec2Bcd(15)); // Envia 34 = (34min)
I2C1_Stop();
I2C1_Start();
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x02); // Escreve no REG 02 (HORAS)
I2C1_Wr(Dec2Bcd(9)); // Envia 10 = (10hrs)
I2C1_Stop();
I2C1_Start();
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x03); // Escreve no REG 03 (DIA DA SEMANA)
I2C1_Wr(Dec2Bcd(2)); // Envia 6 = (sexta feira)
I2C1_Stop();
I2C1_Start();
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x04); // Escreve no REG 04 (DATA)
I2C1_Wr(Dec2Bcd(21)); // Envia 22 = DIA 22
I2C1_Stop();
I2C1_Start();
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x05); // Escreve no REG 05 (MÊS)
I2C1_Wr(Dec2Bcd(3)); // Envia 1 = Janeiro
I2C1_Stop();
I2C1_Start();
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x06); // Escreve no REG 05 (ANO)
I2C1_Wr(Dec2Bcd(16)); // Escreve 16 = 2016
I2C1_Stop();
45
delay_ms(100); // Delay de 100 Milissegundos
I2C1_Start();
I2C1_Wr(0xD0); // Endereço DS1307 + 0 = ESCRITA
I2C1_Wr(0); // Escreve no REGISTRADOR 0
I2C1_Wr(0); // Escreve 0 = Habilita a Contagem + 0 seg
I2C1_Stop(); // Finaliza a transmissão
46
dia_bcd = I2C1_Rd(1);
data1 = I2C1_Rd(1);
mes = I2C1_Rd(1);
ano = I2C1_Rd(0); // Lê o REG 6.
I2C1_Stop(); // Finaliza a leitura
// DIA DA SEMANA
dia = Bcd2Dec(dia_bcd); //Converte de bcd para decimal
// Escreve no LCD o dia referente ao valor da variável 'dia':
switch(dia)
{
case1: Lcd_Out(2,13,"DOM"); break;
case2: Lcd_Out(2,13,"SEG"); break;
case3: Lcd_Out(2,13,"TER"); break;
case4: Lcd_Out(2,13,"QUA"); break;
case5: Lcd_Out(2,13,"QUI"); break;
case6: Lcd_Out(2,13,"SEX"); break;
case7: Lcd_Out(2,13,"SAB"); break;
} //end switch
delay_ms(50);
} //end while
} //end void main
///////////////////////////////////////////////////////////////////////////////////////////////
47
//Define os pinos das colunas do Teclado
#define col_1 RB6_bit
#define col_2 RB7_bit
//Define os pinos das linhas
#define row_A RB2_bit
#define row_B RB3_bit
//end definições do teclado
void LE_I2C(){
//LEITURA I2C
I2C1_Start();
I2C1_Wr(11010000); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x00); // Endereço da Leitura (SEG)
I2C1_Repeated_Start(); // Reinicia
I2C1_Wr(0xD1); // Endereço do slave (DS1307=1101000) + 1
// ESCRITA I2C
I2C1_Start(); // Inicia a transmissão
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x01); // Escreve no REG 01 (MINUTOS)
48
I2C1_Wr(Dec2Bcd(mint)); // Envia o valor de Mint decrementado
I2C1_Stop();
} // end else if
}//end void inc_but
// ESCRITA I2C
I2C1_Start(); // Inicia a transmissão
I2C1_Wr(0xD0); // Endereço do slave (DS1307=1101000) + 0
I2C1_Wr(0x01); // Escreve no REG 01 (MINUTOS)
I2C1_Wr(Dec2Bcd(mint)); // Envia o valor de Mint decrementado
I2C1_Stop(); // Finaliza a transmissão
} // end else if
}//end void dec_but
TRISC.RC0 = 0;
PORTC.RC0 = 0;
Lcd_Init(); // Inicializa LCD
Lcd_Cmd(_LCD_CLEAR); // Limpa display
Lcd_Cmd(_LCD_CURSOR_OFF); // Desliga o cursor
49
I2C1_Wr(0); // Escreve 0 = Habilita a Contagem + 0 seg
I2C1_Stop(); // Finaliza a transmissão
// DIA DA SEMANA
dia = Bcd2Dec(dia); //Converte de bcd para decimal
50
} //DIG 'D'
} // end if botoes
delay_ms(50); // delay de ciclo
} // end while
} // end main
///////////////////////////////////////////////////////////////////////////////////////////////
51
Considerações Finais
Apesar de ser considerada antiga, C ainda é uma das linguagens de programação mais
utilizadas no mundo pois trata-se de uma linguagem leve, porém eficiente e poderosa, devido a isso
é amplamente utilizada em Microcontroladores PIC, com intuito de trazer maior simplicidade,
rapidez e eficiência aos algoritmos.
52