IVN2013 0 22 марта, 2015 Опубликовано 22 марта, 2015 · Жалоба Доброго времени суток! Начал осваивать работу с 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(); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 5 22 марта, 2015 Опубликовано 22 марта, 2015 · Жалоба Если я ничего не путаю, писать надо следующим образом: CS = 0 Write (WriteEnable_CMD) CS = 1 задержка, min. длительность - в даташите CS = 0 Write (Write_CMD, address) Write (data, data, data, ...) CS = 1 Читать, соответственно, без всяких "SPI_MasterTransmit(0b00000110); //wren". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 22 марта, 2015 Опубликовано 22 марта, 2015 · Жалоба Вот тут http://electronix.ru/forum/index.php?showtopic=126893 тоже ответ - и ещё поднимите CS в "1" перед выдачей первой команды. А то микросхема "наестся" по перепадам на SPI CLOCK - первая команда не будет правильно выполнена. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IVN2013 0 23 марта, 2015 Опубликовано 23 марта, 2015 · Жалоба Большое спасибо так и сделал, заработало. 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. :модераторам - тему случайно продублировал, удаляйте если нужно одну из двух Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 26 марта, 2015 Опубликовано 26 марта, 2015 · Жалоба а если красиво оформить то функциями можно пользоваться на любом контролере. 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IVN2013 0 26 марта, 2015 Опубликовано 26 марта, 2015 (изменено) · Жалоба Нечто подобное уже сделал, еще оформлю в виде библиотеки. 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 дело. Изменено 26 марта, 2015 пользователем IVN2013 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться