Autor Tema: Mini curso "Programación en XC8"  (Leído 588173 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re: Mini curso "Programación en XC8"
« Respuesta #345 en: 09 de Diciembre de 2015, 18:45:40 »
Interrupciones de alta y baja prioridad.

 En este programa vamos a utilizar las interrupciones externas del pic18F4550 en los pines RB0, RB1 y RB2
   configurando lso flancos de subida para INT0, INT1, e INT2.

  En el 4550 la INT0 es siempre de alta prioridad. No se puede setear como de baja prioridad
   Las INT1 e INT2 las configuramos en baja prioridad.

   Cada vez que se produzca una interrupción en INT0 cambiará el estado del pin RA0
   Cada vez que se produzca una interrupción en INT1 cambiará el estado del pin RA1
   Cada vez que se produzca una interrupción en INT2 cambiará el estado del pin RA2

        Saludos.
              Jukinch

Código: C
  1. File:   main.c
  2.    Author: JUKINCH
  3.  
  4.    Created on 31 de mayo de 2013, 14:49
  5.  
  6.    PRUEBA DE INTERRUPCIONES en baja y alta prioridad
  7.    EN INT0 (RB0) INT1 (RB1) E INT2 (RB2)
  8.  
  9.  
  10.    pic: 18f4550
  11.    crystal: NO
  12.    CPU: 8Mhz (valor establecido dentro de main cambiando los bits IRCF2, IRCF1 e IRCF0 del registro OSCCON)
  13.         en RA6 sale la frecuencia de Fosc/4   ------->   8Mhz/4 = 2Mhz
  14.  
  15.    FUSES: los bits de configuración se establecen en el archivo "configuracion_de_fuses.c"
  16.  
  17.    CONEXIONES entrenadora FELIXLS:
  18.     1 módulo conectado en IDC(RB0) en modo botón
  19.     1 módulo conectado en IDC(RA0) en modo leds
  20.     los cambios se pueden hacer en el archivo configuracion_hard.c
  21.  
  22.  */
  23.  
  24.  
  25.  
  26. /*Includes globales*/
  27. #include <xc.h>
  28. #include <delays.h> /* Para utilizar demoras en nuestro código*/
  29.  
  30. /*Includes locales*/
  31. #include "configuracion_de_fuses.c"
  32. #include "configuracion_hard.c"
  33.  
  34.  
  35.  
  36.  
  37.  
  38. volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones
  39.  
  40.  
  41. //******************************************************//
  42. // Rutina de Interrupcion de Alta Prioridad
  43. //******************************************************//
  44. //
  45.  
  46. void interrupt interrupcionDeAlta(void)//prototipo de la interrupción de alta prioridad
  47.         {
  48.             if(INTCONbits.INT0IF)          //pregunta por bandera de interrupción en rb0
  49.                     {
  50.                     LED0 = ~LED0;          // invierto estado del led
  51.                     myVolatileVariable++;
  52.                     INTCONbits.INT0IF = 0; //limpia bandera y salimos
  53.                     }
  54.         }
  55.  
  56.  
  57. //
  58. //******************************************************//
  59. // Rutina de Interrupcion de baja prioridad
  60. //******************************************************//
  61. //
  62. void interrupt low_priority   interrupcionDeBaja(void)//prototipo de la interrupción de baja prioridad
  63.         {
  64.             if(INTCON3bits.INT1IF)       //pregunta por bandera de interrupción
  65.                 {
  66.                 LED1 = ~LED1;            // invierto estado del led
  67.                 myVolatileVariable++;
  68.                 INTCON3bits.INT1IF = 0;  //limpia bandera y salimos
  69.                 }
  70.  
  71.  
  72.             if(INTCON3bits.INT2IF)       //pregunta por bandera de interrupción
  73.                 {
  74.                 LED2 = ~LED2;            // invierto estado del led
  75.                 myVolatileVariable++;
  76.                 INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
  77.                 }
  78.         }
  79.  
  80.  
  81.  
  82.  
  83.  
  84. //******************************************************//
  85. // Programa Principal
  86. //******************************************************//
  87. void main(void)
  88. {
  89. ADCON0 = 0X00,ADCON1 = 0X0F,CMCON = 0X07; //puerto A con todos los pines digitales
  90.  
  91. PINLED0=0; // Configuración de pines como salida para los leds
  92. PINLED1=0;
  93. PINLED2=0;
  94. PINBOTON0=1; // Configuración de pines como entrada para los botones
  95. PINBOTON1=1;
  96. PINBOTON2=1;
  97.  
  98. LATA = 0X00; // todo el puerto A a cero.
  99.  
  100.  
  101. RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
  102. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  103. INTCONbits.GIEH = 1;// permitimos interrupciones de alta prioridad (Global Interrupt Enable High)
  104. INTCON2bits.INTEDG0 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB0
  105. INTCON2bits.INTEDG1 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB1
  106. INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
  107.  
  108. INTCONbits.INT0IE=1; // activa la interrupción externa por flanco del pin RB0
  109.                      // La Int0 es siempre de alta prioridad. No se puede setear como de baja prioridad
  110.  
  111. INTCON3bits.INT1IE=1; // activa la interrupción externa por flanco del pin RB1
  112. INTCON3bits.INT1IP=0; // selecciona la interrupción de baja prioridad del pin RB1
  113.  
  114. INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
  115. INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
  116.  
  117. //*******************************************************
  118. //*******************************************************
  119.  
  120.  
  121. while (1);
  122.  
  123.  
  124.  
  125. }
  126. //*******************************************************
  127. //*******************************************************

HOLA JUKINCH, tengo un problema con las interrupciones, estoy utilizando un 4550 en XC8 y proteus, y me guie de este ejemplo para hacer la interrupcion, les cuento lo que hago y que me pasa:

tengo un led en RA4 que se prende si tengo un estado dentro del programa activo, luego que esta encendido el led quiero poder apagarlo con un pulsador.

el pulsador lo monte en RB2, interrupcion de baja prioridad, y la interrupcion por flanco de subida o colocando el alto en el pin.

en el VOID MAIN defino esto:

    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2


tambien tengo definida esas patas como entradas y salidas:

    TRISB=0x1F; // RB2 entrada pulsado para silenciar alarma
    TRISA=0x6F; // RA4 SALIDA DE ALARMA

luego defino la funcion de interrupcion y variable volatil:

volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones


    void interrupt isr (void)//prototipo de la interrupción de baja prioridad
    {
        if(INTCON3bits.INT2IF==1)       //pregunta por bandera de interrupción
          {
           LATAbits.LATA4= ~LATAbits.LATA4;            // invierto estado del led
           myVolatileVariable++;
           INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
          }
    }


EStoy haciendo esto y no quiere apagar el led en RA4, el programa copila bien y no arroja ningun error pero nose que pasa, si pueden ayudarme estaria muy agradecido.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #346 en: 09 de Diciembre de 2015, 19:05:23 »
Tal ves te falta configurar las entradas RB4:0 Como digitales, en especial si tus fuses estan puestos para que puedan ser digital o analogicos esos

ADCON1 = 0X0F

Tambien intenta primero activar las interrupciones del modulo y como punto final activar las interrupciones globales, no activar la interrrupcion global y lluego configurar el modulo

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #347 en: 09 de Diciembre de 2015, 19:15:46 »
Tal ves te falta configurar las entradas RB4:0 Como digitales, en especial si tus fuses estan puestos para que puedan ser digital o analogicos esos

ADCON1 = 0X0F

Tambien intenta primero activar las interrupciones del modulo y como punto final activar las interrupciones globales, no activar la interrrupcion global y lluego configurar el modulo

tengo una pregunta con lo primero queme dices killer:

en el puerto A tengo todas entradas menos RA4 que es la salida del led

y la tengo digital como puse TRISA=0x6F; // RA4 SALIDA DE ALARMA
lo que me dices lo deberia poner asi:

ADCON1 = 0XEF ???

y lo otro que me dices seria solo dejar las las interrupciones del modulo osea estas:
INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #348 en: 09 de Diciembre de 2015, 20:15:06 »
El PORTA ( en su mayoria) + PORTB 4 a 0, son analogicos por defecto.

Es decir ante un reset, esos puertos se configuran como entradas todos (RA4 es una excepcion y queda como salida) y como analogicos. Si los tratas como digitales y queres leer, siempre vas a leer un 0, por lo tanto no funcionaria como "entrada". Para pasarlos a digital deberias modificar el valor de ADCON1, podes buscarlo en el datasheet y veras que con un 0x0F pondrias todos los posibles ANx como digitales, es decir: Configurados como entradas Y digitales. Tenes una tabla en el datasheet sobre eso

Tambien en ese PIC, hay un fuse que pone RB4 a 0 como digitales ignorando el valor del ADCON1. El fuse es : PBADEN de CONFIG3H

Distinto es cuando lo configuras como salida, al configurarlo como salida ignora los bits de ADCON1 y presenta a la salida el valor de LATx ( esto ocurre en estos PICs, los PIC16 por ahi es necesario ponerlos digital por igual, aunque no puedo hablar por todos los PIC16 )

Citar
y lo otro que me dices seria solo dejar las las interrupciones del modulo osea estas:

Sobre las interrupciones comente por que habias puesto esto:

Código: [Seleccionar]
    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2

Cuando deberia ser algo asi:

Código: [Seleccionar]
    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad

    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2
    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2

    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)

Es decir habilitar las interrupciones LUEGO de configurar las interrupciones que necesites

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #349 en: 09 de Diciembre de 2015, 21:51:54 »
gracias de nuevo KILLERJC, algo que no te comente esque estoy utilizando todo el puerto A como entradas, (AN0, AN1, AN2, AN3, AN4 y las dos entradas del cristal OSC1 y OSC2) y la RA4 es la única salida, y bueno si esta configurada como una salida porque si me prende el LED cuando me tiene que prender, el problema es que pareciera que no hace efecto la interrupción, ya modifique la configuración que me dijiste por prioridades, pero nada que puedo apagarlo, nose si de todos modos tengo que agregar el registro ADCON1 que me estas diciendo....

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #350 en: 09 de Diciembre de 2015, 23:06:21 »
A ver si me explico mejor. Si lo tenes como analogico no va a pasar de 0 a 1 o de 1 a 0 el pin, siempre va a leer 0. Por eso no entra a la interrupcion.
Ponelo como digital y va a poder realizarse eso. asi que si no usas el ADC directamente ponelo a todos como digitales con el registro ADCON1.

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #351 en: 12 de Diciembre de 2015, 19:16:00 »
A ver si me explico mejor. Si lo tenes como analogico no va a pasar de 0 a 1 o de 1 a 0 el pin, siempre va a leer 0. Por eso no entra a la interrupcion.
Ponelo como digital y va a poder realizarse eso. asi que si no usas el ADC directamente ponelo a todos como digitales con el registro ADCON1.

HOLA KILLERJC, de nuevo gracias.

Ya funciona la interrupcion, tenia que poner el fuse PBADEN en OFF como me recomendaste, tambien me faltaba poner en 1 el registro GILH de las interrupciones, me tuve que fijar en el diagrama de compuertas en el datasheet.

la interrupcion ya funciona =), pero tengo un nuevo problema....

EL PROGRAMA SE CUELGA cuando presiono el pulsador que activa la interrupción, (la pantalla lcd no muestra nada) y me muestra este warnning en proteus:

(PIC18 STACK)PC=0X30AE. Stack overflow is forcing device reset.

me parece que esto es porque cuando activo la interrupcion el programa se queda en la función de la interrupcion y no entra de nuevo al main, intente ponerle un return a la funcion de interrupcion para que se saliera pero nada, si pueden ayudarme estare muy agradecido....

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #352 en: 12 de Diciembre de 2015, 19:25:08 »
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #353 en: 12 de Diciembre de 2015, 19:46:06 »
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.

mira lo que encontre en el datasheet en la parte final de interrupciones KILLERJC

Context Saving During Interrupts:

During interrupts, the return PC address is saved on
the stack. Additionally, the WREG, STATUS and BSR
registers are saved on the Fast Return Stack. If a fast
return from interrupt is not used (see Section 5.3
“Data Memory Organization”), the user may need to
save the WREG, STATUS and BSR registers on entry
to the Interrupt Service Routine. Depending on the
user’s application, other registers may also need to be
saved. Example 9-1 saves and restores the WREG,
STATUS and BSR registers during an Interrupt Service
Routine.

pero ni idea de como habilitar el fast return stack... sigo leyendo un poco y dice que es con el registro MOVLB y MOVFF, sabes algo de esto? ya te paso el codigo igual...

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #354 en: 12 de Diciembre de 2015, 19:47:05 »
Podrias pasar de nuevo el codigo?.

Mas que eso es como si se llamara continuamente a una funcion y nunca se volviera, interrupcion dentro de otra interrupcion, muchas veces seguidas, lo cual es absurdo ya que al entrar se deshabilitan las mismas.
Y es C, con lo cual el tema de CALL - RETURN se manejan solos. Te piedo el codigo para probarlo yo en mi PC y ver cual es el problema.


// PIC18F4550 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>
#include "LCD_4bits.h"
#include <stdio.h>
#include "adc_4550.h"


// #pragma config statements should precede project file includes.
// Use project enums instead of#define for ON and OFF.

// CONFIG1L
#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator (HS))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)

// CONFIG2H
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config ICPRT = OFF      // Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)

void main (void)
{
   

    float presion1, presion2, presion3, presion4, presion5;
    float presion1_anterior = 0, presion2_anterior = 0, presion3_anterior = 0, presion4_anterior = 0, presion5_anterior = 0; // para que solo escriba en pantalla si cambia la presion
    char T[17]; // cadena de 16 caracteres incluyendo el final \0

    //TRISCbits.RC0=0;
    //TRISC=0X00;
    TRISB=0x1F; // RB2 entrada pulsado para silenciar alarma
    TRISA=0x6F; // RA4 SALIDA DE ALARMA
    //TRISE=0x0F; //entrada analogica #6 en RE1

    LCD_init();
   
    ADC_init(0x09  | ADC_10bit | ADC_FOSC32 | ADC_02TAD ); // 6 entradas analogicas

//ADC_init(ADC_AN01  | ADC_10bit | ADC_FOSC32 | ADC_02TAD );
   
//ADC_init(ADC_AN02 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

//ADC_init(ADC_AN03 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

//ADC_init(ADC_AN04 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

// ADC_init(ADC_AN05 | ADC_10bit | ADC_FOSC32 | ADC_02TAD );

    /*CONFIGURACION INTERRUPCION EN RB2*/

    RCONbits.IPEN = 1; // Activa modo alta y baja prioridad
    INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
    INTCONbits.GIEH=1;  //alto en ultima compuerta
    INTCON2bits.INTEDG2 = 1;//configura interrupcion por flanco de subida para la interrupcion en RB2

    INTCON3bits.INT2IE=1; // activa la interrupción externa por flanco del pin RB2
    INTCON3bits.INT2IP=0; // selecciona la interrupción de baja prioridad del pin  RB2
   
   

    /*CONFIGURACION INTERRUPCION EN RB2*/
   
    LCD_clear();

    while (1)
    {
     //presion = (float)ADC_get(0);  calculo de numero binario para voltaje analogico (se utilizo para hallar el numero binario para cada voltaje analogico

     

     presion1=(((float)ADC_get(0)/203.7221)-0.5)/0.01333333333;
     if (presion1<30)
     {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c ", presion1, 0x3C);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB5=1;
          LATAbits.LATA4=1;
         
         }
     }
     else if (presion1 >= 30 && presion1 <=40)
     {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c", presion1, 0x2D);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion1 != presion1_anterior)
         {
          sprintf(T, "%03.1f %c", presion1, 0x3E);
          LCD_gotoxy(0,0);
          LCD_puts(T);
          presion1 = presion1_anterior;
          LATBbits.LATB7=1;
         
         }
      }


     presion2=(((float)ADC_get(1)/203.7221)-0.5)/0.01333333333;
     if (presion2<30)
     {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c ", presion2, 0x3C);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion2 >= 30 && presion2 <=40)
     {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c", presion2, 0x2D);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion2 != presion2_anterior)
         {
          sprintf(T, "%03.1f %c", presion2, 0x3E);
          LCD_gotoxy(0,1);
          LCD_puts(T);
          presion2 = presion2_anterior;
          LATBbits.LATB7=1;
         
         }
      }
     
     presion3=(((float)ADC_get(2)/203.7221)-0.5)/0.01333333333;
     if (presion3<30)
     {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c ", presion3, 0x3C);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion3 >= 30 && presion3 <=40)
     {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c", presion3, 0x2D);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion3 != presion3_anterior)
         {
          sprintf(T, "%03.1f %c", presion3, 0x3E);
          LCD_gotoxy(0,2);
          LCD_puts(T);
          presion3 = presion3_anterior;
          LATBbits.LATB7=1;
         
         }
      }

     presion4=(((float)ADC_get(3)/203.7221)-0.5)/0.01333333333;
     if (presion4<30)
     {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c ", presion4, 0x3C);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion4 >= 30 && presion4 <=40)
     {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c", presion4, 0x2D);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion4 != presion4_anterior)
         {
          sprintf(T, "%03.1f %c", presion4, 0x3E);
          LCD_gotoxy(0,3);
          LCD_puts(T);
          presion4 = presion4_anterior;
          LATBbits.LATB7=1;
         
         }
      }

     presion5=(((float)ADC_get(4)/203.7221)-0.5)/0.01333333333;
     if (presion5<30)
     {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c ", presion5, 0x3C);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB5=1;
         
         }
     }
     else if (presion5 >= 30 && presion5 <=40)
     {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c", presion5, 0x2D);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB6=1;
          LATBbits.LATB5=0;
          LATBbits.LATB7=0;
         }
     }
      else
      {
         if(presion5 != presion5_anterior)
         {
          sprintf(T, "%03.1f %c", presion5, 0x3E);
          LCD_gotoxy(9,0);
          LCD_puts(T);
          presion5 = presion5_anterior;
          LATBbits.LATB7=1;
         }

      }
    /*LCD_gotoxy(0,0);
    LCD_puts("linea 1");
    LCD_gotoxy(0,1);
    LCD_puts("linea 2");
    LCD_gotoxy(0,2);
    LCD_puts("linea 3");
    LCD_gotoxy(0,3);
    LCD_puts("linea 4");*/
}
   
   
}

//volatile int myVolatileVariable=0;//variable para utilizar con las interrupciones


    void interrupt isr (void)//prototipo de la interrupción de baja prioridad
    {
        if(INTCON3bits.INT2IF==1)       //pregunta por bandera de interrupción
          {
           LATAbits.LATA4= 0;            // invierto estado del led
          //myVolatileVariable++;
           INTCON3bits.INT2IF = 0;  //limpia bandera y salimos
          }
        //return;
    }

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #355 en: 13 de Diciembre de 2015, 10:30:35 »
Bueno.. Ahi mire el programa y lo probe, solo probe la parte del sprintf, y todo lo del micro, nada de ADC/LCD, estos son los problemas que encontre, aunque voy a ir con tu problema primero:

- La interrupcion esta como "alta velocidad" ( le falta el low_priority), pero vos tenes definida la interrupcion como baja prioridad. Ademas tenes habilitada las 2 interrupciones, las de alta y las de baja cuando solo usarias la de baja:

Código: C
  1. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  2.     INTCONbits.GIEH=1;  //alto en ultima compuerta

En si el problema es el siguiente. la interrupcion de alta prioridad se encuentra en 0x0008 y la de baja en 0x0018, MPLAB no se por que pone todo el codigo a partir de la direccion 0x800 tal ves esperando un bootloader. Entonces cuando ocurre una interrupcion, catalogada como baja prioridad va a 0x0018, PERO tu call a la funcion de interrupcion se da en 0x0008, de esta forma primero que nada estas ejecutando NOP hasta que vuelve a las instrucciones de reset ( va de 0x0018 a 0x0800 ejecutando NOPs), lo feo es que si se habia ejecutado un CALL por ejemplo ( como para comparar los flotantes ) y se produce la interrupcion, ese CALL, nunca ejecuta un RETURN. LLenando el STACK poco a poco ya que jamas se saca nada, y eso termina en el STACK OVERFLOW que tenes.

- Mas problemas con tu programa:

- Comparacion:

Código: C
  1. presion1 = presion1_anterior;

