Перейти к содержанию
    

Не получается соединить STM32L152 и N25Q128!

попробую дергать cs по другому и вечером отпишусь

 

вот, для примера, как у меня. все работает.

 

инициализация

 

GPIOB->AFR[1] |= 0
		  |  (AF5<<20) | (AF5<<24) | (AF5<<28) // AF5 - SPI2
		  |  0;

GPIOB->MODER	 = 0
			 | GPIO_MODER_MODER0		  //
			 | GPIO_MODER_MODER1		  //
			 | GPIO_MODER_MODER2		  //
			 | GPIO_MODER_MODER3		  //
			 | GPIO_MODER_MODER4		  //
			 | GPIO_MODER_MODER5_0		// SPI2_CS
			 | GPIO_MODER_MODER6_0		//
			 | GPIO_MODER_MODER7		  //
			 | GPIO_MODER_MODER8		  //
			 | GPIO_MODER_MODER9		  //
			 | GPIO_MODER_MODER10		 //
			 | GPIO_MODER_MODER11_0	   //
			 | GPIO_MODER_MODER12		 //
			 | GPIO_MODER_MODER13_1	   // SPI2_SCK
			 | GPIO_MODER_MODER14_1	   // SPI2_MISO
			 | GPIO_MODER_MODER15_1	   // SPI2_MOSI
			 | 0;

GPIOB->PUPDR	 = 0
		   //| GPIO_PUPDR_PUPDR0		  //
		   //| GPIO_PUPDR_PUPDR1		  //
		   //| GPIO_PUPDR_PUPDR2		  //
		   //| GPIO_PUPDR_PUPDR3		  //
		   //| GPIO_PUPDR_PUPDR4		  //
			 | GPIO_PUPDR_PUPDR5_0		// SPI2_CS
		   //| GPIO_PUPDR_PUPDR6		  // 
		   //| GPIO_PUPDR_PUPDR7		  // 
		   //| GPIO_PUPDR_PUPDR8		  // 
		   //| GPIO_PUPDR_PUPDR9		  // 
		   //| GPIO_PUPDR_PUPDR10		 // 
		   //| GPIO_PUPDR_PUPDR11		 // 
		   //| GPIO_PUPDR_PUPDR12		 // 
			 | GPIO_PUPDR_PUPDR13_0	   // SPI2_SCK
			 | GPIO_PUPDR_PUPDR14_1	   // SPI2_MISO
			 | GPIO_PUPDR_PUPDR15_1	   // SPI2_MOSI
			 | 0;

SPI2->CR1 = 0				
	  | SPI_CR1_CPHA
	  | SPI_CR1_CPOL
	  | SPI_CR1_MSTR
	  | SPI_CR1_SSI
	  | SPI_CR1_SSM
	  | 0;

SPI2->CR2 = 0;

 

прием/передача

 

#define STORAGE_pinCS_HI	{ GPIOB->BSRRL = (1 <<  5); }
#define STORAGE_pinCS_LO	{ GPIOB->BSRRH = (1 <<  5); }


uint8_t STORAGE_SRB(uint8_t Value)
{
 SPI2->DR = Value;
 while (!(SPI2->SR & SPI_SR_RXNE));
 return SPI2->DR;
}

uint8_t STORAGE_CMD(uint8_t CMD, uint8_t WithReadResult)
{
 uint8_t result = 0;

 STORAGE_pinCS_LO;
 ICP_msDelay(1);
 STORAGE_SRB(CMD);
 if (WithReadResult) result = STORAGE_SRB(0xFF);
 STORAGE_pinCS_HI;

 return (result);
}

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А где ты включаешь SPI ?

вот этот бит не устанавливаешь:

SPI_CR1_SPE; ???

 

Подключил логический анализатор к CS MOSI MISO SCK все нормально посылается, CS нормально дергается установкой и снятием бита SSOE, как было изначально в моей программе!

 

Вставил твою функцию приема передачи байта, убрал задержки, на логическом анализаторе все идеально, но все равно ответ на readID один и тот же, может чип такой! Хотел спросить может запись делаю не так ?? Какой должен быть алгоритм записи подробно??? И про обвязку памяти хотел спросить какой вывод каким резистором и куда подтягивать, может куда конденсатор вставить, я уже про все варианты думаю, что может быть не правильно!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И про обвязку памяти хотел спросить какой вывод каким резистором и куда подтягивать, может куда конденсатор вставить, я уже про все варианты думаю, что может быть не правильно!!!

