Библиотека SPIFlash – позволяет читать Winbond – скачать данную библиотеку и о том как установить её в ручную (без интернета) читайте здесь “микроник.рус/7676/”
Также данную библиотеку можно скачать здесь “github.com/idodoyo/SPIFlash/tree/master”
Подключил winbond 25q32 по следующей схеме к Ардуино Нано:
Код скретча:
#include <SD.h>
#include <SPIFlash.h>
#define Flash_CS 9
File myFile;
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
uint8_t data_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < maxPage; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
flash.readByteArray(page, 0, &data_buffer[0], 256);
// Записываем блок в файл на карте памяти
myFile.write(data_buffer, 256);
// Обновляем контрольную сумму
for (int i = 0; i < 256; i++) {
checkSum += data_buffer[i];
}
// Выводим контрольную сумму
Serial.print("Checksum (32 bit): 0x");
Serial.println(String(checkSum, HEX));
Serial.println("Done.");
}
}
void loop()
{
// Пустой цикл
}
Структура флеш памяти W25QXX
Pages (256 bytes) — > Sectors (4096 bytes) -> Blocks (65536 bytes)
Вся память разбита на блоки, количество которых зависит от общего объема памяти.
Размер каждого блока составляет 65536 байт.
Каждый блок состоит из 16 секторов по 4096 байт.
Каждый сектор состоит из 16 страниц по 256 байт каждая.
ВНИМАНИЕ: Перед записью данных нужно стереть весь сектор целиком! Иначе перезапись данных внутри сектора производиться не будет.
———————————————
Далее код представлен для другой библиотеки, но принцип работы одинаковый – если будет время подредактирую код.
———————————————
void W25qxx_EraseSector(uint32_t SectorAddr);
Читать данные можно всегда любым удобным способом.
Чтение данных
Побайтно
W25qxx_ReadByte(Buf(uint8_t), Addr(0-...));
uint8_t buf[64] = {0,};
W25qxx_ReadByte(&buf[0], 0);
W25qxx_ReadByte(&buf[1], 1);
W25qxx_ReadByte(&buf[2], 2);
...
Сразу несколько байт в буфер pbuf
uint8_t pbuf[256]; W25qxx_ReadBytes(pbuf,0,256);
Пока не проверил за ненадобностью, можно ли с помощью W25qxx_ReadBytes читать несколько байтов сразу из нескольких страниц/секторов/блоков. Для чтения большого количества данных лучше использовать функции чтения страниц, секторов и блоков.
Запись данных
Перед записью данных необходимо стереть сектор или блок
W25qxx_EraseSector(Addr(0-...)); W25qxx_EraseSector(0); W25qxx_EraseSector(1); ...
Далее записываем Байты, страницу, сектор или блок.
Буфер записи 256 байт (1 страница).
uint8_t pbuf[256]; ... W25qxx_WritePage(pbuf,0,0,0);
Как преобразовать однобайтное число в четырехбайтное (и наоборот)
Так как чтение происходит побайтно, максимальное значение однобайтного (8-битного) числа от 0 до 255 (256 значений). Если требуется записать или прочитать 32-битное число (четырехбайтное), необходимо его преобразовать из/в массив из четырех 8-байтных чисел.
Ниже предложенный способ хорошо и быстро работает. Для меня такой способ более привычен. Если вам такой способ по какой-то причине не нравится, используйте другие функции.
Чтобы получить 32 бит целое число из 4 отдельных байтов, можно произвести следующие расчеты
uint32_t TestINT32; uint8_t pbuf[4]; TestINT32 = pbuf[0]*16777216 + pbuf[1]*65536 + pbuf[2]*256 + pbuf[3];
Для разбития 32 разрядного числа на 4 байта расчеты выглядят так
pbuf[0] = TestINT32/16777216; pbuf[1] = TestINT32/65536; pbuf[2] = TestINT32/256; pbuf[3] = TestINT32-pbuf[2]*256;
——————————————————
Примечание: flash.readCharArray
#include <SD.h>
#include <SPIFlash.h>
#define Flash_CS 9
File myFile;
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
uint8_t data_buffer[256];
char data2_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < maxPage; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
//flash.readByteArray(page, 0, &data_buffer[0], 256);
flash.readCharArray(page, 0, &data2_buffer[0], 256);
// Записываем блок в файл на карте памяти
//myFile.write(data_buffer, 256);
// Обновляем контрольную сумму
for (int i = 0; i < 256; i++) {
checkSum += data_buffer[i];
Serial.print(data2_buffer[i]);
}
// Выводим контрольную сумму
Serial.print("Checksum (32 bit): 0x");
Serial.println(String(checkSum, HEX));
Serial.println("Done.");
}
}
void loop()
{
// Пустой цикл
}
————————————————
Вывод в серийный порт:
Для flash.readByteArray
Initializing SPI Flash…
08:51:25.835 -> 1/16384
08:51:25.835 -> 40016000040623326519401000019119601242811554001141421283481126901367313318000010013670133180000110136671331800001201366413318000001918600093616969173009362096917332191860009360103917307212864010412864641686009613664208360128136643219186010936010391730224128642224128640232128642232128641128864560960367291194769023032170000201036480421192196036729113077906401136488431709603672912769010443301281460331209610020018932112202125525523933Checksum (32 bit): 0x2cde
08:51:26.207 -> Done.
08:51:26.207 -> 25225522421000033120961255255140332482551282100000224128642224128640232128642232128641128864028936367291130749023032170000201036480421022495236729166759064011364884311283936367291194739010443301281460331209610020118932112202125525523933252255224210000331209612552551403324825512821000032191860209360103917301616600208144640128166000519022241764012816608016540051902224176402551363613633208166012801654222414464013616600091900208128643713648200017440163443817225225532200000Checksum (32 bit): 0x6cc2
08:51:26.424 -> Done.
…
Для flash.readCharArray
09:25:03.680 -> R+ѥ���饹� SPI Flash…
09:25:03.680 -> 1/16384
09:25:03.680 -> ( A�<|s6r��"Q~ $I!
09:25:03.680 -> $F!$C!$@!�< $` � $` � �< $g �H�@h�@@<`�@$��@ �< $g ���@��@�@�@�@8 <$H �L
09:25:03.680 -> $P*� <$H �M @$X+ <$H L ,!� Done.
———————————————-
Примечание 2
———————————————-
Тест 1:
Записали в ручную символы в EEProm Winbond
Теперь читаем их:
#include <SPIFlash.h>
#define Flash_CS 9
int p0=0;
int p1=0;
int p2=0;
int p3=0;
int p4=0;
int p5=0;
int p6=0;
int p7=0;
int p8=0;
int p9=0;
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
uint8_t data_buffer[256];
char data2_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < maxPage; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
//flash.readByteArray(page, 0, &data_buffer[0], 256);
flash.readCharArray(page, 0, &data2_buffer[0], 256);
// Записываем блок в файл на карте памяти
//myFile.write(data_buffer, 256);
// Обновляем контрольную сумму
for (int i = 0; i < 256; i++) {
checkSum += data_buffer[i];
Serial.println(data2_buffer[i]);
p0=data2_buffer[0];
p1=data2_buffer[1];
p2=data2_buffer[2];
p3=data2_buffer[3];
p4=data2_buffer[4];
Serial.println(p0);
Serial.println(p1);
Serial.println(p2);
Serial.println(p3);
Serial.println(p4);
}
// Выводим контрольную сумму
Serial.print("Checksum (32 bit): 0x");
Serial.println(String(checkSum, HEX));
Serial.println("Done.");
}
}
void loop()
{
// Пустой цикл
}
Смотрим на вывод серийного порта:
13:07:18.747 -> 8Initializing SPI Flash…
13:07:20.261 -> 1/16384
13:07:20.261 -> A65
13:07:20.261 -> 66
13:07:20.261 -> 67
13:07:20.261 -> 68
13:07:20.261 -> 69
13:07:20.261 -> B65
13:07:20.261 -> 66
13:07:20.261 -> 67
13:07:20.261 -> 68
13:07:20.261 -> 69
13:07:20.261 -> C65
13:07:20.261 -> 66
13:07:20.261 -> 67
13:07:20.261 -> 68
…
———————————————-
Тест 2
—————————————-
Всё отлично, теперь упрощаем код – будем читать только первую страницу и 5 первых символов, а также сохраним их в цифровом значении в переменных p0-p4 и выведем их на экран:
#include <SPIFlash.h>
#define Flash_CS 9
int p0=0;
int p1=0;
int p2=0;
int p3=0;
int p4=0;
int p5=0;
int p6=0;
int p7=0;
int p8=0;
int p9=0;
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
uint8_t data_buffer[256];
char data2_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < 1; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
//flash.readByteArray(page, 0, &data_buffer[0], 256);
flash.readCharArray(page, 0, &data2_buffer[0], 256);
// Записываем блок в файл на карте памяти
//myFile.write(data_buffer, 256);
// Обновляем контрольную сумму
for (int i = 0; i < 5; i++) {
checkSum += data_buffer[i];
Serial.print(data2_buffer[i]);
p0=data2_buffer[0];
p1=data2_buffer[1];
p2=data2_buffer[2];
p3=data2_buffer[3];
p4=data2_buffer[4];
Serial.println(p0);
Serial.println(p1);
Serial.println(p2);
Serial.println(p3);
Serial.println(p4);
}
// Выводим контрольную сумму
Serial.print("Checksum (32 bit): 0x");
Serial.println(String(checkSum, HEX));
Serial.println("Done.");
}
}
void loop()
{
// Пустой цикл
}
—————————————————
Тест 3. Добавляем массив.
—————————————————
#include <SPIFlash.h>
#define Flash_CS 9
int melody[] = {0,0,0,0,0,0,0,0,0,0,0,0};
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
//uint8_t data_buffer[256];
char data2_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < 1; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
flash.readCharArray(page, 0, &data2_buffer[0], 256);
for (int i = 0; i < 5; i++) {
Serial.println(data2_buffer[i]);
melody[i]=data2_buffer[i];
// Serial.println("M");
Serial.println(melody[i]);
}
}
}
void loop()
{
// Пустой цикл
}
Вывод будет следующий:
Initializing SPI Flash…
1/16384
A
65
B
66
C
67
D
68
E
69
—————————————-
Тест 4. Давайте запишем музыку на EEPROM Winbond – будем читать ноты с неё и проигрывать на Ардуино музыку – аналогично записи – “микроник.рус/7651/” – где мы Читаем данные (ноты) с EEPROM 24c04 и проигрываем музыку на Arduino
————————————–
Пьезодинамик будем подключать к выводу D7
Код будет следующим:
#include <SPIFlash.h>
#include <Wire.h>
#define Flash_CS 9
// измените это значение, чтобы сделать песню медленнее или быстрее
int tempo=144;
// замените этот pin на тот, который вы хотите использовать
int buzzer = 7;
int melody[] = {0,0,0,0,0,0,0,0,0,0,0,0};
// sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
// there are two values per note (pitch and duration), so for each note there are four bytes
int notes=sizeof(melody)/sizeof(melody[0])/2;
// this calculates the duration of a whole note in ms (60s/tempo)*4 beats
int wholenote = (60000 * 4) / tempo;
int divider = 0, noteDuration = 0;
SPIFlash flash(Flash_CS);
void setup() {
Serial.begin(115200);
pinMode(Flash_CS, OUTPUT);
//pinMode(10, OUTPUT); // Нужно, если к D10 не подключен ни один CS
// Инициализация SPI Flash
Serial.println("Initializing SPI Flash...");
flash.begin();
// Читаем/записываем блоками/страницами по 256 байт
//uint8_t data_buffer[256];
char data2_buffer[256];
// Количество страниц
uint32_t maxPage = flash.getMaxPage();
// Checksum (32 bit)
uint32_t checkSum = 0;
for (int page = 0; page < 1; page++) {
// Выводим прогресс работы
if ((page % 1000) == 0) {
Serial.print(page + 1);
Serial.print("/");
Serial.println(maxPage);
}
// Читаем страницу SPI Flash
flash.readCharArray(page, 0, &data2_buffer[0], 256);
for (int i = 0; i < 9; i++) {
Serial.println(data2_buffer[i]);
melody[i]=data2_buffer[i];
//Serial.println("M");
Serial.println(melody[i]);
}
}
kkk();
}
void loop()
{
// Пустой цикл
}
void kkk()
{
//melody[0]=659;
melody[1]=4;
//melody[2]=494;
melody[3]=8;
//melody[4]=523;
melody[5]=8;
//melody[6]=587;
melody[7]=4;
//melody[8]=523;
melody[9]=8;
// iterate over the notes of the melody.
// Remember, the array is twice the number of notes (notes + durations)
for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
// calculates the duration of each note
divider = melody[thisNote + 1];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
// we only play the note for 90% of the duration, leaving 10% as a pause
tone(buzzer, melody[thisNote], noteDuration*0.9);
// Wait for the specief duration before playing the next note.
delay(noteDuration);
// stop the waveform generation before the next note.
noTone(buzzer);
}
}
Здесь можете раскомментировать строчки, чтобы услsшать мелодию из Тетрис:
//melody[0]=659; melody[1]=4; //melody[2]=494; melody[3]=8; //melody[4]=523; melody[5]=8; //melody[6]=587; melody[7]=4; //melody[8]=523; melody[9]=8;






