Страница 1 из 2
Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 12:50:52
Slavast
Добрый день!
Хочу связать ATMega 2561 и флеш-память AT45DB041A через SPI.
На данном этапе хочу хотя бы считать состояние регистр статуса.
Но не работает.
Помогите плиз!
Re: Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 13:29:33
Zheleznjakov
чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный 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;
}
не забыть про инверсию на чип селект
Re: Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 13:30:08
Engineer_Keen
Код: Выделить всё
;PB0 - SS
;PB1 - SCLK
;PB2 - MOSI
;PB3 - MISO
; Установка MOSI и SCK на вывод, все остальные на ввод
ldi r19,(0<<PB3)|(1<<PB2)|(1<<PB1)|(0<<PB0)
out DDRB,r18
Почему SS (PB0) на ввод? AT45 принимает команды по SPI при низком уровне SS, им должен управлять контроллер!
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Во вторых: перед началом обмена по SPI - CBI PORTB,PB0, после окончания приема/передачи - SBI PORTB,PB0.
Пока что все...
Опередили... Ну зато у меня ассемблер

Re: Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 13:47:43
Slavast
Engineer_Keen писал(а):Код: Выделить всё
;PB0 - SS
;PB1 - SCLK
;PB2 - MOSI
;PB3 - MISO
; Установка MOSI и SCK на вывод, все остальные на ввод
ldi r19,(0<<PB3)|(1<<PB2)|(1<<PB1)|(0<<PB0)
out DDRB,r18
Почему SS (PB0) на ввод? AT45 принимает команды по SPI при низком уровне SS, им должен управлять контроллер!
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Во вторых: перед началом обмена по SPI - CBI PORTB,PB0, после окончания приема/передачи - SBI PORTB,PB0.
Пока что все...
Опередили... Ну зато у меня ассемблер

