Frage zu "Ringpuffer"

Sorry wenn ich noch mal nerve...
@Dirk



CodeBox C
  // get data of selected MOb
   for (i=0; i<recMsg.length; i++)   
   {   
     CAN_RingBuffer[0].Data[i] = CANMSG;
     //recMsg.data[i] = CANMSG;
   }
     RingBuffer_Insert(CAN_RingBuffer[0]);


Deine Funktion "RingBuffer_Insert" müsste doch auch angepasst werden, so das ich meine ganzen Bytes dort unter kriege? Müsste es nicht auch 2 Dimensionen haben dann?
 
Du schreibst in deiner CAN-Empfangsroutine direkt in den Buffer, das darfst du nicht machen! Und dann willst du diesen Buffer wieder einfügen :confused:

Hier noch ein paar Zeilen Code wie man es machen könnte, am Beispiel RingBuffer_Insert.
Viel weiter kann ich dir leider nicht mehr helfen, da ich nicht so die Zeit habe, sorry :)


CodeBox C
void RingBuffer_Insert(tCANMSG canmsg)
{
  
   uint8_t int_reg = SREG;
   cli();  
  
   RingBuffer[RingBufferInfo.In].Message = canmsg.Message;
   RingBuffer[RingBufferInfo.In].DataLength = canmsg.DataLength;
   for (uint8_t i=0; i<9; i++) RingBuffer[RingBufferInfo.In].Data[i] = canmsg.Data[i];
    
   RingBufferInfo.In++;
  
   if (RingBufferInfo.In == RingBufferInfo.Size)
   RingBufferInfo.In = 0;
    
   RingBufferInfo.Count++;
  
   SREG = int_reg;
  
}

void meinecanempfangsroutine(void)
{
   tCANMSG meine_can_message;
  
   // empfangen
  
   meine_can_message.Message = 1234; // hier die Daten sinnvoll füllen
   meine_can_message.DataLength = 9;
   meine_can_message.Data[0] = 14;
   // ...
   meine_can_message.Data[8] = 14;
   //...
  
   if (!RingBuffer_IsFull())
   {
     RingBuffer_Insert(meine_can_message);
   } else {
     // Buffer voll, Fehler
   }
  
}
 
Habe ich doch genau so gemacht? Bis auf "RingBuffer_Insert"



CodeBox C
void RingBuffer_Insert(CANMSG_t CAN_MESSAGE)
{
   
   RingBuffer[RingBufferInfo.In][0] = CAN_MESSAGE.Message_ID; // contains actual id from message x
   RingBuffer[RingBufferInfo.In][1] = CAN_MESSAGE.DataLength; // contains actual data length from message x
   
   /* store actual data from message x */
   for (uint8_t x = 2 ; x < 10 ; x++)
   {
     RingBuffer[RingBufferInfo.In][x] = CAN_MESSAGE.Data[1];
   }
   
   RingBufferInfo.In++;
   
   if (RingBufferInfo.In == RingBufferInfo.Size)
   RingBufferInfo.In = 0;
   
   uint8_t int_reg = SREG;
   cli();
   
   RingBufferInfo.Count++;
   
   SREG = int_reg;
}



CAN Empfangsroutine:


