www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik sprintf mehrfach


Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich hab jetzt ne Weile die Beiträge zum Thema sprintf gelesen aber 
leider nichts gefunden was meinem Problem ähnelt.
Und zwar läuft die Funktion wenn ich sie nur einmal aufrufe wunderbar. 
Sobald aber ein zweiter sprintf Befehl hinzukommt, erhalte ich einen 
HardFault_Handler. Kann es Probleme geben wenn man die Funktion zweimal 
aufruft?
ich arbeite mit einem LPC1768 und möchte Daten vom CAN-Bus ausgeben. 
Hier beide anweisungen, falls ihr was seht immer her damit =)
mph = 123;
char feld[12];
sprintf(feld,"%1u",mph); 
lcd_draw_string(font_vw_24px, NORMAL_STYLE,feld,43,60,255);

kmm = 123459;
char kmm[12];
sprintf(kmm,"%1u",km);
lcd_draw_string(font_vw_24px, NORMAL_STYLE,kmm,5,155,255); 


Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> kmm = 123459;
  ^^^
> char kmm[12];
       ^^^
> sprintf(kmm,"%1u",km);
          ^^^       ^^

Tippfelher

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> sprintf(feld,"%1u",mph);
Was willst du mit dem Modifier %1u (prozent eins u) erreichen?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ADD: Dein Compiler sollte eine Warnung geschmissen haben. Wenn keine 
Warnung kam, nachsehen, wie man die Warnungen aktiviert.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> kmm = 123459;
> char kmm[12];

was genau bezweckst du mit diesem Code?

Zuerst weißt du einer nicht deklarierten Variable den Wert 123459 zu 
(schon das müsste einen Fehler ergeben). Danach deklarierst du die 
Variablen (12 Stück) als char (=8bit). Solltest du kmm vorher schon 
deklariert haben ergibt das auch einen Fehler da Redeklarationen 
verboten sind.

Wenn du das Array mit 123459 füllen möchtest geht das so:

kmm[12]={1,2,3,4,5,9,0,0,0,0,0,0};

Wenn man ein Array nullen / mit nur einem Wert füllen will geht das so:

kmm[12]={0};

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay vielen dank für die Antworten, hab nun von der sprintf abstand 
genommen und arbeite stattdessen mit einer funktion die den Wert manuell 
in ein ascii zeichen umwandelt und das ganze dann ausgibt, aber vielen 
dnak bis hierher.

Die Ausgabe funktioniert auch jedoch wiederum nur wenn ich eine der 
beiden werte verarbeite, sobald ich den zweiten hinzuschalte erhalte ich 
wieder den HardFault_Handler.
ich poste einfach mal den Code =)

#include "type.h"
#include "can.h"
#include "mfa_display.h"

CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */

volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;
volatile uint32_t data[12];
volatile uint32_t Schalter;
volatile uint8_t TasterCount       = 0;      // Zähler für Wipptasterbetätigung
volatile uint32_t kmph              = 0;      // Variable Stundenkilometer
volatile uint16_t mph               = 0;      // Variable Meilen pro Stunde
volatile uint8_t TASTER_MASK_HOCH   = 0b10;   // Maske Menü hoch
volatile uint8_t TASTER_MASK_RUNTER = 0b01;   // Maske Menü zurück
volatile uint8_t black              = 0;      // Variable für schwarzen Hintergrund
volatile uint32_t km                = 0;      // Variable Kilometerstand


/*****************************************************************************
** Function name:    main
**
** Descriptions:    main routine for CAN module test
**
** parameters:      None
** Returned value:    int
** 
*****************************************************************************/
int main( void )

{
  SystemInit();   // Funktionsaufruf Systeminitialisierung
  lcd_init();
  INOUT_Def();
 
  /* Please note, the bit timing is based on the setting of the 
  PCLK, if different PCLK is used, please read can.h carefully 
  and set your CAN bit timing accordingly. */  
 
  CAN_Init(BITRATE500K15MHZ);       // Bitrate = 500kbaud bei 15MHz
  
 CAN_SetACCF( ACCF_ON );          // Filtermodus festlegen

  while ( 1 )
  { 
    // Wipptasterauswertung
        if((data[0]>>20)&TASTER_MASK_HOCH)   // Tasterauswertung hochzählen
        { LPC_GPIO2->FIOPIN &= ~0xFF;
          TasterCount++;
          data[0] = 0;
          black=1;
        }
        if((data[0]>>20)&TASTER_MASK_RUNTER)   // Tasterauswertung hochzählen
        {LPC_GPIO2->FIOPIN |= 0xFF;
          TasterCount--;
          data[0] = 0;
          black=1;
        }
        if(TasterCount > 8 && TasterCount <=16)
        {
          if(black==1)
          {
            lcd_draw_area(0, 120, 0, 176, 0);
            black = 0;
          }
          // Kilometerstand Ausgabe
          lcd_draw_string(symbols_16px,NORMAL_STYLE,"km",5,140,255);
          km=((data[6]>>8)&0b11111111111111111111);
          lcd_draw_double (font_vw_24px,NORMAL_STYLE,km,7,0,5,155,255);

          // Meilen pro Stunde Ausgabe
          lcd_draw_string(symbols_16px, NORMAL_STYLE,"9",110,30,255);
          lcd_draw_string(symbols_16px, NORMAL_STYLE,"mph",79,60,255);
          kmph=(((data[3]>>14))&0b1111111111)*0.32;
         if(kmph)
          {
            mph = kmph/(1.609);
            lcd_draw_double (font_vw_24px,NORMAL_STYLE,mph,3,0,43,60,255);
          }
          else
          {
            lcd_draw_string(font_vw_16px, NORMAL_STYLE,"-.-",43,60,255);
          }
        }
        else if (TasterCount<9)
        {
        if(black==1)
          {
            lcd_draw_area(0, 120, 0, 176, 0);
            black = 0;
          }
        lcd_draw_string(font_vw_24px, NORMAL_STYLE,"Normal",43,60,255);
        }
  /* please note: FULLCAN identifier will NOT be received as it's not set 
  in the acceptance filter. */
   if ( CAN1RxDone == TRUE )
  {  
           if ( MsgBuf_RX1.Frame & (1 << 10) )  /* by pass mode */
    {
    MsgBuf_RX1.Frame &= ~(1 << 10 );
    }
          CAN1RxDone = FALSE;         
  } /* Message on CAN 2 received */
   
  }

}



