PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pic Mikrocontroller + externer Flash-Speicher



clauszoechling
11.08.2013, 21:47
Hallo
Ich möchte mit einem Pic-Mikrocontroller einen Flash-Speicher lesen und beschreiben(nur einfache Variablenwerte) und habe bis jetzt noch nie mit dem SPI-Bus gearbeitet.
Leider klappt es nicht, obwohl ich jetzt schon 2 Wochen experimentiere:
Pic 18F4620 - 8MHZ-Quarz
Flash ist das Flash-Click von Mikros mit einem M25P80
Ich poste meinen C-Code und 3 Bilder vom Oszilloskop.

Beim SDI_CLOCK des Flash sieht man das 0x06 Byte, welches zum Flash gesendet wird im Vergleich zur Clock. Sollte eigentlich passen: bei steigender Flanke liegt Bit1+Bit2 an, Bit0 wieder 0.
26198
den SDO des Flash(ALLES.Jpeg) hab ich als Gesamtbild aller 5 übertragenen Bytes, damit man sieht, dass da gar nichts passiert, ausser ein leichtes Ansteigen am Anfang.
26199
Beim CS-Bild sieht man das Clock-Signal im Vergleich zum CS-Signal.
26200
Für das Beschreiben, Löschen, aber auch Write Nable Bit Setzen steht Folgendes im Datenblatt:
Chip Select (S) must be driven High exactly at a byte boundary, otherwise the instruction is rejected, and is not executed. That is, Chip Select (S) must driven High when the number of clock pulses after Chip Select (S) being driven Low is an exact multiple of eight.

Passt mein Clock-CS Verhalten(nach allen 8 Bits auf High, oder muss das genau gleichzeitig sein? Was könnte ich am Code falsch haben oder was ist mein Verständnisfehler beim Flash-Speicher?
Ich habe die meisten Zeilen kommentiert, damit man meine Gedankengänge vielleicht verstehen kann ;-)
Vielen Dank für eure Hilfe.
claus

#pragma config OSC = HS // Oscillator HS
#pragma config WDT = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRT = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)

#include <p18f4620.h>
#include <delays.h>

#define RS LATBbits.LATB4 // LCD
#define RW LATBbits.LATB3 // LCD
#define E LATBbits.LATB2 // LCD
#define LCD_DATA LATD // LCD
#define CS LATCbits.LATC2 // CS Flash //
#define HOLD LATCbits.LATC1 // HOLD Flash
#define SDI PORTCbits.RC4 // SDI Flash
#define SDO LATCbits.LATC5 // SDO Flash
#define CLK LATCbits.LATC3 // CLK Flash

/*VARIABLEN*/
char i;
int ergebnis;
unsigned char byte;
char tempvar;
/***********/

/*PROTOTYPEN*/
void command(void); // LCD
void data(void); // LCD
void LCD_INIT(void); // LCD
unsigned char ReadSPI( void ); // Flash
unsigned char WriteSPI( unsigned char data_out ); // Flash
void Init_SPI(void); // Flash
unsigned char sendSPI (unsigned char byte); // Flash
void LCD_AUSGABE(int ergebnis);
/************/

void main()
{
/***********FLASH-SPEICHER***********/
//TRISCbits.TRISC1=0; // HOLD - Flash
TRISCbits.TRISC2=0; // CS - Flash
TRISCbits.TRISC3=0; // SCK - Flash
TRISCbits.TRISC4=1; // SDI - Flash
TRISCbits.TRISC5=0; // SDO - Flash

/***********LCD-DISPLAY***********/
TRISD=0; // Set Port B as output port
TRISBbits.TRISB4=0; // RS (Register select signal)
TRISBbits.TRISB3=0; // R/W (Data read/write)
TRISBbits.TRISB2=0; // E (Enable signal)

/******INITIALISIERUNGEN******/
LCD_INIT(); // LCD initialization
Init_SPI(); // Initialisieren des SPI

while(1)
{
sendSPI(0x06); // instruction code: Write enable bit setzen
sendSPI(0x01); // instruction code: write status register
sendSPI(0b00011100); // instruction code: BP1(Block Protect Bit) setzen
sendSPI(0x05); // instruction code: read status register
ergebnis=sendSPI(0x00); // dummy senden; Auslesen des Status Registers

LCD_AUSGABE(ergebnis); // Ausgeben des gelesenen SPI-Wertes am LCD-Display
}
}

/************Funktionen************/
void Init_SPI(void)
{
SSPCON1bits.SSPEN=0; // Synchronous Serial Port disabled
SSPSTATbits.CKE=1; // Daten werden beim Wechsel von Aktive zu Leerlauf der SCK-Leitung gesendet
SSPCON1bits.SSPEN=1; // Synchronous Serial Port enabled
}

