Полная версия этой страницы:
Работа с внешней памятью
SidAlex
Feb 28 2011, 14:38
Привет всем ГУРУ программирования МК.
Возникла такая проблемка. Есть внешняя память FM25L256. Почитал pdf на эту микросхему, вроде бы все понятно. Решил поработать. Написал алгоритм инициализации микросхемы, функции чтения и записи. Но, при выполнении этих функций, они работают, но результата никакого. Т.е. вроде бы пишет, вроде бы читает, но в массиве одни нули. Подскажите где что не так делаю? Просто уже несколько дней с этим мучаюсь, а результата ноль. Микруха подцеплина через SPI, он настроен корректно, вроде. Вот и чешу в затылке. К тому же я человек в этом деле новый, много не знаю. Прошу, пожалуйста, помогите.
Заранее всем спасибо.
С уважением, Александр.
Первое, что приходит в голову: проверьте настройку SPI - в смысле фазы данных и клока. Не поможет - надо смотреть код. У меня есть опыт с M25P32 - это вроде из одного класса. Проблем не было...
SidAlex
Mar 1 2011, 10:17
У меня тут вот какой вопрос родился. Какие действия в какой последовательности должны проходить. Я, например, делаю так:
1. Chip Select
2. Передача команды на разрешение записи в память
3. Передача команды записи данных
4. Передача адреса, с которого нужно начинать писать
5. Передача данных
6. После передачи сбросить Chip Select.
Естественно до этого происходит настройка SPI всех необходимых портов.
Цитата(SidAlex @ Mar 1 2011, 14:17)

...4. Передача адреса, с которого нужно начинать писать...
Важен порядок передачи байтов - начинать со старшего. Ну и обязательно дождаться статуса окончания записи. И еще пин разрешеня записи сбросить в "0".
SidAlex
Mar 1 2011, 10:44
Извините пожалуйста, а что значит "...обязательно дождаться статуса окончания записи..." И когда сбрасывать пин разрешения записи?
Цитата(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
Mar 1 2011, 10:48
А тогда подскажите пожалуйста, нужен ли между этими действиями таймаут или нет???
[quote name='rx3apf' date='Mar 1 2011, 14:45' post='892940']
Неправильно. После пункта 2 надо деактивировать CS, а перед пунктом 3 - вновь активировать.
/quote]
Да, конечно, не заметил...

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

И еще тогда вопрос, а как читать? Порядок действий тот же или нет?
Тот же. Только CS дважды дергать не надо.
SidAlex
Mar 1 2011, 11:13
т.е.
1. Chip Select
2. Передача команды на разрешение чтения
4. Передача адреса, с которого нужно начинать читать
5. Чтение данных
6. После всего сбросить Chip Select.
Правильно???
Цитата(SidAlex @ Mar 1 2011, 15:13)

Правильно???
100%
Цитата(Axel @ Mar 1 2011, 13:55)

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

Для рамтроновской памяти - не нужно, запись выполняется мгновенно, и бит готовности всегда равен нулю.
Посмотрел сейчас даташит - действительно, Вы правы. Я пользовал Numonyx, а там совсем даже не ноль...
SidAlex
Mar 1 2011, 11:44
Ребята ничего не понимаю, вроде написано все как говорите, но ничего не происходит. Точнее запись вроде есть, а вот прочитать не могу. Где что не так?
Функции записи чтения прилагаю:
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
}/* конец определения ------------------------------------------------------------------*/
К сожалению сейчас некогда рассматривать Ваш код. Может попозже... И посмотрите, как включать код в сообщение, а то читать в таком виде затруднительно...
SidAlex
Mar 1 2011, 13:01
Вот переделал, вставил, чтобы читать было удобнее
Код
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
}/* конец определения ------------------------------------------------------------------*/
Если с пинами (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
Mar 1 2011, 14:03
Еще раз прошу прощения, но что значит WP и HOLD в порядке? Они должны быть установлены в каком то положении??? Они у меня подняты в единицу.
Цитата(SidAlex @ Mar 1 2011, 18:03)

Еще раз прошу прощения, но что значит WP и HOLD в порядке? Они должны быть установлены в каком то положении??? Они у меня подняты в единицу.
Это нормально.
SidAlex
Mar 2 2011, 07:10
В общем не работает. Слать в микруху я данные шлю - это я вижу на осциллографе, а читать ничего не читаю. Скажите, пожалуйста, как должны быть установлены 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;
}
Проверить трудно, поскольку Вы не указали тип контроллера.
SidAlex
Mar 2 2011, 10:18
микроконтроллер MSP430F1611IPM
Цитата(SidAlex @ Mar 2 2011, 14:18)

микроконтроллер MSP430F1611IPM
Вряд-ли смогу помочь - лет шесть с ними не работал...
defunct
Mar 7 2011, 13:12
Цитата(SidAlex @ Mar 2 2011, 09:10)

что WP - это аппаратная защита от записи.
Да правильно. Для МС которую вы пользуете - в нормальном режиме работы (чтение/запись) WP и HOLD должны быть подтянуты к VCC.
По поводу настройки SPI - проконсультируйтесь в тематическом форуме по MSP.
Если есть сомнения в настройках железа - можно попробовать программно эмулировать SPI - ногодрыганием.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.