Forum: Mikrocontroller und Digitale Elektronik dsPIC33EV ECAN-DMA Problem


von Robin (Gast)


Lesenswert?

Hallo Leute,

ich arbeite jetzt schon ein paar tage an der Realisierung eines CAN 
Moduls mit dem dsPIC33EV32GM102 als Controller und einem MCP2551 als CAN 
Transceiver. Als zweiten Knoten auf dem Bus benutze ich ein MCP2515 Demo 
Board von Microchip. Nun zu meinem Problem. Leider funktioniert die CAN 
Kommunikation weder aus- noch eingehend. Ich habe viele der verfügbaren 
Beispielcodes implementiert, leider ohne Erfolg. Ich habe auch noch 
nicht ganz verstanden wie die Datenübertragung per DMA und das ECAN 
Peripherie-Modul sich gegenseitig triggern. So weit ich es verstanden 
habe, setzte ich das Bit für einen Message Transmit Request. Dieser löst 
einen Interrupt aus (der nicht aktiviert sein darf, so dass er vom DMA 
Controller abgearbeitet wird). Der DMA Controller beginnt dann die Daten 
aus dem RAM in den Transmit Buffer des CAN Moduls zu kopieren und löst 
nach Beenden des Vorgangs den DMA Interrupt aus. So weit ich verstehe 
mü+sste das CAN Modul dann automatisch die Daten an den Transceiver 
weiterreichen.

Mein CAN Bus ist für 125kbits/s konfiguriert und mein Controller läuft 
auf 35MHz. Sowohl Standard Messages, als auch Extended Messages werden 
unterstützt.

Empfangen werden sollen diverse verschiedene Adressen, deshalb sind so 
viele Filter konfiguriert.

Ich bin für jede Hilfe sehr dankbar!

Wünsche ein schönes Wochenende!

Robin

Hier mal noch der relevante Code:
Oscillator Konfiguration:
1
 
2
CLKDIVbits.PLLPRE = 0b0000; //Quartz oscillator frequency is divided by 2
3
    PLLFBDbits.PLLDIV = 0b000100001; //PLL feedback divides F_PLL by 35
4
    CLKDIVbits.PLLPOST = 0b01; //Further divides by 4 -> F_osc = 35MHz
5
    
6
    //built in unlock sequence for OSCCON high byte
7
    __builtin_write_OSCCONH(0x03); //New clock source is 0b011 (Primary Oscillator with PLL)
8
    
9
    //iniiate clock switching
10
    __builtin_write_OSCCONL(OSCCON | 0x01);
11
    
12
    // Wait for Clock switch to occur
13
    while (OSCCONbits.COSC!= 0b011);
14
    
15
    // Wait for PLL to lock
16
    while (OSCCONbits.LOCK!= 1);


Anlegen der Buffer:
1
 #define NUM_OF_ECAN_BUFFERS 16
2
3
4
__eds__ unsigned int canbuf[NUM_OF_ECAN_BUFFERS][8] 
5
__attribute__((eds,aligned(NUM_OF_ECAN_BUFFERS * 16))); //16 buffers with 8 words each (256 byte)


Relevanter Ausschnitt aus der Initialisierung:
1
//CAN
2
    C1CTRL1bits.REQOP = 0b100; //Switch to configuration mode
3
    while(C1CTRL1bits.OPMODE != 0b100); //Wait for operation mode to change
4
    
5
    C1CTRL1bits.WIN = 1; //filter window
6
    C1CTRL1bits.CSIDL = 0; //CAN module continues operation in device IDLE
7
    C1CTRL1bits.CANCKS = 0; //F_CAN is equal to F_P=17,5MHz
8
    C1CFG1bits.BRP = 0b000111; //T_Q is 2x7x1/F_CAN= 800ns 
9
    C1CFG1bits.SJW = 0b00; //SJW is 1T_Q
10
    C1CFG2bits.PRSEG = 0b100; //Prop segment is 3T_Q
11
    C1CFG2bits.SEG1PH = 0b100; //Segment 1 is 3T_Q
12
    C1CFG2bits.SEG2PH = 0b100; //Segment 2 is 3T_Q
13
    C1CFG2bits.SEG2PHTS = 0; 
14
    C1CFG2bits.SAM = 1; //Bus line is sampled three times per sample point
15
    C1CFG2bits.WAKFIL = 0; //CAN bus line filter is used for wake up
16
    C1FEN1 = 0x3FFF; //Enable Filter 0:13
17
    C1BUFPNT1 = 0xFFFF; //messages are received in FIFO buffer
18
    C1BUFPNT2 = 0xFFFF;
19
    C1BUFPNT3 = 0xFFFF;
20
    C1BUFPNT4 = 0x00FF;
21
    
22
    C1RXF0SIDbits.SID = 0b00000000001; //Filter 0
23
    C1RXF0SIDbits.EID = 0b00; //Filter 0 (Extended Identifier)
24
    C1RXF0EID = 0x0000; //Filter 0 (Extended Identifier)
25
    C1RXF1SIDbits.SID = 0b00000000010; //Filter 1
26
    C1RXF1SIDbits.EID = 0b00; //Filter 1 (Extended Identifier)
27
    C1RXF1EID = 0x0000; //Filter 1 (Extended Identifier)
28
    C1RXF2SIDbits.SID = 0b00000000011; //Filter 2
29
    C1RXF2SIDbits.EID = 0b00; //Filter 2 (Extended Identifier)
30
    C1RXF2EID = 0x0000; //Filter 2 (Extended Identifier)
31
    C1RXF3SIDbits.SID = 0b00000000100; //Filter 3
32
    C1RXF3SIDbits.EID = 0b00; //Filter 3 (Extended Identifier)
33
    C1RXF3EID = 0x0000; //Filter 3 (Extended Identifier)
34
    C1RXF4SIDbits.SID = 0b00000000101; //Filter 4
35
    C1RXF4SIDbits.EID = 0b00; //Filter 4 (Extended Identifier)
36
    C1RXF4EID = 0x0000; //Filter 4 (Extended Identifier)
37
    C1RXF5SIDbits.SID = 0b00000000110; //Filter 5
38
    C1RXF5SIDbits.EID = 0b00; //Filter 5 (Extended Identifier)
39
    C1RXF5EID = 0x0000; //Filter 5 (Extended Identifier)
40
    C1RXF6SIDbits.SID = 0b00000000111; //Filter 6
41
    C1RXF6SIDbits.EID = 0b00; //Filter 6 (Extended Identifier)
42
    C1RXF6EID = 0x0000; //Filter 6 (Extended Identifier)
43
    C1RXF7SIDbits.SID = 0b00000001000; //Filter 7
44
    C1RXF7SIDbits.EID = 0b00; //Filter 7 (Extended Identifier)
45
    C1RXF7EID = 0x0000; //Filter 7 (Extended Identifier)
46
    C1RXF8SIDbits.SID = 0b00000001001; //Filter 8
47
    C1RXF8SIDbits.EID = 0b00; //Filter 8 (Extended Identifier)
48
    C1RXF8EID = 0x0000; //Filter 8 (Extended Identifier)
49
    C1RXF9SIDbits.SID = 0b00000001010; //Filter 9
50
    C1RXF9SIDbits.EID = 0b00; //Filter 9 (Extended Identifier)
51
    C1RXF9EID = 0x0000; //Filter 9 (Extended Identifier)
52
    C1RXF10SIDbits.SID = 0b0000001011; //Filter 10
53
    C1RXF10SIDbits.EID = 0b00; //Filter 10 (Extended Identifier)
54
    C1RXF10EID = 0x0000; //Filter 10 (Extended Identifier)
55
    C1RXF11SIDbits.SID = 0b00000001100; //Filter 11
56
    C1RXF11SIDbits.EID = 0b00; //Filter 11 (Extended Identifier)
57
    C1RXF11EID = 0x0000; //Filter 11 (Extended Identifier)
58
    C1RXF12SIDbits.SID = 0b00000001101; //Filter 12
59
    C1RXF12SIDbits.EID = 0b00; //Filter 12
60
    C1RXF12EID = 0x0000; //Filter 12
61
    C1RXF13SIDbits.SID = 0b00000001110; //Filter 13
62
    C1RXF13SIDbits.EID = 0b00; //Filter 13 (Extended Identifier)
63
    C1RXF13EID = 0x0000; //Filter 13 (Extended Identifier)
64
    
65
    C1FMSKSEL1 = 0x0000; //Mask0 determines the acceptance mask for all used filters
66
    C1FMSKSEL2 = 0x0000;
67
    C1RXM0SID = 0xFFF7; //All identifier digits are relevant, standard fames and extended frames are receivable
68
    C1RXM0EID = 0xFFFF;
69
    
70
    C1CTRL1bits.WIN = 0; //buffer window   
71
    C1FCTRLbits.DMABS = 0b100; //16 DMA buffers in RAM
72
    C1FCTRLbits.FSA = 0b00001; // FIFO area from TRB1 to RB15
