control de tiempos en el compilador "mikro C for pic"

#1
hola gente de foros de electronica.

soy un amateur en el mundo de los micropocesadores y de un tiempo aca, he descubirto el compilador "mikro C pro for pic", desde entonces he trabajado comodamente con el, pero tengo un problema, que los tutoriales sobre este compilador son muy limitados y solo te enseñan cosas basicas. bueno.....en la universidad donde estudio electronica, mi profesor me ha pedido que diseñe un programa que me cuente las pulsaciones del corazon por minuto y que obviamente lo visualice por un display.

creo que el programa consiste en un contador de "altos" a la entrada del sistema. realmente es un programa facil de realizar en "mikro C pro for pic", pero el problema que tengo es, como hacer para que el sistema deje de contar los altos, pasados 60 segundos de haber iniciado el conteo.

¿sera que existe alguna funcion para controlar tiempos en "mikro C pro for pic"?, es decir que me realice el conteo de los 60 segundos, sin intervenir en el conteo de los altos.

necesito ayuda.
 
#3
es micro con k?

no he hallado nada para ese soft.
Que raro que no lo conozcas, no es mi compilador favorito pero es muy bueno y conocido en el mundillo de los microcontroladores PIC y AVR. http://www.mikroe.com/


Para chaly:
¿sera que existe alguna funcion para controlar tiempos en "mikro C pro for pic"?, es decir que me realice el conteo de los 60 segundos, sin intervenir en el conteo de los altos.
Eso no existe en el compilador; lo que puedes hacer es usar un timer del pic, usar su interrupción para contar los segundos... pero que inicie la cuenta de segundos cuando detecte el 1er pulso "alto", entonces el programa principal se dedica a contar los latidos y la parte de interrupción que se dedique contar los segundos..., al terminar los 60, detienes el contador del programa principal.
Puedes usar el Timer1 configurado con oscilado externo de 32Khz para que te de segundos más precisos.
 
#5
Hola:
Esto lo saque de un ejemplo que tiene el MikroC para el timer1...
PHP:
unsigned short cnt;

void interrupt() {
  if (TMR1IF_bit) {
    cnt++;                    // increment counter
    TMR1IF_bit = 0;           // clear TMR0IF
    TMR1H = 0x80;
    TMR1L = 0x00;
  }
}

void main() {
  ANSEL  = 0;                 // Configure AN pins as digital
  ANSELH = 0;
  C1ON_bit = 0;               // Disable comparators
  C2ON_bit = 0;
  PORTB = 0xFF;               // Initialize PORTB
  TRISB = 0;                  // PORTB is output
  T1CON = 1;                  // Timer1 settings
  TMR1IF_bit = 0;             // clear TMR1IF
  TMR1H = 0x80;               // Initialize Timer1 register
  TMR1L = 0x00;
  TMR1IE_bit = 1;             // enable Timer1 interrupt

  cnt =   0;                  // initialize cnt
  INTCON = 0xC0;              // Set GIE, PEIE

  do {
    if (cnt >= 72) {
      PORTB  = ~PORTB;        // Toggle PORTB LEDs
      cnt = 0;                // Reset cnt
    }
  } while (1);
}
Lo importante ahí es que debes de configurar la interrupción que quieres que se realice, para eso debes de conocer los registros del PIC; también escribir la función "interrupt" tal y como la vez en el ejemplo.
NT: Si usas más de una interrupción debes de comprobar de quien fue en la misma función "interrupt"...
Todo está en el archivo de ayuda del mismo compilador y los ejemplos en la carpeta de instalación, que hay muchos... claro en ingles pero es lo de menos.
 
#7
hola Carlos Alexis.

bueno no he comenzado a trabajar en el proyecto porque he esta ocupado con los parciales, pero ahora que tengo tiempo libre, comenze ha investigar sobre el timer1 y te comento que ya se como configurarlos, pero tengo un problema, que nose como utilizar la interrupcion para que me cuente los 60 segundos mientras se ejecuta el progrma principal.

he intentado realizar un programa sencillo sobre eso:

un secuenciador de luces que se detenga pasado 60 segundos.

pero no lo he logrado hacer, por favor haber si me ayudas con este ejercicio.

edito:
estoy trabajando con el pic16f877, nose las interrupciones se trabajan iguales que con el pic 16f887, tengo esa duda.

salu2.
 
Última edición:
#8
Hola chaly



Te dejo esto para que veas si te sirve de algo:


