Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с внешней памятью
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
SidAlex
Привет всем ГУРУ программирования МК.

Возникла такая проблемка. Есть внешняя память FM25L256. Почитал pdf на эту микросхему, вроде бы все понятно. Решил поработать. Написал алгоритм инициализации микросхемы, функции чтения и записи. Но, при выполнении этих функций, они работают, но результата никакого. Т.е. вроде бы пишет, вроде бы читает, но в массиве одни нули. Подскажите где что не так делаю? Просто уже несколько дней с этим мучаюсь, а результата ноль. Микруха подцеплина через SPI, он настроен корректно, вроде. Вот и чешу в затылке. К тому же я человек в этом деле новый, много не знаю. Прошу, пожалуйста, помогите.

Заранее всем спасибо.
С уважением, Александр.
Axel
Первое, что приходит в голову: проверьте настройку SPI - в смысле фазы данных и клока. Не поможет - надо смотреть код. У меня есть опыт с M25P32 - это вроде из одного класса. Проблем не было...
SidAlex
У меня тут вот какой вопрос родился. Какие действия в какой последовательности должны проходить. Я, например, делаю так:
1. Chip Select
2. Передача команды на разрешение записи в память
3. Передача команды записи данных
4. Передача адреса, с которого нужно начинать писать
5. Передача данных
6. После передачи сбросить Chip Select.

Естественно до этого происходит настройка SPI всех необходимых портов.
Axel
Цитата(SidAlex @ Mar 1 2011, 14:17) *
...4. Передача адреса, с которого нужно начинать писать...


Важен порядок передачи байтов - начинать со старшего. Ну и обязательно дождаться статуса окончания записи. И еще пин разрешеня записи сбросить в "0".
SidAlex
Извините пожалуйста, а что значит "...обязательно дождаться статуса окончания записи..." И когда сбрасывать пин разрешения записи?
rx3apf
Цитата(SidAlex @ Mar 1 2011, 13:17) *
У меня тут вот какой вопрос родился. Какие действия в какой последовательности должны проходить. Я, например, делаю так:
1. Chip Select
2. Передача команды на разрешение записи в память
3. Передача команды записи данных
4. Передача адреса, с которого нужно начинать писать
5. Передача данных
6. После передачи сбросить Chip Select.

Неправильно. После пункта 2 надо деактивировать CS, а перед пунктом 3 - вновь активировать.


Цитата(SidAlex @ Mar 1 2011, 13:44) *
Извините пожалуйста, а что значит "...обязательно дождаться статуса окончания записи..."

Для рамтроновской памяти это не требуется, запись выполняется мгновенно.

SidAlex
А тогда подскажите пожалуйста, нужен ли между этими действиями таймаут или нет???
Axel
[quote name='rx3apf' date='Mar 1 2011, 14:45' post='892940']
Неправильно. После пункта 2 надо деактивировать CS, а перед пунктом 3 - вновь активировать.
/quote]

Да, конечно, не заметил... laughing.gif

Таймаут вроде не нужен, хватает команд, естественно выполняемых между операциями. А вот без проверки статуса при многостраничной записи не обойтись.
SidAlex
И еще тогда вопрос, а как читать? Порядок действий тот же или нет?
Axel
Цитата(SidAlex @ Mar 1 2011, 15:05) *
И еще тогда вопрос, а как читать? Порядок действий тот же или нет?


Тот же. Только CS дважды дергать не надо.
SidAlex
т.е.
1. Chip Select
2. Передача команды на разрешение чтения
4. Передача адреса, с которого нужно начинать читать
5. Чтение данных
6. После всего сбросить Chip Select.

Правильно???
Axel
Цитата(SidAlex @ Mar 1 2011, 15:13) *
Правильно???


100% biggrin.gif
rx3apf
Цитата(Axel @ Mar 1 2011, 13:55) *
Таймаут вроде не нужен, хватает команд, естественно выполняемых между операциями. А вот без проверки статуса при многостраничной записи не обойтись.

Для рамтроновской памяти - не нужно, запись выполняется мгновенно, и бит готовности всегда равен нулю.
Axel
Цитата(rx3apf @ Mar 1 2011, 15:18) *
Для рамтроновской памяти - не нужно, запись выполняется мгновенно, и бит готовности всегда равен нулю.