73
    C1TR01CONbits.TXEN0 = 1; //Set TRB0 as transmit buffer
74
    IEC4bits.C1TXIE = 0; //deactivate interrpt processing by CPU
75
    IEC2bits.C1RXIE = 0;
76
    
77
    //DMA
78
    DMA0CONbits.AMODE = 0b10; //Peripheral indirect mode
79
    DMA0REQbits.IRQSEL = 0b00100010; //Connect to CAN RX peripheral
80
    DMA0PAD = (volatile unsigned int) &C1RXD; //Read from CAN1 RX register (address) 
81
    IEC0bits.DMA0IE = 1; //Enable interrupt for DMA channel 0
82
    DMA0CNT = 7; //8 words to be transmitted
83
    DMA1CONbits.AMODE = 0b10; //Peripheral indirect mode
84
    DMA1CONbits.DIR = 1; //Channel 1 reads data from RAM to CAN
85
    DMA1REQbits.IRQSEL = 0b01000110; //Connect to CAN TX peripheral
86
    DMA1PAD = (volatile unsigned int) &C1TXD; //Writes to CAN1 TX register (address)
87
    IEC0bits.DMA1IE = 1; //Enable interrupt for DMA channel 1
88
    DMA1CNT = 7; //8 words to be transmitted
89
    
90
    DMA0STAL = (unsigned int) &canbuf; //CAN receive FIFO buffer (16 buffer, 8 words each)
91
    DMA0STAH = 0x0000;
92
    DMA1STAL = (unsigned int) &canbuf;
93
    DMA1STAH = 0x0000;
94
    
95
    DMA0CONbits.CHEN = 1; //Enable DMA channel 0 for CAN RX
96
    DMA1CONbits.CHEN = 1; //Enable DMA channel 1 for CAN TX
97
    
98
    C1CTRL1bits.REQOP = 0b000; //Switch to normal CAN operation mode
99
    while(C1CTRL1bits.OPMODE != 0b000); //Wait for opeation mode to change
100
    
101
    //MUST be last operation here
102
    IFS1bits.CNIF = 0; //Reset all used interrupt flags
103
    IFS0bits.DMA0IF = 0;
104
    IFS0bits.DMA1IF = 0;
105
    IFS0bits.T1IF = 0;
106
    IFS2bits.C1RXIF = 0;
107
    IFS4bits.C1TXIF = 0;
108
    INTCON2bits.GIE = 1; //Global interrupt enable


