Обращение к флеш-памяти по SPI
Обращение к флеш-памяти по SPI
Добрый день!
Хочу связать ATMega 2561 и флеш-память AT45DB041A через SPI.
На данном этапе хочу хотя бы считать состояние регистр статуса.
Но не работает.
Помогите плиз!
Хочу связать ATMega 2561 и флеш-память AT45DB041A через SPI.
На данном этапе хочу хотя бы считать состояние регистр статуса.
Но не работает.
Помогите плиз!
- Вложения
-
- spi.RAR
- (235.09 КБ) 421 скачивание
- Реклама
- Zheleznjakov
- Нашел транзистор. Понюхал.
- Сообщения: 190
- Зарегистрирован: Сб июн 12, 2010 16:19:17
- Откуда: Россия, Томск
- Контактная информация:
Re: Обращение к флеш-памяти по SPI
чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi)
не забыть про инверсию на чип селект
вот рабочий код, правда на си (и не через апаратный spi)
Код: Выделить всё
//-------------------------------------------------------------------------------------------------
uint8_t flash_spi_io(uint8_t data)
{
uint8_t bit_number;
for (bit_number = 8; bit_number-- > 0;)
{
Pin_AT45DB_CLK_OFF();
if ((data & 0x80) == 0x80)
Pin_AT45DB_MOSI_ON();
Pin_AT45DB_CLK_ON();
data <<= 1;
if (Pin_AT45DB_MISO_SIGNAL() != 0x00)
data |= 1;
Pin_AT45DB_MOSI_OFF();
}
return data;
}
//-------------------------------------------------------------------------------------------------
uint8_t flash_read_status_register(void)
{
uint8_t status;
Pin_AT45DB_CS_ON();
flash_spi_io(CMD_STATUS_REGISTER_READ);
status = flash_spi_io(0);
Pin_AT45DB_CS_OFF();
return status;
}
Последний раз редактировалось Zheleznjakov Вт ноя 30, 2010 13:30:36, всего редактировалось 1 раз.
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Мой блог: http://ziblog.ru
- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Обращение к флеш-памяти по SPI
Код: Выделить всё
;PB0 - SS
;PB1 - SCLK
;PB2 - MOSI
;PB3 - MISO
; Установка MOSI и SCK на вывод, все остальные на ввод
ldi r19,(0<<PB3)|(1<<PB2)|(1<<PB1)|(0<<PB0)
out DDRB,r18
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Во вторых: перед началом обмена по SPI - CBI PORTB,PB0, после окончания приема/передачи - SBI PORTB,PB0.
Пока что все...
Опередили... Ну зато у меня ассемблер
Re: Обращение к флеш-памяти по SPI
SS на флеш памяти идет с инверсией. Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?Engineer_Keen писал(а):Почему SS (PB0) на ввод? AT45 принимает команды по SPI при низком уровне SS, им должен управлять контроллер!Код: Выделить всё
;PB0 - SS ;PB1 - SCLK ;PB2 - MOSI ;PB3 - MISO ; Установка MOSI и SCK на вывод, все остальные на ввод ldi r19,(0<<PB3)|(1<<PB2)|(1<<PB1)|(0<<PB0) out DDRB,r18
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Во вторых: перед началом обмена по SPI - CBI PORTB,PB0, после окончания приема/передачи - SBI PORTB,PB0.
Пока что все...
Опередили... Ну зато у меня ассемблер
У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Re: Обращение к флеш-памяти по SPI
Пардон, не понял. Т. е. помимоEngineer_Keen писал(а):Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)Код: Выделить всё
ldi r19,(0<<PB0) out DDRB,r19
ldi r19,(0<<PB0)
out DDRB,r19
нужно еще добавить
out PORTB, 0x01 ?
Т. Е непосредственно единицу на сам порт этого пина?
- Реклама
- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Обращение к флеш-памяти по SPI
ДаSlavast писал(а): Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?
Здрасьте приехали... У вас же уже есть 2 отдельные процедуры, одна для записи (SPI_MasterTransmit), одна для чтения (SPI_MasterReceive). Послали сколько надо, прочитали сколько надо, чего переключать-то?Slavast писал(а): У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Нам же нужно со старта программы держать высокий уровень на SS пока не начался процесс обмена по SPI.Slavast писал(а): Т. Е непосредственно единицу на сам порт этого пина?
Re: Обращение к флеш-памяти по SPI
Engineer_Keen писал(а):Slavast писал(а): Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?
Может загвоздка в следующем. В даташите пишут:
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?
Т.е. чтоб задать SS нужно:
ldi r16,(1<<PB0)
ldi r17,(1<<DDB0)
out PORTB,r16
out DDRB,r17
или только
ldi r17,(1<<DDB0)
out DDRB,r17 ?
Re: Обращение к флеш-памяти по SPI
Спасибо. А есть такой же примерно код на ассемблере?Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi)не забыть про инверсию на чип селектКод: Выделить всё
- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Обращение к флеш-памяти по SPI
Когда мы начинаем передавать данные по SPI, МК сам ставит сигналы MOSI и SCK в нужные состояния (при настройке SPI задается режим 0 или 3). Но пином SS (лииня CS) он не управляет. Управлять линией CS можно вообще с любого свободного пина МК, и делается это программно, особенно если на SPI сидит более одного устройства.Slavast писал(а): Вот тут и непонятно: MOSI и SCK нужно задавать в 1 на DDRB или PORTB (т.е. указывать только направление или в заранее заданном на выход порт выдавать 1 или 0)? Это же ведь существенно! В Си коде за этим не могу уследить. Точно также и SS - нужно 1 посылать в DDRB или PORTB?
Читаем даташит на память, раздел Device operation: "A valid instruction starts with FALLING EDGE of CS followed by the....".
Значит перед началом передачи данных должен быть переход линии CS с высокого уровня на низкий, следовательно нужно программно установить при старте SS в 1, а перед передачей его установить в 0.
Чтобы еще лучше понять читайте раздел AC Waveforms, там оба режима (0 и 3) нарисованы.
Пример, правда для тини24, и SPI программно-аппаратный (CLK управляется программно), процедура SPIOUT служит одновременно для записи и для чтения. PA3 - CS (вывод), PA4 - CLK (вывод), PA5 - MOSI (вывод), PA6 - MISO (ввод)
Код: Выделить всё
ReadWord:
CBI PORTA,PA3 ;CS low
LDI r16,0x03 ;0x03 - read EEPROM
RCALL SPIOUT ;write instruction
MOV r16,adrS01
RCALL SPIOUT ;write high adr. byte
MOV r16,adrS02
RCALL SPIOUT ;write mid adr. byte
MOV r16,adrS03
RCALL SPIOUT ;write low adr. byte
RCALL SPIOUT ;read data
STS SND00,R16
RCALL SPIOUT ;read data
STS SND01,R16
SBI PORTA,PA3 ;CS high
RET
SPIOUT: ;fastest possible out via USI
OUT USIDR,r16 ;send byte to SPI data register
LDI r16,(1<<USIWM0)|(0<<USICS0)|(1<<USITC) ;clk=0
LDI r17,(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK) ;clk=1
OUT USICR,r16
OUT USICR,r17 ;clock 1
OUT USICR,r16
OUT USICR,r17 ;clock 2
OUT USICR,r16
OUT USICR,r17 ;clock 3
OUT USICR,r16
OUT USICR,r17 ;clock 4
OUT USICR,r16
OUT USICR,r17 ;clock 5
OUT USICR,r16
OUT USICR,r17 ;clock 6
OUT USICR,r16
OUT USICR,r17 ;clock 7
OUT USICR,r16
OUT USICR,r17 ;clock 8
IN r16,USIDR ;read byte from SPI data register
RET
- Zheleznjakov
- Нашел транзистор. Понюхал.
- Сообщения: 190
- Зарегистрирован: Сб июн 12, 2010 16:19:17
- Откуда: Россия, Томск
- Контактная информация:
Re: Обращение к флеш-памяти по SPI
к сожалению нет.Slavast писал(а):Спасибо. А есть такой же примерно код на ассемблере?Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi)не забыть про инверсию на чип селектКод: Выделить всё
да и очень прозрачно все.
переходите на си.
можно ведь просто один к одному заменить команды и в симуляторе глянуть что да как
ауже потом ножко дрыганье заменить на хардварный спи
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Мой блог: http://ziblog.ru
Re: Обращение к флеш-памяти по SPI
В конечном итоге получилось только передать по SPI: осциллографом щупаю MOSI - вижу передаваемые данные, SS - вижу низкие уровни в момент передачи,на SCLK - тактирование. Но на MISO ничего нет.!.(((((((((
И на UART выдаются 00
((((((((
HELP!
Код прикрепляю.
И на UART выдаются 00
((((((((
HELP!
Код прикрепляю.
- Вложения
-
- SPI_Posled.rar
- (59.24 КБ) 391 скачивание
- Zheleznjakov
- Нашел транзистор. Понюхал.
- Сообщения: 190
- Зарегистрирован: Сб июн 12, 2010 16:19:17
- Откуда: Россия, Томск
- Контактная информация:
Re: Обращение к флеш-памяти по SPI
Ну как говорится "Чудес не бывает!" 
Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Мой блог: http://ziblog.ru
Re: Обращение к флеш-памяти по SPI
Ресет на флеш подается вместе с ресетом на МК.Zheleznjakov писал(а):Ну как говорится "Чудес не бывает!"
Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
Вот решил вместо первой флешки на плате использовать вторую - на MISO появились какие-то сигналы. Похож вроде на состояние Статус регистра: RDY|-BUSY- COMP 0 1 1 x x x Только вместо высого сяигнала на RDY|BUSY стоит низкий (BUSY). Может так и надо. Но все же UART не выдает на терминал. Может надо использовать так называемый режим UART в SPI??
- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Обращение к флеш-памяти по SPI
Почему в процедуре вывода по UART стоит STS, а не OUT?
И зачем делать
если в даже в даташите написано элементарно?
PS: настройки SPI/UART не проверял. Модифицированный (AT25 вместо AT45, команда RDID вместо 0хD7) вариант проверен в симуляторе - работает.
И зачем делать
Код: Выделить всё
www1:
lds r23, UCSR0A
SBRS r23,UDRE0 ; Пропуск если нет флага готовности,
; если 1 - то готов отправлять данные
RJMP www1 Код: Выделить всё
WWW1:
SBIS UCSR0A,UDREN
RJMP WWW1Re: Обращение к флеш-памяти по SPI
www2:Engineer_Keen писал(а):Почему в процедуре вывода по UART стоит STS, а не OUT?
PS: настройки SPI/UART не проверял. Модифицированный (AT25 вместо AT45, команда RDID вместо 0хD7) вариант проверен в симуляторе - работает.
SBiS UCSR0A,UDRE0
RJMP www2
out UDR0, r20
break
Здесь AVR STUDIO ругается:
D:\Slava\Atmel\Projects\SPI sobran\SPIsobran.asm(114): error: Operand 1 out of range: 0xc0
D:\Slava\Atmel\Projects\SPI sobran\SPIsobran.asm(117): error: Operand 1 out of range: 0xc6
Можете свой вариант на AT25 кинуть?
У меня примерно все остальное так же?
- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Обращение к флеш-памяти по SPI
Понятно почему на OUT ругается, слишком адрес большой, странно что в даташите этого не учли. Наверно пример тупо с другой меги содрали 
- Вложения
-
- SPI_M2561_AT25.rar
- Чтение мегой2561 Идентификатора устройства памяти AT25 по SPI
- (20.98 КБ) 374 скачивания
Re: Обращение к флеш-памяти по SPI
Подскажите что я делаю не так. Пытаюсь считать ID из флешь памяти ID как бы считывает но почему-то не принимается вместо этого одни FF принимаются.

где-то в середине видно READID [1F60] но вот вместо 1F и 60 принимаются почему-то FF
Для выбора кристалла SS переход с высокого уровня на низкий сделал в функции передачи но мне кажется что это не очень хорошо как сделать правильно ?
И ещё вопросик что бы записать регистр состояния надо сначала подать команду записи регистра (0x1) а следующим байтом отправить что записывать в сам регистр ?
на русском описание не нашёл вот сижу два дня читаю даташит по тихонько начинаю понимать =)
Код полностью

где-то в середине видно READID [1F60] но вот вместо 1F и 60 принимаются почему-то FF
Для выбора кристалла SS переход с высокого уровня на низкий сделал в функции передачи но мне кажется что это не очень хорошо как сделать правильно ?
И ещё вопросик что бы записать регистр состояния надо сначала подать команду записи регистра (0x1) а следующим байтом отправить что записывать в сам регистр ?
на русском описание не нашёл вот сижу два дня читаю даташит по тихонько начинаю понимать =)
Код: Выделить всё
void SPI_MasterTransmit(char cData)
{
PORTB=(0<<PORTB0); //переход с высого уровня на назкий (SS)
/* Запуск передачи данных */
SPDR = cData;
/* Ожидание завершения передачи данных */
while(!(SPSR & (1<<SPIF)));
input=SPDR;
PORTB=(1<<PORTB0);
}Спойлер
Код: Выделить всё
#include <mega128.h>
#include <stdio.h>
#include <delay.h>
// Alphanumeric LCD functions
#asm
.equ __lcd_port=0x15 ;PORTC // Для изменения порта подключения вставляем вместо .equ __lcd_port=0x15 ;PORTC (исходя из даташита стр. Register Summary)
#endasm // .equ __lcd_port=0x1B ;PORTA или .equ __lcd_port=0x18 ;PORTB или .equ __lcd_port=0x12 ;PORTD (даташит atmega16)
#include <lcd.h>
char x;
int input;
// LCD
//
char lcd_buffer[33];
unsigned char data;
int temp;
void SPI_MasterInit(void)
{
/* Установка MOSI и SCK на вывод, все остальные на ввод */
DDRB = (1<<DDB2)|(1<<DDB1)|(1<<DDB0); // 1<<DDB0 для SS
/* Разрешение SPI в режиме мастера, установка скорости связи fck/16
*/SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
}
void SPI_MasterTransmit(char cData)
{
PORTB=(0<<PORTB0); //переход с высого уровня на назкий (SS)
/* Запуск передачи данных */
SPDR = cData;
/* Ожидание завершения передачи данных */
while(!(SPSR & (1<<SPIF)));
input=SPDR;
PORTB=(1<<PORTB0);
}
void lcd_show(void)
{
lcd_gotoxy(0,1);
sprintf(lcd_buffer,"x=%u",input);
lcd_puts(lcd_buffer);
}
void main(void)
{
PORTF=0;
DDRF=0xFF;
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out
PORTB=(1<<PORTB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=0
//PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (1<<PORTB0);
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000,000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
//SPCR=(1<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
//SPSR=(0<<SPI2X);
// Clear the SPI interrupt flag
#asm
in r30,spsr
in r30,spdr
#endasm
x=4;
// Global enable interrupts
#asm("sei")
lcd_init( 16 );
SPI_MasterInit();
SPI_MasterTransmit(0x15);
SPI_MasterTransmit(0xF);
SPI_MasterTransmit(0xA);
lcd_show();
while (1)
{
}
}
- Вложения
-
- SPI.rar
- (86.77 КБ) 315 скачиваний
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: Обращение к флеш-памяти по SPI
Правильно чтобы CS/SS лежала в нуле пока идет обмен с памятью, не надо ее постоянно дергать.
Re: Обращение к флеш-памяти по SPI
Хорошо, но так тоже принимаются одни FF.
Вытащил их из функции и сделал так

Вытащил их из функции и сделал так
Код: Выделить всё
PORTB=(0<<PORTB0); //переход с высого уровня на назкий (SS)
SPI_MasterTransmit(0x15);
SPI_MasterTransmit(0xFF);
SPI_MasterTransmit(0xFF);
PORTB=(1<<PORTB0);-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: Обращение к флеш-памяти по SPI
На www.gaw.ru есть полный перевод даташитов этой памяти.
Формат команды смогу посмотреть только завтра. С телефона неудобно доки читать.
Формат команды смогу посмотреть только завтра. С телефона неудобно доки читать.


