Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Atmega 2561 + флеш AT45DB041A - как связать по SPI?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Slavast
Не получается связать Atmega 2561 + флеш AT45DB041A. На данном этапе хочу хотя бы прочитать состояние статус регистра Памяти.
Но не работает.(((
Информацию состояния Статус-регистра вывожу на терминал компьютера через UART. UART работает 100 %.
Подскажите плиз - что не так?
Спасибо откликнувшимся.
xelax
Цитата(Slavast @ Nov 30 2010, 12:59) *
Не получается связать Atmega 2561 + флеш AT45DB041A. На данном этапе хочу хотя бы прочитать состояние статус регистра Памяти.
Но не работает.(((
Информацию состояния Статус-регистра вывожу на терминал компьютера через UART. UART работает 100 %.
Подскажите плиз - что не так?
Спасибо откликнувшимся.


Что-то не понятно. Во первых почему у вас SS как вход сконфигурирован. Надо его сделать выходом и в добавок ко всему управлять им во время совершения транзакций на SPI шине. А во вторых SPI интерфейс, передавая байт через MOSI, одновременно по тем же тактам принимает байт из MISO. А у вас приём и передача разнесена по времени.
Slavast
Цитата(xelax @ Nov 30 2010, 13:23) *
Что-то не понятно. Во первых почему у вас SS как вход сконфигурирован. Надо его сделать выходом и в добавок ко всему управлять им во время совершения транзакций на SPI шине. А во вторых SPI интерфейс, передавая байт через MOSI, одновременно по тем же тактам принимает байт из MISO. А у вас приём и передача разнесена по времени.


Как управлять SS во время транзакций? До посылки каждого байта ставить в 0, а после пересылки в 0?
как переходить в режим чтения после каждого переданного бита - захватывать состояние MISO в SPDR, включая при этом на время SS?
Для прочтения состояния регистра статуса в флеш памяти - даташит пишет что после полной отправки OPCODa D7 в течение последующих 8 тактов 8 бит регистра статуса будет полностью перенесено на MISO и только теперь якобы его можно прочитать. Поэтому я делаю последовательно.
Sergey_Aleksandrovi4
Slavast, читаем мануал на флешку вместе (4 старница)
Цитата
To read the status register, an
opcode of 57H or D7H must be loaded into the device.
After the last bit of the opcode is shifted in, the eight bits of
the status register, starting with the MSB (bit 7), will be
shifted out on the SO pin during the next eight clock cycles.

Дословно "Для чтения статусного регистра в устройство должен быть записан код 0x57 или 0xD7. После того, как последний бит "опкода" будет вдвинут в регистр, 8 бит статусного регистра (начиная со старшего 7-го бита) будут выдвигаться наружу на вывод SO (MISO) на протяжении следующих 8 тактов".
Т.е. Вам надо сперва передать опкод 0x57, потом передать 0x00 (при этом линия MOSI будет в 0, а по SCK пройдут 8 тактовых импульсов и микросхема памяти будет по MISO слать в МК значение статусного регистра). Только после этого из SPDR читаете принятый байт данных.
Приём и передачу неправильно так разносить ибо для SPI они по времени едины. Лучше чтобы ваша функция возвращала прочитанный в SPDR байт через регистр (пусть будет r16)
Код
;--------------- Передача по SPI --------------------

            SPI_MasterTransmit:
// НЕ ЗАБЫВАЕМ УСТАНАВЛИВАТЬ SlaveSelect (SS) в 0
CBI PORTB,0
                ldi r16,0xD7; Посылаем OPCODE для чтения Статус-регистра
                out SPDR,r16
        Wait_Transmit:        ; Wait for transmission complete
                lds r18, SPSR
                sbrs r18,SPIF
                rjmp Wait_Transmit

// Передаёи байт 0x00 для чтения результата из DataFlash в МК
                ldi r16,0
                out SPDR,r16
                            Wait_Transmit1:
                lds r18, SPSR
                sbrs r18,SPIF
                rjmp Wait_Transmit1

// Деактивируем SlaveSelect (SS) после каждой транзакции с DataFlash
SBI PORTB,0

in r16,SPDR   //ПРИ ВЫХОДЕ ИЗ ФУНКЦИИ в r16 будет лежать прочитанный байт (там с ним творите что хотите, хоть в UART его передать, хоть сохранить куда-нить)
             ret
Slavast
Цитата(Sergey_Aleksandrovi4 @ Nov 30 2010, 13:45) *
Slavast, читаем мануал на флешку вместе (4 старница)



Ааа! Вот оно что! Теперь понял.
Но а что же делать с SS в теч всео этого времени - начиная от "SPI_MasterTransmit:" и до "rjmp Wait_Transmit1". все время держать его в 0? А после этого поставить его в 1?
И главный вопрос - чем переключить ATMega2561 в режим чтения? Или его не нужно переключать? наша информация и так автоматически попадет в SPDR?

Цитата(Slavast @ Nov 30 2010, 14:00) *
Но а что же делать с SS в теч всео этого времени - начиная от "SPI_MasterTransmit:" и до "rjmp Wait_Transmit1". все время держать его в 0? А после этого поставить его в 1?


Простите, по попводу SS не увидел в конце ваших советов. теперь ясно.
Что же касается переключения в режим чтения - это все еще вопрос.
mempfis_
Цитата(Slavast @ Nov 30 2010, 15:11) *
Что же касается переключения в режим чтения - это все еще вопрос.

Чтение/запись для SPI это одно и то же.
Вы ложите в SPDR байт и он отправляется. Одновременно с этим в SPDR вдвигается байт ответа.
Т.о. процедура чтения регистра статуса сводится к следующему:
1. SS в 0
2. В SPDR опкод - чтение регистра статуса, дождаться отправки.
3. В SPDR любое число, после отправки считать SPDR - получим регист статуса
Если операция выполнена (смотреть на биты в регистре статуса) SS в 1 и выход
Иначе возврат на П3.
Slavast
Цитата(mempfis_ @ Nov 30 2010, 14:34) *
Чтение/запись для SPI это одно и то же.
Вы ложите в SPDR байт и он отправляется. Одновременно с этим в SPDR вдвигается байт ответа.
Т.о. процедура чтения регистра статуса сводится к следующему:
1. SS в 0
2. В SPDR опкод - чтение регистра статуса, дождаться отправки.
3. В SPDR любое число, после отправки считать SPDR - получим регист статуса
Если операция выполнена (смотреть на биты в регистре статуса) SS в 1 и выход
Иначе возврат на П3.


Теперь ясно. Ни в какой режим чтения заходить не надо. Вcе со следующим циклом задвинется в SPDR.
НО до сих пор не работает..(((
Может нужно в DORD определить какой бит будет слаться первым - старший или младший?
mempfis_
Цитата(Slavast @ Nov 30 2010, 15:59) *
Теперь ясно. Ни в какой режим чтения заходить не надо. Вcе со следующим циклом задвинется в SPDR.
НО до сих пор не работает..(((
Может нужно в DORD определить какой бит будет слаться первым - старший или младший?


Пример инициализации SPI на C из документации на atmega128 (взято из рабочего проекта).
Там же есть и примеры на ассемблере.
Также пример ожидания готовности памяти по регистру статуса.

Код
void SPIMasterInit(void)
{
/* Enable SPI, Master, set clock rate fck/4 */
SPCR = (1<<SPE)|(1<<MSTR);
}

void SPIWriteChar(unsigned char data)
{
  /* Start transmission */
  SPDR = data;
  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)));
}

unsigned char SPIReadChar(void)
{
  /* Start transmission */
  SPDR = 0x00;
  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)));
  return SPDR;

/***************************************************************/
//активация/деактивация микросхемы памяти перед операциями
inline void at45xx_init_op(void){SPI_PORT &= ~( (1<<nSS_AT45DBXX)|(1<<SCK)|(1<<MOSI) );}
inline void at45xx_end_op(void){ SPI_PORT |= (1<<nSS_AT45DBXX);}
/***************************************************************/

#define STATUS_REGISTER_READ  0xD7 /**< status register */

/***************************************************************/
//ожидание готовности памяти
unsigned char at45xx_wait(void)
{
  unsigned int i = 25000;
  unsigned char read_data;  
  
  at45xx_init_op(); //активация микросхемы памяти
  SPIWriteChar(STATUS_REGISTER_READ); //инициализация опкода

  while(i>0)
  {
    __watchdog_reset();
    delay_us(100);
    read_data = SPIReadChar(); //чтение регистра статуса
    if( (read_data & 0x80 ) != 0 ) break;
    i--;
  }
  
  at45xx_end_op(); //деактивация микросхемы памяти

  if (i != 0) return DF_NO_ERROR; //обработка ошибок
  else     return DF_WAIT_FAIL;
}
/***************************************************************/
}



SS настроен как выход? Какое его исходное состояние (должно быть 1)? Опкод правильно посылается?
И что подразумевается под "не работает" ?
Slavast
Цитата(mempfis_ @ Nov 30 2010, 16:11) *
Пример инициализации SPI на C из документации на atmega128 (взято из рабочего проекта).
Там же есть и примеры на ассемблере.
Также пример ожидания готовности памяти по регистру статуса.

SS настроен как выход? Какое его исходное состояние (должно быть 1)? Опкод правильно посылается?
И что подразумевается под "не работает" ?


А есть такой же пример на Ассемблере?
Если можно - киньте плииз!
"Не работает" - на UART вижу только 00.

Может загвоздка в следующем. В даташите пишут:

SPI_MasterInit: ; Set MOSI and SCK output, all others input
ldi r17,(1<<DD_MOSI)|(1<<DD_SCK)
out DDR_SPI,r17 ; Enable SPI, Master, set clock rate fck/16
ldi r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
out SPCR,r17
ret

Вот тут и непонятно: MOSI и SCK нужно задавать в 1 на DDRB или PORTB (т.е. указывать только направление или в заранее заданном на выход порт выдавать 1 или 0)? Это же ведь существенно! В Си коде за этим не могу уследить. Точно также и SS - нужно 1 посылать в DDRB или PORTB?

Т.е.

ldi r16,(1<<PB0)
ldi r17,(1<<DDB0)
out PORTB,r16
out DDRB,r17


или только

ldi r17,(1<<DDB0)
out DDRB,r17 ?
mempfis_
Прочитайте раздел SPI в документации. Там всё подробно описано. Примеры инициализации и работы на 100% рабочие.
Зациклите передачу по SPI (например постоянно опрашивайте регистр статуса) и потыкайте осциллографом на MOSI, MISO, SCK и SS.
Посмотрите что передаётся, что принимается.
По поводу настроек портов MOSI, SCK, SS настаиваете на выход (соотв. биты в DDR установлены в 1), исходные состояния пинов MOSI, SCK 0 (соотв. биты в PORT сброшены в 0), SS - 1. MISO настройте как вход без подтягивающего резистора (бит в DDR 0, бит в PORT тоже в 0).
Как вариант перед активацией микросхемы памяти приводите MOSI, SCK в исходное состояние (0,0) и только потом тяните SS в 0.
Я так делаю постоянно - SPI работает как положено.

Также почитайте и посмотрите приложенные файлы.
Палыч
Цитата(Slavast @ Dec 1 2010, 11:13) *
Вот тут и непонятно: MOSI и SCK нужно задавать в 1 на DDRB или PORTB (т.е. указывать только направление или в заранее заданном на выход порт выдавать 1 или 0)? Это же ведь существенно!
Для MOSI и SCK в инициализации указывают только направление - всё остальное лежит на аппаратуре.

Цитата(Slavast @ Dec 1 2010, 11:13) *
Точно также и SS - нужно 1 посылать в DDRB или PORTB?
Для мастера SS не используется при работе SPI. Разработчик может эту ногу МК использовать по своему усмотрению. Например, может соединить SS мастера и SS слэйва. В этом случае в инициализации мастера указывают направление и начальный уровень (по даташиту слэйва). Можно SS слэйва подключить к другой ноге МК мастера (если слэйвов несколько, то - так и будет).
Slavast
А для команд вывода на SPDR и SPSR нужно использовать команду OUT или STS?
Палыч
Цитата(Slavast @ Dec 1 2010, 17:07) *
А для команд вывода на SPDR и SPSR нужно использовать команду OUT или STS?
Эти регистры лежат в области I/O Registers, к которой можно обращаться командой OUT. При необходимости можно обращаться к этим регистрам и командой STS (адрес при этом на 20h больше, чем при обращении командой OUT).
mempfis_
Цитата(Slavast @ Dec 1 2010, 17:07) *
А для команд вывода на SPDR и SPSR нужно использовать команду OUT или STS?


Такое чувство что Вы даже не заглядываете в документацию на Ваш контроллер.
Под рукой нету доков на atmega2561 поэтому сами откройте раздел относящийся к SPI и посмотрите на примеры.
Если всё ещё будет не понятно какие команды использовать то найдите таблицу адресов всех регистров (Register Summary) atmega2561 найдите в ней SPDR, SPSR. Посмотрите сколько адресов соответствуют этим регистрам. Если 1 то они расположены в пространстве оперативной памяти (доступ LDS/STS), если 2 - в пространстве ввода-вывода (доступ IN/OUT)
ILYAUL
Цитата(mempfis_ @ Dec 1 2010, 18:38) *
Такое чувство что Вы даже не заглядываете в документацию на Ваш контроллер.
Под рукой нету доков на atmega2561 поэтому сами откройте раздел относящийся к SPI и посмотрите на примеры.

Этот совет был дан ему давным давно , но с того времени ничего не изменилось
Slavast
Цитата(mempfis_ @ Dec 1 2010, 19:38) *
SPDR, SPSR. Посмотрите сколько адресов соответствуют этим регистрам. Если 1 то они расположены в пространстве оперативной памяти (доступ LDS/STS), если 2 - в пространстве ввода-вывода (доступ IN/OUT)


Спасибо. Теперь знаю как проверять. В Registers summary SPDR, SPSR действительно занимают по 1 байту - значит lds/sts.
Палыч
Цитата(Slavast @ Dec 2 2010, 11:54) *
В Registers summary SPDR, SPSR действительно занимают по 1 байту - значит lds/sts.
Что-то я не пойму... Речь, вроде, идет о mega2561? Тогда: регистр SPDR имеет адрес 2E при обращении к нему командами in/out и адрес 4Е при обращении командами lds/sts; соответственно для регистра SPSR - эти адреса 2D и 4D.
Slavast
Цитата(Палыч @ Dec 2 2010, 14:25) *
Что-то я не пойму... Речь, вроде, идет о mega2561? Тогда: регистр SPDR имеет адрес 2E при обращении к нему командами in/out и адрес 4Е при обращении командами lds/sts; соответственно для регистра SPSR - эти адреса 2D и 4D.


Все таки поменял на InOut - по крайней мере с 2D и 2E точно должно читать.



Спасибо Sergey_Aleksandrovi4, Mempfis, Палыч!
В конечном итоге получилось только передать по SPI: осциллографом щупаю MOSI - вижу передаваемые данные, SS - вижу низкие уровни в момент передачи,на SCLK - тактирование. Но на MISO ничего нет.!.(((((((((
Вроде делаю все по аналогии.
И на UART выдаются 00.......((((((((
HELP!

Код прикрепляю.
Slavast
Может для вывода на терминал нужно использовать режим UART c SPI?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.