www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Vinculum VNC1L


Autor: Martin Ra (rama123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte einen Datenlogger mit einem Atmega88 und einem VNC1L Chip von 
Vinculum bauen. Der Atmega empfängt alle 10ms 10 Byte Daten über den 
USART und gibt diese über Soft-SPI an den Vinculumchip weiter.
Auf dem VNC1L ist die neuste Firmaware aufgespielt und der Schaltplan 
ist genauso wie der im Vdrive von Vinculum. Der VNC1L arbeitet im short 
command mode.
Beim Programmcode für den Atmel habe ich mich weitestgehend an der 
Application Note AN 102 (Data-Logging Using the Vinculum VNC1L) 
gehalten.
Mein Vorgehen ist Folgendes:
Jedes über den USART Empfangene Datenbyte löst einen Inerrupt aus und 
wird in einen Ringbuffer gespeichert.
Nach dem die Schaltung mit Spannung versorgt wurde, schickt der Atmega 
zur synchronisation ein echo command an den VNC1L. Dieser antwortet wenn 
alles in Ordnung ist.
Anschließend wird überprüft ob ein USB-Stick eingesteckt wurde, wenn ja
wird eine Datei geöffnet.
Wenn 64 Byte im Ringbuffer sind, werden diese in die Datei geschrieben
Bei 512 Byte wird die Datei zur Aktualisierung geschlossen und 
anschießend gleich wieder geöffnet.
Dies soll solange geschehen bis die Messung beendet ist und über den 
USART das Messungsendezeichen kommt.

Nach jedem geschicktem Befehl zum VNC1L Frage ich das Promt ab was der 
VNC1L schickt.

Das erste was ich festgestellt habe ist, das der VNC1L manchmal sehr 
lange braucht bis er das Promt-Zeichen schickt nachdem er die Daten 
empfangen hat, die er auf den Stick speichern soll. Dies geschieht nur 
relativ selten. Hat das vielleicht auch schon jemand beobachtet?
Dadurch ist mein Ringbuffer übergelaufen was zu einem error geführt hat, 
durch vergrößern des Buffers habe ich dieses Problem aber gelöst.

Jetzt habe ich das Problem das die Speicherung der Daten nach genau 
622.592 Bytes nicht mehr weiter geht, jedenfalls ist die Datei auf dem 
Stick dann immer so groß. Das bedeutet ja das die Datei  1216 mal 
geöffnet und wieder geschlossen wurde. Kennt dafür jemand eine 
Erklärung? Gibt es vielleicht ein max. Größe von Dateien? Kann ich mir 
eigentlich nicht vorstellen.

Hoffe mir kann jemand weiter helfen,
gruß Martin.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
www.mikrocontroller.net/topic/186852
Hier ist das was für dich?
Gruss Holger.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der SPI-Mode hat so seine tücken.

Hier einige Erfahrungen:
Beitrag "USB-Stick am Mikrocontroller VNC1L"

Pausen kommen gelegentlich vor. Meist wenn der USB-Stick mit sich selber 
zu tun hat oder der Receive-Buffer des VNC1L voll ist. Mit welchem 
SPI-Takt arbeitest Du?

Du wertest hoffentlich das Status-Byte (RXF# Receive-Buffer voll) aus? 
Ohne dies klappt die Kommunikation nicht zuverlässig. Die alleinige 
Kontrolle des Status-Bits im SPI-Zyklus, ob das gesendete Byte 
akzeptiert wurde, reicht nicht aus.

Autor: Martin Ra (rama123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Holger,
danke für den Link. Hatte ich schon gelesen, hat mich aber leider nicht 
weitergebracht.
Ich nutze den Chip im SPI Modus und nicht im UART Modus.
Mitlerweile habe ich auch noch ein paar andere Dinge ausprobiert. z.B. 
senden eines Echo Commandos nach jeden schließen der Datei oder nach 
5kByte in eine neue Datei schreiben.
Aber leider keine Änderung. Der VNC1L macht sobald die Datei 622.592 
Byte groß ist nichts mehr.
Ich weiß auch nicht ob es an der Dateigröße liegt, was ich eigentlich 
nicht glaube da er ja auch nichts mehr macht wenn ich den Dateinamen 
ändere, oder an was anderem.

Autor: Martin Ra (rama123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Matthias,

erstmal danke, mit welchem SPI-Takt ich arbeite kann ich dir garnicht so 
genau sagen. Da der VNC1L ja mit 12Bit SPI arbeitet, muss ja leider ein 
Software SPI programmiert werden. Diesen habe ich aus der Application 
Note AN 102 von FTDI übernommen.
int spiXfer(int spiDirection, char *pSpiData)
{
  unsigned char retData;
  unsigned char bitData;
  
  // CS goes high to enable SPI communications
  CS_H;

  // Clock 1 - Start State
  SDI_H;

  spiDelay();
  SCLK_H;
  spiDelay();
  SCLK_L;

  // Clock 2 - Direction
  SDI_L;
  if (spiDirection) SDI_H;
  //PORT_SDI = spiDirection;

  spiDelay();
  SCLK_H;
  spiDelay();
  SCLK_L;;

  // Clock 3 - Address
  SDI_L;

  spiDelay();
  SCLK_H;
  spiDelay();
  SCLK_L;

  // Clocks 4..11 - Data Phase
  bitData = 0x80;
  if (spiDirection)
  {
    // read operation
    retData = 0;

    while (bitData)
    {
      spiDelay();
      retData |= SDO_VNC?bitData:0;
      SCLK_H;
      spiDelay();
      SCLK_L;
      bitData = bitData >> 1;
    }

    *pSpiData = retData;
  }
  else
  {
    // write operation
    retData = *pSpiData;

    while (bitData)
    {
      SDI_L;
      if ((retData & bitData) > 0) SDI_H;    
      //((retData & bitData) < 0)?SDI_H:SDI_L; 
      spiDelay();
      SCLK_H;
      spiDelay();
      SCLK_L;
      bitData = bitData >> 1;
    }
  }

  // Clock 12 - Status bit
  spiDelay();
  bitData = SDO_VNC;
  SCLK_H;
  spiDelay();
  SCLK_L;

  // CS goes high to enable SPI communications
  CS_L;

  // Clock 13 - CS low
  spiDelay();
  SCLK_H;
  spiDelay();
  SCLK_L;

    return bitData;
}

Den Receive-Buffer werte ich bisher noch nicht aus. Habe ich das richtig 
verstanden, dass ich dafür die ersten drei Bit im SPI Zyklus eine 1 
schicken muss und dann schauen was der VNC1L antwortet?
Fragt man den Buffer jedes mal ab bevor man ein Byte an den VNC1L 
schickt?

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein bitData ist nur das Status-Bit. Reicht zur sicheren Kommunikation 
nicht aus. Statusbyte auslesen vor jedem Schreibvorgang und Bit RXF# 
prüfen. SCLK Taktrate solltest Du kennen, im wesentlichen von µC und 
Quarz abhängig. Max.12 MHz möglich, habe auch schon mit 18 MHz probiert, 
ging, muss aber nicht. Hier ein Snap meiner Schreibroutinen:
// ***********************************************************************
// VNC1L - 13-Bit-SPI Senden eines Zeichens
// SPI Mode
// Übergabe: wr_byte   : Auszugebendes Zeichen
// Rückgabe: status    : 0=Accept (ok) 1=Byte nicht vom VNC1L angenommen
// ***********************************************************************
unsigned char vnc_wr_spi(unsigned char wr_byte) {
unsigned char stelle, status, cnt;
  cnt = TIMEOUT_SPI;  // Anzahl der Schreib-Versuche bis Timeout
  do {
    CS_VNC_H;      // SPI-Interface aktiv
    SDI_H;        // Startbit (immer 1)
    SCLK_H;  SCLK_L;  // L/H Flanke
    SDI_L;        // RW-Bit (0=Write)
    SCLK_H;  SCLK_L;  // L/H Flanke
    SDI_L;        // ADDR (0=Daten)
    SCLK_H;  SCLK_L;  // L/H Flanke
    // 8 Datenbits senden (MSB zuerst)
    for ( stelle = 0x80; stelle; stelle >>= 1 ) {
      if (wr_byte & stelle) SDI_H; else SDI_L;
      SCLK_H;  SCLK_L;  // L/H Flanke
    }
    // Statusbit einlesen
    status = SDO_VNC;  // Statusbit (0=Accept, 1=Reject)
    SCLK_H;  SCLK_L;  // L/H Flanke
    // End Sequenz
    CS_VNC_L;      // SPI-Interface inaktiv
    SCLK_H;  SCLK_L;  // L/H Flanke
    // SDO    = 1;     // nur bei 8051: Datenlatch freigeben (8051-Spezifik)  
    cnt--;
  if (status) _delay_us(150);  // Pause, wenn Byte nicht bestätigt wurde
  } while (status && cnt);
#ifdef  USART_MONITORING
  usart_send_byte(wr_byte);  // gesendetes Zeichen seriell senden
#endif
#ifdef LCD_MONITORING
  lcd_monitor_byte(wr_byte);  // gesendetes Zeichen auf LCD anzeigen
#endif
  return status;
} 

// ***********************************************************************
// VNC1L - 13-Bit-SPI Empfangen eines Zeichens
// SPI Mode
// Übergabe: rd_fkt    : Funktion (0=Datenbyte, 1=Statusbyte)
// Datenbyte wird im Buffer vnc-Stukturvariable gespeichert
// Rückgabe: status    : 0=Neues Byte im Buffer (ok) 1=kein neues Byte vom VNC1L vorhanden
// ***********************************************************************
unsigned char vnc_rd_spi(unsigned char rd_fkt) {
unsigned char stelle, daten, status;
unsigned int cnt;
  cnt = TIMEOUT_SPI;  //  Anzahl der Lese-Versuche bis Timeout
  do {
    daten  = 0;
    CS_VNC_H;      // SPI-Interface aktiv
    SDI_H;        // Startbit (immer 1)
    SCLK_H;  SCLK_L;  // L/H Flanke
    SDI_H;        // RW-Bit (1=Read)
    SCLK_H;  SCLK_L;  // L/H Flanke
    if (rd_fkt) SDI_H; else SDI_L;  // ADDR (0=Daten, 1=SPI-Statusinformation) 
    SCLK_H;  SCLK_L;  // L/H Flanke
    // 8 Datenbits empfangen (MSB zuerst)
    for ( stelle = 0x80; stelle; stelle >>= 1 ) {
      if (SDO_VNC) daten |= stelle;  // Datenbit speichern
      SCLK_H;  SCLK_L;  // L/H Flanke
    }
    // Statusbit einlesen
    status = SDO_VNC;  // Statusbit (0=New Data, 1=Old Data)
    SCLK_H;  SCLK_L;  // L/H Flanke
    // End Sequenz
    CS_VNC_L;      // SPI-Interface inaktiv
    SCLK_H;  SCLK_L;  // L/H Flanke
    if (!status) {
      // empfangenes Zeichen ist ein neues Zeichen
      // Empfangsbuffer um eine Stelle verschieben
      for ( stelle = VNC_BUFFER_SIZE - 1; stelle; stelle-- ) vnc.rec_buffer[stelle] = vnc.rec_buffer[stelle - 1];
      vnc.rec_buffer[0] = daten;  // neues Zeichen an 1. Stelle speichern
#ifdef  USART_MONITORING
    if (!rd_fkt) {
      usart_send_byte(vnc.rec_buffer[0]);    // empfangenes Zeichen seriell senden
    }
#endif
#ifdef LCD_MONITORING
    if (!rd_fkt) {
      lcd_monitor_byte(vnc.rec_buffer[0]);  // empfangenes Zeichen auf LCD anzeigen
    }
#endif
    }
    cnt--;
  if (status) _delay_us(150);             // Pause, wenn keine neues Byte vorliegt
  } while (status && cnt);
  return status;
} 

// ***********************************************************************
// VNC1L - Senden eines Zeichens
// Übergabe: wr_byte   : Auszugebendes Zeichen
// Rückgabe: status    : 0=Accept (ok) 1=Byte nicht vom VNC1L angenommen
// ***********************************************************************
unsigned char vnc_wr_byte(unsigned char wr_byte) {
unsigned char status;
unsigned int cnt;
  cnt = TIMEOUT_READ_WRITE;        // Anzahl der Sende-Versuche bis Timeout
  do {
    // VNC1L Status-Byte lesen
    if (vnc_rd_spi(1)) return 1;    // Fehler, Byte wurde nicht angenommen
  // Statusbyte liegt jetzt im Buffer
  status = vnc.rec_buffer[0] & 0x01;  // Test auf VNC1L RECEIVE-BUFFER voll (RXF# Bit0=1)
    cnt--;
  if (status) _delay_us(150);      // Pause, wenn RECEIVE-BUFFER voll (RXF#)
  } while (status && cnt);
  if (status || (!cnt)) return 1;    // Fehler, Byte wurde nicht angenommen
  // VNC1L ist jetzt empfangsbereit
  if (vnc_wr_spi(wr_byte)) return 1;  // Fehler Byte wurde nicht angenommen
  return 0;  // Byte wurde gesendet
}

// ***********************************************************************
// VNC1L - Empfangen eines Zeichens
// Rückgabe: status    : 0=Neues Byte im Buffer (ok) 1=kein neues Byte vom VNC1L vorhanden
// ***********************************************************************
unsigned char vnc_rd_byte(void) {
unsigned char status;
unsigned int cnt;
  cnt = TIMEOUT_READ_WRITE;      // Anzahl der Empfangs-Versuche bis Timeout
  do {
    // VNC1L Status-Byte lesen
    status = vnc_rd_spi(0);      // Wenn Status=1 liegt kein neues Byte vor
  // Prüfung auf TXE# im Status-Byte brachte keinen Vorteil
    cnt--;
  if (status) _delay_us(150);    // Pause, wenn kein neue Byte vorliegt
  } while (status && cnt);
  if (status || (!cnt)) return 1;  // Fehler, kein Byte empfangen
  return 0;  // Byte wurde empfangen
}

Autor: Martin Ra (rama123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benutze einen Atmega88 mit einem 8MHz Quarz. SCLK von meiner SPI 
Übertragung habe ich mal gemessen. Ein Impuls SCLK_High/SCLK_Low dauert 
250us. Das sollte nicht zu schnell sein.

Die Abfrage des RXF# Bits habe ich in meinen Code eingebunden, leider 
hat es keine Verbesserung gebracht. Das Schreiben bricht immernoch nach 
der gleichen Anzahl von geschriebenen Bytes ab.

Was ich auch noch festgestellt habe ist, dass wenn der USB Stick als 
FAT32 und nicht als FAT formatiert ist, die Speicherung der Daten sehr 
schnell abbricht. Es dauert dann meist nur deutlich unter einer Sekunde.

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SCL 250us ist recht langsam, auch die anderen Timing-Sequenzen sind von 
Bedeutung.

Fällt mir nicht mehr viel ein. Eventuell mal viele Delays einfügen und 
testen, ob dann wenigsten alles korrekt durchläuft.

Anderen Stick hast Du sicher schon probiert.

Eventuell versuchsweise auf UART umstellen, ob Problem bleibt.

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.