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);
}

}

}

segunda-feira, 25 de outubro de 2010

Placar de truco :

este exemplo de codigo é uma contribuição de Rafael Varago para mais informação sobre este projeto
veja o link no final dessa postagem.

   visualização do projeto

codigo fonte :

/**************************************************************************
*                    Placar Eletronico de Truco                           *
***************************************************************************
* Rafael Varago de Aguiar                       Varago Automatics         *
***************************************************************************
* Versão: 2.0                                                             *
* Data: 19/10/2010                                                        *
*                                                                         *
* RAM: 6%   ROM: 7%                                                       *
***************************************************************************
* Controle de 4 Displays 7 segmentos para servir de placar de truco       *
* que vai de 0 a 12, sendo 2 displays para casa equipe                    *
* os pontos são computados através de 3 botões                            *
* DOWN: decrementa 1,UP: incrementa 1, TR: soma 3; o placar               *
* e salva na EEPROM os valores dos contadores para inicia-lo com eles     *
* na proxima vez que o circuito for ligado.                               *
**************************************************************************/
#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 dw1 pin_b0 // DOWN1 (decremeta 1 para a equipe 1)
#define up1 pin_b1 // UP1 (incrementa 1 para a equipe 1)
#define tr1 pin_b2 // TR1 (soma 3 para a equipe 1)
#define dw2 pin_b3 // DOWN2 (decremeta 1 para a equipe 2)
#define up2 pin_b4 // UP2 (incrementa 1 para a equipe 2)
#define tr2 pin_b5 // TR2 (soma 3 para a equipe 2)
/**************************************************************************
**************************************************************************/
// Variaveis globais
int pl1,pl2; // 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};
/**************************************************************************
**************************************************************************/
main(){ // Rotina principal
   int1 max1,min1,max2,min2; // Sinalizadores para indicar contagem min e max
   port_b_pullups(true); // Ativa pull-ups do portb
   setup_adc_ports(no_analogs); // Configura todas as entradas como digitais
   pl1=0; // Garante que o contador da equipe 1 comece em 0
   pl2=0; //    "     "  o    "     da   "    2   "    em 0
   delay_ms(500); // Estabilização da EEPROM
   pl1=read_eeprom(1); // Carrega o ultimo valor da EEPROM salvo do contador 1
   pl2=read_eeprom(2); //    "    o   "      "   da   "      "   do    "     2
   while(1){ // Laço de repetição infinito
/**************************************************************************
**************************************************************************/
// Fragmento do software para a contagem da primeira equipe
      if(min1 == 0){ // Se o display não estiver em 0
         if(!input(dw1)){ // Se o botão DOWN1 for pressionado
            while(input(dw1) == 0){
            } // Laço para soltar botão
            max1=0; // Limpa o sinalizador de display igual a 12
            pl1--; // Decrementa 1 da variavel de contagem da equipe 1
            if(pl1 == 0) // Se a contagem da equipe 1 estiver em 0
               min1=1; // Joga 1 no sinalizador de display igual a 0
            write_eeprom(1,pl1); // Salva o valor do contador 1 na EEPROM
         }
      } // Fim do bloco
      if(max1 == 0){ // Se o display não estiver em 12
         if(!input(up1)){ // Se o botão UP1 for pressionado
            while(input(up1) == 0){
            } // Laço para soltar botão
            min1=0; // Limpa o sinalizador de display igual a 0
            pl1++; // Incrementa 1 da variavel de contagem da equipe 1
            if(pl1 == 12) // Se a contagem da equipe 1 estiver em 12
               max1=1; // Joga 1 no sinalizador de display igual a 12
         write_eeprom(1,pl1); // Salva o valor do contador 1 na EEPROM
         }
      } // Fim do bloco
      if(max1 == 0){ // Se o display não estiver em 12
         if(!input(tr1)){ // Se o botão TR1 for pressionado
            while(input(tr1) == 0){
            } // Laço para soltar botão
            min1=0; // Limpa o sinalizador de display igual a 0
            pl1=pl1+3; // Incrementa 3 da variavel de contagem da equipe 1
            if(pl1 > 12){ // Se a contagem da equipe 1 ultrapassar 12
               pl1=12; // Contador da equipe 1 igual a 12
               max1=1;  // Joga 1 no sinalizador de display igual a 12
            }
         write_eeprom(1,pl1); // Salva o valor do contador 1 na EEPROM
         }
      } // Fim do bloco
/**************************************************************************
**************************************************************************/
// Fragmento do software para a contagem da segunda equipe
      if(min2 == 0){ // Se o display não estiver em 0
         if(!input(dw2)){ // Se o botão DOWN2 for pressionado
            while(input(dw2) == 0){
            } // Laço para soltar botão
            max2=0; // Limpa o sinalizador de display igual a 12
            pl2--; // Decrementa 1 da variavel de contagem da equipe 2
            if(pl2 == 0) // Se a contagem da equipe 2 estiver em 0
               min2=1; // Joga 1 no sinalizador de display igual a 0
            write_eeprom(2,pl2); // Salva o valor do contador 2 na EEPROM
         }
      } // Fim do bloco
      if(max2 == 0){ // Se o display não estiver em 12
         if(!input(up2)){ // Se o botão IP2 for pressionado
            while(input(up2) == 0){
            } // Laço para soltar botão
            min2=0; // Limpa o sinalizador de display igual a 0
            pl2++; // Incrementa 1 da variavel de contagem da equipe 2
            if(pl2 == 12) // Se a contagem da equipe 2 estiver em 12
               max2=1; // Joga 1 no sinalizador de display igual a 12
            write_eeprom(2,pl2); // Salva o valor do contador 2 na EEPROM
         }
      } // Fim do bloco
      if(max2 == 0){ // Se o display não estiver em 12
         if(!input(tr2)){ // Se o botão TR2 for pressionado
            while(input(tr2) == 0){
            } // Laço para soltar botão
            min2=0; // Limpa o sinalizador de display igual a 0
            pl2=pl2+3; // Incrementa 3 da variavel de contagem da equipe 2
            if(pl2 > 12){ // Se a contagem da equipe 2 ultrapassar 12
               pl2=12; // Contador da equipe 2 igual a 12
               max2=1;  // Joga 1 no sinalizador de display igual a 12
            }
            write_eeprom(2,pl2); // Salva o valor do contador 2 na EEPROM
         }
      } // Fim do bloco
/**************************************************************************
**************************************************************************/
// Joga valores nos displays
      output_c(0xfe); // Seleciona display dezena equipe 1
      output_d(tabela[pl1/10]); // Joga o valor do contador
      delay_ms(10); // Tempo para display ligado
      output_c(0xfd); // Seleciona display unidade equipe 1
      output_d(tabela[pl1%10]); // Joga o valor do contador
      delay_ms(10); // Tempo para display ligado
      output_c(0xfb); // Seleciona display dezena equipe 2
      output_d(tabela[pl2/10]); // Joga o valor do contador
      delay_ms(10); // Tempo para display ligado
      output_c(0xf7); // Seleciona display unidade equipe 2
      output_d(tabela[pl2%10]); // Joga o valor do contador
      delay_ms(10); // Tempo para display ligado
   } // Fim do laço de repetição
} // Fim do programa

