Forum: Mikrocontroller und Digitale Elektronik STM32 - CAN-Filter - ST Library v3.40


von nexulm (Gast)


Lesenswert?

Hallo,

ich moechte gerne den CAN-Filter des STM32 (hier: STM32F103) zur 
Filterung von CAN-Botschaften (0x700 - 0x70f) nutzen.
Irgendwie klappt die Filterung aber nicht mit der unten aufgefuehrten 
Initialisierung. Bisher geht entweder alles durch oder nix.
Ich verwende hierzu die ST Library v3.40. Leider finde ich nirgendwo 
eine Beispielcode, der eine Filterung vornimmt. Auch bei den ST 
Beispielen ist der Filter immer "offen" CAN_FilterIdLow=0x0000.
Wer hat diese Struktur schon erfolgreich mit Filterfunktion im Einsatz 
und kann nochmal kurz beispielhaft aufzeigen wie ich eine einzelne 
CAN-ID filter und wie einen Bereich. Die Zusammenhaenge von 
CAN_FilterMode_IdMask und CAN_FilterMode_IdList sowie 
CAN_FilterScale_32bit und CAN_FilterScale_16bit sind mir in ihrer 
Anwendung nicht richtig klar.

/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0700;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; 
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x07F0;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

Mike

von nexulm (Gast)


Lesenswert?

...Problem erkannt und geloest.
Warum ist das nur so kompliziert in die Library eingelossen!?!
Die urspruengliche Initilaisierung muss nur im 5 bit nach links 
geschiftet werden, damit die Bits an der richtigen Stelle des StdId 
ankommen.
Endlich habe ich das Datenblatt und die ST library Struktur verstanden.
Dieser Code-Schnipsel als moegliches Beispiel fuer die Nachwelt.

Endweder...
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0700 << 5;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x07F0 << 5;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

...oder
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0xF000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFE00;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

von Christoph (Gast)


Lesenswert?

Dem kann ich leider nicht zustimmen. Laut dem Aufbau der Register musst 
du deinen kompletten Identifier von 29 Bit um 3 Bit nach links 
verschieben. Dies liegt daran, dann die ersten drei LSB reserviert sind. 
Reference Manual RM0008 Seite 664.

Hier mein Beispiel:
1
uint32_t ID1 = 0x1FFFFFFF << 3; //Shift um 3 nach links, da die ersten 3 LSB reserviert sind
2
CAN_FilterInitStructure.CAN_FilterIdHigh = ID1 >> 16;  //Shift um 16 Bit nach rechts, um an die oberen 16 Bit zu kommen. Hier können nur 16 Bit übergeben werden.
3
CAN_FilterInitStructure.CAN_FilterIdLow =  ID1 & 0x0000FFFF; //Maskierung der ersten 16 Bit, um an die unteren 16 Bit zu kommen. Hier können nur 16 Bit übergeben werden.

Wenn du jedoch den 11 Bit Identifier benutzt, dann stimme ich deinem << 
5 mehr zu. Alledings habe ich das nicht geprüft. Dann müsstest du aber 
auch die Auswahl bei FilterScale ändern:
1
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;

Nun ist sowohl die IdHigh, als auch die IdLow eine eigenständige ID. 
Reference Manual RM0008 Seite 642.

von Leonhard (Gast)


Lesenswert?

Ich habe genau das selbe Problem. Die Lösung, wie von nexulm beschrieben 
funktioniert tatsächlich. Er tut so, als hätte er eine 32-Bit-ID.

Wie müsste denn die Initialisierung aussehen, wenn man das über 
Standard-IDs machen wollte. Ich habe es so versucht, weiß aber nicht, 
was daran falsch ist.
1
//akzeptiere ID 0x110 .. 0x11F
2
sFilter.CAN_FilterMode           = CAN_FilterMode_IdMask;
3
sFilter.CAN_FilterScale          = CAN_FilterScale_16bit;
4
sFilter.CAN_FilterIdHigh         = 0x0000;
5
sFilter.CAN_FilterIdLow          = 0x0110 << 5;   //ID   001 0001 0000
6
sFilter.CAN_FilterMaskIdHigh     = 0x0000;
7
sFilter.CAN_FilterMaskIdLow      = 0x07F0 << 5;   //Mask 111 1111 0000
8
sFilter.CAN_FilterFIFOAssignment = CAN_FIFO0;
9
sFilter.CAN_FilterActivation     = ENABLE;
10
sFilter.CAN_FilterNumber         = 0;
11
CAN_FilterInit(&sFilter);

Ich setze die FW-Lib v3.30 ein

von Michael L. (michael_l93)


Lesenswert?

...auch wenn es schon lange her ist hier der Codeschnipsel zur 
Richtigstellung zur Filterung des CAN-ID Bereiches 0x110-0x11F:
1
CAN_FilterInitStructure.CAN_FilterIdHigh =  0x0000;
2
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0110 << 5;
3
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
4
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x07F0 << 5;
Bei der Variante von Leonhard wurde der Filter durch FilterMaskIDHigh = 
0x0000; (= dont care) ausgehebelt und alle Botschaften wurden 
durchgelassen.

von Meier D. (Gast)


Lesenswert?

Falls noch jemand auf diesen Thread stösst (scheint einer der 
informativsten zu sein), hier noch etwas wichtiges, wenn jemand Extended 
Identifier filtern will:
Beim Erstellen der Filter muss das IDE-Bit des CAN-Registers zusätzlich 
noch gesetzt werden:
1
uint32_t ID1 = 0x1FFFFFFF << 3; //Shift um 3 nach links, da die ersten 3 LSB reserviert sind
2
CAN_FilterInitStructure.CAN_FilterIdHigh = ID1 >> 16;  //Shift um 16 Bit nach rechts, um an die oberen 16 Bit zu kommen. Hier können nur 16 Bit übergeben werden.
3
CAN_FilterInitStructure.CAN_FilterIdLow =  (ID1 & 0x0000FFFF) | 0x04; //Maskierung der ersten 16 Bit, um an die unteren 16 Bit zu kommen. Zusätzlich Setzen des IDE-Bits.

von Informant (Gast)


Lesenswert?

Auch wenn der Thread schon uralt ist - das Problem ist noch aktuell.

Anbei ein Link, mit dem ich es dann endlich verstanden habe.

https://schulz-m.github.io/2017/03/23/stm32-can-id-filter/

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.