Посмотрел сейчас даташит - действительно, Вы правы. Я пользовал Numonyx, а там совсем даже не ноль...
SidAlex
Ребята ничего не понимаю, вроде написано все как говорите, но ничего не происходит. Точнее запись вроде есть, а вот прочитать не могу. Где что не так?
Функции записи чтения прилагаю:

void WriteFM25L256(unsigned int adress, char *mass, int nbyte)
{
unsigned int a;

// OFF_HOLD_FRAM(); //продолжить передачу данных из FRAM
// OFF_WP_FRAM(); //отключить защиту записи
CS_FRAM(); //чип-селект для FRAM

while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WREN_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
// __no_operation();
// __no_operation();
// __no_operation();
// __no_operation();
OFF_CS_FRAM(); //сброс чипселекта FRAM
CS_FRAM(); //чип-селект для FRAM
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WRITE_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress >> 8; //запись старшего байта адреса
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress; //запись младшего байта адреса
while(!(U0TCTL & TXEPT));
for(a = 0; a < nbyte; a++)
{
// while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
// U0TXBUF = mass[a] >> 8; //передать старший байт элемента массива
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = mass[a]; //передать младший байт элемента массива
while(!(U0TCTL & TXEPT));
};
// while(!(U0TCTL & TXEPT)); //пусты ли регистры TX
// WP_FRAM(); //включить защиту записи
OFF_CS_FRAM(); //сброс чипселекта FRAM
}

void ReadFM25L256(unsigned int adress, char *mass, int nbyte)
{
unsigned int a;
CS_FRAM(); //чип-селект для FRAM

while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = READ_FM25L; //команда //разрешение чтения из FM25L256
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = adress >> 8; //запись старшего байта адреса
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = adress; //запись младшего байта адреса
while(!(U0TCTL & TXEPT));
for(a = 0; a < nbyte; a++)
{
while (!(IFG1 & UTXIFG0)); //ожидание готовности TX-буфера
U0TXBUF = 0x40; //тактирование FRAM
while(!(U0TCTL & TXEPT));
while (!(IFG1 & URXIFG0)); //ожидание готовности RХ-буфера
mass[a] = U0RXBUF; //считывание из RX-буфера в массив страшего байта
while(!(U0TCTL & TXEPT));
}
//while(!(U0TCTL & TXEPT)); //пусты ли регистры TX
OFF_CS_FRAM(); //сброс чипселекта FRAM
}/* конец определения ------------------------------------------------------------------*/
Axel
К сожалению сейчас некогда рассматривать Ваш код. Может попозже... И посмотрите, как включать код в сообщение, а то читать в таком виде затруднительно...
SidAlex
Вот переделал, вставил, чтобы читать было удобнее

Код
void WriteFM25L256(unsigned int adress, char *mass, int nbyte)
{
unsigned int a;

// OFF_HOLD_FRAM(); //продолжить передачу данных из FRAM
// OFF_WP_FRAM(); //отключить защиту записи
CS_FRAM(); //чип-селект для FRAM

while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WREN_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
// __no_operation();
// __no_operation();
// __no_operation();
// __no_operation();
OFF_CS_FRAM(); //сброс чипселекта FRAM
CS_FRAM(); //чип-селект для FRAM
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WRITE_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress >> 8; //запись старшего байта адреса
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress; //запись младшего байта адреса
while(!(U0TCTL & TXEPT));
for(a = 0; a < nbyte; a++)
{
// while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
// U0TXBUF = mass[a] >> 8; //передать старший байт элемента массива
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = mass[a]; //передать младший байт элемента массива
while(!(U0TCTL & TXEPT));
};
// while(!(U0TCTL & TXEPT)); //пусты ли регистры TX
// WP_FRAM(); //включить защиту записи
OFF_CS_FRAM(); //сброс чипселекта FRAM
}