Eso no tiene sentido por que siempre asignaria un 0 a presion1 y jamas daria igualdad entre lo anterior y presion1 e imagino que quisiste hacerlo al reves, es decir:

Código: C
  1. presion1_anterior = presion1;

- Repeticion de codigo... es terrible la cantidad de codigo que se repite y algunas condiciones que tampoco tienen sentido.
Podrias haber realizado con un for, todo eso, para cada una de las entradas, pero hiciste una por 1, tambien comprobas cosas que habias comprobado antes, como es el ejemplo de ver que es menos de 30 y luego en el else comparar si es mayor o igual, si ya hiciste antes esa comparacion, ¿por que nuevamente?. La otra tambien es la de preguntar siempre si es igual o no que el valor anterior. Un solo if fuera y esta listo.

Tu programa:

Código: C
  1. float presion[5], presion_anterior[5] = 0; // para que solo escriba en pantalla si cambia la presion
  2.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  3.     int i;

Código: C
  1. while (1)
  2.     {
  3.  
  4.         for(i=0;i<5;i++)
  5.         {
  6.             presion[i]=(((float)ADC_get(i)/203.7221)-0.5)/0.01333333333;
  7.             if(presion[i] != presion_anterior[i])
  8.             {
  9.                 terminacion = 0x3C;
  10.                 if (presion[i]<30)
  11.                 {
  12.                     LATBbits.LATB5=1;
  13.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  14.                 }
  15.                 else if (presion[i] <=40)
  16.                 {
  17.                     LATBbits.LATB6=1;
  18.                     LATBbits.LATB5=0;
  19.                     LATBbits.LATB7=0;
  20.                     terminacion = 0x2D;
  21.                 }
  22.                 else
  23.                 {
  24.                     LATBbits.LATB7=1;
  25.                 }
  26.                 sprintf(T, "%03.1f %c ", presion[i], terminacion);
  27.                 if (i==4) LCD_gotoxy(9,0);
  28.                 else LCD_gotoxy(0,i);
  29.                 LCD_puts(T);
  30.                 presion_anterior[i] = presion[i];
  31.             }
  32.          }
  33.     }

Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso.

Creo que la reduccion es poca, ya que lo que mas ocupa son otras cosas como lo de float y sprintf pero tenes:

    Program space        used  1642h (  5698) of  8000h bytes   ( 17.4%)

versus un 20%+ ocupado como lo tenias en tu programa. Y tal ves no sea necesario calcular todo, solo cuando sea necesario ademas, tenes que darte cuenta que la coma flotante para que se produzca una igualdad es bastante complejo. Por gusto probe con enteros :)

Código: C
  1. int presion[5], presion_anterior[5]; // para que solo escriba en pantalla si cambia la presion
  2.     float resultado;
  3.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  4.     short int i;

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 if (presion[i]<183)
  9.                 {
  10.                     LATBbits.LATB5=1;
  11.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  12.                 }
  13.                 else if (presion[i] <=210)
  14.                 {
  15.                     LATBbits.LATB6=1;
  16.                     LATBbits.LATB5=0;
  17.                     LATBbits.LATB7=0;
  18.                     terminacion = 0x2D;
  19.                 }
  20.                 else
  21.                 {
  22.                     LATBbits.LATB7=1;
  23.                 }
  24.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  25.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  26.                 if (i==4) LCD_gotoxy(9,0);
  27.                 else LCD_gotoxy(0,i);
  28.                 LCD_puts(T);
  29.             }
  30.          }

Una curiosidad que encontre.

Tiempos:

Comparacion, activar saidas, etc: 89 a 120 ciclos
Calculo: 1960 a 2000 ciclos ( Solo la linea con la matematica )
Pasarlo a texto: 11600 a 13800 ciclos ( Solo la linea del sprintf )

-------------------------

Una mejora para el calculo, simplificandolo:

Código: C
  1. resultado=((float)(test/2.71629)-37.5);

Ocupa 900 ciclos menos aproximadamente.
Floats de 24 bits, no de 32! Pero suficiente para la precision que estas buscando.
« Última modificación: 13 de Diciembre de 2015, 11:41:09 por KILLERJC »

Desconectado fernandogomav

  • PIC10
  • *
  • Mensajes: 32
Re:Mini curso "Programación en XC8"
« Respuesta #356 en: 13 de Diciembre de 2015, 21:27:14 »
Bueno.. Ahi mire el programa y lo probe, solo probe la parte del sprintf, y todo lo del micro, nada de ADC/LCD, estos son los problemas que encontre, aunque voy a ir con tu problema primero:

- La interrupcion esta como "alta velocidad" ( le falta el low_priority), pero vos tenes definida la interrupcion como baja prioridad. Ademas tenes habilitada las 2 interrupciones, las de alta y las de baja cuando solo usarias la de baja:

Código: C
  1. INTCONbits.GIEL = 1;// permitimos interrupciones de baja prioridad (Global Interrupt Enable Low)
  2.     INTCONbits.GIEH=1;  //alto en ultima compuerta