unsigned char sendSPI (unsigned char byte)
{
unsigned char tmp;
CS = 0; // Clock Select auf low gesetzt, damit aktiv
SSPBUF = byte; // byte(zu sendende Daten) wird in SSPBUF geschrieben
while(!SSPSTATbits.BF); // warten bis Buffer beschrieben(BF wird gesetzt)
SSPSTATbits.BF=0; // Buffer full - Bit wird gelöscht
tmp = SSPBUF; // SSPBUF wird gelesen
CS = 1; // Clock Select auf high gesetzt, damit inaktiv
return tmp; // der ausgelesene Wert wird zurückgegeben
}

Flash-Speicher: http://www.mikroe.com/downloads/get/1881/flash_click_manual.pdf

Datenblatt M25P80:
http://www.google.at/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDMQFjAA&url=http%3A%2F%2Fwww.micron.com%2F~%2Fmedia%2FDocu ments%2FProducts%2FData%2520Sheet%2FNOR%2520Flash% 2FSerial%2520NOR%2FM25P%2FM25P80.pdf&ei=dukHUvr8BITVtQaj9oBQ&usg=AFQjCNEtGo583vxY52sXq8rMf9bREKpRTg&bvm=bv.50500085,d.Yms&cad=rja

Andre_S
12.08.2013, 10:28
Hallo,

habe den Speicher auch und es klappt ohne Probleme.
Dein Programm habe ich jetzt nicht genau analysiert, sieht bei mir einiges anders aus, allein CS wird bei mir nicht nach jedem übertragenem Byte (schreiben/lesen) wieder gesetzt. Beispiel ein Byte aus Flash Speicher Adresse lesen:
CS <- low;
SPI1_Write (0x03) [_SERIAL_FLASH_CMD_READ]
SPI1_Write(Higher(address)) (3 Byte Adresse)
SPI1_Write(Hi(address))
SPI1_Write(Lo(address))
temp = SPI1_Read(0)
CS <- high
usw.
Schreiben lasse ich jetzt hier für erste mal weg, kannst Du aus dem Exambles extrahieren, da ist natürlich einiges mehr zu tun…

Hast Du schon mal nur zwecks Kontrolle passender SPI Initialisierung die ID ausgelesen?
CS <- low
SPI1_Write (0x9F) [_SERIAL_FLASH_CMD_RDID)]
temp = SPI1_Read(0)
CS <- high

Warum nutzt Du nicht als Orientierung das zugehörige „flash_click_examples“ für PIC18F45k22. Dies hatte ich am Anfang zum Test auch. Ein entsprechender „Serial_Flash_driver“ ist da bereits eingebunden. Zumindest kannst Dir die benötigten Informationen holen.
Für MicroC kannst Du aber auch gern von mir ein paar Auszüge bekommen, soweit Du nicht weiter kommst.


Gruß André

clauszoechling
12.08.2013, 14:27
Hallo André
Danke für die schnelle Antwort.
Die Examples von MikroC hab ich gesehen und versucht sie zu verwenden.
Ich arbeite aber mit MBLABX und einen Mac.

Das CS = 0 bzw =1 hab ich nur anfangs und am Ende ausprobiert, doch noch kein Erfolg.
was sollte ich beim Auslesen mit 0x09 erhalten? die ID des Gerätes?(dann sollte ich Lows und Highs am Oszi sehen)

Ich glaub fast, dass bei der Initialisierung was nicht stimmt.
Verdrahtet hab ich hoffentlich alles richtig.
Beschriftung am Flash SDI zu PIC SDO und umgekehrt.
Oder muss ich sonst noch Elektronik verbauen?(Pullups, Pulldowns, sonstiges), denke aber, dass das am Board schon alles inkludiert ist.

Hab jetzt auch CPOL und CPHA auf 0 gesetzt und das Sample Bit auf 0, damit in der Mitte des Bytes gesampled wird.

tschuess
claus

Andre_S
12.08.2013, 15:30
Hallo Claus,

ja, elektrisch verbunden passt so, da gibt es eigentlich auch keine Besonderheit die mir jetzt einfällt,
...außer die 3,3V (!!!)

Mit 0x9F sollte die ID kommen,… steht so auch im Datenblatt.
26203
Aber egal, mit ein paar Byte mehr (Instruktionsbyte + 3 Adressbyte) müsstest Du beim Lesen des Flash zumindest ein 0xFF bekommen.


Ich initialisiere beim dsPIC30Fxxx:
_SPI_MASTER
_SPI_8_BIT
_SPI_PRESCALE_SEC_1
_SPI_PRESCALE_PRI_64
_SPI_SS_DISABLE
_SPI_DATA_SAMPLE_MIDDLE
_SPI_CLK_IDLE_HIGH
_SPI_ACTIVE_2_IDLE

beim 18F hatte ich es so gesehen, aber logischerweise nicht testen können:
_SPI_MASTER_OSC_DIV4
_SPI_DATA_SAMPLE_MIDDLE
_SPI_CLK_IDLE_LOW
_SPI_LOW_2_HIGH

MPLAB habe ich bis voriges Jahr noch in Assembler programmiert, auf MPLAB - X Umgebung oder gar C bin ich nicht gewechselt, da kann ich Dir leider nicht weiter helfen.
Aber es gibt hier auch noch andere Mitstreiter welche bei der Umgebung tiefer in der Materie stehen…


Gruß André

clauszoechling
12.08.2013, 16:57
Hallo André

Die 3,3V hab ich.

Hab aber nur SDI,SDO,SLC,CS,3,3V,GND angeschlossen.
Alles andere des Boards nicht(WP,Hold,alle NC).
Ist das ok oder hab ich da einen Fehler?

Danke
tschuess
claus

RoboHolIC
12.08.2013, 23:00
... nur SDI,SDO,SLC,CS,3,3V,GND angeschlossen.
Alles andere des Boards nicht(WP,Hold,alle NC).
Ist das ok oder hab ich da einen Fehler?
Das von dir verlinkte Datenblatt beantwortet auf Seite 10, Figure 4 und Notes 1-5 (Seite 10) deine Frage.

clauszoechling
12.08.2013, 23:55
Danke, wenn ich es richtig verstanden habe, dann beide auf High.

Die Stromversorgung des Boards hab ich auf 3,3 Volt.
Die anderen Pins(SDI,SDO,SLC,CS) haben aber das 5V-Signal des PICs.
Stimmt das eh, oder muss ich das anders lösen?

Vielen Dank
claus

Andre_S
13.08.2013, 09:15
Hallo,

die Belegung von deinem Board findest Du hier, allerdings gab es auch Boards mit 3.3/5V.
http://www.mikroe.com/downloads/get/1881/flash_click_manual.pdf

Ob der Flash Chip 5V tolerant ist (habe es zumindest beim Überfliegen im Datenblatt nicht entdecken können) oder ob Dein PIC Eingang den Pegel erfasst weiß ich leider nicht, da ich diese Kombination nicht habe.
Wenn Du unsicher bist oder keiner mit der Kombi Erfahrungen hat und dies bestätigen kann, solltest Du auf jeden Fall eine Pegelanpassung vornehmen.


Gruß André

clauszoechling
13.08.2013, 10:55
Hallo
OK, Danke.
Dann werd ich mir heute einen 74HC4050 und einen 74HCT125 besorgen. Ich hoffe, die sind lagernd.

Dazwischen hab ich noch eine Frage:
Im Datenblatt sieht es bei den Skizzen der Übertragungen so aus, dass
wenn z.B das Instructionbyte versendet wurde, die auszulesenden SDO-Bytes des Flash direkt angehängt sind.
Bei mir sind laut Oszilloskop zwischen den Bytes immer Abstände, je nachdem ob Clock/4 oder /16 oder /64 verschieden groß.(siehe Bild SDO_Flash)
26209
Passt das so, oder müsste der CLK-Takt durchgehend sein?
Wenn ja, worin liegt der Fehler?

Danke
claus

indeas
13.08.2013, 15:33
Daten via SPI werden beim 8Bit Controller immer Byte für Byte verschickt (also mit Lücken).
Der PIC hat eine doppelte Pufferung für DI und DO; damit kann man während der Übertragung wieder nachladen und ein "quasi" lückenloser Betrieb ist also möglich.
Je nachdem wie es der Compiler anstellt, nutzt er dieses Feature. Schau doch mal in das ASM-File bzw. das LST-File.
Ob und wie groß die Lücken sind, hängt davon ab wie schnell bzw. wann der PIC die Register beschreibt.
Grundsätzlich spielt es aber keine Rolle, denn der SPI Slave wartet immer auf die nächste Flanke. Wenn die 9. Flanke ein bisschen später kommt ist das trotzdem die nächste Flanke.

clauszoechling
13.08.2013, 21:43
OK, Danke, dann kann ich da mal einen Fehler ausschliessen.
Hab heute die 2 Pegelwandler bekommen und werd da mal probieren.
Zur Sicherheit hab ich das Flashboard nochmal bestellt.
Nicht, dass ich es zerstört hab und da dann noch ein Fehler dazu kommt.
Ich werde weiter berichten, wenn ich es getestet habe.
Vielen Dank vorerst mal für eure Hilfe.
mfg
claus

clauszoechling
15.08.2013, 21:41
Hallo nochmal

Hab jetzt das Flashboard ausgetauscht(sicher ist sicher) und verwende jetzt die Pegelwandler.

Habe jetzt ordentliche 5V-Signale(d.h. scharfe Kanten von 0V auf 5V und umgekehrt).

Ich schau mir sowohl das SDI als auch das SDO des Flashboards mit dem Oszilloskop an.

Beim SDI(d.h., was in das Flashboard hineingeht) kann ich ordentlich triggern und erhalte so ein schönes Bild am Oszilloskop.
Beim SDO gelingt mir das Triggern nicht, d.h. wenn ich auf RUN-STOP drücke erhalte ich immer in anderes Bild mit Signalen.
Habe mich schon stundenlang mit den Trigger-Einstellungen am Oszilloskop herumgespielt, trotzdem gelingt es mir nicht.(beim SDI klappt es hervorragend).
Was kann ich tun, bzw. was ist eventuell an der Software schuld, dass ich so ein "Zappelsignal" erhalte.

Vielen Dank im Voraus
mfg
claus

clauszoechling
22.08.2013, 11:28
Hallo
Da bin ich wieder.
Hab jetzt ein kleines Erfolgserlebnis:
Kann jetzt das Statusregister beschreiben und auslesen(beobachte momentan alles nur auf dem Oszilloskop).
Werde heute versuchen eine Variable in den Speicher zu schreiben und anschließend am Display ausgeben.

was hab ich verändert:
erstens musste ich das CKE-Bit auf 1 ändern(1 = Transmit occurs on transition from active to Idle clock state).
und zweitens(das verwundert mich ein bisschen) geh ich jetzt nicht über den Pegelwandler 5V=>3,3V, sondern stattdessen direkt mit 5V-Signalen(CS,SLK,MOSI) in den Flashspeicher.
MISO mit Pegelwandler 3,3V=>5V. Stromversorgung natürlich auch mit 3,3V.
Nur wenn ich direkt mit 5V-Signalen in den Flash gehe, erhalte ich ein stabiles Oszilloskopsignal.

Weiss irgendwer warum das so ist?(Bin ja nur zufällig draufgekommen und bei einem anderen Gerät mach ich vielleicht was kaputt.
Kann es an der Länge der Leitungen liegen?
Ist alles nur auf mehreren Steckboards aufgebaut und alle Leitungen(ausser Stromversorgung) sind 40-45cm lang.

Danke
claus

clauszoechling
27.08.2013, 19:26
Hallo nochmal
Hab jetzt weiter experimentiert und kann jetzt auch ein Byte schreiben und lesen.
Die Flanken der Signale sind schön.
Trotzdem ist das Signal noch instabil, sowohl das Signal am Oszilloskop als auch das am Display angezeigte Ergebnis "flackert" immer wieder hin und her(ist ein bisschen laienhaft ausgedrückt).
Glaube, dass es an der Elektronik und nicht an der Software liegt.
Brauche ich Abblockkondensatoren(wenn ja wo) bzw. Serienwiderstände oder Pullups?
@André: Hast du SDI,SDO,SCL,CS direkt zwischen uC und Flash verbunden oder was oben Genanntes dazwischengeschaltet.

Vielen Dank
tschuess
claus

Andre_S
29.08.2013, 11:37
Hallo Claus,

ich weiß wirklich nicht was Du mit "flackern" meinst, aber ich habe das Flash Clickbord auf dem Entwicklerboard MikroBUS stecken. Laut Spezifikation gibt es da keine Serienwiederstände oder Kondensatoren.
Auch auf der in der Entwicklung befindlichen Steuerungsplatine ist diesbezügliches nichts vorgesehen, wie unser Hardwareentwickler mir soeben bestätigte, allerdings habe ich dieses noch nicht programmiert und somit noch nicht im Einsatz.
Laut Spezifikation sollte da, soweit die Pegel passen, auch nichts rein, wie andere seriell angebundene Komponenten (zwar nur eine Richtung) auch zeigen:
http://www.mikroe.com/chapters/view/61/chapter-13-examples/#example9
Kommen die Probleme eventuell durch die Pegelwandler...?


Gruß André

clauszoechling
29.08.2013, 15:23
Hallo Andrè
Vielen Dank für die Antwort

Hab jetzt den (hoffentlich)letzten Fehler gefunden.
Habe ein paar "offene" Pins gehabt und mit ein paar Pulldown-Widerständen das Signal jetzt stabil hingekriegt.
Kann jetzt auch mehrere Bytes auf einmal schreiben und lesen.

Vielen Dank an alle, die mir Ratschläge gegeben haben.
tschuess
claus