Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32f1xx - внешняя флеш память по SPI
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
KamilSafin
Пытаюсь общаться по SPI с внешней флеш памятью at45db081
Инициализация SPI:
CODE
void spi_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
port.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &port);

port.GPIO_Mode = GPIO_Mode_Out_PP;
port.GPIO_Pin = GPIO_Pin_4;
port.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &port);

SPI_StructInit(&spi);
spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi.SPI_Mode = SPI_Mode_Master;
spi.SPI_DataSize = SPI_DataSize_8b;
spi.SPI_CPOL = SPI_CPOL_Low;
spi.SPI_CPHA = SPI_CPHA_2Edge;
spi.SPI_NSS = SPI_NSS_Soft;
spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
spi.SPI_FirstBit = SPI_FirstBit_MSB;
spi.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &spi);
SPI_Cmd(SPI1, ENABLE);
SPI_DataSizeConfig(SPI1, ENABLE);
}


отсылка и прием байта данных:
CODE
uint8_t sendByte(uint8_t byteToSend)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, byteToSend);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return (uint8_t)SPI_I2S_ReceiveData(SPI1);
}


В main пробую записать в начало памяти одну страницу данных (команда 0x85, три байта адреса и посылка), прочитать статусный регистр (команда 0xD7 - регистр читается, память не занята), а потом пробую читать с самого начала памяти (команда 0xE8, три байта адреса и 4 незначащих) - но принимаются одни и те же данные, независимого от того, что писал, т.е. это даже не прием данных:
CODE
int main(void)
{
SetSysClockTo72();
spi_init();
uint8_t data= 0;
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
data = sendByte(0x85);
data = sendByte(0x00);
data = sendByte(0x00);
data = sendByte(0x00);
for (int i = 0; i < 264; i++)
{
data = sendByte(0xEE);
}
GPIO_SetBits(GPIOA, GPIO_Pin_4);
for (int i = 0; i < 1000; i++);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xD7);
data = sendByte(DUMMY); // чтение статусного регистра
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xE8);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
sendByte(0x00);
while(1)
{
data = sendByte(DUMMY);
}
}

прием проверяю через debug в CooCox
гугление и поиск по форуму не помогли, не могу найти видимо какую то глупую ошибку
Lmx2315
Я сам не применял, но вроде код ниже это для общения с подобной флешкой:

CODE
u8 SPI_Send(u8 data)
{
WDG_func();

SPI_I2S_SendData(SPI2, data); // отправили данные

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){Circl_FUNC ();}; // ждём, пока данные не отправятся

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){Circl_FUNC ();}; // ждём пока данные появятся

u8 received = SPI_I2S_ReceiveData(SPI2);

return received;
}

//Dataflash opcodes
#define FlashPageRead 0x52 // Main memory page read
#define FlashToBuf1Transfer 0x53 // Main memory page to buffer 1 transfer
#define Buf1Read 0x54 // Buffer 1 read
#define FlashToBuf2Transfer 0x55 // Main memory page to buffer 2 transfer
#define Buf2Read 0x56 // Buffer 2 read
#define StatusReg 0x57 // Status register
#define AutoPageReWrBuf1 0x58 // Auto page rewrite through buffer 1
#define AutoPageReWrBuf2 0x59 // Auto page rewrite through buffer 2
#define FlashToBuf1Compare 0x60 // Main memory page to buffer 1 compare
#define FlashToBuf2Compare 0x61 // Main memory page to buffer 2 compare
#define ContArrayRead 0x68 // Continuous Array Read (Note : Only A/B-parts supported)
#define FlashProgBuf1 0x82 // Main memory page program through buffer 1
#define Buf1ToFlashWE 0x83 // Buffer 1 to main memory page program with built-in erase
#define Buf1Write 0x84 // Buffer 1 write
#define FlashProgBuf2 0x85 // Main memory page program through buffer 2
#define Buf2ToFlashWE 0x86 // Buffer 2 to main memory page program with built-in erase
#define Buf2Write 0x87 // Buffer 2 write
#define Buf1ToFlash 0x88 // Buffer 1 to main memory page program without built-in erase
#define Buf2ToFlash 0x89 // Buffer 2 to main memory page program without built-in erase




