Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F100 + флешка EN25T80 + soft SPI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Artos5
Добрый вечер дорогие форумчане! Помогите пожалуйста решить проблему....

значит проблема такая:
Ни в какую не удаётся прочитать данные из флешки. Почему то , ее выход "болтается в воздухе" HI-Z состояние . Потому как в момент чтения , если приблизить руку к ней - данные хаотично принимаются.

код при обращении такой:

Код
soft_spi_write_instruct(SPI_FLASH_INS_READ); // comand
     soft_spi_write_addr(0x000000); // adress


Код
// в вечном цикле читаю данные и вывожу прямо на экран дисплея + показываю считанный байт

sprintf(buffer, "A=%x  P=%d         ", soft_spi_read(), y++); // колл. этапов
lcd_xy(3,1);
lcd_out(buffer);



библиотека такая , сильно не пинайте , писал на скорую руку , да и опыта конечно не много в этом деле sm.gif :

CODE
файл .С


#include "EN25T80.h"

#define DLY 10000

void delay(long x)
{
while(x)
{
x--;
}
}

void soft_spi_init()
{


//GPIOC->CRH |=0x24200000; //
//GPIOD->CRL |=0x00000002; //
}

void soft_spi_write_instruct(unsigned char instruct)
{
char x;
SPI_CS_CLR;
delay(DLY);
for(x=0;x<8;x++) // instruction
{
if (0x80 & instruct)
{
SPI_DATA1;
}
else
{
SPI_DATA0;
}

SCK_SPI_CLR;
delay(DLY);
SCK_SPI_SET;


instruct = instruct<<1;

delay(DLY);
}
SPI_CS_SET;
}

void soft_spi_write_addr(long addr_dev)
{
char x;

SPI_CS_CLR;
delay(DLY);
for(x=0;x<24;x++) // instruction
{
if (0x800000 & addr_dev)
{
SPI_DATA1;
}
else
{
SPI_DATA0;
}

SCK_SPI_CLR;
delay(DLY);
SCK_SPI_SET;
addr_dev = addr_dev<<1;

delay(DLY);
}
SPI_CS_SET;
}

int soft_spi_read()
{
int data_buff=0;
char x;

SPI_CS_CLR;
delay(DLY);

for(x=0;x<8;x++)
{
SCK_SPI_CLR;
delay(DLY);

if (SPI_IN)
{
data_buff |=1;
}
data_buff = data_buff<<1;

SCK_SPI_SET;
SPI_DATA1;



delay(DLY);
}

SPI_CS_SET;

return data_buff;
}

файл .Н

#include "stm32f10x_gpio.h"



#define BIT_IN (1<<1) // номер бита входа SPI
#define SCK_SPI_SET GPIO_SetBits(GPIOC, GPIO_Pin_1)
#define SCK_SPI_CLR GPIO_ResetBits(GPIOC, GPIO_Pin_1)

#define SPI_DATA1 GPIO_SetBits(GPIOC, GPIO_Pin_0)
#define SPI_DATA0 GPIO_ResetBits(GPIOC, GPIO_Pin_0)

#define SPI_CS_SET GPIO_ResetBits(GPIOC, GPIO_Pin_2)
#define SPI_CS_CLR GPIO_SetBits(GPIOC, GPIO_Pin_2)


//****************** SPI Definitions **************//
//#define CHIP_SELECT_AT25 PORTE.3=0;delay_ms(100);
//#define CHIP_UNSELECT_AT25 PORTE.3=1;delay_ms(100);
//******************* SPI Definitions *************//

//******************* Instruction Set ************//
// Read Commands
#define SPI_FLASH_INS_READ 0x03 // Read array
#define SPI_FLASH_INS_FAST_READ 0x0B // Read array(low frequency)

