Hallo,
folgendes Problem
nachdem ich den CAN-Bus konfiguriert habe möchte ich wieder in den
Normal-Mode zurück... das geschieht ja bekanntlich mit folgendem
Codeschnipsel
1
CANCON=0x00;
2
3
while(CANSTATbits.OPMODE0==TRUE&&
4
CANSTATbits.OPMODE1==TRUE&&
5
CANSTATbits.OPMODE2==FALSE);
aber der PIC(PIC18F2480) bleibt in dieser While-schleife einfach
hängen... also irgendwie läst sich die 0x00 nicht in das CANCON-Register
schreiben wie mir scheint?
kann mir jemand helfen? habe ich etwas nicht beachtet?
MfG
Christoph
Hallo Christoph,
ich nutze den Code aus den Microchip Beispielen und da wird das
folgendermaßen erledigt...
1
typedefenum_CAN_OP_MODE
2
{
3
CAN_OP_MODE_BITS=0xe0,// Use this to access opmode bits
4
CAN_OP_MODE_NORMAL=0x00,
5
CAN_OP_MODE_SLEEP=0x20,
6
CAN_OP_MODE_LOOP=0x40,
7
CAN_OP_MODE_LISTEN=0x60,
8
CAN_OP_MODE_CONFIG=0x80
9
}CAN_OP_MODE;
10
11
:::
12
13
voidCAN_SetOperationMode(CAN_OP_MODEmode)
14
{
15
CANCON&=0x1F;// clear previous mode
16
CANCON|=mode;// set new mode
17
// Wait untill desired mode is set
18
while((CANSTAT&CAN_OP_MODE_BITS)!=mode);
19
}
Das ist ja bis hier praktisch identisch mit deinem Code. Allerdings wird
diese Funktion nur für das Umschalten in den ConfigMode benutzt, beim
zurück Schalten in den NormalMode nutzt Microchip ein nicht
blockierendes Makro (Funktion) ala...
1
#define CANSetOperationModeNoWait(mode) \
2
{ \
3
CANCON &= 0x1F; \
4
CANCON |= mode; \
5
}
Der Aufruf im Programm sieht dann in etwa so aus...
1
voidCAN_Init(void)
2
{
3
CAN_SetOperationMode(CAN_OP_MODE_CONFIG);
4
:::
5
CANSetOperationModeNoWait(CAN_OP_MODE_NORMAL);
6
}
Ich hab mir darüber noch nie Gedanken gemacht, so mach ich es auch und
es funktioniert! Was will man mehr...
Gruß, Steffen
erstmal besten Dank!
habs noch nicht ausprobiert aber wenns bei dir funzt und es von
microchip ist bin ich da guter dinge...
allerdings ist mein Code-schnipsle auch von Microchip... und
funktioniert nicht...
wo genau hast du das her?
Gerade noch mal nachgeschaut...
in der AN738 von Microchip macht man es auch so wie Du. Hier mal der
Codeauschnitt.
1
enumCAN_OP_MODE
2
{
3
CAN_OP_MODE_BITS=0b11100000,// Use this to access opmode
4
// bits
5
CAN_OP_MODE_NORMAL=0b00000000,
6
CAN_OP_MODE_SLEEP=0b00100000,
7
CAN_OP_MODE_LOOP=0b01000000,
8
CAN_OP_MODE_LISTEN=0b01100000,
9
CAN_OP_MODE_CONFIG=0b10000000
10
};
11
12
:::
13
14
voidCANSetOperationMode(enumCAN_OP_MODEmode)
15
{
16
// Request desired mode.
17
CANCON=mode;
18
19
// Wait till desired mode is set.
20
while((CANSTAT&CAN_OP_MODE_BITS)!=mode);
21
}
Hab es jetzt nicht mehr genau in Erinnerung, aber ich würde behaupten
das auch das bei mir funktioniert hat.
Obwohl, ich sehe gerade... hängst Du hier nicht in einer Endlosschleife
fest?
1
CANCON=0x00;
2
3
while(CANSTATbits.OPMODE0==FALSE&&
4
CANSTATbits.OPMODE1==FALSE&&
5
CANSTATbits.OPMODE2==FALSE);
Die CANSTATbits müssen doch 0 sein. Deine Abfrage macht so doch nicht
das selbe wie der Code von Microchip.
Gruß, Steffen
ich schreibe doch in das CANSTAT-Register eine 0x00 und frage dann ab ob
auch wirklich alle null sind? wenn alle null sind gehts weiter. Ich denk
das ist so richtig... funktioniert hat es allerdings nicht... aber wenns
falsch ist versteh ich nicht warum...
noch eine Frage zu diesen AN´s,
also ich hab die AN945 gefunden... blicke da aber überhaupt nicht
durch...
die von dir erwähnt AN738 erscheint mir wesentlich übersichtlicher.
Kann ich die AN738 nutzen? gibt es irgendwo mal einen vollständigen Code
damit ich mir angucken kann wie soetwas auszusehen hat?
Christoph Herzog schrieb...
> ich schreibe doch in das CANSTAT-Register eine 0x00 und frage dann ab ob> auch wirklich alle null sind? wenn alle null sind gehts weiter. Ich denk> das ist so richtig...
Eben nicht... eine While-Schleife wird doch so lange ausgeführt, wie die
Bedingung wahr ist. Wenn du die CANSTATbits auf FALSE (0) testest ergibt
es doch Wahr, also wird die Schleife nie verlassen.
Schau dir mal die AN878 an, ist so ähnlich wie AN738, nutzt nur den ECAN
Mode.
diese ECAN.def-Datei soll ja noch definiert werden?
ist es sinnvoll das mit dieser Software zu machen oder per Hand? ich hab
mir die software mal angeguckt und die Datei ... naja und beide sind für
den Einstieg noch recht schwerzu verstehen finde ich
Keine Ahnung, hab damit nicht gearbeitet. Ich tue mich mit fremdem Code
auch immer schwer, jeder hat ja da so seine Vorlieben. Ich nehme mir
immer Teile davon vor und schreibe damit meine eigenen Funktionen. Dabei
lernt man dann auch wie es wirklich funktioniert.
Hier mal Teile meiner can.h und can.c
1
#define PORT_CAN_TX_PIN LATCbits.LATC6
2
3
// CAN Baud Rate Prescaler bei FOSC 64MHz und BitTime 16TQ
4
#define CAN_BRP_100K 0x13 // 100kbit
5
#define CAN_BRP_125K 0x0F // 125kbit
6
#define CAN_BRP_250K 0x07 // 250kbit
7
#define CAN_BRP_500K 0x03 // 500kbit
8
#define CAN_BRP_1000K 0x01 // 1000kbit
9
10
11
typedefenum_CAN_FLAGS
12
{
13
CAN_MSG_STD=0,
14
CAN_MSG_XTD=1,
15
16
CAN_CONFIG_B0_BITS=0b01100100,
17
CAN_CONFIG_B1_BITS=0b01100000,
18
19
CAN_DBL_BUFFER_ON=0b00000100,// XXX1XXXX
20
CAN_DBL_BUFFER_OFF=0b00000000,// XXX0XXXX
21
22
CAN_ALL_MSG=0b01100000,// X11XXXXX
23
CAN_VALID_XTD_MSG=0b01000000,// X10XXXXX
24
CAN_VALID_STD_MSG=0b00100000,// X01XXXXX
25
CAN_ALL_VALID_MSG=0b00000000// X00XXXXX
26
}CAN_FLAGS;
27
28
29
voidCAN_SetBaudRate(BYTEbrp)
30
{
31
/* Sync Jump Width
32
<--->
33
|_Sync_|_Delay _|______Phase1______|__Phase2__|
34
| ^ ^ ^ |
35
| SamplePoint |
36
|<---------------- Bit Time ----------------->| */
37
38
// Die folgenden 4 Elemente ergeben die CAN Bit Time
folgendes Probelm tut sich gerad bei meinem Code auf
1
typedefenum_BOOL{FALSE=0,TRUE}BOOL;
ich habe mich zu diesem enum-Zeug ein bissel belesen und kann kein
Fehler finden... ist ja eigentlich auch von Mircochip selbst... ich hab
das gar nicht angefast... :(
ECAN.h:77: error: enum tag "_BOOL" redefined (from C:\Program Files
(x86)\Microchip\xc8\v1.12\include\GenericTypeDefs.h:65)
in der GenericTypeDefs.h hab ich mich auch mal umgeschaut...
was will der compiler jetzt von mir?
hallo nochmal... also ich habe die Konfiguration für den CAN-Bus jetzt
fertig denke ich...
wenn ich jetzt einen Frame senden möchte wird allerdings das ERRI und
das IRXI Flag gesetzt...
ich weiß aber nicht genau was die beiden auslöst...
Auf dem Bus ist auf jeden fall ne Menge los. wenn ich ein Frame senden
möchte hört der Pic gar nicht mehr auf zu senden.
wie kann ich mir das erklären?
an bei mal meine Init und die Transmitfunktion
wer toll wenn mal einer drüber schauen könnte
MfG
Christoph
Da kann ich dir jetzt leider auch nicht direkt helfen, ich habe das
CAN-Modul im Mode0 benutzt.
Was für einen Quarz hängt an deinem PIC und benutzt Du die interne PLL?
Bedenke das die Werte im BRP-Register von FOSC ausgehen. Z.B. bei einem
8MHz Quarz und 4xPLL = 32MHz. Die Pic rechnet dann wieder nur mit 8MHz,
da er immer 4 Taktzyklen für einen Befehl benötigt.
Stimmen alle Richtungen der IO's? Ich weiß jetzt nicht ob sich das
CAN-Modul die Ein- und Ausgänge selber setzt. Ich mußte bei mir, in der
Init() Routine den CAN-TX Pin von Hand auf high setzen, sonst ging
nichts. Aber bei dir scheint ja auf dem Bus schon was los zu sein...
Kennst Du das Tool MBTime von Microchip, mit dem kann man die Werte für
die BRP-Register berechnen lassen. Funktioniert für den mcp2551 und die
pic18.
http://www.codeforge.com/article/200254
Gruß, Steffen
Sehe gerade das man sich zum Download anmelden muß, also wenn du es
benötigst kurze Nachricht an mich. Sende es dir dann per mail.
ich werde das jetzt auch alles für den Mode 0 machen...
zum einen weiß ich noch gar nicht genau was der FIFO-Mode ist zum
anderen brauch ich den EXTENDED-Kram gar nicht...
Auf dem Bus ist schon ordentlich Party ja... also gesendet wird sobald
ich das will... aber ich weiß halt nicht genau für was die beiden
Fehler-bits ERRI und IRXI stehen...
der andere Busteilnehmer müssten doch den empfang bestätigen ne? sonst
hört der sendende Busteilnehmer nicht auf???
Christoph Herzog schrieb:> der andere Busteilnehmer müssten doch den empfang bestätigen ne? sonst> hört der sendende Busteilnehmer nicht auf???
Genau so sollte es sein. Allerdings müßte der sendende Knoten irgendwann
in der Error Status gehen und das Senden aufgeben. Haben auch alle
Knoten die selbe Baudrate?
Versuch doch mal den Loopback Modus, dann solltest Du keinen weiteren
Teilnehmer benötigen. Du empfängst dann praktisch deine eigenen
Telegramme.
Baudrate ist die gleiche... sind beides Pic18F2480 mit internen 8Mhz
gleiche ECAN-ini... nur die Filter sind geändert bzw. die Identifier.
was genau bringt mir der Loopback modus... also ich habe ihn schon mal
ausprobiert und benutzt allerdings nicht mit dir jetztige von mir selbst
geschriebenen ECAN.h / ECAN.c.
also ich schicke was und Empfange es gleich wieder... liegt es dann auch
auf dem bus?oder Passiert das nur intern im Controller?
muss ich im Loopback-modus den gleichen Filter haben wie ich als
identifier raus gebe?
na mal sehen was wird ;) teste das jetzt mal
danke erstmal
PS.: auch für die Datei
Du arbeitest mit dem internen 8Mhz Oszillator? Ich kann mich täuschen,
aber ich glaube da reichen die Toleranzen nicht. Bei CAN sollte man
schon einen externen Quarz nehmen, oder mal ganz ganz niedrige Baudraten
versuchen.
So ganz genau kenne ich mich mit dem Loopbackmodus auch nicht aus. Ich
habe das so verstanden, das er dann quasi mit sich selbst kommuniziert
ohne die Signale auf den Bus zu legen. Du mußt natürlich auch die Filter
so setzen, das die Frames durchgehen. Damit kann man im Prinzip die
grundlegende Funktionalität ohne weitere Teilnehmer testen.
PS: Gerne...
eine Frage mal noch zum auslesen bzw. senden auf den Can-Bus
ich habe das ganze jetzt erstmal im Loop-modus zu laufen.
wenn ich einmal sende ist alles oki... es wird gesendet und empfangen
und der pic läuft weiter...
wenn ich ein zweites mal senden will bleibt das ding irgendwo hängen,
also in einem Interrupt mit sicherheit. komischer weiße wird mir nicht
angezeigt welches der 4 Flags auslöst ( ERRI IRXIF TXB0IF TXB1IF)
da stellt sich mir die frage was ich mit den empfangenen Daten anstellen
darf/muss... müssen irgendwelche bits nach dem Empfangen manuel zurück
gesetzt werden??
beim schreiben setze ich einfache alle notwendigen variablen und setze
am ende das TXREQ-Bit zum senden
beim auslesen, lese ich alle Daten aus beschreibe sie danach mit Null
und setze das PIR3.RXB0IF = 0
Kann dir jetzt auf die Schnelle nur meine Intrruptabfrage zeigen, muß
gleich los...
1
// CAN Receive Buffer 0 Interrupt Flag
2
if(PIR5bits.RXB0IF)
3
{
4
if(RXB0CONbits.RXFUL)
5
{
6
CAN_ReceiveMessage();
7
RXB0CONbits.RXFUL=0;
8
}
9
PIR5bits.RXB0IF=0;// Clear the received flag.
10
}
11
12
// CAN Receive Buffer 1 Interrupt Flag
13
if(PIR5bits.RXB1IF)
14
{
15
if(RXB1CONbits.RXFUL)
16
{
17
CAN_ReceiveMessage();
18
RXB1CONbits.RXFUL=0;
19
}
20
PIR5bits.RXB1IF=0;// Clear the received flag.
21
}
Die Funktion CAN_ReceiveMessage() liest nur die Register aus, da wird
nichts geändert. Störe dich nicht an den Registernamen, ich arbeite mit
dem PIC18F46K80. Versuch doch auch mal mit den Prioritäten der Interrups
zu spielen, sind da alle Register richtig gesetzt?
Gruß, viel Erfolg und ein schönes WE... :-)