|
|
  |
Чтение\запись по SPI |
|
|
|
Mar 13 2013, 16:16
|
Местный
  
Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199

|
Какой развернутый ответ... Готовность микросхемы я проверяю. Более того, я делаю запись регистра статуса (все биты 0) для разрешения записи во всю МС. На WP при этом у меня 1. Цитата ...при записи блока нужно выравнивать размер записи на границу размера буфера. Иначе происходит переполнение счетчика и запись в буфер происходит по кольцу. Для вычисления адреса начала буфера достаточно адрес начала записи поделить, а затем умножить на размер буфера (или наложить маску той же размерности, что и размер буфера). Соответственно для вычисления адреса конца буфера нужно прибавить к адресу начала буфера его размер. Вот это немного сложно пока. Даже примеры пока не спасают. Давайте представим, что я хочу записать 10 байт в микросхему M95512 по адресу FFF0. Адрес начала буфера - FFF0 \ 80 = 1FF * 80 = FF80. Адрес конца буфера - FF80 + 7F = FFFF. То есть, буфер от FF80 до FFFF. Получается, что отправив в МС адрес FFF0 реально произойдет запись начиная с адреса FF80 что ли?
Сообщение отредактировал d7d1cd - Mar 13 2013, 16:51
|
|
|
|
|
Mar 13 2013, 18:02
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(d7d1cd @ Mar 13 2013, 21:16)  Получается, что отправив в МС адрес FFF0 реально произойдет запись начиная с адреса FF80 что ли? Нет конечно! Посмотрите Figure 4. Block diagram в datasheet M95512. Видите там прямоугольник с надписью Address register and counter? Вот в этот регистр записывается начальный адрес, который вы передаете в команде записи. Младшие 7 бит этого адреса автоматически инкрементируются при последовательной записи данных в буфер (размером 128 байт), начиная от начального адреса. Если побитно рассматривать, то адрес выглядит как XXXX XXXX XCCC CCCC, где биты X, транслированные в м/с EEPROM после кода команды, не меняются, а биты C инкрементируются при записи каждого последующего байта данных. Если вы запишете в буфер больше, чем позволяет разрядность его счетчика, то этот счетчик переполнится и адрес вернется вновь к началу буфера. При побайтной записи (один байт на каждую команду записи) можно писать по какому угодно адресу. Но при блочной записи необходимо выравнивать данные так, чтобы счетчик адреса не переполнился.
|
|
|
|
|
Mar 14 2013, 02:51
|
Местный
  
Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199

|
Понял. Со счетчиком все ясно. Вернувшись к моей задаче (о записи 10 байт по адресу FFF0) получается, что все 10 байт, по идее, должны записаться в память. Однако этого не происходит. Готовность МС к записи я определяю путем чтения регистра статуса и проверки бита WIP (должен быть 0). Далее я отправляю WREN, потом WRITE, адрес и байты. rezident, Вы писали, что надо проверять биты WIP и WEL. Может быть мне сначала проверить бит WIP, отправить команду WREN, проверить бит WEL и только тогда приступать к записи?
|
|
|
|
|
Mar 14 2013, 05:29
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Да, именно так и нужно. 1.Читаете регистр статуса (команда RDSR). Если WIP=1, то повторяете чтение регистра статуса до тех пор, пока WIP не станет = 0. 1а.при необходимости изменения состояния битов BPx в регистре статуса (изменение размеров области памяти, защищенной от записи) переводите вывод WP в неактивное состояние (= 1) 1б.проверяете, что в регистре статуса бит SRWD = 0 (запись в регистр статуса разрешена) 1в.сбрасываете/устанавливаете биты BPx в регистре статуса (производите запись в регистр статуса соответствующей командой WRSR), чтобы снять блокировку записи с требуемых секторов EEPROM 2.Отправляете команду WREN. 3.Читаете регистр статуса, чтобы убедиться, что WEL = 1. 4.Отправляете на запись данные командой WRITE с учетом границы буфера. 5.Читаете регистр статуса, проверяя WIP до тех пор пока он не станет = 0. Если нужно еще дописать, то переходите к п.2. Если нет, то 6. при необходимости защиты от записи секторов EEPROM устанавливаете биты BPx в регистра статуса (командой WRSR). 6а. WP переводите в активное состояние (= 0) для установки защиты от записи регистра статуса Если защиту от записи не используете, то пункты манипуляций с WP и BPx (1а, 1б, 1в, 6, 6а) можно пропустить
|
|
|
|
|
Mar 15 2013, 02:48
|
Местный
  
Группа: Участник
Сообщений: 442
Регистрация: 26-11-10
Пользователь №: 61 199

|
Цитата необходимость подачи команды WREN перед записью в регистр статуса и контроль окончания выполнения записи в него (анализ бита WIP) Цитата ...если, например, вы попытаетесь транслировать команду WREN до окончания выполнения записи. А я в своем алгоритме после записи регистра статуса (байт 0х00), сразе же отправляю команду WREN (почему то я подумал, что регистр статуса пишется "мгновенно" и проверять WIP нет необходимости). Возможно, что ошибка именно тут: регистр статуса еще "пишется", а я снова отправляю команду на разрешение записи. Конечно она не проходит. Это как раз и объясняет почему микросхема FRAM пишется, а EEPROM нет. Сегодня, если будет время, обязательно это все проверю.
|
|
|
|
|
Mar 22 2015, 18:51
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 12-08-13
Пользователь №: 77 889

|
Доброго времени суток! Начал осваивать работу с 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(); }
}
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|