para mais informação escreva para  rafaelvarago@yahoo.com.br .


quinta-feira, 16 de setembro de 2010

sequencial de 22 leds com atmega8 (avr)

Olá ,aqui está um exemplo de codigo para quem precisar fazer um sequencial de leds

//************************************************************************
//                             usando sequencial
//  Version : 1.0
//  microcontrolador : AVR ATMega8
//  Autor     : Aguivone
//  descrição  : acesso individual usando define
//  data : 16/09/2010.
//
//************************************************************************
#define F_CPU 1000000UL  // 1 MHz deve vir antes das interrupçoes
#include <avr/io.h> //standard include for ATMega16 # Include <avr/io.h> / padrão para incluir ATMEGA16
#include <util/delay.h>
#define liga_pino(x,y) x |= _BV(y)
#define desliga_pino(x,y) x &= ~(_BV(y))
#define alterna_pino(x,y) x ^= _BV(y)
#define pino_alto(x,y) ((x & _BV(y)) == _BV(y)) //o pino deve estar como entrada ,testa se está em nivel logico 1

///* _BV(a) is a macro which returns the value in hex corresponding to 2 to the power 'a'. / * _BV (A) é uma macro que retorna o valor em hexadecimal correspondente a 2 elevado à potência 'a'. Thus _BV(PX3) would be 0x08 or 0b00001000 */ Assim _BV PX3 () seria 0x08 ou 0b00001000 * /
int main (void)
{
    unsigned int valor = 50;
   // DDRB= 0xf7 ; //PORTB as OUTPUT DDRB = 0xff; / PORTB / as OUTPUT
    DDRB = 0xFF;
    DDRC = 0xFF;
    DDRD = 0xFF;
    PORTB = 0x00 ; //All pins of PORTB LOW PORTB = 0x00 / / Todos os pinos do PORTB LOW
    PORTC = 0x00 ; //All pins of PORTB LOW PORTB = 0x00 / / Todos os pinos do PORTB LOW
    PORTD = 0x00 ; //All pins of PORTB LOW PORTB = 0x00 / / Todos os pinos do PORTB LOW
    while (1)
    {
    //////////////////////////////////////////////
       liga_pino(PORTB,PB0);
    _delay_ms(1);
       desliga_pino(PORTC,PC5);
        _delay_ms(valor);
       liga_pino(PORTB,PB1);
    _delay_ms(1);
       desliga_pino(PORTB,PB0);
        _delay_ms(valor);
  liga_pino(PORTB,PB2);
  _delay_ms(1);
       desliga_pino(PORTB,PB1);
        _delay_ms(valor);
       liga_pino(PORTB,PB3);
    _delay_ms(1);
       desliga_pino(PORTB,PB2);
        _delay_ms(valor);
     
     liga_pino(PORTB,PB4);
  _delay_ms(1);
       desliga_pino(PORTB,PB3);
        _delay_ms(valor);
       liga_pino(PORTB,PB5);
    _delay_ms(1);
       desliga_pino(PORTB,PB4);
        _delay_ms(valor);
  liga_pino(PORTB,PB6);
  _delay_ms(1);
        desliga_pino(PORTB,PB5);
        _delay_ms(valor);
        liga_pino(PORTB,PB7);
     _delay_ms(1);
        desliga_pino(PORTB,PB6);
        _delay_ms(valor);
       ///////////////////////////////////////////////////////////
     liga_pino(PORTD,PD0);
    _delay_ms(1);
       desliga_pino(PORTB,PB7);
        _delay_ms(valor);
       liga_pino(PORTD,PD1);
    _delay_ms(1);
       desliga_pino(PORTD,PD0);
        _delay_ms(valor);
  liga_pino(PORTD,PD2);
  _delay_ms(1);
       desliga_pino(PORTD,PD1);
        _delay_ms(valor);
       liga_pino(PORTD,PD3);
    _delay_ms(1);
       desliga_pino(PORTD,PD2);
        _delay_ms(valor);
     
     liga_pino(PORTD,PD4);
  _delay_ms(1);
       desliga_pino(PORTD,PD3);
        _delay_ms(valor);
       liga_pino(PORTD,PD5);
    _delay_ms(1);
       desliga_pino(PORTD,PD4);
        _delay_ms(valor);
  liga_pino(PORTD,PD6);
  _delay_ms(1);
        desliga_pino(PORTD,PD5);
        _delay_ms(valor);
        liga_pino(PORTD,PD7);
     _delay_ms(1);
        desliga_pino(PORTD,PD6);
        _delay_ms(valor);
  ///////////////////////////////////////////
  liga_pino(PORTC,PC0);
    _delay_ms(1);
       desliga_pino(PORTD,PD7);
        _delay_ms(valor);
       liga_pino(PORTC,PC1);
    _delay_ms(1);
       desliga_pino(PORTC,PC0);
        _delay_ms(valor);
  liga_pino(PORTC,PC2);
  _delay_ms(1);
       desliga_pino(PORTC,PC1);
        _delay_ms(valor);
       liga_pino(PORTC,PC3);
    _delay_ms(1);
       desliga_pino(PORTC,PC2);
        _delay_ms(valor);
     
     liga_pino(PORTC,PC4);
  _delay_ms(1);
       desliga_pino(PORTC,PC3);
        _delay_ms(valor);
       liga_pino(PORTC,PC5);
    _delay_ms(1);
       desliga_pino(PORTC,PC4);
        _delay_ms(valor);

       }
}