PHP:
int cnt;
void interrupt()
{
cnt++;
PIR1.TMR1IF=0;
TMR1H=0x80;
TMR1L=0x00;
}
void main()
{
PORTB=0xF0;
TRISB=0;
T1CON=1;
PIR1.TMR1IF=0;
TMR1H=0x80;
TMR1L=0x00;
PIE1.TMR1IE=1;
cnt=0;
INTCON = 0xC0;
while(1)
{
if(cnt>=3650)
PORTB=0;
else
{
PORTB=1;
delay_ms(500);
PORTB=3;
delay_ms(500);
PORTB=0;
delay_ms(500);
}
}
}

Es una mini-secuencia de luces que se detiene pasado 60 segundos...


Saludos...
 
#9
hola iDan

excelente aporte compañero, si funciona, pero lo unico malo del codigo es la temporizacion, pero ya lo corregi.:)

forma corregida:
int cnt;
void interrupt()
{
cnt++;
PIR1.TMR1IF=0;
TMR1H=0x9E;
TMR1L=0x58;
}
void main()
{
PORTB=0xF0;
TRISB=0;
T1CON=49;
PIR1.TMR1IF=0;
TMR1H=0x9E;
TMR1L=0x58;
PIE1.TMR1IE=1;
cnt=0;
INTCON = 0xC0;
while(1)
{
if(cnt>=300)
PORTB=0;
else
{
PORTB=1;
delay_ms(500);
PORTB=3;
delay_ms(500);
PORTB=0;
delay_ms(500);
}
}
}
de esa forma lo intente hacer con el codigo que me facilito Carlos Alexis, pero no funciono, me pregunto porque?

salu2.
 
Última edición:
#10
Alguien me puede ayudar en como programar una interrupción que sea de 1500us y 2500us para controlar un servomotor, ya trate de hacerla pero no funciona, no le entiendo muy bien a eso,
saludos.


Código:
unsigned cnt;        // Declarar la variable cnt
unsigned char a=191;
int x=0;

void interrupt() {   // Rutina de interrupción
  cnt++;             // Interrupción causa el incremento de cnt por 1
  TMR0 = 191;        // Temporizador (o contador) Timer0 devuelve su valor inicial
  INTCON = 0x20;     // Bit T0IE está a 1, bit T0IF está a 0
}


void main() {

ANSEL  = 0;                          // Configure AN pins as digital I/O
ANSELH = 0;

TRISC=0x00;

OPTION_REG = 0x2A;   // Pre-escalador (1:8) se le asigna al temporizador Timer0
TMR0= 191;            // Temporizador T0 cuenta de 155 a 255
INTCON = 0xA0;    // Habilitada la generación de interrupción para el
                    // temporizador Timer0
while(1){

portc.f2=1;
INTCON.T0IE = 1;
INTCON.GIE = 1; //Habilito Interrupciones generales


if(INTCON.TMR0IF == 0)
{
portc.f2=0;
delay_ms(19);
}

}
}
 
Última edición por un moderador:
#11
Saludos tengo el mismo problema, necesito implementar un tacometro y presentar los rpm en un display multiplexado, uso el t0cki(contador externo) que me debe contar los pulsos en altos pero no me funca o presenta en los displays.
Adjunto el codigo
Código:
/***********************
#include "mask.c"
/*Header******************************************************/
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections


unsigned short mask(unsigned short num);
long digit_no,digit1000, digit100, digit10, digit1, i,digit;
long temp, temp2,temp3,temp4, digit_1,digit_2,digit_3,digit_4;
long cont1,cont,cnt;

char texto1[7];
long rpm, numflancos=0;
//int rads;

