Перейти к содержанию
    

AVR - FRAM FM25CL64B

Доброго времени суток! Начал осваивать работу с FRAM FM25CL64B. Контроллер -AVR mega16, копмилятор Написал тестовую программу записи / считывания (при отправке на mega16 по USART любого байта пишу и считываю). Только вот приходят одни нули. На MISO FRAM - низкий уровень, в то время как осуществляю чтение. Выкладываю код программки, может кто что подскажет. Заранее спасибо!

#include <iom16v.h>
#include <macros.h>
#include <eeprom.h>
#include <string.h>

#pragma interrupt_handler UART_RX_interrupt:12

#define ToggleBit(x, bit) (x^=(1<<bit))

static volatile unsigned char readdata=0x00;
static volatile unsigned char readdata1=0x00;
static volatile unsigned char readdata2=0x00;

void InitUART(void)
{
UBRRL = 0X03;		// baud rate = 115200
UBRRH = 0x00;
UCSRA = 0x00;
UCSRB = (1<<RXEN)|(1<<TXEN);
UCSRC = (3<<UCSZ0)|(0<<USBS)|(1<<URSEL);
 /* Set frame format: 8data, 1stop bit */
UCSRC = (1<<URSEL)|0x06;
}

void SPI_MasterInit(void)
{
/* Set MOSI, chip select and SCK (clock) output, MISO - input */
DDRB |= (1<<PB7)|(0<<PB6)|(1<<PB5)|(1<<PB4);
PORTB |= 0b01000000; // подтягиваем пин входа

/* Enable SPI, Master, set clock rate fck/16 */
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);					//SPI Enable, SCK frequency = fosc/16

//SPCR |=(0x0C);
}

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

void UART_RX_interrupt( void )
{  
 // отправляю данные   
 PORTB &= ~0b00010000;   // chip select в 0
 SPI_MasterTransmit(0b00000110);//wren
 SPI_MasterTransmit(0b00000010); //write
 SPI_MasterTransmit(0b00000011); //address
 SPI_MasterTransmit(0b00000011); //address
 SPI_MasterTransmit(0b01011100); //data
 SPI_MasterTransmit(0b00001111); //data
 SPI_MasterTransmit(0b11110000); //data
 PORTB |= 0b00010000;	// chip select в 1
 ////////////////////////////////////////////

// считываю
PORTB &= ~0b00010000;   // chip select в 0
SPI_MasterTransmit(0b00000110); //wren
SPI_MasterTransmit(0b00000011); //read
SPI_MasterTransmit(0b00000011); //address
SPI_MasterTransmit(0b00000011); //address

//SPCR |=(0x0C);
SPI_MasterTransmit(0xff);   // бросаем данные чтобы генерировались такты на sck
readdata= SPDR;//			// считываю данные
SPI_MasterTransmit(0xff);
readdata1= SPDR;
SPI_MasterTransmit(0xff);
readdata2= SPDR;
PORTB |= 0b00010000;			// chip select в 1
/////////////////////////////////////////////////////////////////

 while(!( UCSRA & (1 << UDRE)));
	UDR = readdata;					//передаю на PC по USART
	while(!( UCSRA & (1 << UDRE)));
	UDR = readdata1;
	while(!( UCSRA & (1 << UDRE)));
	UDR = readdata2;

ToggleBit(DDRC,7);		//мигаю диодом

}   