terça-feira, 14 de setembro de 2010

usando lcd 4 bits com atmega8 AVR STUDIO

Aqui a proposta é controlar um lcd de forma facil e sem biblioteca :
///************************************************************************/
//                             usando LCD
//  Version    : 1.0
//  microcontrolador : AVR ATMega8
//  Autor        : Aguivone
//  descrição  : usando lcd interface de 8 bits
//  data : 02/09/2010.
//
//************************************************************************/
#define F_CPU 4000000UL  // 4 MHz
#include <avr/io.h>
#include <util/delay.h>
#include <string.h> 

/////////////////////////////////////variaveis usada no lcd ///////////////////////////////////////////
//#define LCD PORTC //define qual porta vai usar neste caso port C
#define LCD PORTD //define qual porta vai usar neste caso port D
//o pino r/w é conectado ao terra pois não é feita nenhuma leitura no display
//configuração:
//
// pino display  / pino da porta selecionada
//
// D4 = bit 0 da porta
// D5 = bit 1 da porta
// D6 = bit 2 da porta
// D7 = bit 3 da porta
//
// RS = bit 4 da porta
// EN = bit 5 da porta
//
/////////////////////////////////////////////////Funções usadas no LCD/////////////////////////////////////////////

void inicializa_LCD(void)
{
    _delay_ms(15);//tempo para estabilizar a tensão e preparar o display
    // o primeiro digito é de controle e o segundo configuração

    LCD = 0X22;//nesse momento o display ainda está em modo 8bits solicita modo de 4 bits
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X02;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);
                // é preciso colocar este comando pelo menos 2 vezes para que funcione o display
    LCD = 0X22;//nesse momento o display  está em modo 4bits 
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X02;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

    LCD = 0X28;//nesse momento o display  está em modo 4bits,manda usar 2 linhas 
    _delay_ms(1);//tempo estabilizar o pino
    LCD =0X08;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

    LCD = 0X20;//manda limpar o display
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X21;//segundo nibble (limpa display)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X01;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 
    
     LCD = 0X20;//manda deslocar a direita (0x06)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

     LCD = 0X26;//segundo nibble (desloca a direita)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X06;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X20;//cursor desligado (0X0C)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X2C;//segundo nibble (cursor deligado)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X0C;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 
    
}
// escreve nibble
void escr(unsigned char crt,int vlr)
{
    if(vlr == 1)
    {
    LCD = crt | 0X30 ;//escreve dados
    _delay_us(30);//tempo estabilizar o pino
    LCD = crt | 0X10;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_us(30);
    }
    else
    {
    LCD = crt | 0X20 ;//escreve comando
    _delay_us(30);//tempo estabilizar o pino
    LCD = crt | 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_us(30);
    }
}
// escreve caracter ou comando
void escreve(unsigned char carac,int val)
{
    unsigned char temp=carac;
    carac = ((carac >> 4) & 0X0F);
    temp  = temp & 0X0F;
    escr(carac,val);  //escreve primeiro nibble
    escr(temp,val);  //escreve segundo nibble
}