En si el problema es el siguiente. la interrupcion de alta prioridad se encuentra en 0x0008 y la de baja en 0x0018, MPLAB no se por que pone todo el codigo a partir de la direccion 0x800 tal ves esperando un bootloader. Entonces cuando ocurre una interrupcion, catalogada como baja prioridad va a 0x0018, PERO tu call a la funcion de interrupcion se da en 0x0008, de esta forma primero que nada estas ejecutando NOP hasta que vuelve a las instrucciones de reset ( va de 0x0018 a 0x0800 ejecutando NOPs), lo feo es que si se habia ejecutado un CALL por ejemplo ( como para comparar los flotantes ) y se produce la interrupcion, ese CALL, nunca ejecuta un RETURN. LLenando el STACK poco a poco ya que jamas se saca nada, y eso termina en el STACK OVERFLOW que tenes.

- Mas problemas con tu programa:

- Comparacion:

Código: C
  1. presion1 = presion1_anterior;

Eso no tiene sentido por que siempre asignaria un 0 a presion1 y jamas daria igualdad entre lo anterior y presion1 e imagino que quisiste hacerlo al reves, es decir:

Código: C
  1. presion1_anterior = presion1;

- Repeticion de codigo... es terrible la cantidad de codigo que se repite y algunas condiciones que tampoco tienen sentido.
Podrias haber realizado con un for, todo eso, para cada una de las entradas, pero hiciste una por 1, tambien comprobas cosas que habias comprobado antes, como es el ejemplo de ver que es menos de 30 y luego en el else comparar si es mayor o igual, si ya hiciste antes esa comparacion, ¿por que nuevamente?. La otra tambien es la de preguntar siempre si es igual o no que el valor anterior. Un solo if fuera y esta listo.

Tu programa:

Código: C
  1. float presion[5], presion_anterior[5] = 0; // para que solo escriba en pantalla si cambia la presion
  2.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  3.     int i;

Código: C
  1. while (1)
  2.     {
  3.  
  4.         for(i=0;i<5;i++)
  5.         {
  6.             presion[i]=(((float)ADC_get(i)/203.7221)-0.5)/0.01333333333;
  7.             if(presion[i] != presion_anterior[i])
  8.             {
  9.                 terminacion = 0x3C;
  10.                 if (presion[i]<30)
  11.                 {
  12.                     LATBbits.LATB5=1;
  13.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  14.                 }
  15.                 else if (presion[i] <=40)
  16.                 {
  17.                     LATBbits.LATB6=1;
  18.                     LATBbits.LATB5=0;
  19.                     LATBbits.LATB7=0;
  20.                     terminacion = 0x2D;
  21.                 }
  22.                 else
  23.                 {
  24.                     LATBbits.LATB7=1;
  25.                 }
  26.                 sprintf(T, "%03.1f %c ", presion[i], terminacion);
  27.                 if (i==4) LCD_gotoxy(9,0);
  28.                 else LCD_gotoxy(0,i);
  29.                 LCD_puts(T);
  30.                 presion_anterior[i] = presion[i];
  31.             }
  32.          }
  33.     }

Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso.

Creo que la reduccion es poca, ya que lo que mas ocupa son otras cosas como lo de float y sprintf pero tenes:

    Program space        used  1642h (  5698) of  8000h bytes   ( 17.4%)

versus un 20%+ ocupado como lo tenias en tu programa. Y tal ves no sea necesario calcular todo, solo cuando sea necesario ademas, tenes que darte cuenta que la coma flotante para que se produzca una igualdad es bastante complejo. Por gusto probe con enteros :)

Código: C
  1. int presion[5], presion_anterior[5]; // para que solo escriba en pantalla si cambia la presion
  2.     float resultado;
  3.     char T[17], terminacion; // cadena de 16 caracteres incluyendo el final \0
  4.     short int i;

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 if (presion[i]<183)
  9.                 {
  10.                     LATBbits.LATB5=1;
  11.                     if(!i) LATAbits.LATA4=1;        //Solo para canal0
  12.                 }
  13.                 else if (presion[i] <=210)
  14.                 {
  15.                     LATBbits.LATB6=1;
  16.                     LATBbits.LATB5=0;
  17.                     LATBbits.LATB7=0;
  18.                     terminacion = 0x2D;
  19.                 }
  20.                 else
  21.                 {
  22.                     LATBbits.LATB7=1;
  23.                 }
  24.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  25.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  26.                 if (i==4) LCD_gotoxy(9,0);
  27.                 else LCD_gotoxy(0,i);
  28.                 LCD_puts(T);
  29.             }
  30.          }

Una curiosidad que encontre.

Tiempos:

Comparacion, activar saidas, etc: 89 a 120 ciclos
Calculo: 1960 a 2000 ciclos ( Solo la linea con la matematica )
Pasarlo a texto: 11600 a 13800 ciclos ( Solo la linea del sprintf )

-------------------------

Una mejora para el calculo, simplificandolo:

Código: C
  1. resultado=((float)(test/2.71629)-37.5);

Ocupa 900 ciclos menos aproximadamente.
Floats de 24 bits, no de 32! Pero suficiente para la precision que estas buscando.

Primero que todo KILLERJC agradecerte porque el problema esta solucionado, ya la interrupción actúa y puedo apagar el LED con el pulsador, como dijiste me faltaba declarar la funcion de interrupcion como low_priority!! algo que queria comentarte, intente robarla sin el GIEH=1 y no funciona, solo funciona habilitando esa tambien.