void ReadFM25L256(unsigned int adress, char *mass, int nbyte)
{
unsigned int a;
CS_FRAM(); //чип-селект для FRAM

while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = READ_FM25L; //команда //разрешение чтения из FM25L256
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = adress >> 8; //запись старшего байта адреса
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = adress; //запись младшего байта адреса
while(!(U0TCTL & TXEPT));
for(a = 0; a < nbyte; a++)
{
while (!(IFG1 & UTXIFG0)); //ожидание готовности TX-буфера
U0TXBUF = 0x40; //тактирование FRAM
while(!(U0TCTL & TXEPT));
while (!(IFG1 & URXIFG0)); //ожидание готовности RХ-буфера
mass[a] = U0RXBUF; //считывание из RX-буфера в массив страшего байта
while(!(U0TCTL & TXEPT));
}
//while(!(U0TCTL & TXEPT)); //пусты ли регистры TX
OFF_CS_FRAM(); //сброс чипселекта FRAM
}/* конец определения ------------------------------------------------------------------*/
Axel
Если с пинами (W и HOLD) все в порядке, то замечание только одно:
CODE
void WriteFM25L256(unsigned int adress, char *mass, int nbyte)
{
unsigned int a;

CS_FRAM(); //чип-селект для FRAM
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WREN_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
// __no_operation();
// __no_operation();
// __no_operation();
// __no_operation();
OFF_CS_FRAM(); //сброс чипселекта FRAM
// ------- необходим таймаут хотя-бы на один такт SPI ------------
CS_FRAM(); //чип-селект для FRAM
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = WRITE_FM25L; //разрешение записи в FM25L256
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress >> 8; //запись старшего байта адреса
while(!(U0TCTL & TXEPT));
while (!(IFG1 & UTXIFG0));//провека готовности ТХ-буфера
U0TXBUF = adress; //запись младшего байта адреса
while(!(U0TCTL & TXEPT));
for(a = 0; a < nbyte; a++)
{
while (!(IFG1 & UTXIFG0)); //провека готовности ТХ-буфера
U0TXBUF = mass[a]; //передать младший байт элемента массива
while(!(U0TCTL & TXEPT));
};
OFF_CS_FRAM(); //сброс чипселекта FRAM
}
SidAlex
Еще раз прошу прощения, но что значит WP и HOLD в порядке? Они должны быть установлены в каком то положении??? Они у меня подняты в единицу.
Axel
Цитата(SidAlex @ Mar 1 2011, 18:03) *
Еще раз прошу прощения, но что значит WP и HOLD в порядке? Они должны быть установлены в каком то положении??? Они у меня подняты в единицу.


Это нормально.
SidAlex
В общем не работает. Слать в микруху я данные шлю - это я вижу на осциллографе, а читать ничего не читаю. Скажите, пожалуйста, как должны быть установлены WP и HOLD. Вообще, если смотреть в мануал, то получается, что WP - это аппаратная защита от записи. Или я ошибаюсь? Про HOLD тоже вроде понятно, что если ноль, то все будет игнорироваться. А можно еще подсказать настройки SPI? Я вот так настраиваю:
Код
  switch(UsartNumber)
  {
    case 0:
      U0CTL |=  SWRST;
      U0CTL |= MM + SYNC + CHAR;             //Master, SPI, 8-bit Data;
      U0TCTL |= STC + SSEL0 + SSEL1;
      U0BR0 = 0x02;                          
      U0BR1 = 0x00;
      U0MCTL = 0x00;                        
      ME1 |= USPIE0;                        
      U0CTL &= ~SWRST;                  
      break;
    case 1:
      U1CTL |= SWRST;
      U1CTL |= SYNC + CHAR;     //Slave, SPI, 8-bit Data;
      U1TCTL |= STC + CKPH;    
      U1BR0 = 0x02;            
      U1BR1 = 0x00;
      U1MCTL = 0x00;          
      ME2 |= USPIE1;            
      U1CTL &= ~SWRST;    
      break;
    default:
      break;
  }
Axel
Проверить трудно, поскольку Вы не указали тип контроллера.
SidAlex
микроконтроллер MSP430F1611IPM
Axel
Цитата(SidAlex @ Mar 2 2011, 14:18) *
микроконтроллер MSP430F1611IPM


Вряд-ли смогу помочь - лет шесть с ними не работал...
defunct
Цитата(SidAlex @ Mar 2 2011, 09:10) *
что WP - это аппаратная защита от записи.

Да правильно. Для МС которую вы пользуете - в нормальном режиме работы (чтение/запись) WP и HOLD должны быть подтянуты к VCC.

По поводу настройки SPI - проконсультируйтесь в тематическом форуме по MSP.
Если есть сомнения в настройках железа - можно попробовать программно эмулировать SPI - ногодрыганием.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.