3 votos

Migrado de C18 a Hi-Tech C 18.. Interrupción no funciona

Aquí está mi código fuente. Este código funciona perfectamente en el compilador C18. No hasta que migré a Hi Tech C. No entra en la rutina de servicio de interrupción. Además, de alguna manera corrompió sid variable pasada a una función. En lugar de pasar un valor de 0x501, pasó 0x000. ¿Hay algo que me haya perdido en la configuración de una interrupción?

    #include <p18f25k80.h>
    #include <stdio.h>
    #include "ect_2014_debugger.h"
    #include "ect_2014_can.h"

    //#pragma config CONFIG1L = 0x15
    __CONFIG(1, RETEN_OFF & INTOSCSEL_HIGH & SOSCSEL_DIG & XINST_OFF);
    //#pragma config CONFIG1H = 0x92
    __CONFIG(2, FOSC_HS2 & PLLCFG_ON & FCMEN_OFF & IESO_ON);
    //#pragma config CONFIG2L = 0x78
    __CONFIG(3, PWRTEN_ON & BOREN_OFF & BORV_3 & BORPWR_ZPBORMV);
    //#pragma config CONFIG2H = 0x7C
    __CONFIG(4, WDTEN_OFF & WDTPS_1048576);
    //#pragma config CONFIG3H = 0x89
    __CONFIG(5, CANMX_PORTB & MSSPMSK_MSK7 & MCLRE_ON);
    //#pragma config CONFIG4L = 0x80
    __CONFIG(6, STVREN_OFF & BBSIZ_BB1K);
    //#pragma config CONFIG5L = 0xF
    __CONFIG(7, CP0_OFF & CP1_OFF & CP2_OFF & CP3_OFF);
    //#pragma config CONFIG5H = 0xC0
    __CONFIG(8, CPB_OFF & CPD_OFF);
    //#pragma config CONFIG6L = 0xF
    __CONFIG(9, WRT0_OFF & WRT1_OFF & WRT2_OFF & WRT3_OFF);
    //#pragma config CONFIG6H = 0xE0
    __CONFIG(10, WRTC_OFF & WRTB_OFF & WRTD_OFF);
    //#pragma config CONFIG7L = 0xF
    __CONFIG(11, EBTR0_OFF & EBTR1_OFF & EBTR2_OFF & EBTR3_OFF);
    //#pragma config CONFIG7H = 0x40
    __CONFIG(12, EBTRB_OFF);

    /* CAN Header */
    // CAN = PORTB
    #define SID_CAN1 0x500
    #define SID_CAN2 0x501
    #define NOMASK 0x7FF

    void interrupt ISR(void) {
        unsigned char rxbuf[8] = {0};
        unsigned int sid = 0, dlc = 0, i = 0;
        unsigned char rtr = 0;

        if (PIR5bits.RXB0IF && PIE5bits.RXB0IE) {
            printf("Interrupt inside\n\r");
            rtr = receive_can_msg_rxb0(rxbuf, &sid, &dlc); // Automatically clears the interrupt flag.
            if (!rtr) { // Data Frame
                if (sid == SID_CAN2) {
                    printf("SID = %x\n\rDLC = %d\n\r", sid, dlc);
                    for (i = 0; i < 8; i++)
                        printf("rxbuf[%d] = %d\n\r", i, rxbuf[i]);
                    printf("\n\r\n\r");
                }
            }
       }
    }
    //void interrupt ISR(void);
    void main() {
        unsigned int sid[2] = {SID_CAN2, 0};
        unsigned int mask[2] = {NOMASK, NOMASK};
        initUART(1); // Used for debugging
        RCONbits.IPEN = 0;  // Disable Priority Interrupts
        initCAN(&sid[0], mask); // SID = 0x501; MASK = NOMASK

        while (1);
    }

Esta es la función initCAN:

    void initCAN(unsigned int * sid, unsigned int * mask) {
            PIE5bits.RXB0IE = 0;
            PIE5bits.RXB1IE = 0;
            char i = 0;
            // 1. Initial LAT and TRIS bits for RX and TX CAN.
            TRISBbits.TRISB2 = 0; // TX
            TRISBbits.TRISB3 = 1; // RX
            LATBbits.LATB2 = 0; // Initialize 0 for TX
            // 2. Ensure that the ECAN module is in Configuration Mode
            /* CANCON is the CAN Control Register */
            CANCONbits.REQOP = 4; // REQOP<2:0> is a group of 3 bits; ensures that ECAN module
        #ifdef CAN_DEBUGGER
            printf("******* ECAN Module Initialization *******\n\r");
            printf("The ECAN Module is currently requesting to be in configuration mode.\n\r");
        #endif
            while (CANSTATbits.OPMODE != 4);
            // A request to configuration mode might not be honored immediately, as do to loopback,
            // disable, and etc. It is a good practice though to wait until the request to configuration
            // mode is completed.
        #ifdef CAN_DEBUGGER
            printf("The ECAN Module is now in configuration mode.\n\r");
        #endif
            // 3. Select ECAN Operational Mode.
            /* ECANCON is the Enhanced CAN Control Register.*/
            ECANCONbits.MDSEL = 0; // Configures the ECAN module to mode 0.
            // 4. Set up the Baud Rate registers.
            // Sync Jump Width is subtracted from Phase_seg2 or added to phase_seg1 to synchronize itself
            // to the data bit to be sampled.
            CIOCONbits.ENDRHI = 1; // 0 - Transcieverless CAN; 1 - Transciever CAN
            CIOCONbits.CLKSEL = 0; // Use the PLL as the CAN clock source, 64MHz
            // FOSC = 64 Mbps; Tosc = 15.625ns
            BRGCON1bits.BRP = 1; // Tq(us) = (2*(1+1))/64MHz = 62.5 ns
            // Nominal Bit Time = Tq*sigma
            // sigma = 1us/62.5ns = 16Tq
            BRGCON1bits.SJW = 0; // SJQ = 1Tq is typically enough as shown in the datasheet.
            BRGCON2bits.SEG2PHTS = 1; // Seg_phase 2 length = Freely Programmable
            BRGCON2bits.SAM = 0; //Bus line is sampled once at the sample point
            BRGCON2bits.SEG1PH = 0b111; //Phase segment 1 = 8TQ
            BRGCON2bits.PRSEG = 0b000; //Propagation segment = 1TQ
            BRGCON3bits.SEG2PH = 0b101; //Phase segment 2 = 6TQ
            // Verifying the baud rate configuration..
            // 1+8+1+6 = 16Tq.
            // Prop_Seg (1) + Phase_Seg1 (8) >= Phase_seg 2 (6) : TRUE
            // Phase_seg2(6) >= Sync Jump Width(1) : TRUE

            // 5. Set up the Filter and Mask Registers
            RXB0CON = 0; // Receive buffer is open to new messages; Receive all messages filtered dependent on
            // EXIDEN bit;
            RXB1CON = 0; // Same as RXB0CON.

        //    // Initialize Acceptance Filters and Masks to 0x00:
            RXF0SIDH = 0; // SID10 to SID3
            RXF0SIDL = 0; // SID2 to SID0; Standard frame
            RXF1SIDH = 0;
            RXF1SIDL = 0;
            RXF2SIDH = 0;
            RXF2SIDL = 0;
            RXF3SIDH = 0;
            RXF3SIDL = 0;
            RXF4SIDH = 0;
            RXF4SIDL = 0;
            RXF5SIDH = 0;
            RXF5SIDL = 0;
            RXM0SIDH = 0xFF;
            RXM0SIDL = 0xFF;
            RXM1SIDH = 0xFF;
            RXM1SIDL = 0xFF;
            // Acceptance Filters (RXF0 and RXF1) and filter mask (RXM0) are associated with RXB0.
            // Acceptance Filters (RXF2 to RXF5) and filter mask (RXM1) are associated with RXB1.
            for (i = 0; i < 5 && *sid != 0; i++) {
                if (i == 0) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB0 **\n\r");
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF0SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF0SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF0EIDH = 0;
                    RXF0EIDL = 0;
                } else if (i == 1) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF1SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF1SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF1EIDH = 0;
                    RXF1EIDL = 0;
                } else if (i == 2) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB1 **\n\r");
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF2SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF2SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF2EIDH = 0;
                    RXF2EIDL = 0;
                } else if (i == 3) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF3SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF3SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF3EIDH = 0;
                    RXF3EIDL = 0;
                } else if (i == 4) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF4SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF4SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF4EIDH = 0;
                    RXF4EIDL = 0;
                } else if (i == 5) {
        #ifdef CAN_DEBUGGER
                    printf("Message Acceptance Filter %d: %x\n\r", i, *sid);
        #endif
                    RXF5SIDH = (*sid & 0x7F8) >> 3; // SID10 to SID3
                    RXF5SIDL = (*sid++ & 0x007) << 5; // SID2 to SID0; Standard frame
                    RXF5EIDH = 0;
                    RXF5EIDL = 0;
                }
            }

            for (i = 0; i < 2 && *mask != 0; i++) {
                if (i == 0) {
        #ifdef CAN_DEBUGGER
                    printf("\n\r** Associated with RXB0 **\n\r");
                    printf("Message Acceptance Mask %d: %x\n\r", i, *mask);
        #endif
                    //Mask 0
                    RXM0SIDH = (*mask & 0x7F8) >> 3;
                    RXM0SIDL = (*mask++ & 0x007) << 5;
                    RXM0EIDH = 0xFF;
                    RXM0EIDL = 0xFF;
                } else if (i == 1) {
        #ifdef CAN_DEBUGGER
                    printf("** Associated with RXB1 **\n\r");
                    printf("Message Acceptance Mask %d: %x\n\r", i, *mask);
        #endif
                    //Mask 1
                    RXM1SIDH = (*mask & 0x7F8) >> 3;
                    RXM1SIDL = (*mask++ & 0x007) << 5;
                    RXM1EIDH = 0xFF;
                    RXM1EIDL = 0xFF;
                }
            }
            // 6. Set the ECAN Module to normal mode or any other mode required by the application logic.
            CANCONbits.REQOP = 0; // Normal Mode
            while (CANSTATbits.OPMODE != 0); // Wait until ECAN module is configured as normal mode.
        #ifdef CAN_DEBUGGER
            printf("******* ECAN Module is now operating in normal mode *******\n\r");
        #endif
            // (Optional) Enable interrupts.
            PIR5bits.RXB0IF = 0;
            PIR5bits.RXB1IF = 0;
            PIE5bits.RXB0IE = 1;
            PIE5bits.RXB1IE = 1;
            INTCONbits.GIE = 1;
            INTCONbits.PEIE = 1;
        #ifdef CAN_DEBUGGER
            printf("******* Interrupts are also enabled! *******\n\r");
        #endif
        }

