Ich habe eine konzeptionelle Frage. Und zwar habe ich zwei MCP2515 basierende Shields und einen Arduino um damit ein unidirektionales Gateway aufzubauen. Es solleb CAN Botschaften auf einem Bus gelesen (Entstehen auf dem Bus im Intervall von 10 ms), umgerechnet und auf dem anderen geschrieben werden (200 ms Sendeperiode). Das ganze hatte ich mir so vorgestellt das für eingehende Nachrichten ein Hardware-Interrupt am Arduino ausgelöst wird, sobald am MCP eine vollständige Botschaft empfangen wurde. Weil es da noch mehr auf dem Bus gibt, möchte ich einen Filter auf die ID setzen, welche mich interessiert. Es könnten später aber mal auch noch zwei, drei weitere IDs dazukommen. Nachdem der MCP den Interrupt ausgelöst hat, soll der Arduino in einer ISR die Botschaft via SPI auslesen und in einen Buffer im RAM schreiben. Dann wäre die Routine auch schon fertig. Ich habe also zur Laufzeit immer eine Kopie der letzten gültigen Botschaft in einem Array. Nun soll die Senderoutine über einen Timer ausgelöst werden, weil ich delays() vermeiden möchte. Der Timer ruft dann alle 200 ms eine andere ISR auf, welche die Daten im Buffer umrechnet und via SPI ans andere Interface sendet. Jetzt weiss ich nicht wie das ist, wenn während dem lesen der Daten vom SPI dort wieder neue Daten vom Bus reinkommen. Ich habe irgendwie Sorge das sich was überschneidet oder überschreibt bei den parallelen Zugriffen. Wie verhindere ich das am besten?
:
Bearbeitet durch User
Olli Z. schrieb: Dein Konzept klingt gut. > > Jetzt weiss ich nicht wie das ist, wenn während dem lesen der Daten vom > SPI dort wieder neue Daten vom Bus reinkommen. Da passiert rein gar nichts, der MCP2515 speichert die und fertig. Das Interrupt-Pin bleibt gesetzt und löst bei der Rückkehr vom Interrupt sofort einen neuen aus.
Also trifft das hier zu? Eingehende CAN Botschaften werden immer im "MAB" (Message Assembly Buffer) empfangen. Dieser wird unter bestimmten Bedingungen in einen der beiden Empfangsbuffer RXB0 oder RXB1 übertragen und das RX0IF bzw. RX1IF Flag gesetzt. Und dazu steht im Datenblatt: "This bit must be cleared by the MCU in order to allow a new message to be received into the buffer. This bit provides a positive lockout to ensure that the MCU has finished with the message before the MCP2515 attempts to load a new message into the receive buffer." Also würde ich dieses Bit nach dem lesen der Nachricht zurücksetzen und wäre somit sicher das während meines Lesevorganges eingehende CAN Nachrichten den Inhalt des RX-Buffers überschrieben. Stattdessen überschreiben sich die eingehenden Nachrichten im MAB. Soweit richtig?! Ich müsste jetzt nur mal in die Lin schauen ob dieses Flag bereits automatisch nach dem Lesen zurückgestellt wird oder ich mich darum selbst kümmern muss. --- Zu dem INT Pin sagt das datenblatt: "If the RXnIE bit (CANINTE) is set, an interrupt will be generated on the INT pin to indicate that a valid message has been received." Diesen /INT Pun würde ich zum HW INT Pin 2 vom Arduino legen um einen external interrupt auszulösen. Weiterhin würde ich mal mit dem DSO schauen wie lang so ein SPI Lesezyklus ist. Wenn nämlich blöd läuft dann ist bereits nach dem lesen einer Botschaft schon der nächste interrupt da und somit läuft nur dieser? Ich brauchte ja nich alle Botschaften, mir würde jede zehnte, fünfzehnte reichen. Aber würde ich das machen das ich einige INTs einfach auslasse? Ich hätte jetzt gesagt über eine volatile Zählervariable. Die wirkt dann am Anfang der ISR wie ein Frequenzteiler.
:
Bearbeitet durch User
Bei mir heissen die Dinger MOBs :-). Das ist alles Zeitlupe bei dir, brauchst keine Sorge zu haben. Nimm aber die Hardware-SPI für beide MCPs, CS per Software erzeugen. SPI-Takt möglichst hoch.
Ich muss da nochmal drüber, aber eine erste Messung ergab einen Lesezyklus von ca. 0,6 ms. Das wäre in der Tat schnell genug. Diese einfachen MCP Shields haben alle einen 8 Mhz Quarz drauf, was den Takt begrenzt. Durch umlöten auf 16 MHz wäre da wohl potentiell noch eine Halbierung drin... Ich denke so wie ich derzeit das Setup habe empfange ich nur im RX0B, dafür würde ich auch den INT auslösen (RX0IE) lassen. Ich hoffe man kann den MCP so konfigurieren, das ein INT nur nach dem Empfang einer Botschaft (Mask und Filter auf die zu empfangende ID gesetzt) auslöst. Zumindest habe ich das Register CANINTF so verstanden. Ansonsten müsste ich vorher ja immer schauen ob ich auch wirklich etwas empfangen habe, oder es einen anderen Grund für den INT gab. Nun kommt dann für mich die Frage nach dem Sleepmode ins Spiel. Ich würde gern meinen Arduino schlafen legen, wenn über CAN eine gewisse Zeit nichts mehr empfangen wird. Macht es Sinn den bis zum nächsten Empfang/Sende-Interrupt in den Schlaf zu versetzten? Oder nach einigen Sekunden ohne Nachrichteneingang? Der MCP hat ja auch sleepmodes. Damit würde ich die Stromaufnahme noch weiter reduzieren können. Eigentlich könnte der auch den Spannungsregler für den Arduino einschalten, wenn dieser sich vorher darüber selbst ausgeschaltet hat.
Olli Z. schrieb: > Also würde ich dieses Bit nach dem lesen der Nachricht zurücksetzen und > wäre somit sicher das während meines Lesevorganges eingehende CAN > Nachrichten den Inhalt des RX-Buffers überschrieben. NICHT überschreiben! > Stattdessen > überschreiben sich die eingehenden Nachrichten im MAB. ??? > Soweit richtig?! Nö. Es gibt 2 Empfangspuffer. Die sind im Normalfall beide leer. Jetzt kommt eine CAN-Bachricht, die landet im Puffer 0. Dann wird das RXB0 Bit gesetzt und der IC löst einen Interrupt über seinen Ausgang aus. Die CPU liest die Nachricht. enn jetzt während des Auslesens schon die nächtste Nachricht reinflattert, landet die im noch leeren Puffer 1. Den liest die CPU praktisch unmittelbar im ANschluß zu Puffer 0. Damit ist immer ein Puffer leer, welcher eine ankommende Nachricht puffern kann, wenn die CPU gerade den anderen Puffer liest. Das ist ein einfaches FIFO. Kann man aber auch als Doppelpuffer betrachten. > Zu dem INT Pin sagt das datenblatt: "If the RXnIE bit (CANINTE) is set, > an interrupt will be generated on the INT pin to indicate that a valid > message has been received." > > Diesen /INT Pun würde ich zum HW INT Pin 2 vom Arduino legen um einen > external interrupt auszulösen. Ja. > Weiterhin würde ich mal mit dem DSO schauen wie lang so ein SPI > Lesezyklus ist. Wenn nämlich blöd läuft dann ist bereits nach dem lesen > einer Botschaft schon der nächste interrupt da Naja, nicht wirklich. Denn selbst bei 1 Mbit/s braucht ein CAN-Frame mit 8 Bytes um die 100 Bit, macht ~100us. Das Lesen einer Nachricht mit 8 Mbit/s über SPI dauer vielleicht 20-30us. > und somit läuft nur > dieser? Nur, wenn die CAN-Datenrate sehr hoch ist, dauerhft Messeages an deine Adresse gehen und das Auslesen lahmarschig ist. > Ich brauchte ja nich alle Botschaften, mir würde jede zehnte, fünfzehnte > reichen. Warum? Du willst ALLE Botschaften haben, die an deine Adresse gehen. Das kann man ja bei den Filtern einstellen. > Aber würde ich das machen das ich einige INTs einfach auslasse? Was soll der Unsinn?
Olli Z. schrieb: > Ich muss da nochmal drüber, aber eine erste Messung ergab einen > Lesezyklus von ca. 0,6 ms. Das wäre in der Tat schnell genug. Wie meinen? Das ist lahm^3. Ein CAN-Nachricht hat maximal 10 Bytes incl. Header. Dad sind bei 8 MHz SPI-Takt 10us. Du mißt 600us! > Diese > einfachen MCP Shields haben alle einen 8 Mhz Quarz drauf, was den Takt > begrenzt. Durch umlöten auf 16 MHz wäre da wohl potentiell noch eine > Halbierung drin... Nö, denn den SPI-Takt macht der Master! > Ich denke so wie ich derzeit das Setup habe empfange ich nur im RX0B, > dafür würde ich auch den INT auslösen (RX0IE) lassen. Ich hoffe man kann > den MCP so konfigurieren, das ein INT nur nach dem Empfang einer > Botschaft (Mask und Filter auf die zu empfangende ID gesetzt) auslöst. Klar kann man das. > Zumindest habe ich das Register CANINTF so verstanden. Ansonsten müsste > ich vorher ja immer schauen ob ich auch wirklich etwas empfangen habe, > oder es einen anderen Grund für den INT gab. Das muss man sowieso, wenn mehrere Interruptquellen aktiv sind. > Nun kommt dann für mich die Frage nach dem Sleepmode ins Spiel. Ich > würde gern meinen Arduino schlafen legen, wenn über CAN eine gewisse > Zeit nichts mehr empfangen wird. Macht es Sinn den bis zum nächsten > Empfang/Sende-Interrupt in den Schlaf zu versetzten? Sicher. > Oder nach einigen > Sekunden ohne Nachrichteneingang? Dann erst recht. Das kann man aber auch schon DEUTLICH kürzer. Mikrocontroller beherrschen das Power-Napping, da sind auch 10ms Schlaf gewinnbringend. > Der MCP hat ja auch sleepmodes. Damit würde ich die Stromaufnahme noch > weiter reduzieren können. Kann man, aber ist das wirklich nötig? Das ist ein CMOS-IC. Wenn der nicht sendet, braucht der fast keinen Strom. > Eigentlich könnte der auch den Spannungsregler > für den Arduino einschalten, wenn dieser sich vorher darüber selbst > ausgeschaltet hat. Unsinn.
Olli Z. schrieb: > Ich muss da nochmal drüber, aber eine erste Messung ergab einen > Lesezyklus von ca. 0,6 ms. ?? SPI-Takt kannst du 4MHz benutzen, eine komplette Botschaft zu lesen waren so um die 20Byte, vielleicht auch 25. Also 0,25µs*20Byte*8Bit=40µs.
Und du kannst es dir auch locker leisten, alle Botschaften in den MC zu holen und erst dort anhand der ID zu entscheiden, ob du damit was tust oder die Dingerchen in den Mülleimer beförderst. Masken/Filter kann man später noch setzen, wirklich nötig wird das erst wenn der MC auch sonst viel zu tun hat. So kann man z.B. in der Entwicklungsphase via USB-CAN-Dongle Daten an den MC senden ohne jedesmal die Filtereinstellungen im CAN-Controller anzupassen. Rec_Interrupt: -message lesen -flag setzen, dass was empfangen wurde main: -rec_flag gesetzt? switch (ID) { }
H.Joachim S. schrieb: > Und du kannst es dir auch locker leisten, alle Botschaften in den MC zu > holen und erst dort anhand der ID zu entscheiden, ob du damit was tust > oder die Dingerchen in den Mülleimer beförderst. Wieso? Das kann der MCP2515 deutlich besser. > Masken/Filter kann man später noch setzen, wirklich nötig wird das erst > wenn der MC auch sonst viel zu tun hat. So kann man z.B. in der > Entwicklungsphase via USB-CAN-Dongle Daten an den MC senden ohne > jedesmal die Filtereinstellungen im CAN-Controller anzupassen. Oh wie schrecklich! Da muss man doch TATSÄCHLICH ein paar Zahlen während der Entwicklung ändern!
Olli Z. schrieb: > Der MCP hat ja auch sleepmodes. Damit würde ich die Stromaufnahme noch > weiter reduzieren können. Ich würde jetzt mal tippen der meiste Strom lässt sich sparen wenn man den Transceiver in den Sleep-Mode setzt.
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.