Обращение к флеш-памяти по SPI

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение Slavast »

Добрый день!
Хочу связать ATMega 2561 и флеш-память AT45DB041A через SPI.
На данном этапе хочу хотя бы считать состояние регистр статуса.
Но не работает.
Помогите плиз!
Вложения
spi.RAR
(235.09 КБ) 422 скачивания
Контактная информация:
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 190
Зарегистрирован: Сб июн 12, 2010 16:19:17
Откуда: Россия, Томск

Сообщение 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;
}
не забыть про инверсию на чип селект
Последний раз редактировалось Zheleznjakov Вт ноя 30, 2010 13:30:36, всего редактировалось 1 раз.
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение 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.

Пока что все...

Опередили... Ну зато у меня ассемблер :)))
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение 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. Правильно?
У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение Slavast »

Engineer_Keen писал(а):

Код: Выделить всё


ldi 	r19,(0<<PB0)
out		DDRB,r19
Так что во первых: 1<<PB0 в DDRB (и сразу этот же пин в единицу в PORTB)
Пардон, не понял. Т. е. помимо
ldi r19,(0<<PB0)
out DDRB,r19

нужно еще добавить

out PORTB, 0x01 ?

Т. Е непосредственно единицу на сам порт этого пина?
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Slavast писал(а): Сначала устанавливаем SS в 1. До посылки байта его в 0 - а после в 1. Правильно?
Да
Slavast писал(а): У меня еще тут Оооочень важный вопрос? А как переключать наш контроллер в режим чтения?
Здрасьте приехали... У вас же уже есть 2 отдельные процедуры, одна для записи (SPI_MasterTransmit), одна для чтения (SPI_MasterReceive). Послали сколько надо, прочитали сколько надо, чего переключать-то?
Slavast писал(а): Т. Е непосредственно единицу на сам порт этого пина?
Нам же нужно со старта программы держать высокий уровень на SS пока не начался процесс обмена по SPI.
Реклама
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение 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 ?
Контактная информация:
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение Slavast »

Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi) не забыть про инверсию на чип селект
Спасибо. А есть такой же примерно код на ассемблере?
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение 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
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 190
Зарегистрирован: Сб июн 12, 2010 16:19:17
Откуда: Россия, Томск

Сообщение Zheleznjakov »

Slavast писал(а):
Zheleznjakov писал(а):чет хлопотно асм ковырять, типичная ошибка при работе с данной флехой забывают дергать чип селектом
вот рабочий код, правда на си (и не через апаратный spi) не забыть про инверсию на чип селект
Спасибо. А есть такой же примерно код на ассемблере?
к сожалению нет.
да и очень прозрачно все.
переходите на си.
можно ведь просто один к одному заменить команды и в симуляторе глянуть что да как
ауже потом ножко дрыганье заменить на хардварный спи
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Контактная информация:
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение Slavast »

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

Код прикрепляю.
Вложения
SPI_Posled.rar
(59.24 КБ) 392 скачивания
Контактная информация:
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 190
Зарегистрирован: Сб июн 12, 2010 16:19:17
Откуда: Россия, Томск

Сообщение Zheleznjakov »

Ну как говорится "Чудес не бывает!" :)
Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
С уважением, Денис Железняков aka ZiB
Мой блог: http://ziblog.ru
Контактная информация:
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение Slavast »

Zheleznjakov писал(а):Ну как говорится "Чудес не бывает!" :)
Ошибки возможны ведь не только в программе но и в железе
Приведите схему включения, фото платы или ещё что.
Что с ресетом у вас? (какой уровень подали)
Ресет на флеш подается вместе с ресетом на МК.
Вот решил вместо первой флешки на плате использовать вторую - на MISO появились какие-то сигналы. Похож вроде на состояние Статус регистра: RDY|-BUSY- COMP 0 1 1 x x x Только вместо высого сяигнала на RDY|BUSY стоит низкий (BUSY). Может так и надо. Но все же UART не выдает на терминал. Может надо использовать так называемый режим UART в SPI??
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Почему в процедуре вывода по UART стоит STS, а не OUT?
И зачем делать

Код: Выделить всё

www1:
			lds r23, UCSR0A			
			SBRS 	r23,UDRE0	; Пропуск если нет флага готовности,
								;  если 1 - то готов отправлять данные
			RJMP	www1 	
если в даже в даташите написано элементарно?

Код: Выделить всё

WWW1:
SBIS UCSR0A,UDREN
RJMP WWW1
PS: настройки SPI/UART не проверял. Модифицированный (AT25 вместо AT45, команда RDID вместо 0хD7) вариант проверен в симуляторе - работает.
Открыл глаза
Сообщения: 66
Зарегистрирован: Чт окт 21, 2010 10:05:27

Сообщение 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 кинуть?
У меня примерно все остальное так же?
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Понятно почему на OUT ругается, слишком адрес большой, странно что в даташите этого не учли. Наверно пример тупо с другой меги содрали :)))
Вложения
SPI_M2561_AT25.rar
Чтение мегой2561 Идентификатора устройства памяти AT25 по SPI
(20.98 КБ) 375 скачиваний
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение 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)
      { 
      
      
      

      }
}
Вложения
SPI.rar
(86.77 КБ) 316 скачиваний
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

Правильно чтобы CS/SS лежала в нуле пока идет обмен с памятью, не надо ее постоянно дергать.
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Хорошо, но так тоже принимаются одни FF.
Вытащил их из функции и сделал так

Код: Выделить всё

     PORTB=(0<<PORTB0); //переход с высого уровня на назкий  (SS)
        SPI_MasterTransmit(0x15);
        SPI_MasterTransmit(0xFF);
        SPI_MasterTransmit(0xFF);                        
        PORTB=(1<<PORTB0);
:dont_know:
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

На www.gaw.ru есть полный перевод даташитов этой памяти.
Формат команды смогу посмотреть только завтра. С телефона неудобно доки читать.
Ответить

Вернуться в «Периферия»