void lcd_send_byte(uint8_t u8_Type, uint8_t u8_Byte)
{
  if (u8_Type == CMD)
  {
    LCD_COMMAND_MODE();
  }
  else
  {
    LCD_PARAMETER_MODE();
  }
  
  // -> Serielle Übertragung des Bytes
  for (uint8_t x = 0; x <= 7 ; x++)
  {
    LPC_GPIO1 -> FIOPIN &= ~XWR;
    
    if (u8_Byte & (1<<(7 - x)))
    {
      LPC_GPIO1 -> FIOPIN |= D0;
    }
    else
    {
      LPC_GPIO1 -> FIOPIN &= ~D0;
    }

    LPC_GPIO1 -> FIOPIN |= XWR;        
  }

}

void lcd_send_pixel(uint32_t u32_Block)
{
  LPC_GPIO1 -> FIOPIN &= ~XWR;
  for (uint32_t x = 0; x <= 31 ; x++)
  {
    if (u32_Block & (1<<(31 - x)))
    {
      LPC_GPIO1 -> FIOPIN |= D0;
    }
    else
    {
      LPC_GPIO1 -> FIOPIN &= ~D0;
    }    
  }
   LPC_GPIO1 -> FIOPIN |= XWR;
}


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:

> ich arbeite mit einem LPC1768 und möchte Daten vom CAN-Bus ausgeben.
> Hier beide anweisungen, falls ihr was seht immer her damit =)

Hauptsächlich sehen wir, dass das nicht der Code ist so wie er in deinem 
Programm steht. Poste bitte deinen richtigen Code.
Viele Leute hier haben die Schnauze voll davon, in im Forum eingetippten 
Code nach Fehlern zu suchen, die im richtigen Code gar nicht vorhanden 
sind. Dafür dürfen wir dann immer die Dinge erraten, die der Poster gut 
meinend, nicht gezeigt hat.
Keine Sorge. Die Profis hier haben überhaupt kein Problem damit, 40, 50, 
100 Zeilen Code zu überblicken und mit 1 oder 2 mal durchlesen zu 
verstehen. Das ist unser täglich Brot.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja ich hab ihn jetzt gepostet, mir ist eben aufgefallen, dass der 
Interrupt auch auftritt, wenn ich nur einen der beiden schreibe jedoch 
erst nach einigen sendevorgängen

hier nochmal was zu dem data[] array, in ihm stehen die Daten zugeordnet 
zu den jeweiligen Identifiern also je nachdem welcher identifier gerade 
empfangen wurde wird das dem entsprehcendem feld im array zugeordnet.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau macht die Funktion

          lcd_draw_double (font_vw_24px,NORMAL_STYLE,km,7,0,5,155,255);


Das 'double' im Funktionsnamen, dazu das Argument km als uint32_t, das 
macht mich nervös


Die LCD Funktionen .... hast du die geschrieben, oder ist das eine 
ausführlich getestete Library?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
// LCD-Funktion: Gibt eine positive double-Zahl auf dem LCD Display aus
// - Parameter dbl_value: auszugebende Zahl
// - Parameter u8_lenght: Größe des LCD Feldes (Zahl wird rechtsbündig 
im Feld ausgegeben)
// - Paramter u8_decimals: Anzahl der anzuzeigenden Nachkommastellen
// - Funktion dürfen nur positive Zahlen übergeben werden
// - Funktion sichert sich nicht gegen zu große Zahlen und unplausbile 
Werte ab !!!

Die LCD-Funktionen hab ich übernommen, das hatte ich nur mit eurer Hilfe 
auf meinen Controller angepasst.

Problem des gesamten programmes ist auch noch, dass es viele daten 
hintereinander nicht verarbeiten kann da kommt ein data overrun und 
nichts geht mehr, aus diesem Grund shcicke ich die Daten momentan auch 
einzeln, damit dieser Fehler nicht auftritt, da ich noch nicht weiß wie 
ich das overrun verhindern kann.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> Die Ausgabe funktioniert auch jedoch wiederum nur wenn ich eine der
> beiden werte verarbeite, sobald ich den zweiten hinzuschalte erhalte ich
> wieder den HardFault_Handler.
Dann ist der Fehler wohl woanders...

> sobald ich den zweiten hinzuschalte erhalte ich
> wieder den HardFault_Handler.
Was heißt dazuschalten?