void main() {
  OSCCON=0x60; //Oscilador interno a 4MHz.
  //OSCCON=0x40; //Oscilador interno a 1MHz.
  ANSEL=0;
  ANSELH=0;
  
  OPTION_REG = 0x80;             // Set timer TMR0     0x80
  TMR0 = 0;
  INTCON = 0xA4;   //A0              // Disable interrupt PEIE,INTE,RBIE,T0IE
  PORTD = 0;                     // Turn off both displays
  TRISD = 0;                    // All port A pins are configured as outputs
  PORTC = 0;                     // Turn off all display segments
  TRISC = 0;                     // All port D pins are configured as outputs
  PORTA = 0;
  TRISA = 0b00110011;// RA0,RA1,RA2 como entradas
  PORTB = 0;
  TRISB = 0;
  porte=0;
  TRISE=0;
  C1ON_bit = 0;               // Disable comparators
  C2ON_bit = 0;
  Lcd_Init();                //Inicializa el LCD.
  Lcd_Cmd(_LCD_CLEAR);       //Borra el display.
  Lcd_Cmd(_LCD_CURSOR_OFF);  //Apaga el cursor.
  Lcd_Out(1,1,"TacometroDigital");
  //Lcd_Out(2,1,"Wmax=15.300 rpm");
  Delay_ms(1500);
  Lcd_Cmd(_LCD_CLEAR);       //Borra el display.

  T1CON=49;
  PIR1.TMR1IF=0;
  TMR1H=0x9E;
  TMR1L=0x58;
  PIE1.TMR1IE=1;
  cnt=0;

  digit_no=0;
  cont=0;
  do {
    if(PORTA.F0==0 && PORTA.F1==1){
      PORTA=0x04;
       if(PORTA.F5==0){
          cont++;
          temp     = cont % 1000;
          digit_1  = cont/1000;
          digit1000= mask(digit_1);  // Prepare mask for displaying ones
          temp2    = temp%100;
          digit_2  = temp/100;
          digit100 = mask(digit_2); // Prepare mask for displaying tens
          temp3    = temp2%10;
          digit_3  = temp2/10;
          digit10 = mask(digit_3); // Prepare mask for displaying centenas
          temp4    = temp3%1;
          digit_4  = temp3/1;
          digit1= mask(digit_4); // Prepare mask for displaying miles
          Delay_ms(150);
       }
      if(cont==9999){
       cont=0;
      }
    }
    if(PORTA.F0==1 && PORTA.F1==0){
        PORTA=0x08;
        OPTION_REG = 0xA0; //Contador de pulsos en T0CKI
        TMR0=0;
        Delay_ms(1000);             //Cuenta durante 1 segundo.
        numflancos=TMR0;          //numflancos=velocidad en rps.
        rpm=(long)(60+(60*numflancos));        //Transformación a rpm.
        IntToStr(rpm,texto1);     //Transformación de rpm a texto.
        Lcd_Out(1,1,"W[rpm]=");
        Lcd_Out(1,8,texto1);
     
        if(rpm >= 9999){
          rpm=9999;
          temp     = rpm % 1000;
          digit_1  = rpm/1000;
          digit1000= mask(digit_1);  // Prepare mask for displaying ones
          temp2    = temp%100;
          digit_2  = temp/100;
          digit100 = mask(digit_2); // Prepare mask for displaying tens
          temp3    = temp2%10;
          digit_3  = temp2/10;
          digit10 = mask(digit_3); // Prepare mask for displaying centenas
          temp4    = temp3%1;
          digit_4  = temp3/1;
          digit1= mask(digit_4); // Prepare mask for displaying miles

        }
        temp     = rpm % 1000;
        digit_1  = rpm/1000;
        digit1000= mask(digit_1);  // Prepare mask for displaying ones
        temp2    = temp%100;
        digit_2  = temp/100;
        digit100 = mask(digit_2); // Prepare mask for displaying tens
        temp3    = temp2%10;
        digit_3  = temp2/10;
        digit10 = mask(digit_3); // Prepare mask for displaying centenas
        temp4    = temp3%1;
        digit_4  = temp3/1;
        digit1= mask(digit_4); // Prepare mask for displaying miles
        cont=0;
    }
  } while (1);                   // Endless loop
}

void interrupt() {

    if (digit_no==0) {
        PORTD = 1;                 // 1=mil
        PORTC = digit1;            //
        PORTD = 1;                 //
        digit_no = 1;
    }
    if(digit_no==1) {
        PORTD = 8;                 //
        PORTC = digit10;           // 8=CENTENAS
        PORTD = 8;                 //
        digit_no = 2;
    }
    if(digit_no==2) {
        PORTD = 4;                 //  4=DECENAS
        PORTC = digit100;          //
        PORTD = 4;                 //
        digit_no = 3;
    }
    else{
        PORTD = 2;                 // 2=Unidades
        PORTC = digit1000;         //
        PORTD = 2;                 //
        digit_no = 0;
    }
    TMR0 = 0;                      // Reset counter TMRO
    INTCON = 0x20;                 // Bit T0IF=0, T0IE=1
}
 
Última edición por un moderador:
Arriba