CodeBox C
// interrupt service for CAN
SIGNAL(SIG_CAN_INTERRUPT1)
{
  // CAN_messageType recMsg; this is a global variable
  uint8_t save_canpage = CANPAGE;     //  actual CANPAGE
  uint8_t mob;
  uint8_t i;
  uint8_t readmodwrite;
  CANMSG_t CAN_RingBuffer[1];

  // check in which MOb the INT was initiated
  mob = getmob(CANSIT2 | (CANSIT1 << 8));
   if( mob == NOMOB )  return;

  // select concerned MOb page
  CANPAGE = (mob << 4);   

  // Senden war erfolgreich
  if (CANSTMOB & (1<<TXOK))
  {
  readmodwrite = CANSTMOB;       
  readmodwrite &= ~(1<<TXOK);   //  reset INT reason
   CANSTMOB = readmodwrite;       
  }
  // Nachricht erfolgreich empfangen
  else if (CANSTMOB & (1<<RXOK))
  {

     // get id of selected MOb
  recMsg.id = 0;
  recMsg.id |= ((uint16_t) CANIDT1<<8);
  recMsg.id |= (CANIDT2&0xE0);
  recMsg.id >>= 5;
   CAN_RingBuffer[0].Message_ID = recMsg.id;

  // get length of selected MOb
  recMsg.length = (CANCDMOB&0x0F);
   CAN_RingBuffer[0].DataLength = (CANCDMOB & 0x0F);
   
  // clear memory
   for (i=0; i<8; i++)   
   {   
    recMsg.data[i] = 0;
   }

  // get data of selected MOb
   for (i=0; i<recMsg.length; i++)   
   {   
     CAN_RingBuffer[0].Data[i] = CANMSG;
     recMsg.data[i] = CANMSG;
   }
     RingBuffer_Insert(CAN_RingBuffer[0]);
   
  // hier kann etwas getan werden oder auch nicht
   // z.B. zum Test eine LED anschalten
   // ansonsten benutzt man die Nachricht aus recMsg dauerhaft in der main
   // und lässt sie durch den INT automatisch aktualisieren

  readmodwrite = CANSTMOB;
  readmodwrite &= ~(1<<RXOK);  //  reset interrupt    
  CANSTMOB = readmodwrite;
   CANCDMOB = (1<<CONMOB1);  //  stay tuned!
  }

  CANPAGE = save_canpage;  //  restore CANPAGE
}
 
Habe ich doch genau so gemacht? Bis auf "RingBuffer_Insert"

Das kann ich nicht wissen, da ich nur einen Bruchteil der Routine sehen konnte. Ich bin davon ausgegangen, dass du direkt in den Buffer schreibst, weil es sich um ein Array gehandelt.


CodeBox C
CAN_RingBuffer[0].Message_ID = recMsg.id;


Ein "Array" brauchst du hier nicht.
CANMSG_t CAN_RingBuffer[1];

Das stimmt so auch nicht, das ist nun wieder einfach ein zweidimensionales Array. Der Compiler müsste sich hiier auch weigern den Code zu erzeugen ;)
RingBuffer[RingBufferInfo.In][0] = CAN_MESSAGE.Message_ID;

Richtig wäre
RingBuffer[RingBufferInfo.In].Message
usw.
 
Jetzt ist nur noch die Frage...
Wie gebe ich die ganzen Werte zurück?
Sprich:

.Data[0-7]
.MsgLength
.MsgID

Also aus der Funktion #Ringbuffer_Remove
 
Zuletzt bearbeitet:
Wie gebe ich die ganzen Werte zurück?
... Also aus der Funktion #Ringbuffer_Remove

Du kannst den Zeiger auf die Struktur als Parameter der Funktion übergeben,
in etwa so ...




CodeBox C
void fuellemeinestruct(tCANMSG *meinestruct)
{
   meinestruct->Message = 1234;
   meinestruct->DataLength = 9;
   meinestruct->Data[5] = 0;
  
   // oder
  
   (*meinestruct).Message = 1234;
   //...
  
}

void meinefunction(void)
{
   tCANMSG meine_can_message;  
  
   if (!RingBuffer_IsEmpty())
   {
     fuellemeinestruct(&meine_can_message);
     // meine_can_message ist gefüllt
     //...
   } else {
     // keine Daten vorhanden
   }
   
}
 
Ja Okay, meinte jetzt aus "RingBuffer_Remove" wie ich dort die Werte zurück gebe?
 
Ja Okay, meinte jetzt aus "RingBuffer_Remove" wie ich dort die Werte zurück gebe?

Das habe ich oben im Beispiel geschrieben.

Die Funktion RingBuffer_Remove ist die Funktion fuellmeinestruct.
 
Damit habe ich doch gar nicht mehr die Funktion vom Ringbuffer gegeben oder bin ich jetzt doof?
 
