Forum: Mikrocontroller und Digitale Elektronik Vinculum VNC1L


von Martin R. (rama123)


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.

von Holger (Gast)


Lesenswert?

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

von Holger (Gast)


Lesenswert?


von Matthias K. (matthiask)


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.

von Martin R. (rama123)


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.

von Martin R. (rama123)


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.
1
int spiXfer(int spiDirection, char *pSpiData)
2
{
3
  unsigned char retData;
4
  unsigned char bitData;
5
  
6
  // CS goes high to enable SPI communications
7
  CS_H;
8
9
  // Clock 1 - Start State
10
  SDI_H;
11
12
  spiDelay();
13
  SCLK_H;
14
  spiDelay();
15
  SCLK_L;
16
17
  // Clock 2 - Direction
18
  SDI_L;
19
  if (spiDirection) SDI_H;
20
  //PORT_SDI = spiDirection;
21
22
  spiDelay();
23
  SCLK_H;
24
  spiDelay();
25
  SCLK_L;;
26
27
  // Clock 3 - Address
28
  SDI_L;
29
30
  spiDelay();
31
  SCLK_H;
32
  spiDelay();
33
  SCLK_L;
34
35
  // Clocks 4..11 - Data Phase
36
  bitData = 0x80;
37
  if (spiDirection)
38
  {
39
    // read operation
40
    retData = 0;
41
42
    while (bitData)
43
    {
44
      spiDelay();
45
      retData |= SDO_VNC?bitData:0;
46
      SCLK_H;
47
      spiDelay();
48
      SCLK_L;
49
      bitData = bitData >> 1;
50
    }
51
52
    *pSpiData = retData;
53
  }
54
  else
55
  {
56
    // write operation
57
    retData = *pSpiData;
58
59
    while (bitData)
60
    {
61
      SDI_L;
62
      if ((retData & bitData) > 0) SDI_H;    
63
      //((retData & bitData) < 0)?SDI_H:SDI_L; 
64
      spiDelay();
65
      SCLK_H;
66
      spiDelay();
67
      SCLK_L;
68
      bitData = bitData >> 1;
69
    }
70
  }
71
72
  // Clock 12 - Status bit
73
  spiDelay();
74
  bitData = SDO_VNC;
75
  SCLK_H;
76
  spiDelay();
77
  SCLK_L;
78
79
  // CS goes high to enable SPI communications
80
  CS_L;
81
82
  // Clock 13 - CS low
83
  spiDelay();
84
  SCLK_H;
85
  spiDelay();
86
  SCLK_L;
87
88
    return bitData;
89
}

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?

