CAN-Bus: Tx-Rx-Problem (AT90CAN128)

OP #607850
Lesenswert?

Hi zusammen,

ich bin so langsam mit meinem Latein am Ende, wobei mein Problem 
folgendes ist:

Ich habe 2 Boards mit je einem AT90CAN128, wovon einer Sender, der 
andere Empfänger ist. Anfangs möchte ich über CAN ein einfaches 
Datenbyte senden, welches empfangen und angezeigt wird. (Später, wenn 
alles funktioniert, schicke ich mehrere Bytes). Das Ganze geschieht bei 
100 kbit/s. Mein benutzter C-Compiler ist CodeVision. Für Sender und 
Empfänger arbeite ich je mit einem Message Object (MOb), und zwar MOb2. 
Die Mask-Register für den Empfänger sind so geschaltet, dass sie alle 
Identifier durchlassen.

Auf der Sendeseite überprüfe ich in 1. Linie, ob das TXOK-flag gesetzt 
wird. Da dies jedoch nicht passiert ist, habe ich auch auf andere Flags 
getestet und sehe nun, dass auf der Sendeseite BERR (bit errors) 
auftreten und letztendlich ein BOFF-flag (bus off) gesetzt wird. 
Letzteres macht ja auch Sinn, da CAN immer wieder erneut versucht zu 
senden, bis der Fehlercounter so hoch ist, dass der Teilnehmer 
abschaltet wird.

Auf beiden Seiten habe ich einen nahezu identischen Code. Natürlich 
überprüfe ich für den Sender das TXOK-flag und für den Empfänger das 
RXOK-flag. Entsprechende Interrupt-enable-Bits habe ich jeweils im 
CANGIE-Register gesetzt.

Das Sendeprogramm geht in die Interrupt-Service-Routine (schließlich 
werden die Flags BERR und BOFF gesetzt). Das Empfangsprogramm erreicht 
seine ISR jedoch nie (was ich komisch finde, denn die Programme sind 
gleich aufgebaut, zumindest müsste irgendein Fehler-Interrupt ausgelöst 
werden meiner Meinung nach...).

Ich habe meinen Empfangscode hier im Anschluss mal gepostet. Der 
Sendecode unterscheidet sich nur durch die darunter gepostete 
can_tx()-Funktion anstelle von can_rx(). (und natürlich durch die 
entsprechenden Registereinstellungen, die nun auf Tx und nicht Rx 
gesetzt sind.)


Sieht von euch jemand einen Bock in meinem Programm oder hat einen Tipp 
für mich? Üebr jede Hilfe bin ich sehr dankbar...

Viele Grüße, Xine
1
 
2
interrupt [CAN_IT] void can_isr(void)   // CANIT interrupt vector code
3
{
4
unsigned char save_canpage;
5
save_canpage = CANPAGE;                
6

7
CANPAGE = (1 << MOBNB1);                // Select MOb2.   
8

9
if (CANSTMOB & (1 << RXOK))            
10
        {
11
        can_data = CANMSG;  
12
        lcd_int2bin(can_data);          // Show received data byte
13
        CANSTMOB &= (~(1 << RXOK));  
14
        }       
15
if (CANGSTA & (1 << BOFF))              // Bus off error flag            
16
        {
17
        lcd_putsf("Bus off");
18
        lcd_int2bin(CANREC);            // Show CANTEC register 
19
        CANGSTA &= (~(1 << BOFF));
20
        } 
21
if (CANSTMOB & (1 << DLCW))    // DLC warning flag
22
        {
23
        lcd_putsf("DLCW"); 
24
        CANSTMOB &= (~(1 << DLCW));
25
        delay_ms(200);     
26
        }  
27
if (CANSTMOB & (1 << CERR))    // CRC error flag
28
        {
29
        lcd_putsf("CERR"); 
30
        CANSTMOB &= (~(1 << CERR));
31
        delay_ms(200);     
32
        } 
33
if (CANSTMOB & (1 << SERR))    // Stuff error flag
34
        {
35
        lcd_putsf("SERR"); 
36
        CANSTMOB &= (~(1 << SERR)); 
37
        }
38
if (CANSTMOB & (1 << FERR))    // Form error flag
39
        {
40
        lcd_putsf("FERR"); 
41
        CANSTMOB &= (~(1 << FERR));   
42
        } 
43
if (CANSTMOB & (1 << AERR))
44
        {
45
        lcd_putsf("CAN MOb ACK error"); 
46
        CANSTMOB &= (~(1 << AERR)); 
47
        } 
48
if (CANSTMOB & (1 << AERR))    // MOb ACK error flag
49
        {
50
        lcd_putsf("CAN MOb ACK error"); 
51
        CANSTMOB &= (~(1 << AERR));  
52
        } 
53
if (CANGIT & (0 << AERG))
54
        {
55
        lcd_putsf("CAN general ACK error"); 
56
        CANGIT &= (~(0 << AERG)); 
57
        }
58
if (CANGIT & (1 << CANIT))
59
        {
60
        lcd_putsf("Some interrupt happened");
61
        }
62
CANPAGE = save_canpage; 
63
}          
64