Кондёр по питанию нужен. Всё остальное в даташите.

Можно по всем линиям данным резисторы 33 Ом поставить. Они помогут сгладить выбросы напряжения, если у вас крутые фронты. Не забывайте, что CS для этой микросхемы немного по-другому работает. Т.е. он должен быть в лог. 0 на время всей команды. Переход CS в лог. 1 обозначает для этой микросхемы сброс команды. Т.е. при передаче данных между байтами CS должен оставаться в лог. 0. Я не наю как это на STM32, но на LPC (арм от NXP) аппаратное управление CS пришлось переделать на программное. Обратите внимание также на максимально допустимые частоты интерфейса.

Ну, а так - микросхема у меня завелась раза со второго. Правда чтение ID. Потом ещё намучился с тем, что минимально стираемый сектору неё 65 Кбайт. А памяти в контроллере - 32 Кбайт. А вот писать в неё можно по 256 байт максимум.

В общем добейтесь чёткого ответа ID, это три байта 0x20, 0xBA, 0x18 (команда 0x9f).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скорость SPI ставлю маленькую 32 МГц / 64 = 500 КГц может скорость не та, которая нужна?

 

На сколько кондер поставить?

 

#W, #HOLD, S# (CS) Притянуты к +3V 10КОМ резисторами, а SCK к земле 10 КОМ резитором

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скорость SPI ставлю маленькую 32 МГц / 64 = 500 КГц может скорость не та, которая нужна?

 

На сколько кондер поставить?

 

#W, #HOLD, S# (CS) Притянуты к +3V 10КОМ резисторами, а SCK к земле 10 КОМ резитором

0.1 мкФ керамику. Ну можно дополнительно тантал 4,7 мкФ.

SCK к земле не надо притягивать.

Минимальная частота, ЕМНИП, 0 Гц.

 

Всё.

 

Дальше ещё раз дебажите логическим анализатором. Если не работает - диаграммы в студию. Ну или можно заменить микросхему. было дело, что у меня выходила из строя по непонятным причинам. Возможно стататика. Обращаться нежно и осторожно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Перепаяю отпишу

 

post-80887-1395009699_thumb.jpg посылаю команду 0x9f

 

 

припаял на питание памяти 0,1 мкФ, отпаял 10 ком от SCK

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну на первый взгляд у вас всё нормально, кроме ответа. Единественное, какое-то непонятно поведение CS вначале. Уберите этот импульс, диаграммка должна выглядить девственно красивой, как в учебнике)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А где ты включаешь SPI ?

вот этот бит не устанавливаешь:

SPI_CR1_SPE; ???

 

Разрешение работы у меня отдельно выполняется. Перед использованием. Но оно не влияет на работу SPI как такового.

 

Подключил логический анализатор к CS MOSI MISO SCK все нормально посылается, CS нормально дергается установкой и снятием бита SSOE, как было изначально в моей программе!

 

Не помню точно где, но читал какую то тему про STM32. Там был "разбор полетов" про аппаратный CS. Результат темы я для себя вынес следующий - CS обрабатывать программно, указывая это в регистрах настройки SPI.

 

Вставил твою функцию приема передачи байта, убрал задержки, на логическом анализаторе все идеально, но все равно ответ на readID один и тот же, может чип такой! Хотел спросить может запись делаю не так ?? Какой должен быть алгоритм записи подробно???

 

Ну если анализатор все показывает верно, то вероятно чип битый. Есть возможность его поменять и попробовать чтение ID?

 

И про обвязку памяти хотел спросить какой вывод каким резистором и куда подтягивать, может куда конденсатор вставить, я уже про все варианты думаю, что может быть не правильно!!!

 

У меня нет как таковой обвязки:

- CS, SCK, MOSI, MISO - в чистом виде на процессор

- VCC, DQ2, DQ2 - на питание

- VSS - земля

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выложите пожалуйста функцию записи в память!!!

 

Именно записи страницы? А чтение нормально заработало?

Или нужна именно функция записи данных по SPI для чтения с микросхемы?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выложите пожалуйста функцию записи в память!!!

Пока не заработает команда чтения, про запись даже не стоит вспоминать.

И еще, у Micron есть драйвера низкого уровня, можете найти их на странице:

https://www.micron.com/products/support/nor-flash-software

 

Изменено пользователем Harvester

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выложите пожалуйста функцию записи в память!!!

 