Die Funktion die Nachrichten versendet:
1
bool SendMessage(uint16_t data_bytes[])
2
{
3
    /*      CAN data frame                                                     *
4
     *                                                                         *
5
     * Word 0:                                                                 *
6
     * bit 13-15    unimplemented                                              *
7
     * bit 2-12     Standard Identifier (SID)                                  *
8
     * bit 1        SRR - Substitute Remote Request bit                        *
9
     *              0 (normal message) - 1 (request remote message)            *
10
     *              MUST be 1 for extended message format                      *
11
     * bit 0        IDE bit - Identifier Extension bit                         *
12
     *              0 (standard message format) - 1 (extended message format)  *
13
     *                                                                         *
14
     * Word 1:                                                                 *
15
     * bit 12-15    unimplemented                                              *
16
     * bit 0-11     Extended Identifier (EID)                                  *
17
     *                                                                         *
18
     * Word 2:                                                                 *
19
     * bit 10-15    Extended Identifier (EID)                                  *
20
     * bit 9        Remote Transmission Request (RTR)                          *
21
     *              0 (normal message) - 1 (request remote transmission)       *
22
     *              IGNORED for standard message format                        *
23
     * bit 8        RB1 bit - MUST be set to 0                                 *
24
     * bit 5-7      unimplemented                                              *
25
     * bit 4        RB0 - MUST be set to 0                                     *
26
     * bit 0-3      Data Length Code - Numnber of bytes to send                * 
27
     *                                                                         *
28
     * Word 3:                                                                 *
29
     * bit 8-15     message byte 1                                             *
30
     * bit 0-7      message byte 0                                             *       
31
     *                                                                         *
32
     * Word 4:                                                                 *
33
     * bit 8-15     message byte 3                                             *
34
     * bit 0-7      message byte 2                                             *       
35
     *                                                                         *
36
     * Word 5:                                                                 *
37
     * bit 8-15     message byte 5                                             *
38
     * bit 0-7      message byte 4                                             *       
39
     *                                                                         *
40
     * Word 6:                                                                 *
41
     * bit 8-15     message byte 7                                             *
42
     * bit 0-7      message byte 6                                             *       
43
     *                                                                         *
44
     * Word 7:                                                                 *
45
     * bit 0-15     unimplemented                                              *      
46
     *                                                                        */
47
    
48
    
49
    unsigned int i, k, n;
50
    unsigned int j = 0;
51
    unsigned int number_of_bytes = sizeof(data_bytes)+1;
52
    
53
    n = (number_of_bytes/8)+1; //determine how many messages are needed
54
    if(number_of_bytes % 8 == 0) n--;
55
    for(k=0;k<n;k++) //send n messages 
56
    {
57
        for(i=0;i<8;i++) canbuf[0][i] = 0; //reset send buffer
58
59
        //save message to buffer
60
        canbuf[0][0] = (SID_OF_MAIN_CONTROLLER << 2) | 0x0003; //SID and send extended message 
61
        canbuf[0][1] = 0x000; //write EID
62
        if((number_of_bytes - k*8) <= 8) canbuf[0][2] = number_of_bytes;
63
        else canbuf[0][2] = 0x0008; //number of bytes to send
64
    
65
        if(canbuf[0][2] % 2 != 0) //if odd number of bytes to send write highest one out of normal flow
66
        {
67
            canbuf[0][3+(canbuf[0][2]/2)] = data_bytes[number_of_bytes - 1];
68
        }
69
        
70
        for(i=0;i<(canbuf[0][2]/2);i++)
71
        {
72
            canbuf[0][i+3] = data_bytes[j+1] << 8; //place upper byte
73
            canbuf[0][i+3] = canbuf[0][i+3] | (data_bytes[j] & 0x00FF); //place lower byte  
74
            j = j+2;
75
        }
76
        
77
        C1TR01CONbits.TXREQ0 = 1; //request message sending
78
    
79
        while(C1TR01CONbits.TXREQ0 == 1 && C1ECbits.TERRCNT == 0); //wait for transmission
80
        if(C1TR01CONbits.TXABT0 != 0 || C1ECbits.TERRCNT != 0)
81
        {
82
            C1ECbits.TERRCNT = 0;
83
            C1TR01CONbits.TXABT0 = 0;
84
            return false;
85
        }
86
    }
87
    
88
    return true; //messages sent without errors
89
}

Und zu guter Letzt die relevanten ISRs:
1
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
2
{
3
    if(DMAPWCbits.PWCOL0 == 1) //write collision detect
4
    {
5
        DMAPWCbits.PWCOL0 = 0; //clear write collison bit
6
    }
7
    
8
    else if(DMARQCbits.RQCOL0 == 1) //user force and interrupt based collision detect
9
    {
10
        DMARQCbits.RQCOL0 == 0; //clear error bit
11
    }
12
    
13
    else if(C1RXOVF1 != 0) //tried to write to already full FIFO buffer
14
    {
15
        C1RXOVF1 = 0; //reset overflow flag
16
    }
17
    
18
    else if(C1ECbits.RERRCNT != 0) //receive error bit counter
19
    {
20
        C1ECbits.RERRCNT = 0; //reset counter
21
    }
22
    
23
    else //message received correctly
24
    {
25
        canmsg = true;
26
        
27
    }
28
    
29
    IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag 
30
    return;
31
}
32
33
void __attribute__((interrupt, no_auto_psv)) _DMA1Interrupt(void)
34
{
35
    IFS0bits.DMA1IF = 0;
36
    return;
37
}

von Robin (Gast)


Lesenswert?

Ich habe noch die Konfiguaration des Input und Output Mappings 
vergessen:
1
//PORTB
2
    ANSELB = 0x0000; //Port B is all digital
3
    TRISB = 0b0000111111100100; //RB15:12 are outputs, RB11:5 are inputs, RB4:3 are outputs, RB2 is input, RB1:0 are outputs
4
    CNPUB = 0b0000111110000000; //Enable internal pull-up resistors on RB11:7
5
    CNENBbits.CNIEB1 = 1; //Enable Change of State interrupt for RB1
6
    CNENBbits.CNIEB11 = 1; //Enable Change of State interrupt for RB11 (when output module is changed ID4 bit always changes)
7
    IEC1bits.CNIE = 1; //globally enable change of state interrupt
8
    RPINR26bits.C1RXR = 0b0100010; //CAN1 RX tied to RPI34
9
    RPOR0bits.RP35R = 0b001110; //CAN1 TX tied to RP35    
10
    LATBbits.LATB4 = 0; //Disable digital output

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.