CAN bus message, stm32f407

Gast #5012556
Hallo!

Ich habe bei deiner Umsetzung einer Aufgabe ein Problem.

Hier ein Fragment von meinem Code. In der Textdatei im Anhang ist er 
komplett:

void CAN1_RX0_IRQHandler (void)
{
      CAN_Receive(CAN1, CAN_FIFO0, &RxMsg);

      if (counter1 == 10)
          {

                                      TxMsg.StdId = 0x11D;
                                            TxMsg.ExtId = 0;
                                      TxMsg.DLC = 1;
                                      TxMsg.IDE = CAN_ID_STD;
                                      TxMsg.RTR = CAN_RTR_DATA;

                                       // send  number of received 
messages
                                      TxMsg.Data[0] = counter2;


                                            CAN_Transmit(CAN1, &TxMsg);
                                       GPIO_ToggleBits(GPIOD,GPIO_Pin_12);

                                        }

      if(RxMsg.StdId == 0x67)
        {
              counter1++;
        }

      else if(RxMsg.StdId == 0x52)
        {
               counter2++;
        }
}

// end of fragment



Ich will eine Nachricht mit bestimmten Inhalt senden, sobald ich die 
Nachricht mit der ID 0x67 zehnmal empfangen habe.

Mit dem CANalyzer konnte ich bisher noch nicht das entsprechende 
Resultat erzielen. Wie kann ich sicherstellen, dass ich genau 10 
messages zähle, abreche und dann keine weitere 0x67 Nachricht beim neuen 
Zählanlauf übersehe (mit dem Raussenden der Nachricht würde eventuell 
eine 11. (die neue erste msg des Folgezyklus) Nachricht übersehen.

Kann mir jemand Tipps geben oder hat ähnliche Probleme bereits gelöst?

Danke, Gruß
Korke
Angehängte Dateien:
Dein ISR empfängt erstmal 10 Msgs mit (RxMsg.StdId == 0x67). Bei der 10. 
dieser Msgs passiert noch: garnichts.

Erst NACH der 10. msg wird JEDE empfangene msg eine Antwort erzeugen. 
Dies passiert so lange, bis eine 11. msg mit (RxMsg.StdId == 0x67) 
empfangen wird. Diese wird noch einmal eine Antwort senden, danach wird 
aber (counter1 > 10) und damit wird nie wieder eine AntwortMsg 
verschickt (korrekter: erst nach 2^32 empfangenen msgs).

Gruß, Stefan
Hi,

Wenn du die CAN Nachricht erst auf die ID 0x67 prüfst , dann den Zähler 
erhöhst. Mit dem Zähler kannst du dann den Rest einer Division durch 
nehmen und den auf
1
if((counter1 % 10) == 0)

prüfen. Damit sollte es gehen , wenn sende Puffer und Empfangspuffer 
getrennt sind. Welche ID hat deine Antwort ? Wenn die größer als 0x67 
ist kann theoretisch die Nachtichten der IDs <= 0x67 deine Antwort 
überschreiben.

Gruß JackFrost
Bastian W. schrieb:
> Wenn die größer als 0x67
> ist kann theoretisch die Nachtichten der IDs <= 0x67 deine Antwort
> überschreiben.

Nein, bei CAN werden keine msgs überschrieben. Die msg mit der 
niedrigeren Priorität wird bei gleichzeitigem Sendeversuch später 
gesendet bzw. wiederholt.

Die höchste Priorität hat beim CAN-Bus eine msg mit der Priorität 0x00.

Gruß, Stefan
Gast
Ich würde nun das probieren. Leider komme ich aber erst morgen wieder an 
CANalyzer:


void CAN1_RX0_IRQHandler (void)
{
      CAN_Receive(CAN1, CAN_FIFO0, &RxMsg);

      if ((counter1 % 10) == 0)
          {

                                      TxMsg.StdId = 0x11D;
                                      TxMsg.ExtId = 0;
                                      TxMsg.DLC = 1;
                                      TxMsg.IDE = CAN_ID_STD;
                                      TxMsg.RTR = CAN_RTR_DATA;

                                       // send  number of received
messages
                                      TxMsg.Data[0] = counter2;


                                            CAN_Transmit(CAN1, &TxMsg);
                                       GPIO_ToggleBits(GPIOD,GPIO_Pin_12);

                                        }

      if(RxMsg.StdId == 0x67)
        {
              counter1++;
        }

      else if(RxMsg.StdId == 0x52)
        {
               counter2++;
        }
}

// end of fragment


Ich habe bezüglich den 8 Bit, die die Message höchstens versenden kann, 
leider keinen Schimmer, wie ich darangehen soll. Wenn ich über die 2^8 
hinaus bin, sehe ich ein, dass es dann ohnehin nicht mehr funktioniert.
So wie Du das machst, wird die Antwort-msg immer dann geschickt, wenn 
counter1 durch 10 teilbar ist.
Zusätzlich: Da zuerst die Abfrage "durch 10 teilbar" und danach 
"counter1++" kommt, geschieht das erst bei der 11. empfangenen 0x67-msg!

Du willst aber nur dann die Antwort senden, wenn die empfangene msg eine 
(RxMsg.StdId == 0x67) ist UND der counter durch 10 teilbar ist.

Also:
1
  if(RxMsg.StdId == 0x67)
2
  {
3
    counter_0x67++;
4

5
    if ((counter_0x67 % 10) == 0)
6
    {
7
      // todo: Antwort-msg auf 0x67 senden
8
      // todo: Led togglen
9
    }
10
  }
11

12
  if(RxMsg.StdId == 0x52)
13
  {
14
    counter_0x52++;
15

16
    if ((counter_0x52 % 10) == 0)
17
    {
18
      // todo: Antwort-msg auf 0x52 senden
19
      // todo: Led togglen
20
    }
21
  }

Ich habe mal Deine counter umbenannt, dann ist der Zusammenhang 
intuitiver.

Korke schrieb:
> Ich habe bezüglich den 8 Bit, die die Message höchstens versenden kann,
> leider keinen Schimmer, wie ich darangehen soll. Wenn ich über die 2^8
> hinaus bin, sehe ich ein, dass es dann ohnehin nicht mehr funktioniert.

Du kannst Deine uint32_t counter (4 Byte) entweder in TxMsg.Data[0] bis 
TxMsg.Data[3] speichern.
Wenn Du nicht weisst, wie das geht, dann kannst Du immer noch Deine 
counter-Definition auf uint8_t ändern. Dann läuft der Counter zwar 
schneller über, aber das Programm ist formal richtiger ...

Viele Grüße, Stefan
Gast
Ist es eventuell besser die Variablen, die global deklariert sind, in 
die main zu packen?

Was wäre ein Grund dafür? - Wir konnten nur antworten, dass wir es 
bisher immer so gemacht haben.
Korke schrieb:
> Ist es eventuell besser die Variablen, die global deklariert sind, in
> die main zu packen?
>
> Was wäre ein Grund dafür? - Wir konnten nur antworten, dass wir es
> bisher immer so gemacht haben.

Autsch, ich hoffe mal nicht an einer Uni. Mein Prof hätte mich bei so 
einer Antwort aus dem Kurs geschmissen mit der Empfehlung nächstes Jahr 
erneut zu belegen...

Denk mal nach, Stichwort Gültigkeitsbereich

Gehört zum allerersten Grundstoff.
Probier es einfach aus.

Die Variablen, die Du in der main() definierst, sind in der ISR nicht 
bekannt. Das wird also nicht funktionieren, der Compiler wird Dir einen 
Error bringen.

Die eigendliche Domäne globaler Variablen ist die Kommunikation zwischen 
Interrupts und dem "normalen" Programm.

Viele Grüße, Stefan

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.