// Program and Erase Commands
#define SPI_FLASH_INS_BLOCK_ERASE_4K 0x20 // Sector erase
#define SPI_FLASH_INS_BLOCK_ERASE_32K 0x52 // Sector erase
#define SPI_FLASH_INS_BLOCK_ERASE_64K 0xD8 // Sector erase
#define SPI_FLASH_INS_CHIP_ERASE_1 0x60 // Sector erase
#define SPI_FLASH_INS_CHIP_ERASE_2 0xC7 // Sector erase
#define SPI_FLASH_INS_PAGE_PROGRAM 0x02 // Byte/Page program

// Protection commands
#define SPI_FLASH_INS_WRITE_ENABLE 0x06 // Write enable
#define SPI_FLASH_INS_WRITE_DISABLE 0x04 // Write disable
#define SPI_FLASH_INS_PROTECT_SECTOR 0x36 // Write disable
#define SPI_FLASH_INS_UNPROTECT_SECTOR 0x39 // Write disable

// Status register commands

#define SPI_FLASH_INS_READ_STATUS_REGISTER 0x05 // Read status register
#define SPI_FLASH_INS_WRITE_STATUS_REGISTER 0x01 // Write status register

// Miscellanous Commands
#define SPI_FLASH_INS_READ_DEVICE_ID 0x9F // Read identification
#define SPI_FLASH_INS_DEEP_POWER_DOWN 0xB9 // Deep power-down
#define SPI_FLASH_INS_RESUME_FROM_DEEP_POWER_DOWN 0xAB // Release from deep power- down

#define SPI_IN ((GPIOA->IDR & BIT_IN)==BIT_IN)

void soft_spi_init();
void soft_spi_write_instruct(unsigned char instruct);
void soft_spi_write_addr(long addr_dev);
int soft_spi_read();



Подскажите пожалуйста что я делаю не так.......
ПС: клок от МК присутствует , и чип селект тоже.

Даташит взял отсюда : http://www.suwa-koubou.jp/micom/TempLogger/EN25T80.pdf

Буду крайне благодарен за любую помощь в решении данной проблемы....
С уважением Артем Угримов.
Golikov A.
#define SPI_CS_SET GPIO_ResetBits(GPIOC, GPIO_Pin_2)
#define SPI_CS_CLR GPIO_SetBits(GPIOC, GPIO_Pin_2)

чип селект точно в эту сторону?

правильнее понятнее и читабильнее делать
FLASH_CS_0 и FLASH_CS_1
обычно все выбирается 0, а в ваших функция в начале на флешку идет 1, а как закончили работу на нее идет 0. Может вы ее просто не выбираете?