// Constants
//Look-up table for these sizes -> 512k, 1M, 2M, 4M, 8M, 16M, 32M, 64M
unsigned char DF_pagebits[] ={ 9, 9, 9, 9, 9, 10, 10, 11}; //index of internal page address bits

// Globals
unsigned char PageBits;

// Functions

/*****************************************************************************
*
* Function name : DF_SPI_init
*
* Returns : None
*
* Parameters : None
*
* Purpose : Sets up the HW SPI in Master mode, Mode 3
* Note -> Uses the SS line to control the DF CS-line.
*
******************************************************************************/
//Set SS high
//Set SS, MOSI and SCK as outputs
//Enable SPI in Master mode, mode 3

/*****************************************************************************
*
* Function name : Read_DF_status
*
* Returns : One status byte. Consult Dataflash datasheet for further
* decoding info
*
* Parameters : None
*
* Purpose : Status info concerning the Dataflash is busy or not.
* Status info concerning compare between buffer and flash page
* Status info concerning size of actual device
*
******************************************************************************/
unsigned char Read_DF_status (void)
{
unsigned char result,index_copy;

DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder
result = SPI_Send(StatusReg); //send status register read op-code
result = SPI_Send(0x00); //dummy write to get result

index_copy = ((result & 0x38) >> 3); //get the size info from status register
PageBits = DF_pagebits[index_copy]; //get number of internal page address bits from look-up table

Transf("Read_DF_status:");
sprintf(strng,"%x",result);
Transf(strng);
Transf("\r\n");

Transf("PageBits:");
sprintf(strng,"%x",PageBits);
Transf(strng);
Transf("\r\n");

Transf("index_copy:");
sprintf(strng,"%x",index_copy);
Transf(strng);
Transf("\r\n");

return result; //return the read status register value
}


/*****************************************************************************
*
* Function name : Page_To_Buffer
*
* Returns : None
*
* Parameters : BufferNo -> Decides usage of either buffer 1 or 2
* PageAdr -> Address of page to be transferred to buffer
*
* Purpose : Transfers a page from flash to dataflash SRAM buffer
*
******************************************************************************/
void Page_To_Buffer (unsigned int PageAdr, unsigned char BufferNo)
{
DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //transfer flash page to buffer 1
{
SPI_Send(FlashToBuf1Transfer); //transfer to buffer 1 op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8))); //lower part of page address
SPI_Send(0x00); //don't cares
}
else
if (2 == BufferNo) //transfer flash page to buffer 2
{
SPI_Send(FlashToBuf2Transfer); //transfer to buffer 2 op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8))); //lower part of page address
SPI_Send(0x00); //don't cares
}

DF_CS_inactive(); //initiate the transfer
DF_CS_active();

while(!(Read_DF_status() & 0x80)); //monitor the status register, wait until busy-flag is high
}



/*****************************************************************************
*
* Function name : Buffer_Read_Byte
*
* Returns : One read byte (any value)
*
* Parameters : BufferNo -> Decides usage of either buffer 1 or 2
* IntPageAdr -> Internal page address
*
* Purpose : Reads one byte from one of the dataflash
* internal SRAM buffers
*
******************************************************************************/
unsigned char Buffer_Read_Byte (unsigned char BufferNo, unsigned int IntPageAdr)
{
unsigned char data;

DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //read byte from buffer 1
{
SPI_Send(Buf1Read); //buffer 1 read op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00); //don't cares
data = SPI_Send(0x00); //read byte
}
else
if (2 == BufferNo) //read byte from buffer 2
{
SPI_Send(Buf2Read); //buffer 2 read op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00); //don't cares
data = SPI_Send(0x00); //read byte
};

return data; //return the read data byte
}