n25q128 массово применяется не в одном серийном устройстве.

Я бы советовал для начала обратится к ней используя софтовый spi.

Приведённый ниже код взят из серийного проекта.

В оригинале используется аппаратный spi, но процессор не STM, поэтому я привёл программный (ранее использовавшийся и также 100% рабочий).

Надёюсь поможет Вам разобраться в проблеме.

 

//-------------------------------------------
unsigned char SPIWriteChar(unsigned char cmd) 
{
 unsigned char i;
 unsigned char recv;
 recv = 0;

 for(i=0; i<8; i++) 
 {
   if((cmd&0x80) != 0) 
   {
     SPI_PORT_SET = MOSI;
   }
   else 
   {
     SPI_PORT_CLR = MOSI;
   }

   SPI_PORT_SET = SCK;

   recv<<=1;    
   if((SPI_PIN & MISO) != 0)
   {
     recv|=0x01;
   }

   SPI_PORT_CLR = SCK;

   cmd<<=1;
 }
 return recv;
}
//-------------------------------------------

//-------------------------------------------
unsigned char SPIReadChar(void)
{
 return SPIWriteChar(0x00);
}
//-------------------------------------------

//-------------------------------------------
//макросы доступа к устройствам SPI
void DESELECT_SPI(void) 
{
 //деактивируем все устройства SPI
 SPI_PORT_SET = nSS_SFLASH;
 SPI_PORT_CLR = SCK|MOSI; //устанавливаем выводы в исходное состояние

}
//-------------------------------------------

//-------------------------------------------
void SELECT_SPI(unsigned int msk) 
{
 DESELECT_SPI(); //деактивируем все устройства SPI
 SPI_PORT_CLR = msk; //активируем необходимое
}
//-------------------------------------------

//-------------------------------------------
//инициализация SPI
void ConfigureSPI()
{  
 //настройка порта и начальных уровней
 SPI_DIR &= ~MISO;
 SPI_DIR |= SCK|MOSI;
 SPI_DIR |= nSS_SFLASH;

 SPI_PORT_SET = nSS_SFLASH;
 SPI_PORT_CLR = SCK|MOSI;
}
//-------------------------------------------

 

//--------------------------------
//------------------------------------
//коды команд работы с памятью
enum {
 N25_WREN = 0x06, //write enable
 N25_WRDI = 0x04, //write disable
 N25_RDID = 0x9f, //read id
 N25_RDSR = 0x05, //read status register
 N25_WRSR = 0x01, //write status reg
 N25_WRLR = 0xe5, //write lock reg
 N25_RDLR = 0xe8, //red lock reg
 N25_READ = 0x03, //read data bytes
 N25_FAST_READ = 0x0b, //fast read data bytes
 N25_PP = 0x02, //page prog
 N25_SE = 0xd8, //sector erase 64k
 N25_SE_4K = 0x20, //sub sector erase 4k
 N25_BE = 0xc7, //bulk erase
};
//------------------------------------

//------------------------------------
//биты регистра статуса
enum {
 N25_WIP = 0x01, //write in progress
 N25_WIL = 0x02, //write enable latch status
 N25_BP2 = 0x04, //
 N25_BP1 = 0x08, //
 N25_BP0 = 0x10, //
 N25_SRWD = 0x80, //status register write disable
};
//------------------------------------


//------------------------------------
//параметры памяти
enum {
 //N25_SECTOR_NUM = 4096, //sectors by 4k
 N25_SECTOR_NUM = 2048, //sectors by 4k
 N25_SECTOR_SIZE = 4096,
 N25_PAGE_SIZE = 256,
 M25_PAGE_PER_SECTOR = N25_SECTOR_SIZE/N25_PAGE_SIZE, //4096/256=16

 N25_PP_TM = 10, //таймаут записи страницы
 N25_SE_4K_TM = 1000, //таймаут стирания сектора
};
//------------------------------------

//процедура разрешения записи в память
void n25setWREN(void)
{
 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_WREN); //запись кода команды
 DESELECT_SPI(); //отпускаем устройство spi
}
//--------------------------------

//--------------------------------
//процедура запрещения записи в память
void n25setWRDIS(void)
{
 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_WRDI); //запись кода команды
 DESELECT_SPI(); //отпускаем устройство spi
}
//--------------------------------