из мануала к флешке
Цитата
Chip Select (CS#)
The SPI Chip Select (CS#) pin enables and disables device operation. When CS# is high the device
is deselected and the Serial Data Output (DO) pin is at high impedance. When deselected, the
devices power consumption will be at standby levels unless an internal erase, program or status
register cycle is in progress. When CS# is brought low the device will be selected, power
consumption will increase to active levels and instructions can be written to and data read from the
device. After power-up, CS# must transition from high to low before a new instruction will be
accepted.


то есть если на плате нет никакого инвертора сигнала CS, вы ее просто не выбираете...
Artos5
Цитата(Golikov A. @ Aug 11 2014, 08:58) *
то есть если на плате нет никакого инвертора сигнала CS, вы ее просто не выбираете...


Да вроде порядок с сигналами....
осциллографом смотрел - ничего подозрительного.
Я даже набросал пример в протеус и МК взял AVR
Прилепил эти библиотеки. В результате флешка точно так себя ведет........... я уже запутался sad.gif


А кто скажет , почему функция не возвращает прочитанное значение из ножки? (это вопрос по прикрепленному архиву).
Genadi Zawidowski
А что, снимать чипселект после команды, опять ставить для передачи адреса и опять снимать - это нормально? Попробуйте на весь цикл обмена оставлять чипселект. Что даташит про это говорит?

Чтение в мегах с выводов выглядит так:
#define SPI_IN ((PINB & BIT_IN)==BIT_IN)

Да и вообще, посмотрите тут: http://188.134.5.254/browser/hfreceiver/trunk/nvram.c#L209
Artos5
Я уже так делал, это проблему не решает.... я сейчас так сделал потому что вчера ставал осциллографом на программатор при чтении такой флешки, и программатор точно так работал...

Цитата(Genadi Zawidowski @ Aug 11 2014, 09:57) *
Чтение в мегах с выводов выглядит так:
#define SPI_IN ((PINB & BIT_IN)==BIT_IN)


Точно! Уже вообще голова не работает...

Теперь заработала функция чтения! Только память не читается.... мало того, еще и выход у нее в HI-Z...........
Genadi Zawidowski
Цитата
Я уже так делал, это проблему не решает....

figure 9 в даташите для Вас.
А сделайте и КОД с исправлениями сюда.
Цитата
Только память не читается.... мало того, еще и выход у нее в HI-Z...........

Это именно от того, что Вы снимаете CS.
Artos5
Цитата(Genadi Zawidowski @ Aug 11 2014, 10:08) *
figure 9 в даташите для Вас.
А сделайте и КОД с исправлениями сюда.

Это именно от того, что Вы снимаете CS.


Геннадий, я вам премного благодарен что помогаете!
Я появлюсь за ПК , попробую еще раз. И выложу пример. Может действительно чего упустил...
Golikov A.
я чет не понимаю...

soft_spi_write_instruct

начинается с

SPI_CS_CLR

который в свою очередь объявлен как

#define SPI_CS_CLR GPIO_SetBits(GPIOC, GPIO_Pin_2)

то есть с установки чип селекта в 1. при этом в описании на флешку написано что это СНИМАЕТ выбор флэшки... как вы хотите чтобы она после этого хоть что-то вернула? если вы все общение производите со снятым выбором? Есть инверсия сигнала на плате чтобы он до флешки 0 доходил при 1?

и еще написано что флешка ловит фронты чипселекта, так что после включения питания чип селектом надо дернуть, нельзя просто в 0 держать.
Библиотеки бл...
Artos5
Цитата(Golikov A. @ Aug 11 2014, 11:31) *
я чет не понимаю...

soft_spi_write_instruct

начинается с

SPI_CS_CLR

который в свою очередь объявлен как

#define SPI_CS_CLR GPIO_SetBits(GPIOC, GPIO_Pin_2)

то есть с установки чип селекта в 1. при этом в описании на флешку написано что это СНИМАЕТ выбор флэшки... как вы хотите чтобы она после этого хоть что-то вернула? если вы все общение производите со снятым выбором? Есть инверсия сигнала на плате чтобы он до флешки 0 доходил при 1?



Нет.... как раз сброс происходит.... [CENSORED] Точно! sm.gif вот это я лопух....

Получается запутался в трёх соснах : ))))

Переделал уже так:

Код
     soft_spi_init();
     SPI_CS_CLR;
     //soft_spi_write_instruct(SPI_FLASH_INS_READ_DEVICE_ID);
     soft_spi_write_instruct(SPI_FLASH_INS_READ);
     soft_spi_write_addr(0x000000);


Код
                                    sprintf(buffer, "A=%x  P=%d         ", soft_spi_read(), y++); // колл. этапов
                                    lcd_xy(3,1);
                                    lcd_out(buffer);


сама библиотека:

CODE
// .Н =================

#include "stm32f10x_gpio.h"



#define BIT_IN (1<<1) // номер бита входа SPI
#define SCK_SPI_SET GPIO_SetBits(GPIOC, GPIO_Pin_1)
#define SCK_SPI_CLR GPIO_ResetBits(GPIOC, GPIO_Pin_1)

#define SPI_DATA1 GPIO_SetBits(GPIOC, GPIO_Pin_0)
#define SPI_DATA0 GPIO_ResetBits(GPIOC, GPIO_Pin_0)