SS на флеш памяти идет с инверсией. Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?
У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Re: Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 14:17:09
Slavast
Engineer_Keen писал(а):
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Пардон, не понял. Т. е. помимо
ldi r19,(0<<PB0)
out DDRB,r19
нужно еще добавить
out PORTB, 0x01 ?
Т. Е непосредственно единицу на сам порт этого пина?
Re: Обращение к флеш-памяти по SPI
Добавлено: Вт ноя 30, 2010 17:31:04
Engineer_Keen
Slavast писал(а):
Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?
Да
Slavast писал(а):
У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Здрасьте приехали... У вас же уже есть 2 отдельные процедуры, одна для записи (SPI_MasterTransmit), одна для чтения (SPI_MasterReceive). Послали сколько надо, прочитали сколько надо, чего переключать-то?
Slavast писал(а):
Т. Е непосредственно единицу на сам порт этого пина?
Нам же нужно со старта программы держать высокий уровень на SS пока не начался процесс обмена по SPI.
Re: Обращение к флеш-памяти по SPI
Добавлено: Ср дек 01, 2010 11:16:31
Slavast
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
Добавлено: Ср дек 01, 2010 11:18:24
Slavast
Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi)
не забыть про инверсию на чип селект
Спасибо. А есть такой же примерно код на ассемблере?
Re: Обращение к флеш-памяти по SPI
Добавлено: Ср дек 01, 2010 13:31:56
Engineer_Keen
Slavast писал(а):
Вот тут и непонятно: MOSI и SCK нужно задавать в 1 на DDRB или PORTB (т.е. указывать только направление или в заранее заданном на выход порт выдавать 1 или 0)? Это же ведь существенно! В Си коде за этим не могу уследить. Точно также и SS - нужно 1 посылать в DDRB или PORTB?
Когда мы начинаем передавать данные по SPI, МК сам ставит сигналы MOSI и SCK в нужные состояния (при настройке SPI задается режим 0 или 3). Но пином SS (лииня CS) он не управляет. Управлять линией CS можно вообще с любого свободного пина МК, и делается это программно, особенно если на SPI сидит более одного устройства.
Читаем даташит на память, раздел 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
Re: Обращение к флеш-памяти по SPI
Добавлено: Ср дек 01, 2010 18:27:39
Zheleznjakov
Slavast писал(а):Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi)
не забыть про инверсию на чип селект
Спасибо. А есть такой же примерно код на ассемблере?
к сожалению нет.
да и очень прозрачно все.
переходите на си.
можно ведь просто один к одному заменить команды и в симуляторе глянуть что да как
ауже потом ножко дрыганье заменить на хардварный спи
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 15:28:27
Slavast
В конечном итоге получилось только передать по SPI: осциллографом щупаю MOSI - вижу передаваемые данные, SS - вижу низкие уровни в момент передачи,на SCLK - тактирование. Но на MISO ничего нет.!.(((((((((
И на UART выдаются 00
((((((((
HELP!
Код прикрепляю.
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 16:15:28
Zheleznjakov
Ну как говорится "Чудес не бывает!"

Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 17:24:24
Slavast
Zheleznjakov писал(а):Ну как говорится "Чудес не бывает!"

Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
Ресет на флеш подается вместе с ресетом на МК.
Вот решил вместо первой флешки на плате использовать вторую - на MISO появились какие-то сигналы. Похож вроде на состояние Статус регистра: RDY|-BUSY- COMP 0 1 1 x x x Только вместо высого сяигнала на RDY|BUSY стоит низкий (BUSY). Может так и надо. Но все же UART не выдает на терминал. Может надо использовать так называемый режим UART в SPI??
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 17:53:11
Engineer_Keen
Почему в процедуре вывода по UART стоит STS, а не OUT?
И зачем делать
Код: Выделить всё
www1:
lds r23, UCSR0A
SBRS r23,UDRE0 ; Пропуск если нет флага готовности,
; если 1 - то готов отправлять данные
RJMP www1
если в даже в даташите написано элементарно?
PS: настройки SPI/UART не проверял. Модифицированный (AT25 вместо AT45, команда RDID вместо 0хD7) вариант проверен в симуляторе - работает.
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 18:14:43
Slavast
Engineer_Keen писал(а):Почему в процедуре вывода по UART стоит STS, а не OUT?
PS: настройки SPI/UART не проверял. Модифицированный (AT25 вместо AT45, команда RDID вместо 0хD7) вариант проверен в симуляторе - работает.
www2:
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 кинуть?
У меня примерно все остальное так же?
Re: Обращение к флеш-памяти по SPI
Добавлено: Пт дек 03, 2010 21:13:22
Engineer_Keen
Понятно почему на OUT ругается, слишком адрес большой, странно что в даташите этого не учли. Наверно пример тупо с другой меги содрали

Re: Обращение к флеш-памяти по SPI
Добавлено: Пн авг 27, 2012 07:37:57
pokk
Подскажите что я делаю не так. Пытаюсь считать ID из флешь памяти ID как бы считывает но почему-то не принимается вместо этого одни FF принимаются.

где-то в середине видно 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)
{
}
}
Re: Обращение к флеш-памяти по SPI
Добавлено: Пн авг 27, 2012 20:34:23
uk8amk
Правильно чтобы CS/SS лежала в нуле пока идет обмен с памятью, не надо ее постоянно дергать.
Re: Обращение к флеш-памяти по SPI
Добавлено: Пн авг 27, 2012 20:37:54
pokk
Хорошо, но так тоже принимаются одни FF.
Вытащил их из функции и сделал так
Код: Выделить всё
PORTB=(0<<PORTB0); //переход с высого уровня на назкий (SS)
SPI_MasterTransmit(0x15);
SPI_MasterTransmit(0xFF);
SPI_MasterTransmit(0xFF);
PORTB=(1<<PORTB0);

Re: Обращение к флеш-памяти по SPI
Добавлено: Пн авг 27, 2012 20:54:40
uk8amk
На
www.gaw.ru есть полный перевод даташитов этой памяти.
Формат команды смогу посмотреть только завтра. С телефона неудобно доки читать.