/*****************************************************************************
*
* Function name : Buffer_Read_Str
*
* Returns : None
*
* Parameters : BufferNo -> Decides usage of either buffer 1 or 2
* IntPageAdr -> Internal page address
* No_of_bytes -> Number of bytes to be read
* *BufferPtr -> address of buffer to be used for read bytes
*
* Purpose : Reads one or more bytes from one of the dataflash
* internal SRAM buffers, and puts read bytes into
* buffer pointed to by *BufferPtr
*
******************************************************************************/
void Buffer_Read_Str (unsigned char BufferNo, unsigned int IntPageAdr, unsigned int No_of_bytes, unsigned char *BufferPtr)
{
unsigned int i;

DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //read byte(s) from buffer 1
{
SPI_Send(Buf1Read); //buffer 1 read op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00); //don't cares
for( i=0; i<No_of_bytes; i++)
{
*(BufferPtr) = SPI_Send(0x00); //read byte and put it in AVR buffer pointed to by *BufferPtr
BufferPtr++; //point to next element in AVR buffer
}
}
else
if (2 == BufferNo) //read byte(s) from buffer 2
{
SPI_Send(Buf2Read); //buffer 2 read op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(0x00); //don't cares
for( i=0; i<No_of_bytes; i++)
{
*(BufferPtr) = SPI_Send(0x00); //read byte and put it in AVR buffer pointed to by *BufferPtr
BufferPtr++; //point to next element in AVR buffer
}
}
}
//NB : Sjekk at (IntAdr + No_of_bytes) < buffersize, hvis ikke blir det bare ball..



/*****************************************************************************
*
* Function name : Buffer_Write_Enable
*
* Returns : None
*
* Parameters : IntPageAdr -> Internal page address to start writing from
* BufferAdr -> Decides usage of either buffer 1 or 2
*
* Purpose : Enables continous write functionality to one of the dataflash buffers
* buffers. NOTE : User must ensure that CS goes high to terminate
* this mode before accessing other dataflash functionalities
*
******************************************************************************/
void Buffer_Write_Enable (unsigned char BufferNo, unsigned int IntPageAdr)
{
DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //write enable to buffer 1
{
SPI_Send(Buf1Write); //buffer 1 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
}
else
if (2 == BufferNo) //write enable to buffer 2
{
SPI_Send(Buf2Write); //buffer 2 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
}
}



/*****************************************************************************
*
* Function name : Buffer_Write_Byte
*
* Returns : None
*
* Parameters : IntPageAdr -> Internal page address to write byte to
* BufferAdr -> Decides usage of either buffer 1 or 2
* Data -> Data byte to be written
*
* Purpose : Writes one byte to one of the dataflash
* internal SRAM buffers
*
******************************************************************************/
void Buffer_Write_Byte (unsigned char BufferNo, unsigned int IntPageAdr, unsigned char Data)
{

DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //write byte to buffer 1
{
SPI_Send(Buf1Write); //buffer 1 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(Data); //write data byte
}
else
if (2 == BufferNo) //write byte to buffer 2
{
SPI_Send(Buf2Write); //buffer 2 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8));//upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_Send(Data); //write data byte
}
}