void main(void)
{
SPI_MasterInit();
InitUART();
UCSRB |= (1<<RXCIE); // enable UART interrupts

 while(1)
	{
			 SEI();	

	}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я ничего не путаю, писать надо следующим образом:

CS = 0

Write (WriteEnable_CMD)

CS = 1

задержка, min. длительность - в даташите

CS = 0

Write (Write_CMD, address)

Write (data, data, data, ...)

CS = 1

 

Читать, соответственно, без всяких "SPI_MasterTransmit(0b00000110); //wren".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут http://electronix.ru/forum/index.php?showtopic=126893 тоже ответ - и ещё поднимите CS в "1" перед выдачей первой команды. А то микросхема "наестся" по перепадам на SPI CLOCK - первая команда не будет правильно выполнена.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Большое спасибо так и сделал, заработало. Wren "оформил" одтельным чип селектом и все остальное тоже отдельным получилось так:

//запись:

PORTB &= ~0b00010000;
     SPI_MasterTransmit(0b00000110);//wren
     PORTB |= 0b00010000;
      
     PORTB &= ~0b00010000; 
     SPI_MasterTransmit(0b00000010); //write
     SPI_MasterTransmit(0b00000000); //address
     SPI_MasterTransmit(0b00000011); //address
     SPI_MasterTransmit(0b01011100); //data
     SPI_MasterTransmit(0b00001111); //data
     SPI_MasterTransmit(0b11110000); //data
     PORTB |= 0b00010000;
//считывание:     
     PORTB &= ~0b00010000;
     SPI_MasterTransmit(0b00000110); //wren
     PORTB |= 0b00010000;
      
     PORTB &= ~0b00010000; 
     SPI_MasterTransmit(0b00000011); //read
     SPI_MasterTransmit(0b00000000); //address
     SPI_MasterTransmit(0b00000011); //address
     // PORTB |= 0b01000000;
     
     SPI_MasterTransmit(0xff);
     readdata= SPDR;// while(!(SPSR & (1<<SPIF)));    
     SPI_MasterTransmit(0xff);
     readdata1= SPDR;
     SPI_MasterTransmit(0xff);
     readdata2= SPDR;
    
    PORTB |= 0b00010000;

 

 

 

 

P.S. :модераторам - тему случайно продублировал, удаляйте если нужно одну из двух

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а если красиво оформить то функциями можно пользоваться на любом контролере.

void LOGGER_Write(uint32_t address, uint32_t lenght, uint8_t *buffer)
{
   // Note!!!Every write operation demands a write enable!!!
SPI_CSlow();
SPI_SendByte(SPIEEPROM_CMD_WREN);
SPI_CShigh();

// start write
SPI_CSlow();
// send write command
SPI_SendByte(SPIEEPROM_CMD_WRITE);
// send address
SPI_SendByte(address>>8);
SPI_SendByte(address&0x00FF);
while(lenght--)
{
	// send data to be written
	 SPI_SendByte(*buffer++);
}
// stop write
SPI_CShigh();
}

void LOGGER_Read(uint32_t address, uint32_t lenght, uint8_t *buffer)
{
if(lenght>PAGE_SIZE)
	return 0;
uint32_t data;
// start read
SPI_CSlow();
// send command
SPI_SendByte(SPIEEPROM_CMD_READ);
// send address
SPI_SendByte(address>>8);
SPI_SendByte(address&0x00FF);
// read contents of memory address
while(lenght--)
{
    data = SPI_TransferByte(0x00); 
    *buffer++ = data;
}
// stop read
SPI_CShigh();
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нечто подобное уже сделал, еще оформлю в виде библиотеки.

void writefram(int address, unsigned char *buff)
{
     unsigned char i;//счетчик
     unsigned char addressh= address >> 8; //старший байт адреса 
     unsigned char addressl = address;               //младший байт адреса      
     //send 
     PORTB &= ~0b00010000; // chip select >> 0
     SPI_MasterTransmit(0b00000110);//wren
     PORTB |= 0b00010000; // chip select >> 1
      
     PORTB &= ~0b00010000; // chip select >> 0
     SPI_MasterTransmit(0b00000010); //write
     SPI_MasterTransmit(addressh); //address
     SPI_MasterTransmit(addressl); //address
          
     for (i=0;i<sizeof(buff);i++)
     {
            SPI_MasterTransmit(buff[i]);
     }
     PORTB |= 0b00010000; // chip select >> 1
     /////////////////////////////////////////////////////
}

void readfram(int address, unsigned char *readdata)
{
     unsigned char i;//счетчик
     unsigned char addressh= address >> 8;//старший байт адреса 
     unsigned char addressl = address;               //младший байт адреса     
          
     PORTB &= ~0b00010000; // chip select >> 0
     SPI_MasterTransmit(0b00000011); //read
     SPI_MasterTransmit(addressh); //address
     SPI_MasterTransmit(addressl); //address
          
     for (i=0;i<10;i++)
     {
            SPI_MasterTransmit(0xff);//отправляем чтобы шли такты на sck
          *readdata= SPDR;             //считываем данные c MISO
          readdata++;
     }
              
     PORTB |= 0b00010000; // chip select >> 1
     /////////////////////////////////////////////////////
    
}

ну а в мэйне: 

unsigned char readdata2[10];
unsigned char buf1[10];

writefram(0x0000, buf1);
readfram(0x0000, (unsigned char*) readdata2);

 

Только начал применять указатели и вот хотел спросить - правильно ли я в процедурах их применяю (заметил разницу с вышеописанными- я инкрементирую readdata ++, а в примере выше инкрементируется в соответствующем месте с * ). И еще когда добавил использование sizeof в процедуре записи, то при считывании обнаружил заполнение 2-х байтов нулями, там где недолжно быть, хотя может и не в sizeof дело.

Изменено пользователем IVN2013

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...