von Matthias K. (matthiask)


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:
1
// ***********************************************************************
2
// VNC1L - 13-Bit-SPI Senden eines Zeichens
3
// SPI Mode
4
// Übergabe: wr_byte   : Auszugebendes Zeichen
5
// Rückgabe: status    : 0=Accept (ok) 1=Byte nicht vom VNC1L angenommen
6
// ***********************************************************************
7
unsigned char vnc_wr_spi(unsigned char wr_byte) {
8
unsigned char stelle, status, cnt;
9
  cnt = TIMEOUT_SPI;  // Anzahl der Schreib-Versuche bis Timeout
10
  do {
11
    CS_VNC_H;      // SPI-Interface aktiv
12
    SDI_H;        // Startbit (immer 1)
13
    SCLK_H;  SCLK_L;  // L/H Flanke
14
    SDI_L;        // RW-Bit (0=Write)
15
    SCLK_H;  SCLK_L;  // L/H Flanke
16
    SDI_L;        // ADDR (0=Daten)
17
    SCLK_H;  SCLK_L;  // L/H Flanke
18
    // 8 Datenbits senden (MSB zuerst)
19
    for ( stelle = 0x80; stelle; stelle >>= 1 ) {
20
      if (wr_byte & stelle) SDI_H; else SDI_L;
21
      SCLK_H;  SCLK_L;  // L/H Flanke
22
    }
23
    // Statusbit einlesen
24
    status = SDO_VNC;  // Statusbit (0=Accept, 1=Reject)
25
    SCLK_H;  SCLK_L;  // L/H Flanke
26
    // End Sequenz
27
    CS_VNC_L;      // SPI-Interface inaktiv
28
    SCLK_H;  SCLK_L;  // L/H Flanke
29
    // SDO    = 1;     // nur bei 8051: Datenlatch freigeben (8051-Spezifik)  
30
    cnt--;
31
  if (status) _delay_us(150);  // Pause, wenn Byte nicht bestätigt wurde
32
  } while (status && cnt);
33
#ifdef  USART_MONITORING
34
  usart_send_byte(wr_byte);  // gesendetes Zeichen seriell senden
35
#endif
36
#ifdef LCD_MONITORING
37
  lcd_monitor_byte(wr_byte);  // gesendetes Zeichen auf LCD anzeigen
38
#endif
39
  return status;
40
} 
41
42
// ***********************************************************************
43
// VNC1L - 13-Bit-SPI Empfangen eines Zeichens
44
// SPI Mode
45
// Übergabe: rd_fkt    : Funktion (0=Datenbyte, 1=Statusbyte)
46
// Datenbyte wird im Buffer vnc-Stukturvariable gespeichert
47
// Rückgabe: status    : 0=Neues Byte im Buffer (ok) 1=kein neues Byte vom VNC1L vorhanden
48
// ***********************************************************************
49
unsigned char vnc_rd_spi(unsigned char rd_fkt) {
50
unsigned char stelle, daten, status;
51
unsigned int cnt;
52
  cnt = TIMEOUT_SPI;  //  Anzahl der Lese-Versuche bis Timeout
53
  do {
54
    daten  = 0;
55
    CS_VNC_H;      // SPI-Interface aktiv
56
    SDI_H;        // Startbit (immer 1)
57
    SCLK_H;  SCLK_L;  // L/H Flanke
58
    SDI_H;        // RW-Bit (1=Read)
59
    SCLK_H;  SCLK_L;  // L/H Flanke
60
    if (rd_fkt) SDI_H; else SDI_L;  // ADDR (0=Daten, 1=SPI-Statusinformation) 
61
    SCLK_H;  SCLK_L;  // L/H Flanke
62
    // 8 Datenbits empfangen (MSB zuerst)
63
    for ( stelle = 0x80; stelle; stelle >>= 1 ) {
64
      if (SDO_VNC) daten |= stelle;  // Datenbit speichern
65
      SCLK_H;  SCLK_L;  // L/H Flanke
66
    }
67
    // Statusbit einlesen
68
    status = SDO_VNC;  // Statusbit (0=New Data, 1=Old Data)
69
    SCLK_H;  SCLK_L;  // L/H Flanke
70
    // End Sequenz
71
    CS_VNC_L;      // SPI-Interface inaktiv
72
    SCLK_H;  SCLK_L;  // L/H Flanke
73
    if (!status) {
74
      // empfangenes Zeichen ist ein neues Zeichen
75
      // Empfangsbuffer um eine Stelle verschieben
76
      for ( stelle = VNC_BUFFER_SIZE - 1; stelle; stelle-- ) vnc.rec_buffer[stelle] = vnc.rec_buffer[stelle - 1];
77
      vnc.rec_buffer[0] = daten;  // neues Zeichen an 1. Stelle speichern
78
#ifdef  USART_MONITORING
79
    if (!rd_fkt) {
80
      usart_send_byte(vnc.rec_buffer[0]);    // empfangenes Zeichen seriell senden
81
    }
82
#endif
83
#ifdef LCD_MONITORING
84
    if (!rd_fkt) {
85
      lcd_monitor_byte(vnc.rec_buffer[0]);  // empfangenes Zeichen auf LCD anzeigen
86
    }
87
#endif
88
    }
89
    cnt--;
90
  if (status) _delay_us(150);             // Pause, wenn keine neues Byte vorliegt
91
  } while (status && cnt);
92
  return status;
93
} 
94
95
// ***********************************************************************
96
// VNC1L - Senden eines Zeichens
97
// Übergabe: wr_byte   : Auszugebendes Zeichen
98
// Rückgabe: status    : 0=Accept (ok) 1=Byte nicht vom VNC1L angenommen
99
// ***********************************************************************
100
unsigned char vnc_wr_byte(unsigned char wr_byte) {
101
unsigned char status;
102
unsigned int cnt;
103
  cnt = TIMEOUT_READ_WRITE;        // Anzahl der Sende-Versuche bis Timeout
104
  do {
105
    // VNC1L Status-Byte lesen
106
    if (vnc_rd_spi(1)) return 1;    // Fehler, Byte wurde nicht angenommen
107
  // Statusbyte liegt jetzt im Buffer
108
  status = vnc.rec_buffer[0] & 0x01;  // Test auf VNC1L RECEIVE-BUFFER voll (RXF# Bit0=1)
109
    cnt--;
110
  if (status) _delay_us(150);      // Pause, wenn RECEIVE-BUFFER voll (RXF#)
111
  } while (status && cnt);
112
  if (status || (!cnt)) return 1;    // Fehler, Byte wurde nicht angenommen
113
  // VNC1L ist jetzt empfangsbereit
114
  if (vnc_wr_spi(wr_byte)) return 1;  // Fehler Byte wurde nicht angenommen
115
  return 0;  // Byte wurde gesendet
116
}
117
118
// ***********************************************************************
119
// VNC1L - Empfangen eines Zeichens
120
// Rückgabe: status    : 0=Neues Byte im Buffer (ok) 1=kein neues Byte vom VNC1L vorhanden
121
// ***********************************************************************
122
unsigned char vnc_rd_byte(void) {
123
unsigned char status;
124
unsigned int cnt;
125
  cnt = TIMEOUT_READ_WRITE;      // Anzahl der Empfangs-Versuche bis Timeout
126
  do {
127
    // VNC1L Status-Byte lesen
128
    status = vnc_rd_spi(0);      // Wenn Status=1 liegt kein neues Byte vor
129
  // Prüfung auf TXE# im Status-Byte brachte keinen Vorteil
130
    cnt--;
131
  if (status) _delay_us(150);    // Pause, wenn kein neue Byte vorliegt
132
  } while (status && cnt);
133
  if (status || (!cnt)) return 1;  // Fehler, kein Byte empfangen
134
  return 0;  // Byte wurde empfangen
135
}

von Martin R. (rama123)


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.

von Matthias K. (matthiask)


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.

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
Noch kein Account? Hier anmelden.