Abend! :=) Habe nun endlich den Fehler bei mir gefunden. Zum Problem: Ich benutze 2 Can-Controller vom Typ MCP2515 und lese mehrere Sachen vom Can-Bus mit dem 1. MCP. Wenn ich alle interessanten Werte habe, rechne ich alles um, und sende es in gewünschter Form mit dem 2. MCP weiter. Lesen funktioniert problemlos. Senden auch. Ein Fehler tritt aber auf. Und zwar beim Senden (2. MCP), darf das Unterprogramm durch den Interrupt (der vom 1. MCP kommt, wenn neue Daten empfangen wurden) auf keinen Fall gestört werden. Desswegen habe ich den Interrupt für die Zeit wo ich sende deaktiviert. Das Senden ist für sich selbst eine Kunst, und darf nicht zu schnell passieren, sonst ist der Empfänger irritiert und steigt aus. Das Senden kann dadurch schon mal 200ms dauern. In der Zeit kommen natürlich immer wieder neue Nachrichten in den 1. MCP. Diese werden durch den deaktivierten Interrupt nicht wahrgenommen und nicht ausgelesen. Nach dem Senden, wird der Interrupt wieder aktiviert und neue Daten gesammelt. Dann wird wieder gesendet und dann alles von vorne. Da die Nachrichten beim Senden nicht ausgelesen werden, steigt der 1.MCP irgendwann mal aus. Der Interrupt bleibt immer auf LOW und es passiert natürlich Nichts. Was bleiben mir das für Möglichkeiten? Beim Senden, darf ich nicht mal ein Bit Ändern, da es leicht zu Fehlfunktionen des Empfängers kommen kann. Nachrichten muss ich aber trotzdem auslesen, da sonst der 1. MCP Irgendwann mal nicht mehr will. Ich denke das kommt davon, dass zu viele Nachrichen einfach ignoriert werden. Kann ich den MCP so konfigurieren, dann ihm der Overflow Nichts ausmacht? Jemand eine Idee? Gruss Alex S.
Mir scheint, du hast ein grundlegendes Verständnisproblem. Prinzipiell hast du die Möglichkeit, den MCP2515 über die SPI deutlich schneller zu bedienen, als eine CAN-Botschaft dauert (ok, bei 1MBit und 2 MCP2515 kann es je nach MC-Takt eng werden). Das gilt sowohl fürs Lesen einer Botschaft als auch das Absenden. Die Sendegeschwindigkeit auf CAN-Seite hat nichts damit zu tun, wie schnell oder langsam da das über die SPI erledigst. Also - Butter bei die Fische. Welche Busgeschwindigkeit? Welche SPI-Frequenz? Wieviele Botschaften/s? Software? Hardware?
PS: Symptome zu bekämpfen ist eigentlich immer der falsche Weg :-)
1. MCP läuft mit 16Mhz bei 500kbit (lesen) 2. Mcp läuft mit 16Mhz bei 100kbit (Schreiben) Die MCPs sind beide an der selben SPI dran, nur die CS Leitung ist unterschiedlich. Somit kann ich den 1. oder 2. MCP ansprechen, indem ich die entsprechende CS Leitung auf masse ziehe. Angenommen bekommt der 2. MCP gerade die Daten über SPI. CS leitung vom 2. MCP ist gerade auf Masse. Wenn ich jetzt (auf wenn das so schnell geht) den Register vom 1. MCP auslese, dann bekommt der 2. MCP "falschen" Daten über SPI, weil der 1. parallel sitzt. Wie gesagt, ab besten wäre es, den Error Counter zu löschen, aber ich finde den richtigen Register nicht.
1Mhz Hast du eine Idee? Habe schon so ziehmlich alles probiert, was ich denken konnte. Gruss Alex
Kurzer Überschlag: SPI-Frequenz 8MHz möglich. Eine komplette CAN-Botschaft bei 8 Datenbytes sind ca. 130Bit, dauert also beim 500kBit-Bus 260µs, zum kompletten Lesen sind ca. 20 SPI-Transfers nötig, das dauert 20µs. Bedeutet im Klartext: selbst wenn der Bus komplett vollgestopft ist (also Botschaft an Botschaft, was in der Praxis nicht vorkommt) lastet der SPI-Transfer den MC nicht mal zu 10% aus, wenn man auf die SPI wartet. Der 100kBit-Bus entsprechend weitere 2% bei full-traffic. Natürlich muss man zwischendurch auch irgendwas anderes tun, aber da ist genug Luft. SPI-Interrupt bringt weiteren Freiraum, falls nötig. Du hast keinen Engpass, du hast allenfalls schlecht programmiert :-)
Bei 1MHz kann es langsam eng werden - aber warum nimmst du 1MHz?
Was bedeutet Engpass? Falsch/nicht optimal programmiert kann ja sein. 1MHz auf der SPI habe ich genommen, weil die SPI Leitungen durch den Flachbandkabel nicht optimal sind. Habe jetzt auf 4Mhz umgestellt, funktioniert auch. Habe jetzt noch eine andere Idee: Die Daten werden in der Do-Loop Schleife ständig gesammelt und umgerechnet. Mit einem Timer wird die ISR beim Überlauf aufgerufen, und die gesammelten Daten werden verschickt. Wenn das Programm in der ISR von Timer ist, werden doch die anderen Interrupts deaktiviert, und beim Verlassen wieder aktiviert, RICHTIG? Dann habe ich aber immer noch das Problem, dass nicht alle Nachrichten abgerufen werden. Gruss Alex
Wie gesagt - für das Abholen der Nachrichten brauchst du 20 (bzw. jetzt bei dir 40µs), neue Nachrichten kommen aber max. alle 260µs. Macht mindestens 220µs Zeit dazwischen bzw. ca. 3500 Prozessortakte. Damit kann man ne Menge machen :-) Der MCP kann ja auch 2 Botschaften speichern (RXB0 und RXB1, Stichwort rollover), ein Problem taucht erst auf, wenn beide Buffer gefüllt sind und die 3. Nachricht komplett empfangen ist. Andersherum: die empfangene Botschaft muss nicht sofort abgeholt werden, man hat da schon Luft, wenn also z.B. gerade eine andere ISR läuft. Kurz und knapp: ohne deine Software gehts hier nicht weiter.
Ok, danke dir. Werde ich mal mein Program überdenken. kannst du, oder jemand anderer sagen, ob der Hardware interrupt während Timer ISR automatisch deaktiviert wird? Gruss Alex
@ Alex S. (dj_beat) >Ein Fehler tritt aber auf. Und zwar beim Senden (2. MCP), darf das >Unterprogramm durch den Interrupt (der vom 1. MCP kommt, wenn neue Daten >empfangen wurden) auf keinen Fall gestört werden. Warum? >Desswegen habe ich den Interrupt für die Zeit wo ich sende deaktiviert. Klingt nicht gut. >Das Senden ist für sich selbst eine Kunst, und darf nicht zu schnell >passieren, sonst ist der Empfänger irritiert und steigt aus. Dann ist er Schrott. >Das Senden kann dadurch schon mal 200ms dauern. Eine Ewigkeit. >In der Zeit kommen natürlich immer wieder neue Nachrichten in den 1. >MCP. Eben. >Diese werden durch den deaktivierten Interrupt nicht wahrgenommen und >nicht ausgelesen. Schlecht. >Nach dem Senden, wird der Interrupt wieder aktiviert und neue Daten >gesammelt. Dann wird wieder gesendet und dann alles von vorne. >Da die Nachrichten beim Senden nicht ausgelesen werden, steigt der 1.MCP >irgendwann mal aus. Nö, es gibt nur ein paar Datenverluste. > Der Interrupt bleibt immer auf LOW und es passiert >natürlich Nichts. Das ist ein Fehler in deinem Programm. >Was bleiben mir das für Möglichkeiten? Es richtig machen. a) Der Empfänger darf nicht so mimosenhaft sein. b) Interrupts sperrt man nicht für 200ms. c) Du musst durch gescheites Timing und Puffern per FIFO die Meldungen vom 1. MCP empfangen, während Daten über den 2. MCP rausgehen. Sprich. Wenn das AUSLESEN des 1. MCP z.B. maximal 100us dauert muss du spätestens 100us VOR dem Senden des nächsten Datenpaktes über MCP #2 die Interrupts sperren, nicht eher. Dann kannst du EXAKT per Timer den Sendetermin des nächsten Datenpakets auslösen. Während der Interruptsperre muss MCP #1 die Nachrichten zwischenpuffern. d) Warum eigentlich zwei MCP? Sind das zwei getrennte CAN-Busse? Wenn nein, sind zwei MCPs Unsinn. >Beim Senden, darf ich nicht mal ein Bit Ändern, da es leicht zu >Fehlfunktionen des Empfängers kommen kann. Schrott. Welches Bit soll sich denn ändern? CAN überträgt SEHR sicher. >Nachrichten muss ich aber trotzdem auslesen, da sonst der 1. MCP >Irgendwann mal nicht mehr will. Siehe oben. >Ich denke das kommt davon, dass zu viele Nachrichen einfach ignoriert >werden. Nö. >Kann ich den MCP so konfigurieren, dann ihm der Overflow Nichts >ausmacht? Macht er sowieso nicht. Udn wie bereits gesat, es gibt keinen Grund, die SPI mit schnarchlangsamen 1 MHz zu betreiben. MFG Falk
@ Alex S. (dj_beat) >kannst du, oder jemand anderer sagen, ob der Hardware interrupt während >Timer ISR automatisch deaktiviert wird? Ja, siehe Interrupt. Und für dein Problem siehe auch Multitasking. Dann erkennst du, warum 200ms Interruptsperre nicht gut sind. MFG Falk
Alex S. schrieb: > Ich benutze 2 Can-Controller vom Typ MCP2515 Das heißt also, Du mußt 2 CAN-Busse bedienen. Jeder MCP2515 kriegt seine eigene Interruptleitung und seine eigenen 2 FIFOs. Ein Empfangsinterrupt liest ein Paket in den FIFO ein und das wars dann. Ein Sendeinterrupt guckt nach, ob ein weiteres Paket im Sende-FIFO ist und sendet dieses. Ist keins da, sperrt er sich. Die FIFOs werden dann im Main ausgelesen bzw. beschrieben. Die MCP2515 interessiert nicht, wann das passiert und sie müssen auch nicht gesperrt werden. Lediglich nach dem Schreiben in den Sende-FIFO muß der MCP2515 wieder seinen Sendeinterrupt freigeben. Nirgends 200ms Interruptsperre, sondern wenige µs. Peter
Danke für die Antworten. Habe den Fehler gefunden. Es war ein schlechter Kontakt beim Flachbandkabel. Bin schon etwas weiter und gleich wieder ein Problem. Die Werte lese ich vom Motor Can-Bus. Bis jetzt habe ich Wassertemperatur, Öltemperatur, Tankinhalt, Geschwindigkeit. Der Bus läuft mit 500kbit. Die Wasser- und Öltemperatur sind auf einer ID, in einer Nachricht(verschiedene Bytes). ca. 300ms Widerholung Der Tankinhalt ist auch kein Problem. 200-400ms Widerholung. Die Geschwindigkeit kommt vom ABS Steuergerät und wird VIEL,VIEL,VIEL öfters geschickt, als Temp, Tankinhalt usw. Das hat nun zur Folge, dass ich fast immer nur Geschwindigkeit empfange. Hört sich jetzt nicht nach einem riesen Problem an, ist aber doch etwas komplizierter. Habe das nun so gemacht, dass ich jeweils nach einem empfangenen Wert eine Variable auf 1 setze, um zu wissen, dass ich den Wert schon habe. Sieht quasi so aus:
1 | Dim q1, q2, q3 as byte |
2 | |
3 | do
|
4 | |
5 | if Filter = 0 and q1 = 0 and q2 = 0 and q3 = 0 then |
6 | wasser_temp = (meine Candaten für Temp) |
7 | Öl_temp = (meine Candaten für Temp) |
8 | q1 = 1 |
9 | end if |
10 | |
11 | |
12 | if Filter = 1 and q1 = 1 and q2 = 0 and q3 = 0 then |
13 | Tank_Inhalt = (meine Candaten für tank) |
14 | q2 = 1 |
15 | end if |
16 | |
17 | if Filter = 2 and q1 = 1 and q2 = 1 and q3 = 0 then |
18 | wasser_temp = (meine Candaten für Geschwindigkeit) |
19 | q3 = 1 |
20 | end if |
21 | |
22 | |
23 | if q1 = 1 and q2 = 1 and q3 = 1 then 'wenn ich alle Werte habe |
24 | gosub Umrechnen_senden 'unterprogramm zum Umrechnen und versenden |
25 | q1 = 0 |
26 | q2 = 0 |
27 | q3 = 0 |
28 | |
29 | loop
|
Beim Interrupt werden Filter erkannt (welcher ausgelöst hat) und Daten vom MCP2515 ausgelesen. So kann ich feststellen, welche Daten das sind. Mein Problem ist aber wie gesagt, dass die Geschwindigkeit zu oft übertragen wird. Diese Nachricht muss ich ja immer auslesen, um dann fest zu stellen, dass ich diesen Wert schon habe, und jetzt eigentlich die Öltemp. haben möchte. Dann verwerfe ich halt die Nachricht und warte auf die nächte.... und DANN.... bekomme ich schon wieder die Geschwindigkeit, und wieder, und wieder, bis irgendwann mal doch das Richtige dazwischen kommt. Tja, und nun die Frage, nach welcher Logik/welchem Verfahren sollte ich die Daten auslesen, um dann möglichst schnell alle zu haben? Meine If-Then Variante scheint in dem Fall nicht ganz zu passen. Danke Gruss Alex S.
Wenn Du 4 Nachrichten empfangen willst, legst Du 4 Puffer an. Jede Nachricht legst Du dann in dem zugehörenden Puffer ab, eine alte gleiche Nachricht wird einfach überschrieben. Dann legst Du noch 4 Bits an, jede Nachricht setzt das zugehörende Bit. Sind alle 4 gesetzt, weißt Du, daß jede Nachricht mindestens einmal empfangen wurde und kannst damit irgendwas machen. Peter
@ Alex S. (dj_beat) >Die Wasser- und Öltemperatur sind auf einer ID, in einer >Nachricht(verschiedene Bytes). ca. 300ms Widerholung >Der Tankinhalt ist auch kein Problem. 200-400ms Widerholung. Gähn. Da schläft jeder Controller ein. >Die Geschwindigkeit kommt vom ABS Steuergerät und wird VIEL,VIEL,VIEL >öfters geschickt, als Temp, Tankinhalt usw. Logisch, dein Tacho sollte ja etwas flüssiger reagieren. >Das hat nun zur Folge, dass ich fast immer nur Geschwindigkeit empfange. Und? Kann man problemlos ignorieren. >Hört sich jetzt nicht nach einem riesen Problem an, Eben. > ist aber doch etwas komplizierter. Warum? Ohh, du machst das in BASCOM? Hmmm, geht auch. >Mein Problem ist aber wie gesagt, dass die Geschwindigkeit zu oft >übertragen wird. Nö. Das kann man igrnorieren, schon direkt im MCP, per Filter. >Dann verwerfe ich halt die Nachricht und warte auf die nächte.... und >DANN.... bekomme ich schon wieder die Geschwindigkeit, und wieder, und >wieder, bis irgendwann mal doch das Richtige dazwischen kommt. Ja und? Dein Controller macht do sowieso nichts großartiges nebenbei. >Tja, und nun die Frage, nach welcher Logik/welchem Verfahren sollte ich >die Daten auslesen, um dann möglichst schnell alle zu haben? Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts steuern. MFG Falk
>Dann legst Du noch 4 Bits an, jede Nachricht setzt das zugehörende Bit. >Sind alle 4 gesetzt, weißt Du, daß jede Nachricht mindestens einmal >empfangen wurde und kannst damit irgendwas machen. Genau so habe ich das im Moment auch. Funktioniert aber wie gesagt nicht so gut. Warum? Kommt unten. >Nö. Das kann man igrnorieren, schon direkt im MCP, per Filter. Der Filter ist ja schon so eingestellt, dass ich die ID für Geschwindigkeit durch kommt. Oder soll ich nach dem ich die Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen, und nach dem Versenden wieder aktivieren? >Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die >passenden Nachrichten empfangen wurden. Etwas genauer,bitte, wenn es geht. Zum Problem noch mal: Ich will die Geschwindigkeit haben. Die passende Nachricht bekomme ich, und habe nun meinen Wert für Geschwindigkeit. Jetzt möchte ich den Tankinhalt haben, also warte ich auf die Can Nachricht. Ich bekomme einen Interrupt, dass eine Nachricht im MCP bereit liegt. Dann lese ich den Inhalt aus und sofort danach gucke ich, welcher Filter durchgelassen hat. Anhang des Filters kann ich die Nachricht zuordnen. (Denn ich weiss dass, zum Beispiel Filter 0 Geschwindigkeit, Filter 1, Tankinhalt, Filter 2 Temperaturen sind.) Bei der nächsten Nachricht sehe ich, dass schon wieder Filter 0 ausgelöst hat. Diesen brauche ich nicht mehr, da ich den Wert schon habe, und warte auf die nächste Nachricht. Und dann bekomme ich wieder die Geschwindigkeit. Natürlich erwische ich irgendwann mal den Tankinhalt und die Temperatur, aber das kann je nach Zufall 0.1 - 2 Sekunden dauern. 2 Sekunden ist zu lange. Das Problem ist wie gesagt, das der µC von der wiederholten Nachricht für Geschwindigkeit abgelenkt wird, und somit den Tankinhalt verpasst. Ich verstehe es natürlich, dass ich einfach Alles empfangen kann, und die Nachrichten entsprechend speichern kann, Geschwindigkeit wird dabei einfach überschrieben, aber das funktioniert, warum auch immer, nicht. Gruss Alex
Irgendwie haut dein gesamtes Softwarekonzept nicht hin. Dein Prozessor ist schnell genug um alle Nachrichten zu empfangen, zu verarbeiten und wieder zu senden. Evtl. wartet den Programm viel zu viel ohne etwas zu machen.
Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang ist und es ist auch nicht sofort klar, was da passiert. Ich möchte einfach nur einen Vorschlag, wie ich das Ganze logisch und schnell machen kann, ohne dass sich das was verhackt. Also kein Sorcecode, sondern den richtigen Ablauf/Idee. Gruss Alex S.
@ Alex S. (dj_beat) >Geschwindigkeit durch kommt. Oder soll ich nach dem ich die >Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen, >und nach dem Versenden wieder aktivieren? Ja. >Natürlich erwische ich irgendwann mal den Tankinhalt und die Temperatur, >aber das kann je nach Zufall 0.1 - 2 Sekunden dauern. 2 Sekunden ist zu >lange. Wieso "erwischen"? Die Nachrichten empfängst du doch aus so, der MCP hat doch mehrere Empfangsboxen, nicht wahr? >Das Problem ist wie gesagt, das der µC von der wiederholten Nachricht >für Geschwindigkeit abgelenkt wird, und somit den Tankinhalt verpasst. Nö. Dein Programm hat ein Problem. >Ich verstehe es natürlich, dass ich einfach Alles empfangen kann, und >die Nachrichten entsprechend speichern kann, Geschwindigkeit wird dabei >einfach überschrieben, aber das funktioniert, warum auch immer, nicht. Programmfehler. Böse Zungen würden hier jetzt einen BASCOM-Witz einwerfen . . . ;-) MfG Falk
Falk Brunner schrieb: > Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die > passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts > steuern. Was fürn Quark...
@ crazy horse (Gast) >> Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die >> passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts >> steuern. >Was fürn Quark... Deine fundierte Kritik ist immer wieder gern gesehen hier . . .
>>Oder soll ich nach dem ich die >>Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen, >>und nach dem Versenden wieder aktivieren? >Ja. Funktioniert nicht. Habe schon erlebt, dass Konfigurationsmodus im laufenden Betrieb schlecht ist. Der Sender erkennt den "Bus-OFF".
Martin schrieb: > Irgendwie haut dein gesamtes Softwarekonzept nicht hin. > > > > Dein Prozessor ist schnell genug um alle Nachrichten zu empfangen, zu > > verarbeiten und wieder zu senden. Evtl. wartet den Programm viel zu viel > > ohne etwas zu machen.Beitrag melden | Bearbeiten | Löschen | Ja Martin, wie Recht du hast. Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den Controler zu haben scheint, wie man es unter C im AVR-Studio hätte. Seine Probleme bei der Logistik der Daten ist der Programmiersprache geschuldet. Sie sind hausgemacht. Aber da muß er schon selbst drauf kommen. Deshalb halte ich mich in diesem Thread zurück.
@Falk: der Wortlaut wurde durchaus mit Absicht so gewählt - mit etwas Selbstreflektion solltest du was erkennen :-) Zur Sache: es gibt keinerlei Grund, im laufenden Betrieb die Konfiguration zu ändern. Neben unnötig ist das sogar problematisch. Will ich die Geschwindigkeit, lasse ich die entsprechende Botschaft durch. Die nicht benötigten Daten sind schneller weggeschmissen, als jedesmal die Filtereinstellungen zu ändern. Tut doch nicht weh, die alle 10ms zu bekommen, aber nur alle 200ms auch auszuwerten.
@ cskulkw (Gast) >Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den >Controler zu haben scheint, wie man es unter C im AVR-Studio hätte. Mit BASCOM kann man per SPI genauso arbeiten wie mit C. >Seine Probleme bei der Logistik der Daten ist der Programmiersprache >geschuldet. Nö, es sind seine begrenzten Kenntnisse und Fähigkeiten bezüglich Programmierung allgemein. > Sie sind hausgemacht. Aber da muß er schon selbst drauf > kommen. Was nur bedingt Sinn eines Forums ist. Ein paar gute Tipps und Hinweise sind schon das Mittel der Wahl und auch Sinn eines Forums. MfG Falk
>Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den >Controler zu haben scheint, wie man es unter C im AVR-Studio hätte. Basic ist da vielleicht auch teilweise das Problem, aber es muss damit auch zu machen sein. Denn wenn meine Strategie/Idee/Vorstellung etwas daneben ist, dann hilft ja nur die Vorgehensweise zu ändern. Und ich komme im Moment nicht drauf, wie ich das anders machen kann. Desswegen auch die Frage, wie Ihr das machen würdet. Gruss Alex S.
@ crazy horse (Gast) >der Wortlaut wurde durchaus mit Absicht so gewählt - mit etwas >Selbstreflektion solltest du was erkennen :-) ;-) Wobei ich schon mein Urteil begründe . . . >Zur Sache: es gibt keinerlei Grund, im laufenden Betrieb die >Konfiguration zu ändern. Neben unnötig ist das sogar problematisch. Mag sein, so genau kenn ich den MCP2515 nicht, hab ihn nur vor einer Weile mal auf die Schnelle in Betrieb genommen, dem Herrn vom kreativen Chaos sei Dank. http://www.kreatives-chaos.com/artikel/ansteuerung-eines-mcp2515 > Will >ich die Geschwindigkeit, lasse ich die entsprechende Botschaft durch. >Die nicht benötigten Daten sind schneller weggeschmissen, als jedesmal >die Filtereinstellungen zu ändern. Tut doch nicht weh, die alle 10ms zu >bekommen, aber nur alle 200ms auch auszuwerten. Sicher. MfG Falk
Alex S. schrieb: > Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang > ist und es ist auch nicht sofort klar, was da passiert. Wenn dein Code zu lang ist, sodass andere Leute in nachvollziehen können, dann hast du schon viel grundlegendere Probleme bei deiner Software! Vermutlich auch noch Spaghetti-Code.
Alex S. schrieb: > Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang > ist und es ist auch nicht sofort klar, was da passiert. > > Ich möchte einfach nur einen Vorschlag, wie ich das Ganze logisch und > schnell machen kann, ohne dass sich das was verhackt. > Also kein Sorcecode, sondern den richtigen Ablauf/Idee. > > Gruss Alex S. Versuchen wir es mal. Basicspezifisches kann ich aber nichts beitragen. Als erstes solltest du versuchen, dir eine passende Variable anzulegen: typedef struct { unsigned int id; unsigned char rtr; unsigned char length; unsigned char data[8]; } CANMessage; definiert einen Variablen-Typ CANMessage, in dem du alle relevanten Daten unterbringen kannst (ob das in Basic geht??, ansonsten musst du dir mit einem array irgendwie helfen. Jetzt erzeugst du eine Variable CANreceive CANMessage CANreceive; In diese werden alle hereinkommenden Botschaften gespeichert. interrupt [EXT_INT0] void ext_int0_isr(void) { can_get_message(&CANreceive); //holt per SPI alle CAN-Daten ab CAN_message_received=1; //zeigt an, dass eine Botschaft empfangen wurde } Das heisst jetzt, dass du alle Botschaften, die den Filter des MCP2515 passieren, interruptgesteuert im MC landen. Wie es jetzt weitergeht, hängt von deiner Anwendung ab. Normalerweise gibt es weitere Variablen CANMessage, beispielsweise: CANMessage motor_receive[5]; //wenn du 5 Botschaften empfangen willst Im Hauptprogramm dann: while (1) {if (CAN_message_received) //Botschaft empfangen? {CAN_message_received=0; switch (CAN_receive.ID) //Verzweigen anhand der ID {case 0x200: motor_receive[0]=CANreceive; break; case 0x223: motor_receive[1]=CANreceive; break; . . default: break; //alles andere wegschmeissen } } } Jetzt hast du ständig die aktuellen Werte in den Variablen motor_receive[?] und kannst damit weiterarbeiten. Beispielsweise willst du die Geschwindigkeit haben. Die steht in z.B. bei ID 0x200, Byte 3 und 4 unsigned int Geschwindigkeit; Geschwindigkeit=(unsigned int)motor_receive[0].data[3] + (unsigned int)motor_receive[0].data[4]<<8;
Habe gerade was ausprobiert. Ist leider Basic, aber ich denke das kann man so leicht lesen und verstehen, was im Programm passiert. Fangen wir an. Beim Interrupt bekommt eine Variable O den Wert 1. Das ist für nachher wichtig. Ausserdem habe ich an 2 Pins LEDs dran. Eine habe ich LED_RX und die andere LED_TX genannt, damit ich ungefähr sehen kann, was im Programm überhaupt passiert. wenn Filter = 0 ist, dann heisst das der RXF0 die Nachricht durch gelassen hat. Wenn Filter = 1 ist, heisst der RXF1 hat die Nachricht durchgelassen. Filter2 = 1 heisst RXF2 (Buffer1) hat die Nachricht akzeptiert. das Programm sieht aktuell so aus.
1 | do
|
2 | |
3 | if O = 1 then 'wenn Interrupt ausgelöst wurde, ist O = 1, ansonsten 0 |
4 | Set LED_RX 'LED einschalten |
5 | Filter_erkennen 'im Subprogramm wird geschaut welcher F. ausgelöst hat |
6 | Read_register_b0 'RXB0 wird ausgelesen |
7 | Read_register_b1 'RXB1 wird ebenfalls ausgelesen,weil es ja schnell geht |
8 | Reset LED_RX 'LED geht aus |
9 | |
10 | if Filter = 0 then |
11 | H2O = Wert2 'Wertx ist der entsprechende Byte nach dem Auslesen |
12 | OEL = Wert3 |
13 | W1 = 1 'hilfsvariable dass Temp. vorhanden ist |
14 | O = 0 'Da ausgelesen, O für Interrupt freigeben |
15 | Goto evtl._senden 'siehe unten |
16 | end if |
17 | |
18 | if Filter = 1 then |
19 | Tank = Wert2 'Wertx ist der entsprechende Byte nach dem Auslesen |
20 | W2 = 1 'hilfsvariable dass Tank vorhanden ist |
21 | O = 0 'Da ausgelesen, O für Interrupt freigeben |
22 | Goto evtl._senden 'siehe unten |
23 | end if |
24 | |
25 | if Filter = 1 then |
26 | Speed = Wert5_b1 ' Byte für Geschw. im Buffer1 |
27 | W3 = 1 'hilfsvariable dass Tank vorhanden ist |
28 | O = 0 'Da ausgelesen, O für Interrupt freigeben |
29 | Goto evtl._senden 'siehe unten |
30 | end if |
31 | |
32 | |
33 | evtl._senden: |
34 | if w1 = 1 and w2 = 1 and w3 = 1 then 'wenn alle Werte vorhanden |
35 | Set LED_TX 'Led ein |
36 | gosub umrechnen_senden 'subprogramm zum Umrechnen und senden |
37 | Read_register_b0 'RXB0 wird ausgelesen, um Interrupt zu löschen |
38 | Read_register_b1 'RXB1 wird ausgelesen, um Interrupt zu löschen |
39 | w1 = 0 'Variablen wieder freigeben, da gesendet wurde |
40 | w2 = 0 |
41 | w3 = 0 |
42 | O = 0 'O muss 0 sein, da Interrupt gelöscht wurde |
43 | Reset LED_TX 'Led aus |
44 | end if |
45 | |
46 | end if |
47 | |
48 | loop
|
In diesem Fall geht die LED_TX gar nicht an, als ob wie w1, w2, w3 != 1 sind, obwohl alle Daten vorhanden sein sollten. Die Filter funktionieren, die Nachrichten werden richtig empfangen, irgendwo hackt das aber immer noch. Sieht Jemand den Fehler? Es muss mit der Logik was nicht stimmen. Danke
>if Filter = 1 then > Speed = Wert5_b1 ' Byte für Geschw. im Buffer1 Sorry, es muss if Filter2 = 1 then Speed = Wert5_b1 heissen Gruss Alex
Warum hängst du dich an den Filtern auf? Ist doch schnurzegal, ob die von RXBUF0 oder 1 kommen. Spätestens, wenn du mal an den Filtereinstellungen rumspielst oder die Sache als Grundlage für ein neues Projekt nehmen willst oder eine 3. zu empfangene Botschaft dazukommt, hast du ein Problem. Die Grundlage der Sache ist und bleibt die ID der Botschaft. Emfange die Botschaft, schau nach, welche ID die hat und entscheide danach, was damit zu tun ist. Nicht mehr und nicht weniger. Und wenn du es so machst wie oben beschrieben, brauchst du überhaupt keine Filter im CAN-Controller. Du bekommst alles rein und kannst auch später schnell noch eine weitere Botschaft mit auswerten, alles, was nicht ausdrücklich benutzt wird, landet im Papierkorb. Die Filter sind nützlich, wenn der Prozessor stark beschäftigt ist und durch das Empfangen unnützer Nachrichten ausgebremst würde. Das ist bei dir mit Sicherheit nicht der Fall. Und ob du nun ständig nur wartest oder zwischendurch auch ein paar Nachrichten einliest und verwirfst, ist doch schnuppe. Wenn die ganze Sache dann mal fertig ist, kannst du die Filter immer noch setzen. Erstmal erschwert es die Sache nur und bringt nichts.
Stimmt, du hast Recht, anhang der ID kann ich die Nachricht auch zuordnen. Aber mit den Filter ist doch quasi das Gleiche?! Wenn ich weiss, das Filter0 nur die ID 280h durchlässt, dann weiss ich automatisch, wenn Filter0 ausgelöst hat, dass die Nachricht die ID 280 hat. Filter komplett ausschalten, und Alles empfangen, halte ich für etwas übertrieben. Auf dem Motor-Can ist eine Menge los, und das Ganze läuft mit 500kbit. Meinst du ich soll erst mal Alles empfangen, und ID vergleichen? Ich werde erst mal versuchen, die Nachrichten nicht nach Filter ordnen, sondern nach IDs. Vielleicht geht das dann besser. Andere Vorschläge sind sehr erwünscht. Gruss Alex S.
Ich hab ne Anwendung, da liegt mein Teil als bridge zwischen Motorsteuergerät und dem Rest des Autos. Beide laufen mit 500kBit und die beiden Seiten sind quasi null-kompatibel. D.h. ne ganze Menge wird auf beiden Seiten empfangen, umsortiert, umgerechnet und auf der anderen Seite wieder verschickt. Nebenbei noch ein paar Analogsensoren auslesen und die Werte auch mit verwursten. Arbeitet komplett ohne Filter und problemlos. Eigentlich wollte ich die am Schluss noch einbauen - aber warum? Hab spasseshalber einen Pin wackeln lassen, wenn nichts zu tun ist - MC-Auslastung (ATMega32@16MHz, SPI 8MHz) liegt bei ca. 60%...
@H.joachim Seifert Mein Respekt!!! Gruss Alex
Sorry, Christoph ist mein Büronachbar. Gruss Alex S.
Wenn ich es richtig verstanden habe, soll auf CAN2 alle 200ms der berechnete Wert gesendet werden, oder? Zum Konzept. *Interrupt 1 (CAN1 Empfangen) schauen welche Nachricht wurde empfangen (egal ob per Filter Nr. oder ID) Den benötigten Wert in eine entsprechende Variable (H2O, OEL, TANK, Speed) speichern. Fertig *Interrupt 2 (Timmer, löst alle 200ms aus) Die Variablen nehmen, Wert berechnen, in Nachricht packen und senden. *Hauptprogramm Mach was, was auch immer, z.B. langweilen Habe ich jetzt was wichtiges übersehen?
PS. Da du beide CAN-Controller an einer SPI Schnittstelle betreist musst du natürlich verhindern, dass während der eine CAN-Controller angesprochen wird auch der andere aktiviert wird. Allso noch eine abgeänderte Version: *Interrupt 1 (CAN1 Empfangen) Timerinterrupt sperren schauen welche Nachricht wurde empfangen (egal ob per Filter Nr. oder ID) Den benötigten Wert in eine entsprechende Variable (H2O, OEL, TANK, Speed) speichern. Timerinterrupt freigeben Fertig *Interrupt 2 (Timer, löst alle 200ms aus) CAN1-Interrupt sperren Die Variablen nehmen, Wert berechnen, in Nachricht packen und senden.CAN1-Interrupt freigeben Der Prozessor hällt sich so nur sehr kurz in den Interruptroutinen auf.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.