65

66
void can_init(void)     // CAN Controller initialization
67
{
68
int i; 
69
int j;
70

71
#asm("cli")              
72

73
// CAN general initialization: 
74

75
CANTCON = 0x00;         // CAN Timer Clock Period: 0,500 us
76

77
CANBT1 = 0x12;          // CAN baudrate: 100 kbit/s                
78
CANBT2 = 0x0C;
79
CANBT3 = 0x36;                                                          
80

81
CANGIE = (1<<ENRX) | (1<<ENIT) | (1<<ENERR); // Enable interrupt sources 
82

83
CANIE2 = (1 << IEMOB2);                 // MOb2 interrupts.  
84
CANIE1 = 0x00;  
85

86

87
// MOb initialization: Clear all MObs.
88

89
for (i=0; i<15; i++)
90
        {
91
        CANPAGE = (i << 4);             // Select MOb
92
        
93
        CANSTMOB = 0x00;                
94
        CANCDMOB = 0x00;                
95
        
96
        CANIDT4 = 0x00;                 // Delete Id.
97
        CANIDT3 = 0x00;
98
        CANIDT2 = 0x00;
99
        CANIDT1 = 0x00;
100
             
101
        CANIDM4 = 0x00;                 // Delete mask.
102
        CANIDM3 = 0x00;
103
        CANIDM2 = 0x00;
104
        CANIDM1 = 0x00;
105
        
106
        for (j=0; j<8; j++)             // Delete data
107
                {
108
                CANMSG = 0x00;
109
                }
110
        }   
111
          
112
// Enable CAN module: 
113

114
CANGCON = (1 << ENASTB);                // Enable CAN. <=> CANGCON=0x02;      
115
}
116

117

118

119
void can_rx(void)      
120
{
121
CANPAGE = (1 << MOBNB1) | (1 << AINC);     // 2. Select MOb2. 
122
CANCDMOB = (1 << CONMOB1) | (1 << DLC0);   // Enable rx, DLC = 1 (1 byte) 
123
}                   
124
   
125

126

127
void main(void)
128
{
129

130
init();
131
can_init();
132
#asm("sei") 
133
can_rx();  
134

135
while (1)
136
      {
137
      };
138
}
OP #607853
Lesenswert?

Hier meine can_tx()-Funktion:
1
 
2
void can_tx(void)
3
{
4
// ++++++++++++++++ Select MOb1 and start tx: +++++++++++++++++++
5
       
6
CANPAGE = (1 << MOBNB1) | (1 << AINC);  // Select MOb2, no auto-increment of index. 
7

8
CANMSG = 0xF0;                          // Put data into mailbox.  
9

10
CANIDT4 = 0x00;                         // Set Id.      
11
CANIDT3 = 0x00;
12
CANIDT2 = 0xA0;
13
CANIDT1 = 0xAA; 
14
          
15
CANCDMOB = (1 << CONMOB0) | (1 << DLC0);        // Enable Tx. Send 1 byte.   
16
}
Gast #607863
Lesenswert?

Grundsätzlich macht man normalerweise keine Anzeige auf einem LCD
in der Interupt Routine.
Man merkt sich nur das was man anzeigen will und lässt
das dann die main-funktion tun.

Zum can problem kann ich jetzt nicht so viel sagen, aber
möglicherweise liegt es schon an dem geschwindigkeitsproblem,
welches ich oben beschrieben habe.

Gruß Sven

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren