प्रस्तावना: यह सवाल एक परियोजना मैं अपने विश्वविद्यालय में प्रोफेसर के साथ पर काम कर रहा हूँ के बारे में है। यह एक ग्रेड के लिए नहीं है, लेकिन इस प्रोफेसर के साथ मेरी प्रतिष्ठा मायने रखती है। इसलिए जब इस परियोजना पर मेरी सफलता मेरे लिए महत्वपूर्ण है, तो मुझे स्टैक ओवरफ़्लो से सहायता लेने के लिए इसे अनुचित नहीं दिखता है।ATmega328 + एसपीआई फ्लैश मेमोरी
यह कहा गया है कि, मेरे प्रोजेक्ट का उच्च स्तर अवलोकन है। मेरे पास एटीमेगा 328 माइक्रोकंट्रोलर है। मेरे पास माइक्रोचिप एसएसटी 64 एमबीटी फ्लैश मेमोरी कार्ड है। एटीमेगा में एसपीआई का हार्डवेयर कार्यान्वयन है। फ्लैश मेमोरी में एसपीआई का हार्डवेयर कार्यान्वयन है।
मेरा लक्ष्य फ्लैश चिप ATmega एसपीआई में मास्टर मोड का उपयोग करने के लिए से डेटा डेटा पढ़ना और लिखना है। स्मृति को कई ओवरले संरचना में व्यवस्थित किया गया है जो मिटाने के लिए अच्छा है लेकिन मेरे उद्देश्यों के लिए, यह मूल रूप से 256 बाइट्स के केवल 32,768 पृष्ठ हैं।
डेटा लिखने के लिए मूल विचार मैं एक निर्देश बाइट तो शुरू करने का पता है, तो डेटा भेजने के लिए, है। डेटा को पढ़ने के लिए मूल विचार यह है कि मैं एक निर्देश बाइट भेजता हूं, फिर प्रारंभिक पता, फिर एक डमी बाइट भेजता है, और फिर यह मुझे डेटा भेजना शुरू करता है।
यहाँ डाटा शीट हैं:
Microcontroller: http://www.atmel.com/dyn/resources/prod_documents/doc8271.pdf
फ्लैश: http://www.sst.com/dotAsset/40498.pdf
कोड:
#include <SPI.h>
#include <Peggy2.h>
#define SS_PIN 16
Peggy2 frame1;
byte toDisp = 0;
byte checker = 0;
void setup()
{
frame1.HardwareInit();
pinMode(SS_PIN,OUTPUT); //set pin16 to output, SS pin
SPI.setClockDivider(SPI_CLOCK_DIV2); //set the SPI clock to f/2, fastest possible
SPI.begin(); //SPI lib function which sets ddr for SCK and MOSI pin
//MISO is auto input
//see SPI.cpp for more info
}
void loop()
{
if(!checker){
enableProgramming();
programData();
toDisp = receiveByte(0);
checker = 1;
frame1.WriteRow(0,toDisp);
}
frame1.RefreshAll(2);
}
byte receiveByte(unsigned long startAddress)
{
//Begin High Speed Read Instruction
//See p. 10 of SST data sheet
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x0B); //high speed read instruction
SPI.transfer(0x00); //next 3 transfers are address bits A32 - A0
SPI.transfer(0x00); //So this will read the first byte on the chip
SPI.transfer(0x00); //last address bits
SPI.transfer(0xFF); //dummy byte is required to start sending data back to uP
SPI.transfer(0xFF); //I'm hoping that if I transfer a bullshit byte, the flash
//chip will transfer it's data to me in the same time
digitalWrite(SS_PIN,HIGH);
//End High Speed Read Instruction
return SPDR;
}
//will perform the read instruction starting from
//startAddress and will receive numOfBytes bytes in
//succession
void receiveBytes(int numOfBytes, unsigned long startAddress)
{
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x0B);//high speed read instruction
}
//will perform:
// 1) Chip Erase
// and loop through:
// 1) Page Program
// 2) increment Page
//until the data has finished **note this can loop and over write beginning of memory
void programData(){
//Begin ChipErase Instruction
//See p. 17 of SST data sheet
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x60);//chip erase instruction
digitalWrite(SS_PIN,HIGH);
delay(50);//spec'd time for CE to finish
//don't bother polling because time to program is irrelevant
//End ChipErase Instruction
//Begin WREN Instruction
//See p. 18 of SST data sheet
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x06);//write enable instruction
digitalWrite(SS_PIN,HIGH);
//End WREN Instruction
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x02); //page program instruction
SPI.transfer(0x00); //first 8 address bits
SPI.transfer(0x00); //2nd 8 address bits
SPI.transfer(0x00); //3rd 8 address bits
SPI.transfer(0xAA); //10101010 is the byte I should be writing
digitalWrite(SS_PIN,HIGH);
delayMicroseconds(3000); //wait 3 ms for page program
/*
//Begin Page-Program Instruction
//see p. 13 of SST data sheet
byte firstAddress = 0;
byte secondAddress = 0;
//this loop will write to every byte in the chips memory
//32,768 pages of 256 bytes = 8,388,608 bytes
for(unsigned int i = 0; i < 32,768; ++i) //long variable is number of pages
{
digitalWrite(SS_PIN,LOW);
++secondAddress; //cycles from 0 to 255, counts pages
firstAddress = i>>8; // floor(i/256)
SPI.transfer(0x02);//Page-Program instruction byte
SPI.transfer(firstAddress); //increments every 256 pages i.e. at page 256 this should be 1
SPI.transfer(secondAddress); //increments every 256 bytes, i.e every page
SPI.transfer(0x00); //beginning of a page boundary
for(int j = 0; j < 256; ++j) //number of bytes per page
{
SPI.transfer(2program[(256*i) + j]);//data byte transfer
}
digitalWrite(SS_PIN,HIGH);
delayMicroseconds(2500); //2500us (2.5ms) delay for each page-program instruction to execute
}
//End Page-Program Instruction
*/
}
//Will prepare the chip for writing by performing:
// 1) arm the status register
// 2) Write Enable instruction
//Only needs to be performed once!
void enableProgramming(){
//Begin EWSR & WRSR Instructions
//See p. 20 of SST data sheet for more info
digitalWrite(SS_PIN,LOW); //lower the SS pin
SPI.transfer(0x50); //enable write status register instruction
digitalWrite(SS_PIN,HIGH); //raise the SS pin
delay(10);
digitalWrite(SS_PIN,LOW); //lower the SS pin
SPI.transfer(0x01); //write the status register instruction
SPI.transfer(0x00);//value to write to register
//xx0000xx will remove all block protection
digitalWrite(SS_PIN,HIGH);
//End EWSR & WRSR Instructions
//Begin WREN Instruction
//See p. 18 of SST data sheet
digitalWrite(SS_PIN,LOW);
SPI.transfer(0x06);//write enable instruction
digitalWrite(SS_PIN,HIGH);
//End WREN Instruction
}
तो यह एक परीक्षण कार्यक्रम माना जाता है कौन सा कार्यक्रम 1 बाइट ओटी ओ फ्लैश और फिर इसे वापस पढ़ता है और मेरे पास एक एलईडी सरणी पर बाइट प्रदर्शित करता है। यदि आप एलईडी सरणी में रूचि रखते हैं, तो यह यहां पाया जा सकता है: http://evilmadscience.com/tinykitlist/157
मेरा मानना है कि मेरा पठन कार्य काम करता है क्योंकि पहली बार मैंने इसे चलाने के बाद, सभी 8 एल ई डी जलाए। इससे मुझे संकेत मिलेगा कि यह फ्लैश मेमोरी पढ़ता है जब यह सभी 1 एस की फैक्ट्री स्थिति में था। अब स्पष्ट रूप से मैंने लेखन के साथ कुछ खराब कर दिया है क्योंकि बाइट जो रोशनी करता है वह उस बाइट के साथ मेल नहीं खाता है जिसे मैं प्रोग्राम करने का प्रयास कर रहा हूं।
मैं भी ध्यान देना चाहिए मैं Arduinos के लिए डिफ़ॉल्ट एसपीआई पुस्तकालय और फ्रेम बफर कार्यों काम उपयोग कर रहा हूँ। जब मैं frame1.WriteRow(toDisp)
करता हूं, तो यह सही तरीके से काम कर रहा है और इसका व्यापक परीक्षण किया गया है।
किसी समय या धैर्य यह पता लगाने की है कि क्या मैं गलत कर रहा हूँ अत्यंत भयानक होगा है।
संपादित करें: डिबगिंग में मदद करने के लिए:
एल ई डी जो रूप में अच्छी तरह एसपीआई इंटरफ़ेस का उपयोग ड्राइवर चिप्स के द्वारा संचालित किया जा रहा है। मैंने कोड के उस हिस्से को नहीं लिखा था। एक ऑसिलोस्कोप पर मैं कोड के उस हिस्से द्वारा संचालित एससीके लाइन देख सकता हूं। हालांकि, मेरे पास एमओएसआई पिन पर भी एक जांच है और यदि मैं किसी भी रोशनी को प्रकाश नहीं देता हूं, तो यह कभी भी ऊंचा नहीं होता है। मेरे लिए इसका मतलब है कि मैं सही ढंग से जानकारी नहीं भेज रहा हूं। AKA ... शायद मेरे SPI.transfer()
को एक सक्षम फ़ंक्शन या कुछ चाहिए?
आपके पास फ्लैश और ड्राइवर चिप्स के लिए अलग दास चयन (एसएस) पिन हैं? – AndrewStone