Damit habe ich doch gar nicht mehr die Funktion vom Ringbuffer gegeben oder bin ich jetzt doof?

Du hattest gefragt ...
Wie gebe ich die ganzen Werte zurück?

darauf habe ich dir ein Beispiel gezeigt, wie man Daten zurückgeben kann. Ich kann dir leider nicht alles für deine Anwendung umschreiben, dafür fehlt mir die Zeit

Wie man in den Buffer schreibt, habe ich ja schon am Beispiel erklärt. Aus dem Buffer lesen, solltest du dadurch hinbekommen.
 
Die Funktion könnte so aussehen ...
(aus der Hand geschrieben, musst mal im Compiler testen)
Ich lese immer alle 9 Databyte, auch wenn DataLength kleiner ist, das macht ja nichts aus.



CodeBox C
void RingBuffer_Remove(tCANMSG *meinestruct)
{
  uint8_t int_reg = SREG;
  cli();

  // Diesen Block hier anpassen
  (*meinestruct).Message = RingBuffer[RingBufferInfo.Out].Message;
  (*meinestruct).DataLength = RingBuffer[RingBufferInfo.Out].DataLength;
  for (uint8_t i=0, i<9; i++) (*meinestruct).Data[i] = RingBuffer[RingBufferInfo.Out].Data[i];
  // Block Ende

  RingBufferInfo.Out++;
  if (RingBufferInfo.Out == RingBufferInfo.Size)
  RingBufferInfo.Out = 0;

  RingBufferInfo1.Count--;
  SREG = int_reg;

}


Aufruf dann zum Beispiel so ...



CodeBox C
int main (void)
{
  tCANMSG meine_can_message; 
  // ...
  while (1)
  {
     if (!RingBuffer_IsEmpty())
     {
       // Daten vorhanden
       RingBuffer_Remove(&meine_can_message);
       // meine_can_message ist gefüllt
       // dann deinen Parser aufrufen
       // ...
     } else {
       // keine Daten vorhanden, nichts zu tun
     }

    // ...

  }

}
 
Mich verwirrt es nur weil ich bei der ursprünglichen Variante einen Rückgabewert hatte und da wusste ich gerade noch so wie ich es hand haben müsste... Hier ist es jetzt ein wenig komplizierter.
 
Mich verwirrt es nur weil ich bei der ursprünglichen Variante einen Rückgabewert hattehatte und da wusste ich gerade noch so wie ich es handhaben müsste... Hier ist es jetzt ein wenig komplizierter.

Ja, das ist nun schon komplexer, aber im Prinzip ja fast das selbe. Du übergibst der Routine einen Zeiger auf eine Instanz einer Struktur. Die Routine kann dann auf deine Instanz zugreifen und "füllt" diese mit Werten für die einzelnen Member (Message, Data[], DataLength).

Nach der Routine hast du dann alle Werte in deiner Instanz aus dem Fifo Buffer gelesen. Jetzt kannst du diese weiterverarbeiten, also deinen Parser aufrufen.

Ich muss noch dazu sagen, ich habe viel aud der Hand raus geschrieben, ich kann es nicht sagen, ob es fehlerfrei ist :)
 
Daraus lerne ich ja Dirk kein Problem. Und der RingPufferRingPuffer speichert auch wirklich dann meine x Bytes zwischen und der älteste wird immer als nächstes verarbeitet?
 
Daraus lerne ich ja Dirk kein Problem. Und der RingPufferRingPuffer speichert auch wirklich dann meine x Bytes zwischen und der älteste wird immer als nächstes verarbeitet?

Ich hoffe mal, probiere es aus :)

Ich hatte den Code aus einem meiner Projekte herauskopiert, er ist angepasst und stammt aus dem Lufa Projekt. Bei mir funktioniert er sehr gut. Du musst hier allgemein aber auch immer abfragen, ob du reinschreiben kannst, also ob der Buffer voll ist und entsprechend reagieren. Genauso überhaupt Daten drin sind, bevor du raus liest. Und nicht vergessen _Init() aufzurufen.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)