Ir ao conteúdo
  • Cadastre-se

PIC Contador Up/ down PIC16F628a


Posts recomendados

Olá , estou tentando desenvolver um contador up/down com 2 displays de 7 segmentos, 2 CI 4511 utilizando o PIC16F628a   ,Uso o Mikro C e já iniciei mais estou tendo algumas dificuldades.

Gostaria que esse contador tivesse o limite superior no numero 60  e inferior no 00, depois vou querer gravar na eeprom do pic um valor selecionado, para isso vai ter uma tecla de gravação  e leitura.

até agora só conseguir a contagem crescente e mais nada.

Se alguém der uma luz eu agradeço.

void nibbleDown(char number);
void nibbleUp(char number);

char counter1 = 0, counter2 = 0;

void main()
{
   CMCON = 0x07;
   TRISA = 0b00000011;
   TRISB = 0x00;
   PORTA = 0x03;
   PORTB = 0x00;

   while(1)
   {
   
if(button(&porta,0,40,0))
{
     counter1++;


     nibbleDown(counter1);
     nibbleUp(counter2);

     if(counter1 == 10)
     {
      counter2++;
      counter1 = 0;
      nibbleDown(counter1);
      nibbleUp(counter2);
          if(counter2 == 10)
          {
            counter2 = 0;
            nibbleUp(counter2);
          }
     }

      delay_ms(300);

   }
}
}

void nibbleDown(char number)
{
  switch(number)
  {
     case 0:
       portb.f0= 0x00;
       portb.f1= 0x00;
       portb.f2= 0x00;
       portb.f3= 0x00;
       break;
     case 1:
       portb.f0= 0x01;
       portb.f1= 0x00;
       portb.f2= 0x00;
       portb.f3= 0x00;
       break;
     case 2:
       portb.f0= 0x00;
       portb.f1= 0x01;
       portb.f2= 0x00;
       portb.f3= 0x00;
       break;
     case 3:
       portb.f0= 0x01;
       portb.f1= 0x01;
       portb.f2= 0x00;
       portb.f3= 0x00;
       break;
     case 4:
       portb.f0= 0x00;
       portb.f1= 0x00;
       portb.f2= 0x01;
       portb.f3= 0x00;
       break;
     case 5:
       portb.f0= 0x01;
       portb.f1= 0x00;
       portb.f2= 0x01;
       portb.f3= 0x00;
       break;
     case 6:
       portb.f0= 0x00;
       portb.f1= 0x01;
       portb.f2= 0x01;
       portb.f3= 0x00;
       break;
     case 7:
       portb.f0= 0x01;
       portb.f1= 0x01;
       portb.f2= 0x01;
       portb.f3= 0x00;
       break;
     case 8:
       portb.f0= 0x00;
       portb.f1= 0x00;
       portb.f2= 0x00;
       portb.f3= 0x01;
       break;
     case 9:
       portb.f0= 0x01;
       portb.f1= 0x00;
       portb.f2= 0x00;
       portb.f3= 0x01;
       break;
  } //end switch

}


void nibbleUp(char number)
{
  switch(number)
  {
     case 0:
       portb.f4= 0x00;
       portb.f5= 0x00;
       portb.f6= 0x00;
       portb.f7= 0x00;
       break;
     case 1:
       portb.f4= 0x01;
       portb.f5= 0x00;
       portb.f6= 0x00;
       portb.f7= 0x00;
       break;
     case 2:
       portb.f4= 0x00;
       portb.f5= 0x01;
       portb.f6= 0x00;
       portb.f7= 0x00;
       break;
     case 3:
       portb.f4= 0x01;
       portb.f5= 0x01;
       portb.f6= 0x00;
       portb.f7= 0x00;
       break;
     case 4:
       portb.f4= 0x00;
       portb.f5= 0x00;
       portb.f6= 0x01;
       portb.f7= 0x00;
       break;
     case 5:
       portb.f4= 0x01;
       portb.f5= 0x00;
       portb.f6= 0x01;
       portb.f7= 0x00;
       break;
     case 6:
       portb.f4= 0x00;
       portb.f5= 0x01;
       portb.f6= 0x01;
       portb.f7= 0x00;
       break;
     case 7:
       portb.f4= 0x01;
       portb.f5= 0x01;
       portb.f6= 0x01;
       portb.f7= 0x00;
       break;
     case 8:
       portb.f4= 0x00;
       portb.f5= 0x00;
       portb.f6= 0x00;
       portb.f7= 0x01;
       break;
     case 9:
       portb.f4= 0x01;
       portb.f5= 0x00;
       portb.f6= 0x00;
       portb.f7= 0x01;
       break;
  } //end switch

}

 