-con lo de la comparacion:

presion1 = presion1_anterior;

aqui lo que trato de hacer es que no escriba en pantalla continuamente, es decir, que no realize el printf a menos que la presion cambie, osea el valor de la entrada analogica, esto es lo que trato de hacer, tu me diras si si esta bien o se puede hacer de otra manera, ademas tienes razon en que son coma flotante y es dificil que se cumpla la igualdad, mas bien creo que ese codigo esta de mas...

lo que me preguntas del porque volver a evaluar términos entre 30 y 40 y no solamente menores a 40, es porque es un ejemplo de el intervalo en donde las presiones se pueden considerar normales, por eso tengo tres intervalos..osea presiones menores a 30 realiza ciertas cosas, entre 30 y 40 esta normal y mayores a 40 altos...

te agradezco muchisimo el codigo de ejemplo que pones, pues veo que realiza lomismo pero en muchisimas menos lineas, bueno ya ves q no tengo tanta experiencia programando, voy aprediendo...=)

en mi programa, el que te pase, todas las presiones tienen los mismos intervalos pero era solo para probarlas, en realidad cada presion tiene intervalos diferentes porque medire diferentes gases, con los gases diferentes ya no podria aplicar el codigo con el for o si???

lo podria aplicar a los que sean iguales y a los diferentes como lo tenia no?'
me dijsite esto: Incluso si tenes que hacer una salida por cada uno seguiria asi el ejemplo. nomas que usaria otra funcion mas aparte de eso, eso fue lo que entendi...

ahora lo que hiciste en el segundo código que probaste con enteros, tendría que ver el valor digital del get(x) para el valor de mi presion, entiendo por esto que estar trabajando directamente en los intervalos con el valor digital de la conversión...no?

ahora lo de el printf una sola vez y el calculo de presion una sola vez con la variable terminacion para el caracter, es simplemente codigo en su estado puro, creo que hubiese necesitado unos meses mas para llegar a eso, de verdad muchas gracias KILLERJC..



y la verdad ya me estaba empezando a preocupar que se llena la memoria y me falta mucho por programar aun....



Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mini curso "Programación en XC8"
« Respuesta #357 en: 13 de Diciembre de 2015, 22:09:28 »
Citar
presion1 = presion1_anterior;

aqui lo que trato de hacer es que no escriba en pantalla continuamente, es decir, que no realize el printf a menos que la presion cambie, osea el valor de la entrada analogica, esto es lo que trato de hacer, tu me diras si si esta bien o se puede hacer de otra manera, ademas tienes razon en que son coma flotante y es dificil que se cumpla la igualdad, mas bien creo que ese codigo esta de mas...

2 cosas ahi:

Estas haciendo:

presion1 <- presion1_anterior

