Флеш-память от ST Microelectronics
Собрался купить для очереного проекта память AT45DB161 в корпусе SO8-300, но не смог по причине отсутсвия у поставщиков :( хотя у одного поставщика нашел по цене в 600 рублей.
Решил глянуть что есть у ST Microelectronics, и как оказалось не зря :)
Есть у них серия микросхем в небольших корпусах, до двух мегабайт в SO-8, выше в SO16-300.
На пробу купил на два мегабайта M25P16, всего за 45 рублей.
Вся область разбита на сектора, сектора в свою очередь на страницы по 256 байт.
Не понравилось то что стереть можно либо всю флешку, либо сектор :( хотелось бы иметь возможность стирать страницу.
Для теста подключил к свободным ножкам МК и простым “ножко-дрыганьем” записал и считал пару страниц.
Команды:
enum M25P16_Command
{
M25P16_WRITE_ENABLE = 0x06,
M25P16_WRITE_DISABLE = 0x04,
M25P16_READ_IDENTEFICATION = 0x9F,
M25P16_READ_STATUS_REGISTER = 0x05,
M25P16_WRITE_STATUS_REGISTER = 0x01,
M25P16_READ = 0x03,
M25P16_READ_FAST = 0x0B,
M25P16_PAGE_PROGAM = 0x02,
M25P16_SECTOR_ERASE = 0xD8,
M25P16_BULK_ERASE = 0xC7,
M25P16_DEEP_POWER_DOWN = 0xB9,
M25P16_RELEASE_FROM_POWER_DOWN = 0xAB,
};
Тестовый кусочек кода:
void m25p16_test(void)
{
for (i = 0; i < 256; i++)
buffer[i] = i;
// разрешаем запись
m25p16_write_enable();
// стираем
m25p16_bulk_erase();
// ожидаем
while (m25p16_read_status() & 0x01)
{
}
// разрешаем запись
m25p16_write_enable();
// пишем
m25p16_page_write(0, &buffer[0]);
// ожидаем
while (m25p16_read_status() & 0x01)
{
}
// разрешаем запись
m25p16_write_enable();
// пишем
m25p16_page_write(1, &buffer[0]);
// ожидаем
while (m25p16_read_status() & 0x01)
{
}
// читаем
m25p16_page_read(0, &buffer[0]);
for (i = 0; i < 256; i++)
_DBH(buffer[i]);
// читаем
m25p16_page_read(1, &buffer[0]);
for (i = 0; i < 256; i++)
_DBH(buffer[i]);
}
Чтение регистра статуса:
uint8_t m25p16_read_status(void)
{
uint8_t status;
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_READ_STATUS_REGISTER);
status = m25p16_io_read();
PIN_M25P16_CS_OFF();
return status;
}
Перед стиранием или программированием необходимо разрешить запись:
void m25p16_write_enable(void)
{
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_WRITE_ENABLE);
PIN_M25P16_CS_OFF();
}
и если передумали отменить:
void m25p16_write_disable(void)
{
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_WRITE_DISABLE);
PIN_M25P16_CS_OFF();
}
Запись одной страницы:
void m25p16_page_write(uint16_t page_address, uint8_t * buffer)
{
uint8_t byte_number;
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_PAGE_PROGAM);
m25p16_io_write(page_address >> 8);
m25p16_io_write(page_address >> 0);
m25p16_io_write(0x00);
for (byte_number = 0; byte_number++ < 255;)
{
m25p16_io_write(*buffer++);
}
m25p16_io_write(*buffer);
PIN_M25P16_CS_OFF();
}
Чтение одной страницы:
void m25p16_page_read(uint16_t page_address, uint8_t * buffer)
{
uint8_t byte_number;
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_READ);
m25p16_io_write(page_address >> 8);
m25p16_io_write(page_address >> 0);
m25p16_io_write(0);
for (byte_number = 0; byte_number++ < 255;)
{
*buffer++ = m25p16_io_read();
}
*buffer = m25p16_io_read();
PIN_M25P16_CS_OFF();
}
Стереть всю флешку:
void m25p16_bulk_erase(void)
{
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_BULK_ERASE);
PIN_M25P16_CS_OFF();
}
Стереть один сектор:
void m25p16_sector_erase(uint8_t sector_address)
{
PIN_M25P16_CS_ON();
m25p16_io_write(M25P16_SECTOR_ERASE);
m25p16_io_write(sector_address);
m25p16_io_write(0x00);
m25p16_io_write(0x00);
PIN_M25P16_CS_OFF();
}
Обмен данными:
void m25p16_io_write(uint8_t data)
{
uint8_t bit_number;
for (bit_number = 8; bit_number-- > 0;)
{
PIN_M25P16_CLK_OFF();
if ((data & 0x80) == 0)
{
PIN_M25P16_DI_OFF();
}
else
{
PIN_M25P16_DI_ON();
}
PIN_M25P16_CLK_ON();
data = data < < 1;
}
PIN_M25P16_CLK_OFF();
}
uint8_t m25p16_io_read(void)
{
uint8_t bit_number;
uint8_t data = 0;
for (bit_number = 8; bit_number-- > 0;)
{
PIN_M25P16_CLK_OFF();
data = data < < 1;
PIN_M25P16_CLK_ON();
if (PIN_M25P16_DO_SIGNAL())
data |= 1;
}
PIN_M25P16_CLK_OFF();
return data;
}
comments powered by Disqus