//--------------------------------
//ожидание завершения операции записи
unsigned int n25waitBusy(unsigned int tm)
{
 volatile unsigned int status;

 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_RDSR); //запись кода команды

 for(unsigned int i=0; i<tm; i++)
 {
   status = SPIWriteChar(0x00); //читаем статус
   if((status & N25_WIP) == 0)
   {
     DESELECT_SPI(); //отпускаем устройство spi
     return 1; //оперция завершена
   }

   //ожидание паузы в 1 mS
   //for(volatile unsigned int j=0; j<(50*1000); j++); //пауза на исполнение
   delay_ms(1);
 }

 DESELECT_SPI(); //отпускаем устройство spi

 return 0; //ошибка таймаута
}
//--------------------------------

//--------------------------------
//процедура чтения страницы памяти
void n25pageRead(unsigned char* buff, unsigned int page, unsigned int byte, unsigned int size)
{  
 unsigned int addr=0;

 //вычисляем физический адрес байта
 addr = page*N25_PAGE_SIZE+byte;

 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_READ); //запись кода команды
 SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса

 while(size--)
 {
   *buff++ = SPIWriteChar(0x00);
 }

 DESELECT_SPI(); //отпускаем устройство spi
}
//-----------------------------

//--------------------------------
//процедура чтения сектора памяти
void n25sectorRead(unsigned char* buff, unsigned int sector, unsigned int byte, unsigned int size)
{  
 unsigned int addr=0;

 //вычисляем физический адрес байта
 addr = sector*N25_SECTOR_SIZE+byte;

 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_READ); //запись кода команды
 SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса

 while(size--)
 {
   *buff++ = SPIWriteChar(0x00);
 }

 DESELECT_SPI(); //отпускаем устройство spi
}
//-----------------------------

//--------------------------------
//процедура записи страницы памяти
void n25pageWrite(unsigned char* buff, unsigned int page, unsigned int byte, unsigned int size)
{
 unsigned int addr=0;

 //вычисляем физический адрес байта
 addr = page*N25_PAGE_SIZE+byte;

 n25setWREN(); //разрешаем запись в память

 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_PP); //запись кода команды
 SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса

 //записываем данные
 while(size--)
 {
   SPIWriteChar(*buff++);
 }

 DESELECT_SPI(); //отпускаем устройство spi

 //ожидаем завершения операции
 n25waitBusy(N25_PP_TM);  

}
//-----------------------------

//--------------------------------
//процедура записи сектора памяти
void n25sectorWrite(unsigned char* buff, unsigned int sector, unsigned int size)
{
 unsigned int page;
 unsigned int page_num;

 //вычисляем кол-во страниц и стартовый адрес страницы
 page = sector*M25_PAGE_PER_SECTOR;
 page_num = size/N25_PAGE_SIZE;

 for(unsigned int i=0; i<page_num; i++)
 {
   n25pageWrite(buff+i*N25_PAGE_SIZE, page+i, 0, N25_PAGE_SIZE);
 }  

}
//-----------------------------


//--------------------------------
//процедура стирания сектора
void n25sectorErase(unsigned int sector)
{
 //вычисляем физический адре байта
 unsigned int addr = sector*N25_SECTOR_SIZE;


 n25setWREN(); //разрешаем запись в память

 SELECT_SPI(nSS_SFLASH); //выбираем устройство spi
 SPIWriteChar(N25_SE_4K); //запись кода команды
 SPIWriteChar( (unsigned char) (addr>>16) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>8) ); //запись адреса
 SPIWriteChar( (unsigned char) (addr>>0) ); //запись адреса

 DESELECT_SPI(); //отпускаем устройство spi

 //ожидаем завершения операции
 n25waitBusy(N25_SE_4K_TM);    

 n25setWRDIS();
}
//--------------------------------


//-----------------------------
//инициализация памяти
void n25xxInit(void)
{
 n25setWRDIS();
}
//-----------------------------

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока не заработает команда чтения, про запись даже не стоит вспоминать.

+1. Чтение там элементарное.

 

Запись маленько мудрёная (нужно проверять флаг занятости девайса).

 

Но самое мудрёное будет сохранить куда-либо 64 Кбайт сектор перед тем, как его стереть, а затем перезаписать 256-байтовыми страницами :rolleyes: Если оперативы для кэша на борту мало, то будет очень медленно работать. Так, что мегабайта 2 ОЗУ бы надо)

 

В общем, действительно сначала считайте уверенно JEDEC ID, и только потом двигайтесь дашльше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...