Será que essa lógica é a melhor para se fazer isso? 

Até tentei fazer uma outra lógica fazendo sub_rotinas para cada numero apresentado no display, mais o programa fica muito grande

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Existem métodos um pouco  melhores que o seu e que usa meia dúzia de linhas e nem precisa de 4511. Envolve conceitos de interrupção e varredura. Infelizmente não consigo explicar rapidamente mas sei quem consegue...é ele mesmo!. Clique e confira

Esta blogueiro diz que fez em c mas infelizmente não conferi pra você ok?

http://larios.tecnologia.ws/iBlog/archives/2931

 

Link para o comentário
Compartilhar em outros sites

Obrigado Isadora, dei uma olhada no site e vi que a linguagem C  que ele usa é bem diferente do MIKRO C, algumas linhas até consigo entender, mais a maioria é bem confusa.

Estou pesquisando uma maneira mais simples de apresentar os números no display, da uma enxugada no código.

até consegui fazer para um display um código bem simples, o problema é colocar o segundo display.

 

#define  S2     porta.f0
#define  S1     porta.f1
#define  led2   porta.f2
#define  led1   porta.f3

void changeCont();                      //Muda o valor do contador
void gravaEEPROM();                     //Grava o valor atual do display da EEPROM


 int cont = 0x00;                      //cont incremento/decremento do display (dado a ser armazenado na EEPROM)

 unsigned char catodo;                 //catodo recebe o valor de cont

 unsigned char segmento[10] = {0x3f,   // display '0'
                               0x06,   // display '1'
                               0x5b,   // display '2'
                               0x4f,   // display '3'
                               0x66,   // display '4'
                               0x6d,   // display '5'
                               0x7d,   // display '6'
                               0x07,   // display '7'
                               0x7f,   // display '8'
                               0x67};  // display '9'

void main()
{

 CMCON = 0x07; //desabilita comparadores

 TRISA = 0x03;
 TRISB = 0x00; //todo PORTB configurado como saída
 PORTA = 0x03;
 PORTB = 0x00; //PORTB inicia em nível baixo

     cont = EEPROM_Read(0x00);

    while(1)
    {

        changeCont();

        if(!S2) gravaEEPROM();

        catodo = segmento[cont]; //numero a ser enviado para PORTB

        PORTB = catodo;          //envia pattern para PORT B

        delay_ms(100);

    } //end while

} //end void main

void changeCont()
{
   if(!S1)
   {
     cont++;
     delay_ms(100);

     if(cont > 0x09) cont = 0x00;

   }

} //end changeCont