Das verdreht mir ja das Auge. Wieviele Einsen sind das denn?
          km=((data[6]>>8)&0b11111111111111111111);
Ich würde es so schreiben:
          km=((data[6]>>8)&0xFFFFF);
Da sehe ich schneller: 5 x 4 Einsen.


Das ist bedenklich:
volatile uint32_t kmph      = 0;    // Variable Stundenkilometer
    kmph=(((data[3]>>14))&0b1111111111)*0.32;
Hier muß der Compiler etliche implizite Konvertierungen durchführen, um 
vom int32 über einen float wieder auf einen int32 zu kommen...

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dazuschalten heißt in meinem Fall ich kommentiere eine aus und hab nur 
noch eine der beiden stehen, hab aber gemerkt, dass es nen Fehler war, 
dass der Fehler dann nicht mehr auftritt, er kommt nur später hinzu ...

hm okay das war mir nicht bewusst, dass dies zu kompliziert ist, kannst 
du mir helfen und sagen wie es einfacher geht?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also das ganze funktioniert nur zuverlässig, wenn ich einfach nur die 
festen sachen (linien feste werte) ausgebe und nichts von den 
empfangenen Nachrichten als string versuche auszugeben.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so also mit sprintf funktioniert das programm nur solange, solange 
sprintf nur einmal aufgerufen wird

mit der ersatzfunktion funktioniert es selbst wenn sie nur einmal 
aufgerufen wird nur eine zeit lang und dann nicht mehr.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> dazuschalten heißt in meinem Fall ich kommentiere eine aus und hab nur
> noch eine der beiden stehen, hab aber gemerkt, dass es nen Fehler war,
> dass der Fehler dann nicht mehr auftritt, er kommt nur später hinzu ...
???????...????

Tom schrieb:
> also das ganze funktioniert nur zuverlässig, wenn ich einfach nur die
> festen sachen (linien feste werte) ausgebe und nichts von den
> empfangenen Nachrichten als string versuche auszugeben.
Auch eine Zeichenkette ist ein statischer Wert. Nur scheint mir, du 
probierst da mal alle funktionen isrgendwie durch und hoffst, dass sich 
was ändert.
Ich tippe auf einen Stack-Overflow (wobei das bei 64k RAM eher 
unwahrscheilich ist) oder einen amoklaufenden Pointer...
:
CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */

volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;
volatile uint32_t data[12];
:
Verschieb mal die CAN-Puffer woanders hin. Evtl. ändert das was...
So:
volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;
volatile uint32_t data[12];
volatile uint32_t Schalter;
:
CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */
Oder so:
CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */

volatile uint32_t xxx[1000];

volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;
volatile uint32_t data[12];
volatile uint32_t Schalter;
:

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nee ändert leider nichts

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so zu meinem Problem mit dem Empfangen der Nachrichten nocheinmal zurück 
ich werd langsam wahnsinnig

hier ist der Beispielcode von der NXP-Homepage (Sample Code Bundle for 
LPC17xx Peripherals using Keil's MDK-ARM V1.02 )
/*****************************************************************************
 *   cantest.c:  CAN test module file for NXP LPC17xx Family Microprocessors
 *
 *   Copyright(C) 2009, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2009.05.27  ver 1.00    Prelimnary version, first Release
 *
******************************************************************************/
#include "lpc17xx.h"
#include "type.h"
#include "can.h"

CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */

volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;

#if CAN_WAKEUP
extern volatile uint32_t CANActivityInterruptFlag;
#endif

#if CAN_WAKEUP
/*****************************************************************************
** Function name:    CAN_WakeupTest
**
** Descriptions:    main routine for CAN wakeup test
**
** parameters:      None
** Returned value:    None
** 
*****************************************************************************/
void CAN_WakeupTest( void )
{
  uint32_t i, j;

  CAN_SetACCF( ACCF_BYPASS );
  NVIC_EnableIRQ(CANActivity_IRQn);       /* enable USB activity interrupt */

  /* Put the MCU into deep sleep mode first. Any CAN message on RX 
  should wake up the MCU. CAN Activity interrupt won't occur until Deepsleep 
  bit is set in SCR. UM needs to be updated regarding this. */
  SCB->SCR |= 0x04;  /* Set SLEEPDEEP bit in SCR in Cortex M3 core. */  
  LPC_SC->PCON = 0x1;
  __WFI();

  while (1)                            /* Loop forever */
  {
  if ( CANActivityInterruptFlag )
  {
    /* If the MCU is waked up from power down mode, the PLL needs to
    be reconfigured, and USB block needs tn be reset and reconnect. */
    CANActivityInterruptFlag = 0;
    SystemInit();

    CAN_Init( BITRATE125K18MHZ );
    CAN_SetACCF( ACCF_BYPASS );
    while ( CAN2RxDone != TRUE );
    CAN2RxDone = FALSE;

    LPC_GPIO2->FIODIR = 0x000000FF;    /* P1.16..23 defined as Outputs */
    LPC_GPIO2->FIOCLR = 0x000000FF;    /* turn off all the LEDs */
      
    /* Wake up first time, now, blink 10 times. */
    for ( j = 0; j < 10; j++ )
    {
    for ( i = 0; i < 0x200000; i++ );
    LPC_GPIO2->FIOSET = 0x000000FF;
    for ( i = 0; i < 0x200000; i++ );
    LPC_GPIO2->FIOCLR = 0x000000FF;
    }

    /* Once the LED blink number of times, the MCU will go to sleep
    or power down mode again. Another incoming CAN message will wake up
    the MCU again. */
    SCB->SCR |= 0x04;  /* Set SLEEPDEEP bit in SCR in Cortex M3 core. */  
    LPC_SC->PCON = 0x1;
    __WFI();
  }
  }
}
#endif

/*****************************************************************************
** Function name:    main
**
** Descriptions:    main routine for CAN module test
**
** parameters:      None
** Returned value:    int
** 
*****************************************************************************/
int main( void )
{

  SystemInit();
  /* Please note, the bit timing is based on the setting of the 
  PCLK, if different PCLK is used, please read can.h carefully 
  and set your CAN bit timing accordingly. */  
  //CAN_Init( BITRATE100K24MHZ );
  CAN_Init( BITRATE125K18MHZ );  

#if CAN_WAKEUP
  CAN_WakeupTest();
#endif
  
  /* send one message from CAN1(TX) and verify received message on 
  CAN2(RX) if it's a match, both CAN TX and RX are working. 
  For more details on acceptance filter program, see Philips
  appnote AN10438 and the zip file associated with this appnote. */

#if !ACCEPTANCE_FILTER_ENABLED
  /* Initialize MsgBuf */
  MsgBuf_TX1.Frame = 0x80080000; /* 29-bit, no RTR, DLC is 8 bytes */
  MsgBuf_TX1.MsgID = 0x00012345; /* CAN ID */
  MsgBuf_TX1.DataA = 0x3C3C3C3C;
  MsgBuf_TX1.DataB = 0xC3C3C3C3;

  MsgBuf_RX2.Frame = 0x0;
  MsgBuf_RX2.MsgID = 0x0;
  MsgBuf_RX2.DataA = 0x0;
  MsgBuf_RX2.DataB = 0x0;
  CAN_SetACCF( ACCF_BYPASS );

  /* Test bypass */
  while ( 1 )
  {
  /* Transmit initial message on CAN 1 */
  while ( !(LPC_CAN1->GSR & (1 << 3)) );
  if ( CAN1_SendMessage( &MsgBuf_TX1 ) == FALSE )
  {
    continue;
  }
   if ( CAN2RxDone == TRUE )
  {
    CAN2RxDone = FALSE;
    if ( MsgBuf_RX2.Frame & (1 << 10) )  /* by pass mode */
    {
    MsgBuf_RX2.Frame &= ~(1 << 10 );
    }
    if ( ( MsgBuf_TX1.Frame != MsgBuf_RX2.Frame ) ||
      ( MsgBuf_TX1.MsgID != MsgBuf_RX2.MsgID ) ||
      ( MsgBuf_TX1.DataA != MsgBuf_RX2.DataA ) ||
      ( MsgBuf_TX1.DataB != MsgBuf_RX2.DataB ) )
    {
    while ( 1 );
    }
    /* Everything is correct, reset buffer */
    MsgBuf_RX2.Frame = 0x0;
    MsgBuf_RX2.MsgID = 0x0;
    MsgBuf_RX2.DataA = 0x0;
    MsgBuf_RX2.DataB = 0x0;
  } /* Message on CAN 2 received */
  }
#else
  /* Test Acceptance Filter */
  /* Even though the filter RAM is set for all type of identifiers,
  the test module tests explicit standard identifier only */
  MsgBuf_TX1.Frame = 0x00080000; /* 11-bit, no RTR, DLC is 8 bytes */
  MsgBuf_TX1.MsgID = EXP_STD_ID; /* Explicit Standard ID */
  MsgBuf_TX1.DataA = 0x55AA55AA;
  MsgBuf_TX1.DataB = 0xAA55AA55;

  MsgBuf_RX2.Frame = 0x0;
  MsgBuf_RX2.MsgID = 0x0;
  MsgBuf_RX2.DataA = 0x0;
  MsgBuf_RX2.DataB = 0x0;
  CAN_SetACCF( ACCF_ON );

  while ( 1 )
  {
  /* Transmit initial message on CAN 1 */
  while ( !(LPC_CAN1->GSR & (1 << 3)) );
  if ( CAN1_SendMessage( &MsgBuf_TX1 ) == FALSE )
  {
    continue;
  }

  /* please note: FULLCAN identifier will NOT be received as it's not set 
  in the acceptance filter. */
   if ( CAN2RxDone == TRUE )
  {
    CAN2RxDone = FALSE;
    /* The frame field is not checked, as ID index varies based on the
    entries set in the filter RAM. */
    if ( ( MsgBuf_TX1.MsgID != MsgBuf_RX2.MsgID ) ||
      ( MsgBuf_TX1.DataA != MsgBuf_RX2.DataA ) ||
      ( MsgBuf_TX1.DataB != MsgBuf_RX2.DataB ) )
    {
    while ( 1 );
    }
    /* Everything is correct, reset buffer */
    MsgBuf_RX2.Frame = 0x0;
    MsgBuf_RX2.MsgID = 0x0;
    MsgBuf_RX2.DataA = 0x0;
    MsgBuf_RX2.DataB = 0x0;
  } /* Message on CAN 2 received */
  }
#endif
}

/******************************************************************************
**                            End Of File
******************************************************************************/
/******************************************************************************
**                            End Of File
******************************************************************************/
/*****************************************************************************
 *  can.c:  CAN module API file for NXP LPC17xx Family Microprocessors
 *
 *   Copyright(C) 2009, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2009.05.27  ver 1.00    Prelimnary version, first Release
 *
*****************************************************************************/
#include "lpc17xx.h"
#include "type.h"
#include "can.h"

/* Receive Queue: one queue for each CAN port */
extern CAN_MSG MsgBuf_RX1, MsgBuf_RX2;
extern volatile uint32_t CAN1RxDone, CAN2RxDone;

volatile uint32_t CANStatus;
uint32_t CAN1RxCount = 0, CAN2RxCount = 0;
uint32_t CAN1ErrCount = 0, CAN2ErrCount = 0;

#if CAN_WAKEUP
volatile uint32_t CANActivityInterruptFlag = 0;
#endif

/******************************************************************************
** Function name:    CAN_ISR_Rx1
**
** Descriptions:    CAN Rx1 interrupt handler
**
** parameters:      None
** Returned value:    None
** 
******************************************************************************/
void CAN_ISR_Rx1( void )
{
  uint32_t * pDest;

  /* initialize destination pointer  */
  pDest = (uint32_t *)&MsgBuf_RX1;
  *pDest = LPC_CAN1->RFS;  /* Frame  */

  pDest++;
  *pDest = LPC_CAN1->RID; /* ID  */

  pDest++;
  *pDest = LPC_CAN1->RDA; /* Data A */

  pDest++;
  *pDest = LPC_CAN1->RDB; /* Data B  */
  
  CAN1RxDone = TRUE;
  LPC_CAN1->CMR = 0x01 << 2; /* release receive buffer */
  return;
}

/******************************************************************************
** Function name:    CAN_ISR_Rx2
**
** Descriptions:    CAN Rx2 interrupt handler
**
** parameters:      None
** Returned value:    None
** 
******************************************************************************/
void CAN_ISR_Rx2( void )
{
  uint32_t *pDest;

  /* initialize destination pointer  */
  pDest = (uint32_t *)&MsgBuf_RX2;
  *pDest = LPC_CAN2->RFS;  /* Frame  */

  pDest++;
  *pDest = LPC_CAN2->RID; /* ID  */

  pDest++;
  *pDest = LPC_CAN2->RDA; /* Data A  */

  pDest++;
  *pDest = LPC_CAN2->RDB; /* Data B  */

  CAN2RxDone = TRUE;
  LPC_CAN2->CMR = 0x01 << 2; /* release receive buffer */
  return;
}

/*****************************************************************************
** Function name:    CAN_Handler
**
** Descriptions:    CAN interrupt handler
**
** parameters:      None
** Returned value:    None
** 
*****************************************************************************/
void CAN_IRQHandler(void)  
{
  CANStatus = LPC_CANCR->CANRxSR;
  if ( CANStatus & (1 << 8) )
  {
  CAN1RxCount++;
  CAN_ISR_Rx1();
  }
  if ( CANStatus & (1 << 9) )
  {
  CAN2RxCount++;
  CAN_ISR_Rx2();
  }
  if ( LPC_CAN1->GSR & (1 << 6 ) )
  {
  /* The error count includes both TX and RX */
  CAN1ErrCount = LPC_CAN1->GSR >> 16;
  }
  if ( LPC_CAN2->GSR & (1 << 6 ) )
  {
  /* The error count includes both TX and RX */
  CAN2ErrCount = LPC_CAN2->GSR >> 16;
  }
  LPC_GPIO2 -> FIOPIN &= ~0xF;
  return;
}

#if CAN_WAKEUP
/******************************************************************************
** Function name:    CANActivity_IRQHandler
**
** Descriptions:    Wake up from CAN handler
**
** parameters:      None
** Returned value:    None
** 
******************************************************************************/
void CANActivity_IRQHandler (void) 
{
  CANActivityInterruptFlag = 1;

  LPC_SC->CANSLEEPCLR = (0x1<<1)|(0x1<<2);
  LPC_CAN1->MOD = LPC_CAN2->MOD &= ~(0x1<<4);
  LPC_SC->CANWAKEFLAGS = (0x1<<1)|(0x1<<2);
  return;
}
#endif

/******************************************************************************
** Function name:    CAN_Init
**
** Descriptions:    Initialize CAN, install CAN interrupt handler
**
** parameters:      bitrate
** Returned value:    true or false, false if initialization failed.
** 
******************************************************************************/
uint32_t CAN_Init( uint32_t can_btr )
{
  CAN1RxDone = CAN2RxDone = FALSE;

  LPC_SC->PCONP |= ((1<<13)|(1<<14));  /* Enable CAN1 and CAN2 clock */

  LPC_PINCON->PINSEL0 &= ~0x0000000F;  /* CAN1 is p0.0 and p0.1  */
  LPC_PINCON->PINSEL0 |= 0x00000005;  
  LPC_PINCON->PINSEL4 &= ~0x0003C000;  /* CAN2 is p2.7 and p2.8 */
  LPC_PINCON->PINSEL4 |= 0x00014000;

  LPC_CAN1->MOD = LPC_CAN2->MOD = 1;    /* Reset CAN */
  LPC_CAN1->IER = LPC_CAN2->IER = 0;    /* Disable Receive Interrupt */
  LPC_CAN1->GSR = LPC_CAN2->GSR = 0;    /* Reset error counter when CANxMOD is in reset  */

  LPC_CAN1->BTR = LPC_CAN2->BTR = can_btr;
  LPC_CAN1->MOD = LPC_CAN2->MOD = 0x0;  /* CAN in normal operation mode */

  NVIC_EnableIRQ(CAN_IRQn);

  LPC_CAN1->IER = LPC_CAN2->IER = 0x01; /* Enable receive interrupts */
  return( TRUE );
}

/******************************************************************************
** Function name:    CAN_SetACCF_Lookup
**
** Descriptions:    Initialize CAN, install CAN interrupt handler
**
** parameters:      bitrate
** Returned value:    true or false, false if initialization failed.
** 
******************************************************************************/
void CAN_SetACCF_Lookup( void )
{
  uint32_t address = 0;
  uint32_t i;
  uint32_t ID_high, ID_low;

  /* Set explicit standard Frame */ 
  LPC_CANAF->SFF_sa = address;
  for ( i = 0; i < ACCF_IDEN_NUM; i +=2 )
  {
  ID_low = (i << 29) | (0x23 << 16); 
  ID_high = (i+1 << 13) | (0x05 << 0);
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = ID_low | ID_high;
  address += 4; 

  }
    
  /* Set group standard Frame */
  LPC_CANAF->SFF_GRP_sa = address;
  for ( i = 0; i < ACCF_IDEN_NUM; i += 2 )
  {
  ID_low = (i << 29) | (GRP_STD_ID << 16);
  ID_high = ((i+1) << 13) | (GRP_STD_ID << 0);
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = ID_low | ID_high;
  address += 4; 
  }
 
  /* Set explicit extended Frame */ 
  LPC_CANAF->EFF_sa = address;
  for ( i = 0; i < ACCF_IDEN_NUM; i++  )
  {
  ID_low = (i << 29) | (EXP_EXT_ID << 0);
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = ID_low;
  address += 4; 
  }

  /* Set group extended Frame */
  LPC_CANAF->EFF_GRP_sa = address;
  for ( i = 0; i < ACCF_IDEN_NUM; i++  )
  {
  ID_low = (i << 29) | (GRP_EXT_ID << 0);
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = ID_low;
  address += 4; 
  }
   
  /* Set End of Table */
  LPC_CANAF->ENDofTable = address;
  return;
}

/******************************************************************************
** Function name:    CAN_SetACCF
**
** Descriptions:    Set acceptance filter and SRAM associated with  
**
** parameters:      ACMF mode
** Returned value:    None
**
** 
******************************************************************************/
void CAN_SetACCF( uint32_t ACCFMode )
{
  switch ( ACCFMode )
  {
  case ACCF_OFF:
    LPC_CANAF->AFMR = ACCFMode;
    LPC_CAN1->MOD = LPC_CAN2->MOD = 1;  // Reset CAN
    LPC_CAN1->IER = LPC_CAN2->IER = 0;  // Disable Receive Interrupt
    LPC_CAN1->GSR = LPC_CAN2->GSR = 0;  // Reset error counter when CANxMOD is in reset
  break;

  case ACCF_BYPASS:                    // can.h -->0x03
    LPC_CANAF->AFMR = ACCFMode;
  break;

  case ACCF_ON:                       // can.h --> 0x00
  case ACCF_FULLCAN:                  // can.h --> 0x04
    LPC_CANAF->AFMR = ACCF_OFF;
    CAN_SetACCF_Lookup();
    LPC_CANAF->AFMR = ACCFMode;
  break;

  default:
  break;
  }
  return;
}

/******************************************************************************
** Function name:    CAN1_SendMessage
**
** Descriptions:    Send message block to CAN1  
**
** parameters:      pointer to the CAN message
** Returned value:    true or false, if message buffer is available,
**            message can be sent successfully, return TRUE,
**            otherwise, return FALSE.
** 
******************************************************************************/
uint32_t CAN1_SendMessage( CAN_MSG *pTxBuf )
{
  uint32_t CANStatus;

  CANStatus = LPC_CAN1->SR;
  if ( CANStatus & 0x00000004 )
  {
  LPC_CAN1->TFI1 = pTxBuf->Frame & 0xC00F0000;
  LPC_CAN1->TID1 = pTxBuf->MsgID;
  LPC_CAN1->TDA1 = pTxBuf->DataA;
  LPC_CAN1->TDB1 = pTxBuf->DataB;
  LPC_CAN1->CMR = 0x21;
  return ( TRUE );
  }
  else if ( CANStatus & 0x00000400 )
  {
  LPC_CAN1->TFI2 = pTxBuf->Frame & 0xC00F0000;
  LPC_CAN1->TID2 = pTxBuf->MsgID;
  LPC_CAN1->TDA2 = pTxBuf->DataA;
  LPC_CAN1->TDB2 = pTxBuf->DataB;
  LPC_CAN1->CMR = 0x41;
  return ( TRUE );
  }
  else if ( CANStatus & 0x00040000 )
  {  
  LPC_CAN1->TFI3 = pTxBuf->Frame & 0xC00F0000;
  LPC_CAN1->TID3 = pTxBuf->MsgID;
  LPC_CAN1->TDA3 = pTxBuf->DataA;
  LPC_CAN1->TDB3 = pTxBuf->DataB;
  LPC_CAN1->CMR = 0x81;
  return ( TRUE );
  }
  return ( FALSE );
}

/******************************************************************************
**                            End Of File
******************************************************************************/


ich habe für meine Zwecke den Empfang auf den CAN1 umgeschrieben (da 
CAN2 bei mir nicht angeschlossen ist) den Wakeup teil weggenommne 
(benötige ich nicht) sowie die Lookuptable vereinfacht und die Taktrate 
geändert.
Sieht jemand so was daran nciht funktionieren könnte? wie gesagt ich 
kann Daten nur empfangen wenn sie sehr sehr langsam kommen, sobald dies 
schneller ist (bei einer Sekunde schon) wird ein Data overrun ausgelöst.
Mein CPU Takt beträgt 96MHz und der Peripherietakt 48MHz

/******************************************************************************
** Function name:    CAN_SetACCF_Lookup
**
** Descriptions:    unlock IDs 
**
** parameters:      none
** Returned value:    none
** 
******************************************************************************/
void CAN_SetACCF_Lookup( void )
{
  uint32_t address = 0; /* effective address */    
  uint32_t Id11_lo_1, Id11_hi_1;  /* ID1 and ID2 */
  uint32_t Id11_lo_2, Id11_hi_2;  /* ID3 and ID4 */
  uint32_t Id11_lo_3, Id11_hi_3;  /* ID5 and ID6 */

  /* IDs --> Attention IDs in ascending order if FullCAN or explicit 11Bit Mode!! */
  Id11_lo_1 = 0x2C1;
  Id11_hi_1 = 0x320;
  Id11_lo_2 = 0x3E1;
  Id11_hi_2 = 0x65D;
  /*Id11_lo_3 = 0x25;
  Id11_hi_3 = 0x26;*/

  LPC_CANAF->SFF_sa = address;    /*score the effective address in SFF_sa --> Start 11Bit explicit IDs */
  /* unlock ID1 and ID2 and adapt address --> next row */
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = (Id11_lo_1 << 16) | Id11_hi_1;
  address += 4;
  /* unlock ID3 and ID4 and adapt address --> next row */
  *((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = (Id11_lo_2 << 16) | Id11_hi_2;
  address += 4;
  /* unlock ID5 and ID6 and adapt address --> next row */
  /**((volatile uint32_t *)(LPC_CANAF_RAM_BASE + address)) = (Id11_lo_3 << 16) | Id11_hi_3;
  address += 4;*/

  LPC_CANAF->SFF_GRP_sa = address;  /* start 11-Bit group */
  LPC_CANAF->EFF_sa = address;      /* start 29-Bit explicit ID */
  LPC_CANAF->EFF_GRP_sa = address;  /* start 29-Bit group */
 
  LPC_CANAF->ENDofTable = address; /* end of table */

  return;
}

/******************************************************************************************
*
*   main.c: Hauptprogramm zur Fremdansteuerung der Multifunktionsanzeige im Golf VI
*   Maike Drewitz
*   History:
*   Version 1.0 13.10.2010    CAN Anbindung
*   Version 2.0 25.10.2010    Displayanbindung
*******************************************************************************************/

/******************************Header Dateien einbinden***********************************/
#include "lpc17xx.h"
#include "type.h"
#include "can.h"

CAN_MSG MsgBuf_TX1, MsgBuf_TX2; /* TX and RX Buffers for CAN message */
CAN_MSG MsgBuf_RX1, MsgBuf_RX2; /* TX and RX Buffers for CAN message */

volatile uint32_t CAN1RxDone = FALSE, CAN2RxDone = FALSE;
volatile uint32_t data[12];
volatile uint32_t Schalter; 




/*****************************************************************************
** Function name:    main
**
** Descriptions:    main routine for CAN module test
**
** parameters:      None
** Returned value:    int
** 
*****************************************************************************/
int main( void )
{

  SystemInit();
  INOUT_Def();
 
  /* Please note, the bit timing is based on the setting of the 
  PCLK, if different PCLK is used, please read can.h carefully 
  and set your CAN bit timing accordingly. */  
 
  CAN_Init(BITRATE500K15MHZ);       // Bitrate = 500kbaud bei 15MHz
  NVIC_EnableIRQ(CAN_IRQn);         // Interrupts freischalten

  MsgBuf_TX1.Frame = 0x00080000;  // 11-bit, no RTR, DLC is 8 bytes 
  MsgBuf_TX1.MsgID = 0x2ee;       // Explicit Standard ID 
  MsgBuf_TX1.DataA = data[0];
  MsgBuf_TX1.DataB = data[1];

 CAN_SetACCF( ACCF_ON );          // Filtermodus festlegen
  while ( 1 )
  {
  /* Transmit initial message on CAN 1 */
  while ( !(LPC_CAN1->GSR & (1 << 3)) );
         MsgBuf_TX1.DataA = data[0];
         MsgBuf_TX1.DataB = data[1];
  if ( CAN1_SendMessage( &MsgBuf_TX1 ) == FALSE )
  {
    continue;
  }

  /* please note: FULLCAN identifier will NOT be received as it's not set 
  in the acceptance filter. */
   if ( CAN1RxDone == TRUE )
  {
    CAN1RxDone = FALSE;
   
  } /* Message on CAN 2 received */

}


Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wichtige Regeln - erst lesen, dann posten!
    * Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang


> hier ist der Beispielcode von der NXP-Homepage (Sample Code Bundle for
> LPC17xx Peripherals using Keil's MDK-ARM V1.02 )
Schöner Code. Und was ist damit?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay sorry

ähm ich habe diesen Code benutzt und ein paar änderungen vorgenommen wie 
oben im letzten Teil beschrieben, und es wird jedes mal wenn ich 
nachrichten hintereinander Sende auch wenn dies eine sekunde 
auseinanderliegt ein Dataoverrun erzeugt.
Daher wollte ich mal fragen, ob sich jemand das mal ansehen könnte ob 
eine meiner Änderungen schuld daran ist.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Beitrag "Re: sprintf mehrfach" ist noch offen

2.

> Die Ausgabe funktioniert auch jedoch wiederum nur wenn ich eine der
> beiden werte verarbeite, sobald ich den zweiten hinzuschalte erhalte ich
> wieder den HardFault_Handler.

Wie sieht der Code aus, wenn der HardFault_Handler nicht angesprungen 
wird und wie wenn er angesprungen wird. Gut lesbar wäre ein Listing im 
Anhang mit einem #if DIES_ERGIBT_FEHLER #endif Konstrukt.

3.

> ähm ich habe diesen Code benutzt und ein paar änderungen vorgenommen wie
> oben im letzten Teil beschrieben, und es wird jedes mal wenn ich

In einem übernommenen Code, den man ändert, sollte man die Änderungen 
unbedingt kennzeichnen. Wenn es sich um größere Teile handelt auch mit 
#if #else #endif, so dass man immer den Originalcode sehen und ggf. auch 
zurückbauen kann. Die Chance ist hoch, dass sich der Fehler in den 
Änderungen befindet.

Autor: Tom (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
so ich hab mich mal dran  gesetzt und den originalcode zu meinen 
gepackt, hab das immer so gekennzeichnet, dass der originale Code 
auskommentiert ist und drüber /**********ORIGINAL****************/ steht

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du machst es einem (anderen, dir kurzfristig schon) wirklich nicht 
leicht.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry ich geb mein bestes, und ich mache es mir auch nicht wirklich 
leicht, da mittlerweile schon Wochen so ins Land gegangen sind und ich 
nicht drauf komme was da falsch ist und ich halte euch alle für extrem 
kompetent und hoffe einfach auf dem weg hilfe zu bekommen =)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde die CAN_SetACCF_Lookup() kritisch unter die Lupe nehmen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Tipp wäre, dass irgendwo ein Array überlaufen wird und du dir den 
Stack ganz kräftig zerschiesst.
Was du mit dem sprintf siehst, sind die Symptome aber nicht die 
eigentliche Ursache. Die liegt ganz woanders und daher hat es auch 
keinen Sinn, da jetzt nach einer Alternative für den sprintf zu suchen.

Wenn ich den Code übernehmen müsste, dann würde ich

abspecken, abspecken, abspecken.

Die lcd Funktionen durchgehen, nach Buffer Overruns Ausschau halten und 
die erst mal gründlichst testen.

Dann sukzessive den CAN Teil, so wie es eben möglich ist, ins Programm 
wieder einbauen. Dabei wieder: den Teil den ich einbaue, kritisch unter 
die Lupe nehmen. Wenn es gar nicht anders geht, dann müssen da 
Sicherungen rein. Die Alarm schlagen, wenn Indizes zu hoch werden oder 
Pointer ihren erlaubten Bereuich verlassen.

Wenn du, wie du sagst, schon Wochen an dem Problem sitzt, dann wärst du 
schon 3 mal fertig geworden, wenn du mit einem neuen Pgm angefangen 
hättest und dieses schön langsam hochgezogen hättest. Sukzessive immer 
einen vorhandenen Baustein einbauen, gründlich unter die Lupe nehmen und 
exzessiv testen.

Solche Rundumschlagdinger, ala ich kopiere mir da 200kB Code aus 25 
verschiedenen Quellen zusammen, garniere das mit meinen eigenen Routinen 
- so was funktioniert meistens nicht.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay gut dann werde ich das mal so probieren =)
Kannst du mir noch sagen wie du erkennst wann ein Array überläuft?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom schrieb:
> Kannst du mir noch sagen wie du erkennst wann ein Array überläuft?
Oh, da gibt es einige Fehlerbilder:
Das Programm "stürzt" ab...
Irgendwas tut nicht mehr so wie es eigentlich soll...
Variable verändern ihre Werte selbständig...
Es werden die falschen Funktionen aufgerufen...
Der uC kommt nach einer Unterroutine nicht mehr "richtig" zurück...
Das Programm funktioniert nicht mehr, wenn irgendwo eine Zeile eingefügt 
wird...

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm okay klingt nach meinem programm =) und woher weißt du um welches 
array oder welchen pointer es sich dabei genau handelt? bzw wie gehts du 
vor um das zu vermeiden?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soho ich hab neuigkeiten =)
Also ich hab in meiner Lookuptable den Beginn der FullCAN IDs auf 0 
gesetzt gehabt (bzw im beispiel war dies auch so) jedoch ist es so, dass 
sollte dieser wert 0 sein die FullCAN IDs disabled werden setzte ich das 
ganze nun auf 1 also ungleich null so läuft es bisher durch ich kann 
zyklische daten senden ohne unterberechungen drin zu haben

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.