en ves de al reves, eso intente hacerte notar, como presion1_anterior inicializa a 0 y vos jamas lo cambias ( ya que tu asignacion estaba al reves, era lo mismo que poner:

presion1 = 0;

Con respecto a los flotantes, siempre que los uses, trata de jamas usar igualdades, siempre menor a o mayor a, es algo que me traje de python pero creo que se aplica aca tambien. Las representaciones binarias no son exactas y bueno puede parecer que son iguales pero que dentro en la representacion no lo son.

Citar
en mi programa, el que te pase, todas las presiones tienen los mismos intervalos pero era solo para probarlas, en realidad cada presion tiene intervalos diferentes porque medire diferentes gases, con los gases diferentes ya no podria aplicar el codigo con el for o si???

Si podes hacerlo. Suponete que fijamos 2 valores por cada "presion", podes utilizar un array de esta forma:

Código: C
  1. const int limites_presion[5][2] = {{10,20},{30,40},{50,60},{700,1000},{80,200}};

El const, te lo pone en flash, pero si ves que esta muy llena tu flash se lo sacas para que quede almacenado en la RAM. y reemplazas los valores de los if:

Código: C
  1. if (presion[i]<30)
  2.                 else if (presion[i] <=40)

por

Código: C
  1. if (presion[i] < limites_presion[i][0])
  2.                 else if (presion[i] <= limites_presion[i][1])

Con respecto a las salidas ya se complica un poco mas.
Voy a suponer por un momento que cada condicion.. es decir: Minimo, Medio, Maximo de cada presion son distintos.
Voy a intentar hacer un codigo facil para que te sea facil verlo. OJO! hay muchas formas mas de hacerlo, esto es solo para que veas una forma y se pueda ver facilmente. todo va a depender de que tan complejas sean tus funciones.

Código: C
  1. for(i=0;i<5;i++)
  2.         {
  3.             presion[i]=ADC_get(i);
  4.             if(presion[i] != presion_anterior[i])
  5.             {
  6.                 presion_anterior[i] = presion[i];
  7.                 terminacion = 0x3C;
  8.                 salida = i*3;
  9.                 if (presion[i] > limite_presion[i][0] && presion[i] <= limite_presion[i][1])
  10.                 {
  11.                         salida++
  12.                         terminacion = 0x2D;
  13.                 }
  14.                 else
  15.                 {
  16.                         salida+=2;
  17.                 }
  18.                 Cambiar_salida(salida);
  19.                 resultado=(((float)presion[i]/203.7221)-0.5)/0.01333333333;
  20.                 sprintf(T, "%03.1f %c ", resultado , terminacion);
  21.                 if (i==4) LCD_gotoxy(9,0);
  22.                 else LCD_gotoxy(0,i);
  23.                 LCD_puts(T);
  24.             }
  25.          }
  26.  
  27.  
  28.  
  29.  
  30. void Cambiar_salida(short valor_salida)
  31. {
  32.         switch(valor_salida)
  33.         {
  34.  
  35.         // i = 0
  36.         case 0:
  37.                 //Valor minimo (presion[0] < limite_presion[0][0])
  38.                 break;
  39.         case 1:
  40.                 //Valor medio (limite_presion[0][0] < presion[0] <= limite_presion[0][1])
  41.                 break;
  42.         case 2:
  43.                 //Valor maximo (presion[0] > limite_presion[0][1])
  44.                 break;
  45.  
  46.         // i = 1
  47.         case 3:
  48.                 //Valor minimo (presion[i] < limite_presion[i][0])
  49.                 break;
  50.         case 4:
  51.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  52.                 break;
  53.         case 5:
  54.                 //Valor maximo (presion[i] > limite_presion[i][1])
  55.                 break;
  56.  
  57.         // i = 2
  58.         case 6:
  59.                 //Valor minimo (presion[i] < limite_presion[i][0])
  60.                 break;
  61.         case 7:
  62.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  63.                 break;
  64.         case 8:
  65.                 //Valor maximo (presion[i] > limite_presion[i][1])
  66.                 break;
  67.  
  68.         // i = 3
  69.         case 9:
  70.                 //Valor minimo (presion[i] < limite_presion[i][0])
  71.                 break;
  72.         case 10:
  73.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  74.                 break;
  75.         case 11:
  76.                 //Valor maximo (presion[i] > limite_presion[i][1])
  77.                 break;
  78.  
  79.         // i = 4
  80.         case 12:
  81.                 //Valor minimo (presion[i] < limite_presion[i][0])
  82.                 break;
  83.         case 13:
  84.                 //Valor medio (limite_presion[i][0] < presion[i] <= limite_presion[i][1])
  85.                 break;
  86.         case 14:
  87.                 //Valor maximo (presion[i] > limite_presion[i][1])
  88.                 break;
  89.  
  90.         default:
  91.                 // Aca entra si existe un error. Deberia desactivar todo.
  92.  
  93.         }
  94.  
  95. }

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re:Mini curso "Programación en XC8"
« Respuesta #358 en: 17 de Diciembre de 2015, 15:37:40 »
Hola compañeros, ¿Podéis decirme porque este simple código no me funciona correctamente? En la simulación solo cambian los 8 bits de la parte baja del Timer y en consecuencia nunca se desborda.
Código: C
  1. #define _XTAL_FREQ 20000000
  2. #include <xc.h>
  3. #include <pic18f2550.h>
  4. #include "config.h"
  5.  
  6. void main(void)
  7. {
  8.     TRISBbits.RB0 = 0;  //Configuramos RB0 como salida
  9.     LATB0 = 0;  //Empezamos con el led apagado
  10.    
  11.     //CONFIGURAMOS TIMER1
  12.     INTCONbits.GIE = 0; //Desabilitamos todas las interrupciones
  13.     T1CONbits.RD16 = 1; //16 bit
  14.     T1CONbits.T1RUN = 0;
  15.     T1CONbits.T1CKPS1 = 0;  //Seleccionamos
  16.     T1CONbits.T1CKPS0 = 0;  //prescaler 1:1
  17.     T1CONbits.T1OSCEN = 0;  // Timer 1 Osc Enable: 0 = off, 1 = on
  18.     T1CONbits.T1SYNC = 0;
  19.     T1CONbits.TMR1CS = 0;   //Internal clock (Fosc/4)
  20.     T1CONbits.TMR1ON = 1;   //Enable Timer1
  21.     TMR1H = 0x00;
  22.     TMR1L = 0x00;
  23.     PIR1bits.TMR1IF = 0;     //Reset the interrupt flag
  24.    
  25.     while(!PIR1bits.TMR1IF){
  26.         LATB0 =~ LATB0;  
  27.     }
  28.     T1CONbits.TMR1ON = 0;   //Stop Timer1
  29. }

Saludos!
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re:Mini curso "Programación en XC8"
« Respuesta #359 en: 17 de Diciembre de 2015, 17:05:31 »
hola miguel, antes de nada decirte que te falta en tu programa un bucle principal, un while (1); si no lo tienes se ejecutara una vez y se acabo, por lo tanto debes agregarlo.


por otro lado cada vez que salta la interrupción debes recargar los registros y limpiar el flag de interrupcion.

es decir cada vez que se desborde debes reiniciarlo

Código: [Seleccionar]
TMR1IF=0;
TMR1 = (lo que le quieras poner, en tu caso 0) ;

o

Código: [Seleccionar]
TMR1IF=0;
TMR1H = 0;
TMR1L=0;

y ya de paso habilita su interrupción, si no me equivoco, eran los registros PIE1, TMR1IE

por cierto los fuses los has colocado en algún lado?

un saludo


 

anything