void gravaEEPROM()
{
   EEPROM_Write(0x00, cont);
   delay_ms(10);
   led1 = 0x01;
   delay_ms(500);
   led1 = 0x00;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Membro VIP
1 hora atrás, Jason Aspire disse:

o problema é colocar o segundo display.

Aí entra o conceito de varredura... algo como o dado é escrito bem rapidinho nos displays e você nem nota que está acendendo um de cada vez. Algo como...

display%207seg_3.png

http://pictronics.com.br/index.php?option=com_content&view=article&id=76:multiplexando-displays-de-7-segmentos-com-pic16f877a&catid=36

... pode lhe servir como introdução pois não é tão inteligente como o método que te disse ...

2 horas atrás, Isadora Ferraz disse:

conceitos de interrupção e varredura.

... por timer... Neste caso pode colocar quantos displays quiser. Lembrando que os segmentos estão em paralelo e apenas o catodo (ou anodo) comum são controlados por fora.

 

Imagine algo como escrever 34 no display

-ao passar pela interrupt você desliga RC7=0, coloca 0x4f, // display '3' = segmento[3] no port e aciona o display 1 RC6=1

-na próxima passada você desliga RC6=0, coloca 0x66, // display '4' = segmento[4] e liga RC7=1

 

 

Olha que fácil pra 8 displays algo como (digito on line...)

unsigned char display[],i=0,k=1;
...
interrupt void timer(void)
{
PORTB=segmentos[[display[i]];
PORTC=k;
i++; if (i>7) {i=0;k=1;}
k<<=1;
}
...
//34
display[0]=3;
display[1]=4;

 

Link para o comentário
Compartilhar em outros sites

Obrigado mais uma vez Isadora, entendi a lógica agora é tentar colocar em pratica, agora só mais uma coisa se possível? e nem sei se pode ser aqui ou tem que abrir outro tópico? E que é continuação desse projeto.

Estou tentando fazer tipo um elevador para peças , pretendo contar o curso do mesmo  por tempo, algo bem simples, um contador de segundos de no máximo 20 segundos por delay mesmo.

A contagem será só na subida, dai eu preciso salvar essa contagem na eeprom e quando ligar novamente e apertar a tecla busca ( busca de tempo/Posição)   ele vai ligar o motor pelo tempo salvo e parar na posição que eu salvei.

Consegui salvar numeros fiz com LCD  e deu certinho, mais e para ligar o motor ?  isso eu não consegui ainda.

 

 

int cont=0;
char texto[15];

void gravaEEPROM();                     //Grava o valor atual do display da EEPROM
void tela();

#define   grava    porta.f0
#define   inc      porta.f1

#define   led1     porta.f3


//******************************************************************************
void tela ()          // mostra o valor no LCD
{
inttostr(cont,texto);
lcd_out(2,4, texto);      // lcd_out(1,2,"SP");
LCD_Out(1,1, "Contador Pulsos");
}
//******************************************************************************
void main( )
{
cmcon=0x07;
trisa=0b00000111;
porta=0;
trisb=0;
portb=0;

LCD_Config(&portb,1,0,2,7,6,5,4);
LCD_Cmd(LCD_Cursor_Off);
LCD_Cmd(Lcd_Clear);
LCD_Out(1,1, "Contador Pulsos");

cont=0;
tela();

INICIO:;

while(1)
{
if (button(&porta,2,40,1)){      //volta a zero
porta.f7=1;
goto VOLTAZERO;
}
else
{
porta.f7=0;
}


if (button(&porta,1,40,1)){      //Incrementa +++++
goto INCREMENTA;
tela();
}

else
{
porta.f6=0;
}



if (button(&porta,0,40,1)&& (button(&porta,4,40,1))) {      //Grava Pos de trabalho
delay_ms(100);
gravaEEPROM();
cont=cont2;
}

else
{
}



if (button(&porta,0,40,1)){      //Busca posição
goto BUSCA;
tela();
}


}        //end while

//******************************************************************************
VOLTAZERO:;

while(1)
{
if(cont !=0){          //cont não vai abaixo de zero
if(cont>0)
{
cont=cont-1;
tela();
if(cont == 00 )
{
cont=0;
porta.f7=0;
tela();
goto INICIO;
}
}
}
delay_ms(1000);
}


//******************************************************************************
INCREMENTA:;

while(1)
{
porta.f6=1;                      //Sobe a badeja até o máximo
if(cont<20){
cont = cont+1;
tela();
delay_ms(500);
}

goto INICIO;
}

//******************************************************************************
BUSCA:;
while(1)
{
cont = EEPROM_Read(0x00);              //vai buscar valor salvo na memória
tela();                                //Mostra o valor no display
delay_ms(1000);                        //aguarda 1 segundo                                //Zera cont                                //Mostra no display que zerou
porta.f6=1;                            //liga o rele Sobe a badeja
if(cont < cont) {    //
cont = cont+1;
tela();
}
if (cont==cont){
porta.f6=0;
goto INICIO;
}
delay_ms(1000);
}


//******************************************************************************
}     //end main

//******************************************************************************
void gravaEEPROM()
{
   EEPROM_Write(0x00, cont);
   delay_ms(10);
   led1 = 0x01;
   delay_ms(500);
   led1 = 0x00;
   delay_ms(2000);
}

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
15 horas atrás, Jason Aspire disse:

Consegui salvar numeros fiz com LCD  e deu certinho, mais e para ligar o motor ? 

você já tem a faca e o queijo na mão. Apenas grave o valor do tempo do motor em endereço difernte uai...

 

15 horas atrás, Jason Aspire disse:

while(1) { cont = EEPROM_Read(0x00); //vai buscar valor salvo na memória

e a busca nao precisa estar dentro do loop. Coloque na inicialização antes do main()... Percebo agora vários loops.. Isso não é totalmente bom. Tenta dar uma revisada/estudada nos princípios  fundamentais do C. P.ex. crie funções dentro de um loop só.
 

for(;;) //o mesmo que while(1)
{
if (x) funcx();
func1();
i++;
func2(2,i);
delay(y);
//etc
}

Nem vai precisar do confuso goto

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...

Dando uma posição sobre o meu programa, eu  resolvi fazer com LCD mesmo.

E consegui salvar o tempo e uma segunda variável para poder ligar o motor.

Mais uma vez eu agradeço a Isadora que me ajudou.

 

segua o código ja funcionando.

char texto[15];

int temp_motor=0;             //Variavél de contagem do tempo do motor
int cont=0;                   //Variavél de contagem de tempo auxiliar

void gravaEEPROM();           //Grava o valor atual do display da EEPROM
void tela();                  //Mostra o valor no Display LCD

#define   pos_trab   porta.f0   //Tecla posição de trabalho
#define   inc        porta.f1   //Tecla incrementa

#define   buzzer     porta.f3   //Saida do Buzzer
#define   rele_sobe  porta.f6   //Rele sobe motor
#define   rele_desce porta.f7   //Rele desce motor

//******************************************************************************
void tela ()          // mostra o valor no LCD
{
inttostr(cont,texto);
lcd_out(1,10, texto);
LCD_Out(1,1, "Cont");


inttostr(temp_motor,texto);
lcd_out(2,10, texto);
LCD_Out(2,1, "Motor");
}
//*****************************************************************************
void main( )
{
cmcon=0x07;
trisa=0b00000111;
porta=0;
trisb=0;
portb=0;

LCD_Config(&portb,1,0,2,7,6,5,4);
LCD_Cmd(LCD_Cursor_Off);
LCD_Cmd(Lcd_Clear);


temp_motor=0;
cont=0;
tela();

//*****************************************************************************
INICIO:;

while(1)
{
if (button(&porta,2,40,1)){      //Tecla retorna a zero
delay_ms(100);
porta.f7=1;
goto VOLTAZERO;
}
else
{
porta.f7=0;
}


if (button(&porta,1,40,1)){      //Incrementa +++++
delay_ms(100);
goto INCREMENTA;
}

else
{
porta.f6=0;
}



if (button(&porta,0,40,1)&& (button(&porta,4,40,1))) {  //Grava Pos de trabalho
delay_ms(100);
gravaEEPROM();
}

else
{
}

if (button(&porta,0,40,1)){      //Busca posição que foi gravada
delay_ms(100);
goto BUSCA;
tela();
}

}        //end while
//******************************************************************************
VOLTAZERO:;

while(1){
cont=0;
temp_motor=0;
tela();
cont=20;
tela();
porta.f7=1;                   //Liga desce bandeja


while(1)
{
delay_ms(1000);
if (cont > 0)            // 20 segundos
{
cont = cont-1;
tela();
if(cont == 0)
{
cont=0;
temp_motor=0;
porta.f7=0;
tela();
goto INICIO;
}
}
//delay_ms(1000);
if (button(&porta,2,40,1))   //Tecla volta zero
{
goto EMERGENCIA;
}
}
}
//******************************************************************************
INCREMENTA:;

while(1)
{
porta.f6=1;                      //liga o rele sobe bandeja
if(cont<20 && temp_motor<20) {
cont = cont+1;
temp_motor=temp_motor+1;
tela();
delay_ms(1000);
}
goto INICIO;
}

//******************************************************************************
BUSCA:;

while(1)
{
cont = EEPROM_Read(0x00);           //vai buscar valor salvo na memória  `0´

temp_motor= EEPROM_Read(0x09);     //Vai buscar valor salvo na memória `9´
tela();                             //Mostra o valor no display

delay_ms(1000);                     //Aguarda 1 segundo
cont=0;                             //Zera cont
tela();                             //Mostra no display cont zerado

while(1)
{
delay_ms(1000);
if (cont < temp_motor )
{
porta.f6=1;                         //Liga o rele sobe Bandeja
cont = cont+1;
tela();
if (cont == temp_motor)
{
porta.f6=0;
goto INICIO;
}
}
//delay_ms(1000);
}
}
//******************************************************************************
EMERGENCIA:;

cont =0;
temp_motor=0;
porta.f7=0;
delay_ms(3000);
goto INICIO;

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

}     //end main

//******************************************************************************
void gravaEEPROM()
{
   EEPROM_Write(0x00, cont);
   delay_ms(10);
   EEPROM_Write(0x09,temp_motor);
   delay_ms(10);
   buzzer = 0x01;
   delay_ms(2000);
   buzzer = 0x00;
   delay_ms(2000);
}

 Jason Aspire

 Autor do tópico

Membros Juniores

 1

3 posts

desde 01/04/2020

 

Denunciar post

 

 

#5  

Postado 3 de abril

Obrigado mais uma vez Isadora, entendi a lógica agora é tentar colocar em pratica, agora só mais uma coisa se possível? e nem sei se pode ser aqui ou tem que abrir outro tópico? E que é continuação desse projeto.

Estou tentando fazer tipo um elevador para peças , pretendo contar o curso do mesmo  por tempo, algo bem simples, um contador de segundos de no máximo 20 segundos por delay mesmo.

A contagem será só na subida, dai eu preciso salvar essa contagem na eeprom e quando ligar novamente e apertar a tecla busca ( busca de tempo/Posição)   ele vai ligar o motor pelo tempo salvo e parar na posição que eu salvei.

Consegui salvar numeros fiz com LCD  e deu certinho, mais e para ligar o motor ?  isso eu não consegui ainda.

 

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!