terça-feira, 30 de novembro de 2010

Calculo do CRC no protocolo modbus


// protocolo modbus
//
//microcontrolador : microchip
//compilador : CCS
//autor : aguivone
//data : 23/11/2010
//descrição : calculando o crc no modbus;
//..................................................................................................
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20M)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)//,enable=PIN_D4)
//////////////////////////////////////////declaração das variaveis///////////////////////////////////
unsigned char buf_485[30];
unsigned char CRC_bytes[2];//cria um vetor para armazenar o valor do crc


///////////////////////////////////////////////funçoes usadas/////////////////////////////////////////
void Calculo_CRC(unsigned int num_of_char,unsigned char *ptr_num)//,register unsigned int checksum) checksum = 0XFFFF
{
char i,j;//variaveis local
long checksum = 0XFFFF;//resultado do crc
for (i=0; i < num_of_char; i++) { checksum ^= *ptr_num; // executa uma operação ex or (XOR) ptr_num++; // pega proximo caracter da sequencia(rotaciona uma unidade a direita no vetor) for (j=0; j < 8; j++) // checa os 8 bits do caracter { if ((checksum & 0x01) == 0) // se LSB bit = 0 { checksum >>= 1;//apenas rotaciona o bit sem nenhum tratamento
}
else
{
checksum = (checksum >> 1) ^ 0XA001;//rotaciona o bit e faz um ou logico(OR) com 0XA001
}
}
}
CRC_bytes[0]=checksum;
CRC_bytes[1]=checksum>>8;

}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
buf_485[0] = 0x01; // Endereço do Slave
buf_485[1] = 0x06; // Função MODBUS: Read Input Register
buf_485[2] = 0x01; // Registro inicial para ler (MSB)
buf_485[3] = 0x2C; // Registro inicial para ler (LSB)
buf_485[4] = 0x32; // Total de registros para ler (MSB)
buf_485[5] = 0x10; // Total de registros para ler (LSB)
Calculo_CRC(6, buf_485); //coloque a quantidade-1,pois a contagem
buf_485[6] = CRC_bytes[0]; // CRC (LSB)
buf_485[7] = CRC_bytes[1]; // CRC (MSB)
printf("MODBUS = %X - %X - %X - %X - %X - %X \r\n",buf_485[0],buf_485[1],buf_485[2],buf_485[3],buf_485[4],buf_485[5]);
printf("CRC = %X - %X ", buf_485[6],buf_485[7]);
}

Esta é a simulação:


sexta-feira, 12 de novembro de 2010

Esteira - contador de objetos

Por Rafael Varango de Aguiar


CÓDIGO FONTE :
 /**************************************************************************
*                       Esteira Contadora de Objetos                      *
***************************************************************************
* Rafael Varago de Aguiar                       Varago Automatics         *
***************************************************************************
* Versão: 2.2                                                             *
* Data: 20/09/2010                                                        *
*                                                                         *
* RAM: 5%   ROM: 17%                                                      *
***************************************************************************
* Controle de 2 Displays 7 segmentos que apresentaram a contagem das peças*
* ao contar uma peça uma buzina tambem soara, o projeto terá a opção de   *
* congelar a contagem, resetar a contagem, guardar valor da contagem na   *
* memória EEPROM, e por último terá a opção de recuperar está valor sempre*
* que desejado, ao contar uma peça uma pequena buzina é acionada por      *
* alguns instantes para servir de sinalizador auditivo                    *
**************************************************************************/
#include <16f628a.h> // Informa o PIC
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOMCLR,INTRC_IO // Configs internas
#use delay (clock=4000000) // Seleciona delay para 4Mhz de clock
/**************************************************************************
**************************************************************************/
// Definições de pinos
#define ldr pin_a0 // Sensor de passagem de peças
#define bz pin_a1 // Indicador sonoro de passagem de peças
#define stop pin_a2 // Congela a Contagem
#define reset pin_a3 // Reseta a    "
#define gcont pin_a4 // Grava a     "      na EEPROM
#define rcont pin_a5 // Recupera a  "      na    "
#define dd pin_a6 // Catodo Display de unidade
#define du pin_a7 //    "      "    de dezena
/**************************************************************************
**************************************************************************/
// Variaveis globais
int cont; // Armazanam o valor da contagem do placar
/**************************************************************************
**************************************************************************/
// Tabela para converter o valor da contagem para exibir no display
byte const tabela[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xe7};
/**************************************************************************
**************************************************************************/
void jogacont(void){ // Rotina para jogar valores no contador
   output_high(du); // Apaga display de unidade
   output_low(dd); // Seleciona display de dezena
   output_b(tabela[cont/10]); // Joga o valor do contador
   delay_ms(50); // Tempo para display ligado
   output_high(dd); // Apaga display de dezena
   output_low(du); // Seleciona display de unidade
   output_b(tabela[cont%10]); // Joga o valor do contador
   delay_ms(50); // Tempo para display ligado
   return; // Retorna
}
int para_cont(int a){ // Rotina para parar contagem
   while(1){ // Laço infinito até STOP ser novamente pressionado
      jogacont(); // Chama rotina para jogar valores no contador
      if(!input(stop)){ // Executa bloco caso botão STOP for pressionado
         while(!input(stop)){
         } // Laço para soltar tecla
         return (1);
      }
      if(!input(reset)){ // Zera o contador caso RESET sejá pressionado
         while(!input(reset)){
         } // Laço para soltar tecla
         cont=0; // Zera cont
      }
      if(!input(gcont)){ // Grava valor do contador na EEPROM
         while(!input(gcont)){
         } // Laço para soltar tecla
         write_eeprom(1,cont); // Salva o valor do contador na EEPROM
      }
      if(!input(rcont)){ // Recupera valor do contador na EEPROM
         while(!input(rcont)){
         } // Laço para soltar tecla
         cont=read_eeprom(1); // Recupera o valor do contador da EEPROM
      }
   }
} // Fim do bloco para botão STOP pressionado
/**************************************************************************
**************************************************************************/
void main(void){ // Rotina principal
   int temp,aux; // Variavel auxiliar de tempo de execução de laço
   aux=0; // Variavel para controlar laço
   set_tris_a(0b00111101); // configuração da direção dos pinos de I/O
   set_tris_b(0b00000000);
   cont=0; // Garante que o contador comece em zero
   delay_ms(300); // Estabilização da EEPROM
   while(1){ // Laço de repetição infinito
      if(!input(ldr)){ // Testa se sensor foi cortado (passagem de peças)
         while(!input(ldr)){
         } // Laço para sensor voltar ao estado normal
         if(cont < 99){ // Executa se o contador estiver abaixo do limite
            cont ++; // Incrementa 1 em cont
            temp=5; // Joga 5 em temp para definir tempo para disparar buzzer
            while(temp != 0){ // Laço para acionar o buzzer
               output_high(bz); // Joga nivel alto no buzzer
               delay_ms(5); // Tempo para gerar frequencia de nivel alto
               output_low(bz); // Joga nivel baixo no buzzer
               delay_ms(5); // Tempo para gerar frequencia de nivel baixo
               temp --; // Decrementa 1 de temp
               delay_ms(temp); // Delay carregado com o valor de temp
            } // Fim do laço do buzzer
         }
         else cont=0; // Se contador já estiver em 99 o mesmo é zerado
      } // Fim do teste de sensor cortado
      if(!input(stop)){ // Executa bloco caso botão STOP for pressionado
         while(!input(stop)){
         } // Laço para soltar tecla
         while(!para_cont(aux)){ // Chama rotina para parar contagem
         }
      } // Fim do bloco para STOP
      if(!input(reset)){ // Zera o contador caso RESET sejá pressionado
         while(!input(reset)){
         } // Laço para soltar tecla
         cont=0; // Zera cont
      }
      if(!input(gcont)){ // Grava valor do contador na EEPROM
         while(!input(gcont)){
         } // Laço para soltar tecla
         write_eeprom(1,cont); // Salva o valor do contador na EEPROM
      }
      if(!input(rcont)){ // Recupera valor do contador na EEPROM
         while(!input(rcont)){
         } // Laço para soltar tecla
         cont=read_eeprom(1); // Recupera o valor do contador da EEPROM
      }
      jogacont(); // Chama rotina para jogar valores no contador
   } // Fim do laço de repetição
} // Fim do programa

ORGÃO ELETRÔNICO

Por Rafael Varango de Aguiar

                                                              
CÓDIGO FONTE:


/**************************************************************************
* Orção Eletronico *
***************************************************************************
* Rafael Varago de Aguiar Varago Automatics *
***************************************************************************
* Versão: 2.1 *
* Data: 21/08/2010 *
* *
* RAM: 5% ROM: 19% *
***************************************************************************
* Controla um alto-falante tocando o som de 9 notas musicais *
* selecionadas via teclado, além do som, a nota e a frequencia *
* serão exibidas no display LCD *
**************************************************************************/
#include <16f877a.h> // Informa o PIC
#device adc=10 // Configura conversor AD para 10 bits
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT // Configs internas
#use delay (clock=4000000) // Seleciona delay para 4Mhz de clock
/**************************************************************************
**************************************************************************/
// Definições de pinos
#define bt0 pin_b0 // Nota DO
#define bt1 pin_b1 // " RE
#define bt2 pin_b2 // " MI
#define bt3 pin_b3 // " FA
#define bt4 pin_b4 // " SOL
#define bt5 pin_b5 // " LA
#define bt6 pin_b6 // " SI
#define bt7 pin_b7 // " DO1
#define bt8 pin_c7 // " RE1
#define fal pin_a0 // Alto-falante
/**************************************************************************
**************************************************************************/
/**************************************************************************
**************************************************************************/
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_e0 // pino enable do LCD
#define lcd_rs pin_e1 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09
/**************************************************************************
**************************************************************************/
// Variaveis globais
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
//Gera um pulso de enable
output_high(lcd_enable); // ENABLE = 1
delay_us(1); // Recomendado para estabilizar o LCD
output_low(lcd_enable); // ENABLE = 0
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,""); ou
// envia_byte_lcd(1,);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// Faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable);// Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x02);// CURSOR HOME - Envia comando para zerar o contador de
// caracteres e retornar à posição inicial (0x80).
delay_ms(1); // Aguarda 1ms para estabilizar o LCD
envia_byte_lcd(0,0x28);// FUNCTION SET - Configura o LCD para 4 bits,
// 2 linhas, fonte 5X7.
envia_byte_lcd(0,0x0c);// DISPLAY CONTROL - Display ligado, sem cursor
limpa_lcd(); // Limpa o LCD
envia_byte_lcd(0,0x06);// ENTRY MODE SET - Desloca o cursor para a direita
return; // Retorna ao ponto de chamada da função
}
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main() // Rotina principal
{
int aux=0; // Auxiliar de laço
// Configura o PIC
setup_adc_ports(no_analogs);
port_b_pullups(true); // Ativa pull-ups do portb
// Reseta portas
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
set_tris_a(0b00111110); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111110);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
inicializa_lcd(); // Inicializa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
while (true) // Laço Infinito
{
if(!input(bt0)){ // Botão letra DO
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA DO"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 200Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(5); // Tempo para gerar frequencia de nivel alto
output_low(fal); // Joga nivel baixo no pino
delay_ms(5); // Tempo para gerar frequencia de nivel baixo
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla DO
/***************************************************************************/
if(!input(bt1)){ // Botão letra RE
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA RE"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 246Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(4); // Tempo para gerar frequencia de nivel alto
delay_us(60);
output_low(fal); // Joga nivel baixo no pino
delay_ms(4); // Tempo para gerar frequencia de nivel baixo
delay_us(60);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla RE
/***************************************************************************/
if(!input(bt2)){ // Botão letra MI
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA MI"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 261Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(3); // Tempo para gerar frequencia de nivel alto
delay_us(800);
delay_us(30);
output_low(fal); // Joga nivel baixo no pino
delay_ms(3); // Tempo para gerar frequencia de nivel baixo
delay_us(800);
delay_us(30);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla MI
/***************************************************************************/
if(!input(bt3)){ // Botão letra FA
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA FA"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 293Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(3); // Tempo para gerar frequencia de nivel alto
delay_us(400);
delay_us(10);
output_low(fal); // Joga nivel baixo no pino
delay_ms(3); // Tempo para gerar frequencia de nivel baixo
delay_us(400);
delay_us(10);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla FA
/***************************************************************************/
if(!input(bt4)){ // Botão letra SOL
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA SOL"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 329Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(3); // Tempo para gerar frequencia de nivel alto
delay_us(30);
delay_us(9);
output_low(fal); // Joga nivel baixo no pino
delay_ms(3); // Tempo para gerar frequencia de nivel baixo
delay_us(30);
delay_us(9);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla SOL
/***************************************************************************/
if(!input(bt5)){ // Botão letra LA
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA LA"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 349Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(2); // Tempo para gerar frequencia de nivel alto
delay_us(800);
delay_us(60);
output_low(fal); // Joga nivel baixo no pino
delay_ms(2); // Tempo para gerar frequencia de nivel baixo
delay_us(800);
delay_us(60);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla FA
/***************************************************************************/
if(!input(bt6)){ // Botão letra SI
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA SI"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 392Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(2); // Tempo para gerar frequencia de nivel alto
delay_us(500);
delay_us(50);
output_low(fal); // Joga nivel baixo no pino
delay_ms(2); // Tempo para gerar frequencia de nivel baixo
delay_us(500);
delay_us(50);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla SI
/***************************************************************************/
if(!input(bt7)){ // Botão letra DO1
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA DO#"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 440Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(2); // Tempo para gerar frequencia de nivel alto
delay_us(200);
delay_us(70);
output_low(fal); // Joga nivel baixo no pino
delay_ms(2); // Tempo para gerar frequencia de nivel baixo
delay_us(200);
delay_us(70);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla DO1
/***************************************************************************/
if(!input(bt8)){ // Botão letra RE1
limpa_lcd(); // Limpa LCD
printf(escreve_lcd,"NOTA RE#"); // Imprime a nota e a frequencia
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"FREQUENCIA 493Hz"); // Imprime a nota e a frequencia
while(aux != 100){ // Tempo de som
output_high(fal); // Joga nivel alto no pino
delay_ms(2); // Tempo para gerar frequencia de nivel alto
delay_us(20);
delay_us(8);
output_low(fal); // Joga nivel baixo no pino
delay_ms(2); // Tempo para gerar frequencia de nivel baixo
delay_us(20);
delay_us(8);
aux++; // Aumenta aux
}
aux=0; // Limpa aux
limpa_lcd(); // Limpa LCD
printf(escreve_lcd," VARAGO"); // Imprime VARAGO
envia_byte_lcd(0,0xc3); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"AUTOMATICS"); // Imprime AUTOMATICS
} // Fim da tecla RE1
/***************************************************************************/
} // Fim do laço infinito
} // Fim do programa
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

teclado matricial com PIC :

POR RAFAEL VARANGO AGUIAR


            CÓDIGO FONTE :


/**************************************************************************
* Teclado Matricial com Display *
***************************************************************************
* Rafael Varago de Aguiar Varago Automatics *
***************************************************************************
* Versão: 2.1 *
* Data: 24/07/2010 *
* *
* RAM: 4% ROM: 5% *
***************************************************************************
* Exibe o numero em um display 7 segmentos de acordo com o *
* botão pressionado no teclado matricial de 0 a 9 enter e backspace *
**************************************************************************/
#include <16f877a.h> // Informa o PIC
#device adc=10 // Configura conversor AD para 10 bits
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT // Configs internas
#use delay (clock=4000000) // Seleciona delay para 4Mhz de clock
/**************************************************************************
**************************************************************************/
// Definições de pinos
#define l0 pin_b3 // Primeira linha do teclado
#define l1 pin_b4 // Segunda " do "
#define l2 pin_b5 // Terceira " do "
#define l3 pin_b6 // Quarta " do "
#define c0 pin_b0 // Primeira coluna do teclado
#define c1 pin_b1 // Primeira " do "
#define c2 pin_b2 // Primeira " do "
/**************************************************************************
**************************************************************************/
// Variaveis globais
int cont; // Armazanam o valor da a exibir no display
/**************************************************************************
**************************************************************************/
// Tabela para converter o valor da contagem para exibir no display
byte const tabela[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xe7};
/**************************************************************************
**************************************************************************/
// Exibe no display o valor do botão pressionado
void zero(){ // Exibe zero no display

cont=0; // Cont é igual a 0
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void um(){ // Exibe um no display

cont=1; // Cont é igual a 1
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
void dois(){ // Exibe dois no display

cont=2; // Cont é igual a 2
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void tres(){ // Exibe tres no display

cont=3; // Cont é igual a 3
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void quatro(){ // Exibe quatro no display

cont=4; // Cont é igual a 4
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void cinco(){ // Exibe cinco no display

cont=5; // Cont é igual a 5
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void seis(){ // Exibe seis no display

cont=6; // Cont é igual a 6
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void sete(){ // Exibe sete no display

cont=7; // Cont é igual a 7
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void oito(){ // Exibe oito no display

cont=8; // Cont é igual a 8
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void nove(){ // Exibe nove no display

cont=9; // Cont é igual a 9
output_d(tabela[cont]); // Joga cont no display
return; // Retorna
} // Fim da sub-rotina
/**************************************************************************
**************************************************************************/
// Varredura de teclas
void scan1(){ // Faz primeira varredura

int aux=50; // Tempo de varredura
while(aux != 0){ // Laço para varredura
output_low(l0); // Joga 0 na coluna a ser varrida e 1 nas demais
output_high(l1);
output_high(l2);
output_high(l3);
if(!input(c0)){ // Testa primeira coluna
delay_ms(250); // Tempo para soltar tecla
um(); // Chama a sub-rotina correspondente a tecla
}
if(!input(c1)){ // Testa segunda coluna
delay_ms(250); // Tempo para soltar a tecla
dois(); // Chama a sub-rotina corresponde a tecla
}
if(!input(c2)){ // Testa terceira coluna
delay_ms(250); // Tempo para soltar a tecla
tres(); // Chama a sub-rotina corresponde a tecla
}
aux--; // Decrementa 1 de aux
delay_us(aux); // Tempo de atraso da varredura é igual a aux
}
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void scan2(){ // Faz segunda varredura

int aux=50; // Tempo de varredura
while(aux != 0){ // Laço para varredura
output_high(l0); // Joga 0 na coluna a ser varrida e 1 nas demais
output_low(l1);
output_high(l2);
output_high(l3);
if(!input(c0)){ // Testa primeira coluna
delay_ms(250); // Tempo para soltar tecla
quatro(); // Chama a sub-rotina correspondente a tecla
}
if(!input(c1)){ // Testa segunda coluna
delay_ms(250); // Tempo para soltar a tecla
cinco(); // Chama a sub-rotina corresponde a tecla
}
if(!input(c2)){ // Testa terceira coluna
delay_ms(250); // Tempo para soltar a tecla
seis(); // Chama a sub-rotina corresponde a tecla
}
aux--; // Decrementa 1 de aux
delay_us(aux); // Tempo de atraso da varredura é igual a aux
}
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void scan3(){ // Faz terceira varredura

int aux=50; // Tempo de varredura
while(aux != 0){ // Laço para varredura
output_high(l0); // Joga 0 na coluna a ser varrida e 1 nas demais
output_high(l1);
output_low(l2);
output_high(l3);
if(!input(c0)){ // Testa primeira coluna
delay_ms(250); // Tempo para soltar tecla
sete(); // Chama a sub-rotina correspondente a tecla
}
if(!input(c1)){ // Testa segunda coluna
delay_ms(250); // Tempo para soltar a tecla
oito(); // Chama a sub-rotina corresponde a tecla
}
if(!input(c2)){ // Testa terceira coluna
delay_ms(250); // Tempo para soltar a tecla
nove(); // Chama a sub-rotina corresponde a tecla
}
aux--; // Decrementa 1 de aux
delay_us(aux); // Tempo de atraso da varredura é igual a aux
}
return; // Retorna
} // Fim da sub-rotina
/*************************************************************************/
void scan4(){ // Faz quarta varredura

int aux=50; // Tempo de varredura
while(aux != 0){ // Laço para varredura
output_high(l0); // Joga 0 na coluna a ser varrida e 1 nas demais
output_high(l1);
output_high(l2);
output_low(l3);
if(!input(c0)){ // Testa primeira coluna
delay_ms(250); // Tempo para soltar tecla
zero(); // Chama a sub-rotina correspondente a tecla
}
if(!input(c1)){ // Testa segunda coluna
delay_ms(250); // Tempo para soltar a tecla
zero(); // Chama a sub-rotina corresponde a tecla
}
if(!input(c2)){ // Testa terceira coluna
delay_ms(250); // Tempo para soltar a tecla
nove(); // Chama a sub-rotina corresponde a tecla
}
aux--; // Decrementa 1 de aux
delay_us(aux); // Tempo de atraso da varredura é igual a aux
}
return; // Retorna
} // Fim da sub-rotina
/**************************************************************************
**************************************************************************/
// Rotina principal do programa
main(){ // Rotina principal

setup_adc_ports(no_analogs); // Configura todas as entradas como digitais
set_tris_a(0b00000000); // configuração da direção dos pinos de I/O
set_tris_b(0b00000111);
set_tris_c(0b00000000);
set_tris_d(0b00000000);
set_tris_e(0b00000000);
while(1){ // Laço infinito
scan1(); // Chama primeira varredura
scan2(); // " segunda "
scan3(); // " terceira "
scan4(); // " quarta "
} // Fim do laço
} // Fim do programa

usando rtc DS1307

olá , este é um exemplo de como usar o RTC DS1307.


CÓDIGO FONTE:

// ****************************************************************************************************************************************************
// usando o relogio de tempo real DS1307
//
// Data: 12/11/2010
// Autor: Aguivone
// Descrição: demonstra como usar um rtc da maxin(dallas)
// *************************************************************************************************************************************************************************************************************************
#include <16F877A.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use I2C(master, scl=PIN_C3, sda=PIN_C4)
/////////////////////////////////////////configuração e parametrização//////////////////
#define DS1307_SEGUNDOS 0
#define DS1307_MINUTOS 1
#define DS1307_HORAS 2 // se no modo 12hrs o bit 5 indica se é AM ou PM
#define DS1307_DIA_DA_SEMANA 3
#define DS1307_DIA_DO_MES 4
#define DS1307_MES 5
#define DS1307_ANO 6
#define DS1307_STATUS_CONTROLE 7
#define DS1307_RAM 8 //endereço inicial da ram
//formato das horas
#define DS1307_12HRS 64 //habilita o bit 6 , das horas
#define DS1307_24HRS 0
//usados para escrita
#define DS1307_Ende_escrita 0xd0
#define DS1307_Ende_leitura 0xd1
//foi disabilitada o SQWV pois consome muito da bateria
#define DS1307_SQWV 0x80
// 32.768 KHz saida (habilitado)
//#define DS1307_SQWV 0x13
///////////////////////////////////////////////////////////////////////////////////////

int segundos=50;
int minutos=59;
int horas=23;
int dia_mes=12;
int mes=11;
int ano=10;//0 à 99
int dia_semana=7;//0 = Sunday, 1 = Monday, etc.// de 0 a 6

char dia_da_semana[8][10] =
{
{"nada"}
,{"Domingo"}
,{"Segunda"}
,{"Terca"}
,{"Quarta"}
,{"Quinta"}
,{"Sexta"}
,{"Sabado"}
};


//----------------------------------------------
void DS1307_escreve_byte(int8 endereco, int8 dados)
{
disable_interrupts(GLOBAL);
i2c_start(); //inicializa a comunicaçao i2c
i2c_write(DS1307_Ende_escrita);
i2c_write(endereco);
i2c_write(dados);
i2c_stop(); //finaliza comunicação
enable_interrupts(GLOBAL);
}

//----------------------------------------------
int DS1307_ler_byte(int endereco)
{
int lido;
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_Ende_escrita);
i2c_write(endereco);
i2c_start();
i2c_write(DS1307_Ende_leitura);
lido = i2c_read(0);//ler sem ack =0 , ler com ack = 1
i2c_stop();
enable_interrupts(GLOBAL);
return(lido); //retorna o valor lido
}

//----------------------------------------------
// converte de binario para bcd (8 bits), de 0 a 99
int BINparaBCD(int valor)
{
int BCD=0;
while(valor>1)
{
if(valor >= 10) //incrementa casas decimais.
{
valor -= 10;
BCD += 0x10;
}
else
{
BCD += valor;
valor=0;
}
}
return(BCD); //retorna o valor
}

// converte de bcd para binario (8 bits), de 0 a 99

int BCDparaBIN(int valor)
{
int temp=15;
int temp2=240;
temp &= valor;
temp2 &= valor;
temp2 >>= 4;
temp2 *= 10;
valor=temp+temp2;
return(valor);
}

//----------------------------------------------
void DS1307_programar_tempo(void)
{

int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_dia_semana;
int8 bcd_dia_mes;
int8 bcd_mes;
int8 bcd_ano;
int8 bcd_sqwv;
// Converte binario para bcd
bcd_sec = BINparaBCD(segundos);
bcd_min = BINparaBCD(minutos);
bcd_hrs = BINparaBCD(horas=horas|DS1307_24HRS); //faz um ou logico para informar o tipo da data
bcd_dia_semana = BINparaBCD(dia_semana) ;
bcd_dia_mes = BINparaBCD(dia_mes) ;
bcd_mes = BINparaBCD(mes) ;
bcd_ano = BINparaBCD(ano);
bcd_sqwv = BINparaBCD(DS1307_SQWV);
// deve-se desabilitar as interrupçoes para fazer a comunicação I2C.
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(DS1307_Ende_escrita);
i2c_write(DS1307_SEGUNDOS); // inicia a partir do registrador 0(segundos e inicia ele com zero).
i2c_write(bcd_sec); //escreve os segundos
i2c_write(bcd_min);
i2c_write(bcd_hrs);
i2c_write(bcd_dia_semana);
i2c_write(bcd_dia_mes);
i2c_write(bcd_mes);
i2c_write(bcd_ano);
i2c_write(bcd_sqwv);
i2c_stop();
enable_interrupts(GLOBAL);
}

//----------------------------------------------
// Lê data e tempo dos registradores do
// PCF8583. Não é preciso parar a contagem durante a operação de leitura

void DS1307_ler_datas(void)
{
disable_interrupts(GLOBAL);
// lê o DS1307.
i2c_start();
i2c_write(DS1307_Ende_escrita);
i2c_write(DS1307_SEGUNDOS); // inicia lendo segundos.
i2c_start();
i2c_write(DS1307_Ende_leitura);
segundos = i2c_read();
minutos = i2c_read();
horas = i2c_read();
dia_semana = i2c_read();
dia_mes = i2c_read();
mes = i2c_read();
ano = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
// converte datas de bcd para inteiro
segundos = BCDparaBIN(segundos);
minutos = BCDparaBIN(minutos);
horas = BCDparaBIN(horas& 0x3F);//pega os 6 bits mais baixos (formato 24hrs)
dia_mes = BCDparaBIN(dia_mes);
dia_semana = BCDparaBIN(dia_semana);
mes = BCDparaBIN(mes);
ano = BCDparaBIN(ano);
if(dia_semana==0)
{
disable_interrupts(GLOBAL);
i2c_start();
DS1307_escreve_byte(3,1);
i2c_stop();
enable_interrupts(GLOBAL);
dia_semana=1;
}
}
/////////////////////////////////////////////////////////////////////////////////////

//=================================
void main()
{
DS1307_programar_tempo();//ajusta data e hora conforme os valores pre ajustados, para simular data atual comente esta linha
DS1307_ler_datas();
while(1)
{
delay_ms(1000);
DS1307_ler_datas();
printf("hora %u:%u:%u \n\r",horas,minutos,segundos);
printf("data %u/%u/%u \n\r",dia_mes,mes,ano);
printf(" hoje e %s \n\r",dia_da_semana[dia_semana]);
if(ano>9)
{
printf(" ano atual = 20%u \n\r",ano);
}
else
{
printf(" ano atual = 200%u \n\r",ano);
}

}

}