/*****************************************************************************
*
* Function name : Buffer_Write_Str
*
* Returns : None
*
* Parameters : BufferNo -> Decides usage of either buffer 1 or 2
* IntPageAdr -> Internal page address
* No_of_bytes -> Number of bytes to be written
* *BufferPtr -> address of buffer to be used for copy of bytes
* from AVR buffer to dataflash buffer 1 (or 2)
*
* Purpose : Copies one or more bytes to one of the dataflash
* internal SRAM buffers from AVR SRAM buffer
* pointed to by *BufferPtr
*
******************************************************************************/
void Buffer_Write_Str (unsigned char BufferNo, unsigned int IntPageAdr, unsigned int No_of_bytes, unsigned char *BufferPtr)
{
unsigned int i;

DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //write byte(s) to buffer 1
{
SPI_Send(Buf1Write); //buffer 1 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
for( i=0; i<No_of_bytes; i++)
{
SPI_Send(*(BufferPtr)); //write byte pointed at by *BufferPtr to dataflash buffer 1 location
BufferPtr++; //point to next element in AVR buffer
}
}
else
if (2 == BufferNo) //write byte(s) to buffer 2
{
SPI_Send(Buf2Write); //buffer 2 write op-code
SPI_Send(0x00); //don't cares
SPI_Send((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_Send((unsigned char)(IntPageAdr)); //lower part of internal buffer address
for( i=0; i<No_of_bytes; i++)
{
SPI_Send(*(BufferPtr)); //write byte pointed at by *BufferPtr to dataflash buffer 2 location
BufferPtr++; //point to next element in AVR buffer
}
}
}
//NB : Monitorer busy-flag i status-reg.
//NB : Sjekk at (IntAdr + No_of_bytes) < buffersize, hvis ikke blir det bare ball..



/*****************************************************************************
*
* Function name : Buffer_To_Page
*
* Returns : None
*
* Parameters : BufferAdr -> Decides usage of either buffer 1 or 2
* PageAdr -> Address of flash page to be programmed
*
* Purpose : Transfers a page from dataflash SRAM buffer to flash
*
******************************************************************************/
void Buffer_To_Page (unsigned char BufferNo, unsigned int PageAdr)
{
DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

if (1 == BufferNo) //program flash page from buffer 1
{
SPI_Send(Buf1ToFlashWE); //buffer 1 to flash with erase op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8))); //lower part of page address
SPI_Send(0x00); //don't cares
}
else
if (2 == BufferNo) //program flash page from buffer 2
{
SPI_Send(Buf2ToFlashWE); //buffer 2 to flash with erase op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)(PageAdr << (PageBits - 8))); //lower part of page address
SPI_Send(0x00); //don't cares
}

DF_CS_inactive(); //initiate flash page programming
DF_CS_active();

while(!(Read_DF_status() & 0x80)); //monitor the status register, wait until busy-flag is high
}


/*****************************************************************************
*
* Function name : Cont_Flash_Read_Enable
*
* Returns : None
*
* Parameters : PageAdr -> Address of flash page where cont.read starts from
* IntPageAdr -> Internal page address where cont.read starts from
*
* Purpose : Initiates a continuous read from a location in the DataFlash
*
******************************************************************************/
void Cont_Flash_Read_Enable (unsigned int PageAdr, unsigned int IntPageAdr)
{
DF_CS_inactive(); //make sure to toggle CS signal in order
DF_CS_active(); //to reset dataflash command decoder

SPI_Send(ContArrayRead); //Continuous Array Read op-code
SPI_Send((unsigned char)(PageAdr >> (16 - PageBits))); //upper part of page address
SPI_Send((unsigned char)((PageAdr << (PageBits - 8))+ (IntPageAdr>>8))); //lower part of page address and MSB of int.page adr.
SPI_Send((unsigned char)(IntPageAdr)); //LSB byte of internal page address
SPI_Send(0x00); //perform 4 dummy writes
SPI_Send(0x00); //in order to intiate DataFlash
SPI_Send(0x00); //address pointers
SPI_Send(0x00);
}

// *****************************[ End Of DATAFLASH.c]*************************


..хотя может я фигню вам написал, что-то команды не совпадают.
_4afc_
Цитата(KamilSafin @ Mar 2 2017, 12:24) *
Пытаюсь общаться по SPI с внешней флеш памятью at45db081

В main пробую записать в начало памяти одну страницу данных (команда 0x85, три байта адреса и посылка), прочитать статусный регистр (команда 0xD7 - регистр читается, память не занята), а потом пробую читать с самого начала памяти (команда 0xE8, три байта адреса и 4 незначащих) - но принимаются одни и те же данные, независимого от того, что писал, т.е. это даже не прием данных:

прием проверяю через debug в CooCox
гугление и поиск по форуму не помогли, не могу найти видимо какую то глупую ошибку


Я писал страницы at45db321d командой 0x82, только предварительно их стерев 0x81 и между адресом и посылкой я снимал CS на 100мс
Genadi Zawidowski
Вот из работающего проекта кусочек... посмотрите, что получится.
Работало с AT26DF081A
На мой взгляд, Вы не делаете кучи обязательных действий (снять защиту записи, например). И задержки "от балды" вовсе не требуются - все процессы в микросхеме отражаются в статусном регистре.
k155la3
Давно работаю с этой флешкой - весч удобная и надежная.
Обратите внимание на следующее:
1. Запись в флеш (если страница заранее стерта и не используется команда "запись со встроенным стиранием")
1.1. записать данные в буфер (1 или 2) SRAM флеш. (ожидание завершение записи не требуется)
1.2. дать команду флеш на запись буфера (1 или 2) в флеш-массив. После записи флеш
будет занята этй операцией, кажется несколько миллисекунд 4-5 мс.
2. Чтение.
Есть чтение через буфер и чтение массива напрямую.
Операция выполняется без ожидания.

Так как цикл работы и проверки состоит из 2 фаз - чтение и запись -
Вам сильно помог бы программатор, который позволяет считать (или записать) флешку "гарантированным" способом.
Для отладки чтения (это проще всего проверяется) я заполнял на программаторе флеш паттерном с инкриментом (номер страницы+номер байта в странице)
До работы с флеш проверьте что SPI настроен и работает (закольцуйте MISO-MOSI)

ps
Код
// Считать из флеш содержимое буфера
// 1-номер буфера (1 2)
// 2-адрес в BF-SRAM, с которого начать чтение
// 3-кол-во байт, которые требуется считать
// 4-указатель внешней памяти (dest, куда)
// 5-проверять-ждать готовность флеш
int AT45_ReadBuf( char n_buf, int a_addr, int n_size, char *to_ptr,  int test_ready)
{    
        char cmd_45 = C45_RD_BUFF_1;                // 054x 0x56 по умолчанию
    if( n_buf == AT45_BUFF_2 ) cmd_45 = C45_RD_BUFF_2;    // ошибки не обрабатываются
        if( n_size > 264 ) return( -2 );    // Err 2
    AT45_TEST_READY( test_ready );    
    // ----------------------        
    SET_CS0_AT45;
    SPI_TX( cmd_45 );    // 54/56 Read430<--Buf(1,2)
    SPI_TX(0);
    SPI_TX( A16_HI(a_addr) );    // старший байт адреса
    SPI_TX( A16_LO(a_addr) );    
    SPI_TX(0x00);            // Additional byte
    for( int i=0; i<n_size; i++) { *to_ptr = SPI_TX(0x00); to_ptr++; }
    CS_ALL_1;
    // ----------------------    
    
    return(1);

}//f
KamilSafin
MOSI и MISO закольцовывал - все нормально, что отправляется, то и доходит
Сейчас какая-то странная проблема - память как будто не стабильно работает, т.е. запускаю отладку один раз - все работает, пишется через 82h и читается через E8h, но иногда при запуске программа застревает в цикле проверки регистра статуса - память просто не выдает регистр, переменная равна 0. И работает память только при значении предделителя 8 (т.е. на 9 MHz), хотя при более низких частотах же тоже должна работать.
Может это быть проблемой настройки SPI или подключения? Уже который день пытаюсь настроить нормально работу, но все в одних и тех же ошибках.
Genadi Zawidowski
какой SPI MODE - 0, 1, 2 или 3 выбрано?
Цитата
spi.SPI_CPOL = SPI_CPOL_Low;
spi.SPI_CPHA = SPI_CPHA_2Edge;

какому оно соответствует? из четырех возможных допустимы только два (0 или 3, кажется).
_4afc_
Цитата(KamilSafin @ Mar 3 2017, 19:55) *
но иногда при запуске программа застревает в цикле проверки регистра статуса - память просто не выдает регистр, переменная равна 0.

Поэтому я не проверял этот регистр, а ставил паузу. Может нужна пауза при проверке статуса...

Цитата(KamilSafin @ Mar 3 2017, 19:55) *
И работает память только при значении предделителя 8 (т.е. на 9 MHz), хотя при более низких частотах же тоже должна работать.


Там ещё все ножки должны быть припаяны, даже брюхо и кондёр по питанию рядом. Ну и качество питания при включении платы.
Флешка не на проводах? На одной плате с контроллером?
k155la3
Цитата(KamilSafin @ Mar 3 2017, 19:55) *
. . . .
Может это быть проблемой настройки SPI или подключения? Уже который день пытаюсь настроить нормально работу, но все в одних и тех же ошибках.

Это цепочка из правильной настройки SPI, правильного обращения к AT45 и правильного алгоритма работы с состояниями AT45.
Для проверки сначала поработайте с буфером (первым или вторым) SRAM - без записи в массив флеш.
Буфер не требует ожидания готовности (так как это оперативная память). Соотв-но флешка "всегда готова".
Если все будет норм. - значит SPI и алгоритм обращения на AT45 правильный.
Если не читается регистр статуса - а он должен читаться ВСЕГДА - то чтото с SPI или Вашим алгоритмом.
Все блоки команд дожны отделятся "своим" CS.
Вам надо контролировать работу с "освобождением" сдвигового регистра, возможно еще не ушла
первая команда, а Вы шлете следующую.
Код
//читаем статус
char AT45_StatusGet(void)
{
    SET_CS0_AT45;
    wrSPI( C45_RD_STATUS );
    wrSPI(0);
    CS_ALL_1;
    return( UCB0RXBUF );
}

char AT45_Ready(void)
{
  if( AT45_StatusGet() & 0x80 ) //
    return(1);    // Ready
  else
    return(0);    // ! Ready
}


// здесь следует добавить временную задержку delay(n) или Sleep(n)
// чтобы не лезть непрерывно на SPI и флеш
#define AT45_TEST_READY( t_rdy ) \
    if( t_rdy )     \
    {        int n_times = 0;    \
            while( ! AT45_Ready() )    \
            if( n_times > 10000 )    \
            return(-1);        \
            else            \
            n_times++;        \
    }                    \

k155la3
Код
. . . .
sendByte(0xD7);
data = sendByte(DUMMY);                
GPIO_SetBits(GPIOA, GPIO_Pin_4); --------------- (!)
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
sendByte(0xE8);
sendByte(0x00);
sendByte(0x00);


(!) - если это CS - то возможно обрубается обмен по SPI
(CS снимается раньше, чем выдвигается-вдвигается shift-регистр SPI)
Не знаю, как организован моудль SPI у STM (буферизация итд)


toweroff
Цитата(k155la3 @ Mar 6 2017, 12:51) *
Не знаю, как организован моудль SPI у STM (буферизация итд)

да также, как у всех sm.gif
нужно флаг контроллить
ivan24190
KamilSafin, вот тестовый проект в keil 4.7 (проверял на плате TE stm32f107, там стоит flash at45db321d), попробуйте, только перенастройте периферию под свой проект. Нажмите для просмотра прикрепленного файла
toweroff
Цитата(ivan24190 @ Mar 7 2017, 08:24) *
KamilSafin, вот тестовый проект

ну о чем и говорилось:
Код
//----------------------------------------------------------------------------------------------------
/* Обмен с Flash-памятью байтом */
uint8_t FlashByteExchg(uint8_t Byte)
{
    while(!(SPI3->SR & SPI_SR_TXE));
    SPI3->DR = Byte;
    while(!(SPI3->SR & SPI_SR_RXNE));
    return SPI3->DR;
}
;
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.