/* spi_flash_02.c * SPI-Kommunikation mit Flash-Speicher SST25VF016B * 1.) Statusregister lesen * 2.) Ein Byte auf Adresse 000101 schreiben * 3.) Ein Byte von Adresse 000101 lesen * 4.) Kompletten Flashspeicher löschen * Controller: ATmega88 @ 8MHz */ #include <avr/io.h> #define WP (1<<PC5) // Write Protect disable @PC5 #define HOLD (1<<PC4) // Stop serial communication disable @PC4 #define CE (1<<PB2) // Chip Enable @PB2 #define MOSI (1<<PB3) // Master Out Slave In @PB3 #define MISO (1<<PB4) // Master In Slave Out @PB4 #define SCK (1<<PB5) // Clock @PB5 uint8_t data, status_register=0; void SPI_MasterInit(void) /* Initiate the SPI-Master */ { DDRB = MOSI|SCK|CE; // Set MOSI, SCK, CE output SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1); // Enable SPI, Master, set clock rate fck/64 } void SPI_MasterTransmit(uint8_t data) /* Transmit data on MOSI */ { SPDR = data; // Start transmission while(!(SPSR & (1<<SPIF))); // Wait for transmission complete } uint8_t SPI_SlaveReceive(void) /* Receive data from MISO */ { while(!(SPSR & (1<<SPIF))); // Wait for reception complete return SPDR; // Return SPI-Dataregister } uint8_t Read_Status_Register(void) /* Read STATUS REGISTER */ { PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x05); // Send command 0x05 (Read the status register) SPI_MasterTransmit(0x00); // Send one dummy byte status_register = SPI_SlaveReceive(); // Receive the value of the status register PORTB |= CE; // CE = high (end of communication) return status_register; // Return the value of the status register } void Enable_Write_Procedure(void) /* Activate write commands in correct sequence */ { /* Enable write status register EWSR */ PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x50); // Send command 0x50 (Enable write status register) PORTB |= CE; // CE = high (end of communication) /* Write status register WRSR */ PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x01); // Send command 0x01 (Write status register) SPI_MasterTransmit(0x02); // Send data 00000010 to clear BPx in status register and set WEL=1 PORTB |= CE; // CE = high (end of communication) /* Write enable WREN */ PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x06); // Send command 0x06 (Set write enable WREN) PORTB |= CE; // CE = high (end of communication) } /* Program one data byte */ void Byte_Program(uint8_t addressbyte1, uint8_t addressbyte2, uint8_t addressbyte3, uint8_t databyte) { PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x02); // Send command 0x02 (program one data byte) SPI_MasterTransmit(addressbyte1); // Send 1. Addressbyte (MSB first) SPI_MasterTransmit(addressbyte2); // Send 2. Addressbyte SPI_MasterTransmit(addressbyte3); // Send 3. Addressbyte SPI_MasterTransmit(databyte); // Send databyte PORTB |= CE; // CE = high (end of communication) } /* Write disable WRDI */ void Write_Disable(void) { PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x04); // WRDI (write disable) Send command 0x04 PORTB |= CE; // CE = high (end of communication) } /* Read memory */ uint8_t Read_Memory(uint8_t addressbyte1, uint8_t addressbyte2, uint8_t addressbyte3, uint8_t dummybyte) { PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x03); // Send command 0x03 Read SPI_MasterTransmit(addressbyte1); // Send 1. Addressbyte (MSB first) SPI_MasterTransmit(addressbyte2); // Send 2. Addressbyte SPI_MasterTransmit(addressbyte3); // Send 3. Addressbyte SPI_MasterTransmit(dummybyte); // Send Dummybyte data = SPI_SlaveReceive(); // Receive the value of data PORTB |= CE; // CE = high (end of communication) return data; // Return the value of data } void Chip_Erase(void) /* Chip erase - Erase full memory array */ { PORTB &= ~CE; // CE = low (start communication) SPI_MasterTransmit(0x60); // Chip erase (Send command 0x60) PORTB |= CE; // CE = high (end of communication) } int main(void) { DDRC |= WP | HOLD; // Set WP, HOLD output PORTC |= WP|HOLD; // Set WP, HOLD high SPI_MasterInit(); // Init SPI Master status_register = Read_Status_Register(); // Read STATUS REGISTER status_register=0; // set the variable to 0 Enable_Write_Procedure(); // Enable a write process Byte_Program(0x00, 0x01, 0x01, 0xA7); // Programm 1 databyte (A7) @ address 000101 Write_Disable(); // Write disable WRDI data = Read_Memory(0x00, 0x01, 0x01, 0x00); // Read 1 databyte @ address 000101 data = 0; Enable_Write_Procedure(); // Enable a write process Chip_Erase(); // Chip erase - Erase full memory array Write_Disable(); // Write disable WRDI while(1) { asm("NOP"); } }