Y aquí está el código fuente C18:

    #include <p18f25k80.h>
    #include <stdio.h>
    #include "ect_2014_debugger.h"
    #include "ect_2014_can.h"
    #pragma config RETEN = OFF    //Ultra low-power regulator is Disabled
    #pragma config XINST = OFF    //Extended Instruction Set Disabled
    #pragma config IESO = ON      //Two speed start-up mode enable
    #pragma config FOSC = HS2     //HS oscillator (High power, 16 MHz - 25 MHz)
    #pragma config PLLCFG = ON    //Enable PLL x4
    #pragma config PWRTEN = ON    //Enable Power Up timer
    #pragma config BOREN = OFF    //Disable Brown Out Detection
    #pragma config WDTEN = OFF    //Disable Watch Dog Timer
    #pragma config MCLRE = ON     //Enable MCLR
    #pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF,CPB = OFF,CPD = OFF
    #pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF,WRTC = OFF,WRTB = OFF,WRTD = OFF
    #pragma config EBTR0 = OFF,EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF,EBTRB = OFF
    #pragma config SOSCSEL = DIG   //RC0 and RC1 are digital IO

    /* CAN Header */
    #pragma config CANMX = PORTB  // ECAN TX and RX pins are located on RB2 and RB3, respectively
    #define SID_CAN1 0x500
    #define SID_CAN2 0x501
    #define NOMASK 0x7FF

    void isr(void);
    #pragma code high_vector=0x08

    void interrupt_at_high_vector(void) {
        _asm GOTO isr _endasm
    }
    #pragma code
    #pragma interrupt isr

    void isr(void) {
        unsigned char rxbuf[8] = {0};
        unsigned int sid = 0, dlc = 0, i = 0;
        unsigned char rtr = 0;
        if (PIR5bits.RXB0IF && PIE5bits.RXB0IE) {
            printf((const far rom char*) "Interrupt inside\n\r");
            rtr = receive_can_msg_rxb0(rxbuf, &sid, &dlc); // Automatically clears the interrupt flag.
            if (!rtr) { // Data Frame
                if (sid == SID_CAN2) {
                    printf((const far rom char*) "SID = %x\n\r", sid);
                    for (i = 0; i < 8; i++)
                        printf((const far rom char *) "rxbuf[%d] = %d\n\r", i, rxbuf[i]);
                    printf((const far rom char *) "\n\r\n\r");
                }
            }
        }
    }

    void main() {

        unsigned int sid[2] = {SID_CAN2, 0};
        unsigned int mask[2] = {NOMASK, NOMASK};
        int i,j;
        initUART(1); // Used for debugging
        initCAN(sid, mask); // SID = 0x501; MASK = NOMASK

        while (1)
            for (i = 0; i < 1000; i++)
                for (j = 0; j < 1000; j++)
                    if (i == 999 && j == 999)
                        printf("RXB0IF = %d\n\rRXB1IF = %d\n\rRXFUL = %d\n\r", PIR5bits.RXB0IF, PIR5bits.RXB0IF,RXB0CONbits.RXFUL);

    }

1voto

AdminAlive Puntos 248

Por favor, compruebe si está activando el bit IPEN (IPEN significa función de prioridad de interrupción). Si está activado, debe declarar la rutina de servicio de interrupción con una prioridad:

void interrupt low_priority LowISR( void )
{

}

void interrupt high_priority HighISR( void )
{ 

}

Vea el siguiente ejemplo de mi función EcanInit para el 18F26K80:

// Configure the port pins for CAN operation
TRISBbits.TRISB3 = 1;   // CANRX in - Changed to accomodate 18F4680 - CG
TRISBbits.TRISB2 = 0;   // CANTX out

// Establish the ECAN interrupt priorities and enable the ECAN receive interrupt.       
BIE0 = ECAN_BUFFER_INTERRUPT_ENABLE;
PIE5 = ECAN_RX_INT_ENABLE_FIFO | ECAN_ERROR_INT_ENABLE;

RCONbits.IPEN = 1;

IPR5 &= 0xE0;
IPR5 |= ECAN_INTERRUPT_PRIORITY;

Espero que esto ayude.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X