#define SPI_CS_CLR GPIO_ResetBits(GPIOC, GPIO_Pin_2)
#define SPI_CS_SET GPIO_SetBits(GPIOC, GPIO_Pin_2)


//****************** SPI Definitions **************//
//#define CHIP_SELECT_AT25 PORTE.3=0;delay_ms(100);
//#define CHIP_UNSELECT_AT25 PORTE.3=1;delay_ms(100);
//******************* SPI Definitions *************//

//******************* Instruction Set ************//
// Read Commands
#define SPI_FLASH_INS_READ 0x03 // Read array
#define SPI_FLASH_INS_FAST_READ 0x0B // Read array(low frequency)

// Program and Erase Commands
#define SPI_FLASH_INS_BLOCK_ERASE_4K 0x20 // Sector erase
#define SPI_FLASH_INS_BLOCK_ERASE_32K 0x52 // Sector erase
#define SPI_FLASH_INS_BLOCK_ERASE_64K 0xD8 // Sector erase
#define SPI_FLASH_INS_CHIP_ERASE_1 0x60 // Sector erase
#define SPI_FLASH_INS_CHIP_ERASE_2 0xC7 // Sector erase
#define SPI_FLASH_INS_PAGE_PROGRAM 0x02 // Byte/Page program

// Protection commands
#define SPI_FLASH_INS_WRITE_ENABLE 0x06 // Write enable
#define SPI_FLASH_INS_WRITE_DISABLE 0x04 // Write disable
#define SPI_FLASH_INS_PROTECT_SECTOR 0x36 // Write disable
#define SPI_FLASH_INS_UNPROTECT_SECTOR 0x39 // Write disable

// Status register commands

#define SPI_FLASH_INS_READ_STATUS_REGISTER 0x05 // Read status register
#define SPI_FLASH_INS_WRITE_STATUS_REGISTER 0x01 // Write status register

// Miscellanous Commands
#define SPI_FLASH_INS_READ_DEVICE_ID 0x9F // Read identification
#define SPI_FLASH_INS_DEEP_POWER_DOWN 0xB9 // Deep power-down
#define SPI_FLASH_INS_RESUME_FROM_DEEP_POWER_DOWN 0xAB // Release from deep power- down

/*
#define BIT_IN (1<<3) // номер бита входа SPI
#define SCK_SPI_SET {GPIOA->BSRR |=(1<<1); GPIOA->BSRR &=~(1<<17);}
#define SCK_SPI_CLR {GPIOA->BSRR |=(1<<17); GPIOA->BSRR &=~(1<<1);}

#define SPI_DATA1 {GPIOA->BSRR |=(1<<2); GPIOA->BSRR &=~(1<<18);}
#define SPI_DATA0 {GPIOA->BSRR |=(1<<18); GPIOA->BSRR &=~(1<<2);}

#define SPI_CS_SET {GPIOA->BSRR |=(1<<4); GPIOA->BSRR &=~(1<<20);}
#define SPI_CS_CLR {GPIOA->BSRR |=(1<<20); GPIOA->BSRR &=~(1<<4);}
*/
#define SPI_IN ((GPIOA->IDR & BIT_IN)==BIT_IN)

void soft_spi_init();
void soft_spi_write_instruct(unsigned char instruct);
void soft_spi_write_addr(long addr_dev);
int soft_spi_read();

// .С =================


#include "EN25T80.h"

#define DLY 10000

void delay(long x)
{
while(x)
{
x--;
}
}

void soft_spi_init()
{

SPI_CS_CLR;
delay(DLY);
SPI_CS_SET;
delay(DLY);
SPI_CS_CLR;
delay(DLY);
SPI_CS_SET;
delay(DLY);
//GPIOC->CRH |=0x24200000; //
//GPIOD->CRL |=0x00000002; //
}

void soft_spi_write_instruct(unsigned char instruct)
{
char x;

delay(DLY);
for(x=0;x<8;x++) // instruction
{
if (0x80 & instruct)
{
SPI_DATA1;
}
else
{
SPI_DATA0;
}
SCK_SPI_CLR;
delay(DLY);
SCK_SPI_SET;
delay(DLY);

instruct = instruct<<1;
}

}

void soft_spi_write_addr(long addr_dev)
{
char x;


delay(DLY);
for(x=0;x<24;x++) // instruction
{
if (0x800000 & addr_dev)
{
SPI_DATA1;
}
else
{
SPI_DATA0;
}
SCK_SPI_CLR;
delay(DLY);
SCK_SPI_SET;
delay(DLY);
addr_dev = addr_dev<<1;
}
SPI_CS_SET;
}

int soft_spi_read()
{
int data_buff=0;
char x;


delay(DLY);

for(x=0;x<8;x++)
{
SCK_SPI_CLR;
delay(DLY);

if (SPI_IN)
{
data_buff |=1;
}
data_buff = data_buff<<1;

SCK_SPI_SET;
SPI_DATA1;



delay(DLY);
}



return data_buff;
}


Результат все тот же... sad.gif

Обнаружил что PORTC.2 после сброса болтается в единице .... а это ножка чип селекта
Genadi Zawidowski
Чипселект ДОЛЖЕН быть опущен в "0" на всё время работы. Сделайте пожалуйста так. Сейчас у Вас после передачи адреса чипселект снимается (переводится в "1").
Golikov A.
мда...

soft_spi_write_instruct

смотрим тело функции

цикл, в нем SPI_CS_SET - есть, а в начале
SPI_CS_CLR - нету.... вы снова не выбрали флешкуsm.gif...

возьмите осцилограф, и смотрите картинки что он рисует, поставьте их на клок и чип селект. Правьте код пока не получите такие же картинки как в мануале... Огромное количество очевидных ошибок из-за невнимательности. 1 - 2 можно понять, иногда зарубает не видишь очевидного, но такое количество легко диагностируемых....

Проинитите порт, задайте частоту если есть, повыставляйте на порт 0 и 1, сделайте для них дефайны, реализуйте алгоритм общения с флэшкой, у вас еще и осцилограф есть...

Artos5
Цитата(Genadi Zawidowski @ Aug 11 2014, 12:43) *
Чипселект ДОЛЖЕН быть опущен в "0" на всё время работы. Сделайте пожалуйста так. Сейчас у Вас после передачи адреса чипселект снимается (переводится в "1").


Перенес чипселект на ПОРТА2 , проработало ровно пару минут, и данные выводились из флешки.... спустя 2 минуты ПОРТА2 Стал себя аналогично вести........ после сброса поднимается в единицу. Это просто какая то магия из этими пинами.....
Golikov A.
я бы сделал функцию

WriteSPIData(int8_t data_out);
ReadSPIData(int8_t *data_in);

макросы
FLASH_CS_0
FLASH_CS_1


и использовал

FLASH_CS_0;
WriteSPIData(...);
...
ReadSPIData(...);
...
FLASH_CS_1;

Artos5
Цитата(Golikov A. @ Aug 11 2014, 12:47) *
мда...

soft_spi_write_instruct

смотрим тело функции

цикл, в нем SPI_CS_SET - есть, а в начале
SPI_CS_CLR - нету.... вы снова не выбрали флешкуsm.gif...

возьмите осцилограф, и смотрите картинки что он рисует, поставьте их на клок и чип селект. Правьте код пока не получите такие же картинки как в мануале... Огромное количество очевидных ошибок из-за невнимательности. 1 - 2 можно понять, иногда зарубает не видишь очевидного, но такое количество легко диагностируемых....