void impri_lcd(char frase[17])
{
      unsigned int indice=0;
      unsigned int tamanho = strlen(frase);
      while(indice<tamanho)
       {         
            if(frase[indice]=='\n')//linha 1 
            {
                 escreve(0X80,0);
            }
            if(frase[indice]=='\r')//linha2
            {
               escreve(0XC0,0);
            }
            if((frase[indice]!='\r') && (frase[indice]!='\n') && (indice<18))//dados
            {
               escreve(frase[indice],1);
            }   
       indice++;
       }
} 

//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRC = 0XFF;  //inicializa portC
           DDRD = 0XFF;  //inicicializa portD como saida
           inicializa_LCD();
           impri_lcd("\n   teste de lcd ");
           impri_lcd("\r      AGUIVONE  ");
          for(;;)
            {
              //faz nada                
            }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////


quarta-feira, 8 de setembro de 2010

Interrupção externa com atmega8 - avr studio

//************************************************************************
// usando interrupção externa
// Version : 1.0
// microcontrolador : AVR ATMega8
// Autor : Aguivone
// descrição : usando interrupção externa int0 e int1
// data : 25/08/2010.
//
//************************************************************************
#define F_CPU 1000000UL // 1 MHz deve vir antes das interrupçoes
#include
#include

//////////////////////////interrupções externas ///////////////////////////////////
ISR(INT0_vect ) //int0
{
PORTC = ~PORTC;
}
ISR(INT1_vect ) //int1
{
PORTB = ~PORTB;
}

