Hallo! Ich schreibe meine Programme in Basic und habe gerade ein Problem. Habe eine Platine mit 2x MCP2515, die als Gateway funktioniert. Der µC läuft mit 16Mhz, MCPs laufen auch mit 16Mhz. SPI 1Mhz. Can 500kb/s. Ca. 40% ausgelastet. Habe manchmal das Problem, dass die Firmware sporadisch stehenbleibt. Bewusst reproduzieren konnte ich das nicht. Ich vermute es liegt an meinem Programmablauf. Ich kann leider kein Quellcode hier posten, deswegen schreibe ich mein Ablauf. µC initialisieren nicht beschaltete Pins aus Ausgang setzen Interrupts konfigirieren. INT0 1. MCP2515 1. MCP2515 initialisieren (nur zum Lesen) 2. MCP2515 initialisieren (nur zum Senden) DO IF A = 1 then (Leitung INT0 ist mit dem INT Pin vom MCP2515 verbunden) Empfangsbuffer erkennen (in welchem Buffer die Nachriegt liegt) Wenn die Nachricht im Buffer0 liegt Daten Buffer0 auslesen und 1:1 mit dem 2. MCP Senden (Sendebuffer 0) Wenn die Nachricht im Buffer1 liegt Daten Buffer1 auslesen und 1:1 mit dem 2. MCP Senden (Sendebuffer 1) Wenn die Nachricht im Buffer0 UND Buffer1 liegt Daten Buffer0 auslesen und 1:1 mit dem 2. MCP Senden (Sendebuffer 0) Daten Buffer1 auslesen und 1:1 mit dem 2. MCP Senden (Sendebuffer 1) A = 0 (Alles quasi abgearbeitet) end if LOOP INT0: A = 1 (Wenn Empfangsinterrupt ausgelöst wurde, Variable A auf 1 setzen, in DO-LOOP dann weiter verarbeiten) Return An sich funktioniert das Programm wie geschmiert. Kann Stundenlang laufen ohne Probleme. ABER, ab und zu habe ich sporadische Ausfälle, wo ich Reset drücken muss. Meine Vermutung: Wenn Nachricht empfangen wurde, wird die Variable A auf 1 gesetzt. Wenn Alles abgearbeitet wurde, wird die Variable A wieder auf 0 zurückgesetzt. ABER, was passiert, wenn mein Programm in der Do-Loop-Schleife gerade z.B. die Nachricht verschickt UND gerade eine NEUE NACHRICHT eintrifft, wird die Variable A nun wieder auf 1 gesetzt. Das merke ich ja nicht, und arbeite meine DO-LOOP Schleife zu Ende ab,und setze die Variable wieder auf 0 (obwohl eine Neue Nachricht da ist). Die neue Nachricht wird nicht ausgelesen, weil A = 0 ist, und Interrupt vom MCP2515 wird auch nicht gelöscht, weil er erst beim Auslesen gelöscht wird. Tja, währen ich den Post geschrieben habe, habe ich mein Problem auch erkannt. Ist plausibel, oder? Biete um Bestätigung. Gruß Ralf
Ich würde A im Int immer um 1 erhöhen und die Schleife in der Main solange ausführen wie a>0 ist. A dann natürlich nach jedem Durchlauf nicht auf 0 setzen sondern um 1 verringern. Gruß Thomas
Hast du dir auch schon die errata-pdf auf der microchip-seite für den MCP2515 angesehen? Könnte hilfreich sein!
Thomas H. schrieb: > Ich würde A im Int immer um 1 erhöhen und die Schleife in der Main > solange ausführen wie a>0 ist. A dann natürlich nach jedem Durchlauf > nicht auf 0 setzen sondern um 1 verringern. Falls der µC ein AVR ist, dann sollte die Variable A auf jeden Fall nur 8bit breit sein und mit volatile deklariert werden. Es kann sonst zu Problemen kommen, wenn A im Interrupt-Handler verändert wird. Gruß Chris
Habe ich jetzt erst durchgelesen. Gib mir bitte einen Tip, worauf ich achten muss. Sehe da selber nichts. Danke
@Christoph H. Habe da Basic gelesen und ging davon aus das Basic das selbst schon berücksichtigt. Kenne nur Bascom und da ist es so ;) Aber klar kommt auch auf den µC an, könnte ja auch ein PIC sein und da kenne ich mich mit Basic Dialekten nicht aus. Gruß Thomas
Das Problem ist, ich habe nur einen Versuch. Ich muss die Platinen bald ausliefern, und die sollen stabil laufen. Falls ich das später umflashen muss, fallen Kosten an umd die Situation an sich ist dann auch schlecht. Die Idee mit : >A im Int immer um 1 erhöhen ...nach jedem Durchlauf nicht auf 0 setzen >sondern um 1 verringern. finde ich gut, habe aber etwas Angst, dass es sich wieder etwas verhacken kann. Weil es kann u.U. sein, dass ich die falschen Daten auslese, weil diese nicht aktuell sind. Wie wäre es mit: A nicht am Ende auf 0 setzen, sondern sofort am Anfang: DO IF A = 1 then (Leitung INT0 ist mit dem INT Pin vom MCP2515 verbunden) A = 0 Empfangsbuffer erkennen (in welchem Buffer die Nachriegt liegt) ... alles erledigen ... LOOP Kann das so stabil laufen? Es ist nicht so schlimm, wenn eine Nachricht verloren geht. VIEL schlimmer ist es, wenn die Daten (Bytes) falsch ausgelesen und gesendet werden, oder das Programm einfach stehen bleibt. Danke Gruß Ralf
Wenn Nachrichten ruhig verloren gehen können könntest du auch nach IF A=1 THEN den Interrupt abschalten und am Ende vor dem END IF wieder aktivieren, dann sollte es egal sein wo du A innerhalb der IF THEN ... END IF auf 0 setzt. Gruß Thomas
Glaube nicht, dass es funktioniert. Der Interrupt reagiert auf fallende Flanke. Wenn ich vor End if Interrupt wieder aktiviere, dann ist der Pin bereits auf LOW. So stehe ich immer noch beim alten Problem. Ich glaube ich mache es doch mit A++ und in der DO-Loop A--. Kann da etwas schief gehen? Gruß
Hallo Ralf, ich würde beides probieren denn wenn der INT Low ist beim wieder aktivieren ist das ja kein Flankenwechsel nach Low, erst müsste die Leitung ja wieder auf High und dann nach Low wechseln um einen Int auszulösen. Aber wie gesagt könnte beides gehen, einfach probieren. Um welchen controller handelt es sich denn nun eigentlich? Gruß Thomas
Ach ja, A-- nicht in der Loop sondern in der IF THEN ... END IF ! Gruß Thomas
Handelt sich um AVR und Bascom. Werde mal probieren, den Fehler zu reproduzieren, wo ich nun weiß wie es zustande kommt. Kann dann die beiden Varianten ausprobieren und gucken, was hilft. Danke für die Beteiligung. Gruß
>Ach ja, A-- nicht in der Loop sondern in der IF THEN ... END IF !
Ja, logisch, habe das so gemeint ;)
Danke für die Aufmerksamkeit.
Interrupt auf fallende Flanke ist ganz schlecht. Setz ihn auf low-level.
>terrupt auf fallende Flanke ist ganz schlecht. Setz ihn auf low-level.
Dann kann ich ja ganz ohne Interrupts arbeiten, oder?
Etwa so:
PinX.x = Input
DO
IF PINx.x = 0 then (Wenn MCP Int Pin auf LOW ist)
Empfangsbuffer erkennen (in welchem Buffer die Nachriegt liegt)
...
alles erledigen
...
LOOP
Spricht da was gegen?
Danke
Nein, nicht drauf verzichten. Wahrscheinlich ist bei dir folgendes Szenario: 1. Interrupt kommt, du liest den MCP aus. Bevor du alles gelesen hast können in der Zwischenzeit aber weitere Interrupts gekommen sein, d.h. die Int-Leitung bleibt low, und du bekommst nie wieder eine Flanke. Also levelgesteuerter Interrupt. Ist noch ein weiterer anhängig, springt der MC direkt nach Verlassen der ISR wieder in die ISR und versucht den nächsten zu bearbeiten.
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.