Проинитите порт, задайте частоту если есть, повыставляйте на порт 0 и 1, сделайте для них дефайны, реализуйте алгоритм общения с флэшкой, у вас еще и осцилограф есть...


Да выбрал я уже флешку sm.gif
в том то и дело. Проработало пару минут , и теперь опять чипселект не опускается....


Фух......... заработало wink.gif
убрал чипселект в функции.

Теперь другой прикол. Почему вместо FF выводится 1FE ? Ну и естественно остальные данные какие попало.

Ребятки, всем огромное спасибо!!!! Все заработало : )))) моей радости нет предела!
Genadi Zawidowski
Сделать так:
Код
     SCK_SPI_CLR;
     delay(DLY);
     SCK_SPI_SET;
     delay(DLY);

      data_buff = (data_buff<<1) | (SPI_IN != 0);

И разберитесь с задержками и оптимизацией в компиляторе - а то следующий вопрос будет "почему всё в release перестало работать".
Artos5
Так все в железе и заработало. По крайней мере чтение из флешки.

Интересный код. Не видел такой реализации раньше.
И на много быстрее такой вариант работает?
Genadi Zawidowski
Цитата(Artos5 @ Aug 11 2014, 18:25) *
Так все в железе и заработало. По крайней мере чтение из флешки.

Интересный код. Не видел такой реализации раньше.
И на много быстрее такой вариант работает?

Delay всю разницу возьмёт на себя.
Без разницы про скорость - но читать после подъёма CLK. Во всяком случае, на такой последовательности тактирования работали все чипы.
Приходите на аппаратный SPI, если скорость вдруг заинтересовала.
Artos5
Да скорость пока не важна. Не те задачи нужно решать sm.gif Программный лучше тем что совместим с любым мк.
Artos5
Возникла вторая проблема. Память не стирается и не записывается. Программная защита от записи отключена, проверил программатором. Читаться , читается память нормально.

Стирание и запись:

Код
soft_spi_init();
     SPI_CS_CLR;

     soft_spi_write_instruct(SPI_FLASH_INS_BLOCK_ERASE_4K);
    

     SPI_CS_SET;
     delay(100000);
     delay(100000);
     delay(100000);
     delay(100000);
     delay(100000);
     delay(100000);
     delay(100000);
     SPI_CS_CLR;

     soft_spi_write_instruct(SPI_FLASH_INS_PAGE_PROGRAM);
     soft_spi_write_addr(0x000000);
    for(x=0; x<255; x++)
     {
     soft_spi_write_instruct(x);
    }

     SPI_CS_SET;


сама функция записи:

Код
void soft_spi_write_instruct(unsigned char instruct)
{
    char x;

     delay(DLY);
    for(x=0;x<8;x++)  // instruction
    {

         SCK_SPI_CLR;

         if (0x80 & instruct)
         {
            SPI_DATA1;
         }
         else
         {
            SPI_DATA0;
         }

         delay(DLY);
         SCK_SPI_SET;
          delay(DLY);
         SCK_SPI_CLR;

      instruct = instruct<<1;
    }

}


Код
void soft_spi_write_addr(long addr_dev)
{
    char x;


     delay(DLY);
    for(x=0;x<24;x++)  // instruction
    {
         SCK_SPI_CLR;
         if (0x800000 & addr_dev)
         {
            SPI_DATA1;
         }
         else
         {
            SPI_DATA0;
         }

         delay(DLY);
         SCK_SPI_SET;
         delay(DLY);
         SCK_SPI_CLR;
          addr_dev = addr_dev<<1;
    }
}
Genadi Zawidowski
Команду WRITE ENABLE (код 0x06) кто даст?
Artos5
Цитата(Genadi Zawidowski @ Aug 11 2014, 21:34) *
Команду WRITE ENABLE (код 0x06) кто даст?


Геннадий, Вам нету цены! Спасибо! Прописал эту команду - и всё заработало : ))))
И чего для особо тугих нету полной "карты" записи страницы?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.