/////////////////////////////////////////////////Funções usadas/////////////////////////////////////////////
void inicializa_interrupt(void)
{
MCUCR = 0X07;//configura a interrupção 1 para qualquer mudança de estado no pino e int0 para borda de subida
GICR = 0xC0;//habilita int1 e int0
sei(); //habilita interrupções
}

//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
DDRC = 0xFF; //inicializa portd
PORTC = 0;
DDRB = 0xFF; //inicializa portd
PORTB = 0; inicializa_interrupt();
for(;;)
{
//faz nada!
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

PWM com o atmega8 - avr studio

//************************************************************************
// usando o PWM
// Version : 1.0
// microcontrolador : AVR ATMega8
// Autor : Aguivone
// descrição : PWM
// data : 30/08/2010.
//
//************************************************************************
#define F_CPU 1000000UL // 1 MHz deve vir antes das interrupçoes
#include

/////////////////////////////////////////////////Funções usadas/////////////////////////////////////////////
void PWM_CTC(void)
{
TCCR2 = 0X55;// toggle OC2 / usar modo CTC / preescaler(1/128) // // aqui se define a frequencia.
OCR2 = 0X40;//valor a ser comparado com o TCNT2 (aqui é mudado a largura do pulso)

//pinos de pwm PB1,PB2,PB3(OC1,2,3).
}

void PWM_NORMAL(void)// o valor da largura de pulso é sempre 50%
{
TCCR2 = 0X15;// toggle OC2 / usar modo normal / preescaler(1/128) // // aqui se define a frequencia.
//pinos de pwm PB1,PB2,PB3(OC1,2,3).
}

void PWM_FAST(void)// o valor da largura de pulso é sempre 50%
{
TCCR2 = 0X7D;// modo invertido OC2 / usar modo fast pwm / preescaler(1/128) // // aqui se define a frequencia.
//pinos de pwm PB1,PB2,PB3(OC1,2,3).

// neste modo gera um pulso muito rapido se no modo invertido a largura do pulso é proximo de 99%
// modo não invertido a largura do pulso é proximo de 1%
}

void PWM_FASE(void)// o valor da largura de pulso é sempre 50%
{
TCCR2 = 0X3F;// seta OC2 quando comparado/ usar modo fase pwm / preescaler(1/128) // // aqui se define a frequencia.
//pinos de pwm PB1,PB2,PB3(OC1,2,3).
// a verificar
}

Usando serial com atmega8 - avr studio

//************************************************************************


// usando a porta serial
// Version : 1.0
// microcontrolador : AVR ATMega8 UART
// Autor : Aguivone
// descrição : exemplo de uso da serial
//
//************************************************************************

#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz deve vir antes das interrupçoes
#include <avr/interrupt.h>
#include <stdio.h>
///////////////////////////////////////////////funçoes usadas////////////////////////////////////////////////

int uart_putchar(char c, FILE *stream)

{
if (c == '\n')
uart_putchar('\r', stream);
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}

int uart_getch(FILE *stream)
{
unsigned char ch;
while (!(UCSRA & (1<<RXC)));
ch=UDR;
return ch;
}

/* assimila I/O stream á UART */

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getch, _FDEV_SETUP_RW);

void ini_serial(int BAUD_RATE)
{
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // calcula o ubrr da comunicação
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
UCSRB = (1<<RXEN)
(1<<TXEN); //habilita tx e rx

UCSRC = (1<<URSEL)
(1<<UCSZ1)
(1<<UCSZ0);//programa para 8bit ,sem paridade,1 stop bit
sei(); // habilita interrupçoes geral
}

void Delay(unsigned int count) // conta tempo

{
while(count>0)
{
count--;
}
}



//////////////////////////////////////////função principal///////////////////////////////////

int main(void)
{
stdout = stdin = &uart_str; /* inicializa a UART */
ini_serial(4800); /* inicializa serial para 4800 bps */
DDRD = 0xFF; // configura o portd
PORTD = 0; // inicializa o portd

for(;;)
{
printf("teste de serial \n\r");
Delay(12000);
}

}

///////////////////////////////////////////fim//////////////////////////////////////////////

Pisca pisca com timer0 - avr studio

//************************************************************************
// usando os timers
// Version : 1.0
// microcontrolador : AVR ATMega8
// Autor : Aguivone
// descrição : interrupção dos timer
// data : 24/08/2010.
//
//************************************************************************
#define F_CPU 1000000UL // 1 MHz deve vir antes das interrupçoes
#include
#include

//////////////////////////interrupções do timer0 ///////////////////////////////////
ISR(TIMER0_OVF_vect )
{ //interrupção overflow
PORTD =~ PORTD; //nessa interrupção não é preciso ler ou zerar o TCNT0
}

/////////////////////////////////////////////////Funções usadas/////////////////////////////////////////////
void inicializa_timer0(void)
{
TCCR0 = 0x05; //pre escaler dividido por 8
TIMSK = 0x01; //habilita interrupção do timer 0(estouro do contador)
sei(); //habilita interrupções
}

//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
DDRD = 0xFF; //inicializa portd
PORTD = 0;
inicializa_timer0();
for(;;)
{
//faz nada!
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

usando a eeprom do atmega8 - avr studio


 1:  //************************************************************************
   2:  //                             usando a memoria do atmel
   3:  //  Version    : 1.0
   4:  //  microcontrolador : AVR ATMega8
   5:  //  Autor        : Aguivone
   6:  //  descrição  : escrevendo e lendo a memoria
   7:  //  data : 01/09/2010.
   8:  //
   9:  //************************************************************************
  10:  #define F_CPU 4000000UL  // 4 MHz deve vir antes das interrupçoes
  11:  #include <avr/io.h>
  12:  #include <avr/interrupt.h>
  13:  #include <util/delay.h>
  14:  #include <string.h>
  15:  #include <avr/eeprom.h>
  16:   
  17:   
  18:  #define liga_pino(x,y) x |= _BV(y)
  19:  #define desliga_pino(x,y) x &= ~(_BV(y))
  20:   
  21:  unsigned char temp;
  22:   
  23:   unsigned char caracter;//
  24:   unsigned int  tam_buffer;//usado para contar o tamanho do buffer de recepção
  25:   unsigned char buffer_serial[14];//buffer da serial
  26:   volatile char rec_buffer ='S';//usado para ler o buffer de recepção (volatile para funcionar pois sempre ira retornar mesmo valor)
  27:   
  28:  ///////////////////////////////////////////////funçoes usadas pela usart////////////////////////////////////////////////
  29:   
  30:  void serial_inicializa(unsigned int BAUD)
  31:  {
  32:  unsigned int valor = F_CPU/16/BAUD-1; //é recomendavel ver o data sheet para ter certeza se está formula irá funcionar na sua mcu
  33:  /* baud rate */
  34:  UBRRH = (unsigned char)(valor>>8);
  35:  UBRRL = (unsigned char)valor;
  36:  UCSRA = 0X20;
  37:  /* habilita receiver and transmitter buffers */
  38:  UCSRB = 0X98;//deve se habilitar somente a interrupção de recepção para não travar o microcontrolador
  39:  /* 8 bits , 1 stop bit, assincrono , sem paridade */
  40:  UCSRC = 0X86;
  41:  }
  42:  void impri_serial(const char frase[80])
  43:  {
  44:        unsigned int indice=0;
  45:        unsigned int tamanho = strlen(frase);      
  46:        while(indice<=tamanho)///veja que o programa pode travar se aqui não tiver as duas aspas
  47:         {
  48:             while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
  49:             UDR =frase[indice];
  50:             indice++;
  51:         }
  52:  }
  53:  void put_serial(unsigned char *carac)
  54:  {
  55:             while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
  56:             UDR = *carac;
  57:  }
  58:  //////////////////////////interrupções requerida para usar a serial///////////////////////////////////
  59:  ISR(USART_RXC_vect)
  60:  {                                            // # caracter *
  61:   caracter = (char)UDR;
  62:    if(caracter == '*')
  63:     {
  64:          if(tam_buffer<14)//max do display
  65:            {
  66:              rec_buffer ='F';
  67:             }
  68:             else
  69:             {
  70:              rec_buffer ='E';//tamanhoa incompativel
  71:             }
  72:     }
  73:    if((caracter != '*')&&(rec_buffer == 'I'))
  74:     {
  75:      buffer_serial[tam_buffer]=caracter;
  76:      tam_buffer++;
  77:      }
  78:    if(caracter == '#')
  79:     {
  80:     rec_buffer ='I';
  81:     tam_buffer=0;
  82:     }
  83:  }
  84:   
  85:   
  86:  ////////////////////////////////////////////////função principal///////////////////
  87:   
  88:  int main(void)
  89:  {
  90:    DDRC = 0x00;  //inicializa portc como entrada
  91:    DDRD = 0XFE;  //inicializa portD
  92:    DDRB = 0xFF;  //inicializa portb como saida
  93:    serial_inicializa(4800);//não importa frequencia e 4800
  94:    sei();
  95:    impri_serial("Inicializado ... \n\r");
  96:    while (1)
  97:        {
  98:             if(rec_buffer == 'F')//tem dados para ler ?
  99:                       {
 100:                        impri_serial("recebeu primeiro caracter :");
 101:                        impri_serial(&buffer_serial[0]);
 102:                        impri_serial("\n\r");
 103:                        if(buffer_serial[0] == 'E')//houve interrupção
 104:                               {
 105:                                   impri_serial("comparou");
 106:                                   temp='n';
 107:                                   _EEPUT(5,buffer_serial[1]);//endereço/dado
 108:                                   _EEGET(temp,5);//local a ser escrito/endereço
 109:                                   impri_serial(& temp); 
 110:                                   liga_pino(PORTB,PB0);
 111:                                   _delay_ms(500);
 112:                                   desliga_pino(PORTB,PB0);
 113:                               }
 114:                        rec_buffer = 'S';
 115:                       } 
 116:                    if(rec_buffer == 'E')//deu erro ?
 117:                       {
 118:                        impri_serial("tamanho inconpativel");
 119:                        rec_buffer = 'S';
 120:                       }
 121:             
 122:   
 123:        }
 124:  }
 125:   
 126:   
 127:  //para usar float é necessario adiconar a biblioteca