W25Q32 spi flash的使用
1、继续使用上节的spi1 ,将数据写入w25Q32,然后读出来,校验一致即可。
2、直接上代码
w25q32.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "spi.h"
#include "gd32f30x.h"
#include "w25q32.h"
#include "message.h"
#define MAX_BLOCKSIZE 128
#define MAX_SECTORSIZE 2048
#define CMD_WRIRE_ENABLE 0x06
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS_R1 0x05
#define CMD_READ_STATUS_R2 0x35
#define CMD_READ_STATUS_R3 0x15
#define CMD_WRITE_STATUS_R 0x01
#define CMD_PAGE_PROGRAM 0x02
#define CMD_QUAD_PAGE_PROGRAM 0x32
#define CMD_BLOCK_ERASE64KB 0xd8
#define CMD_BLOCK_ERASE32KB 0x52
#define CMD_SECTOR_ERASE 0x20
#define CMD_CHIP_ERASE 0xC7
#define CMD_ERASE_SUPPEND 0x75
#define CMD_ERASE_RESUME 0x7A
#define CMD_POWER_DOWN 0xB9
#define CMD_HIGH_PERFORM_MODE 0xA3
#define CMD_CNT_READ_MODE_RST 0xFF
#define CMD_RELEASE_PDOWN_ID 0xAB
#define CMD_MANUFACURER_ID 0x90
#define CMD_READ_UNIQUE_ID 0x4B
#define CMD_JEDEC_ID 0x9f
#define CMD_READ_DATA 0x03
#define CMD_FAST_READ 0x0B
#define CMD_READ_DUAL_OUTPUT 0x3B
#define CMD_READ_DUAL_IO 0xBB
#define CMD_READ_QUAD_OUTPUT 0x6B
#define CMD_READ_QUAD_IO 0xEB
#define CMD_WORD_READ 0xE3
#define CMD_ENABLE_4_BYTE_ADDR 0xB7
#define CMD_EXIT_4_BYTE_ADDR 0xE9
#define SR1_BUSY_MASK 0x01
#define SR1_WEN_MASK 0x02
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25Q256 0XEF18
#define W25QXX_TYPE W25Q32
#if SPI_MODE != SPI_SLAVE_MODE_INT
static void spi_write_read_data(uint8_t *w_data,uint8_t *r_data,int len)
{
#if SPI_MODE == SPI_MASTER_MODE_POLL
spi1_write_read_data(w_data,r_data,len);
#elif SPI_MODE == SPI_MASTER_MODE_DMA
#endif
}
static void spc_dump(char *id,int rc, uint8_t *data,int len)
{
int i;
printf("[%s] = %d\r\n",id,rc);
for(i=0;i<len;i++) {
printf("%0x ",data[i]);
if ( (i % 10) == 9) printf("\r\n");
}
printf("\r\n");
}
static void w25q32_read_manufacturer_id(uint16_t *id)
{
uint8_t tx_data[6] = {CMD_MANUFACURER_ID ,0,0,0,0,0};
uint8_t rx_data[6] = {0};
spi_write_read_data(tx_data,rx_data,6);
*id = (rx_data[4]<<8)|rx_data[5];
}
static void w25q32_read_jedec_id(uint16_t *id)
{
uint8_t tx_data[4] = {CMD_JEDEC_ID ,0,0,0};
uint8_t rx_data[4] = {0};
spi_write_read_data(tx_data,rx_data,4);
*id = (rx_data[2]<<8)|rx_data[3];
}
static void w25q32_read_uniqie_id(void)
{
uint8_t tx_data[12] = {0x4B ,0,0,0};
uint8_t rx_data[12] = {0};
spi_write_read_data(tx_data,rx_data,12);
print_register_value(rx_data,12);
}
/**
* 状态寄存器1:
* BIT7 6 5 4 3 2 1 0
* SPR RV TB BP2 BP1 BP0 WEL BUSY
*/
static int w25q32_read_status_reg1(void)
{
uint8_t tx_data[2];
uint8_t rx_data[2]= {0};
tx_data[0] = CMD_READ_STATUS_R1;
tx_data[1] = 0xff;
spi_write_read_data (tx_data,rx_data,sizeof(rx_data));
//spc_dump(__FUNCTION__,0,rx_data,sizeof(rx_data));
return rx_data[1];
}
/**
* 状态寄存器2:
*BIT7 6 5 4 3 2 1 0
*SUS CMP LB3 LB2 LB1 (R) QE SRP1
*/
static int w25q32_read_status_reg2(void)
{
uint8_t tx_data[2];
uint8_t rx_data[2];
tx_data[0] = CMD_READ_STATUS_R2;
tx_data[1] = 0xff;
spi_write_read_data (tx_data,rx_data,sizeof(rx_data));
//spc_dump(__FUNCTION__,0,rx_data,sizeof(rx_data));
return rx_data[1];
}
static int w25q32_read_status_reg3(void)
{
uint8_t tx_data[2];
uint8_t rx_data[2];
tx_data[0] = CMD_READ_STATUS_R3;
tx_data[1] = 0xff;
spi_write_read_data (tx_data,rx_data,sizeof(rx_data));
//spc_dump(__FUNCTION__,0,rx_data,sizeof(rx_data));
return rx_data[1];
}
int w25q32_is_busy()
{
uint8_t tx_data[2];
uint8_t rx_data[2] = {0};
tx_data[0] = CMD_READ_STATUS_R1;
tx_data[1] = 0xff;
spi_write_read_data (tx_data,rx_data,sizeof(rx_data));
uint8_t r1;
r1 = rx_data[1];
if(r1 & SR1_BUSY_MASK)
return 1;
return 0;
}
//等待空闲
void w25q32_wait_busy(void)
{
while((w25q32_read_status_reg1()&0x01)==0x01);
}
void w25q32_power_down(void)
{
uint8_t tx_data;
uint8_t rx_data;
tx_data = CMD_POWER_DOWN;
spi_write_read_data (&tx_data,&rx_data,1);
}
void w25q32_write_enable(void)
{
uint8_t tx_data[1];
uint8_t rx_data[1];
tx_data[0] = CMD_WRIRE_ENABLE;
spi_write_read_data(tx_data,rx_data,1);
}
void w25q32_write_disable(void)
{
uint8_t tx_data[1];
uint8_t rx_data[1];
tx_data[0] = CMD_WRITE_DISABLE;
spi_write_read_data(tx_data,rx_data,1);
}
int w25q32_erase_all()
{
uint8_t tx_data[1];
uint8_t rx_data[1];
w25q32_write_enable();
tx_data[0] = CMD_CHIP_ERASE;
spi_write_read_data(tx_data,rx_data,1);
w25q32_wait_busy();
return 1;
}
void w25q32_erase_sector(uint32_t dst_addr)
{
uint8_t tx_data[4];
uint8_t rx_data[4];
uint32_t addr = dst_addr;
addr<<=12;
w25q32_write_enable();
tx_data[0] = CMD_SECTOR_ERASE;
tx_data[1] = (addr>>16) & 0xff;
tx_data[2] = (addr>>8) & 0xff;
tx_data[3] = addr & 0xff;
spi_write_read_data (tx_data,rx_data,sizeof(rx_data));
w25q32_wait_busy();
}
uint16_t w25q32_read(uint32_t addr,uint8_t *buf,uint16_t n)
{
uint8_t *tx_data;
uint8_t *rx_data;
tx_data = (uint8_t*)malloc(n+4);
rx_data = (uint8_t*)malloc(n+4);
tx_data[0] = CMD_READ_DATA;
tx_data[1] = (addr>>16) & 0xFF; // A23-A16
tx_data[2] = (addr>>8) & 0xFF; // A15-A08
tx_data[3] = addr & 0xFF; // A07-A00
spi_write_read_data(tx_data,rx_data,n+4);
memcpy(buf,&rx_data[4],n);
free(tx_data);
free(rx_data);
return n;
}
uint16_t W25Q64_fastread(uint32_t addr,uint8_t *buf,uint16_t n)
{
uint8_t *tx_data;
uint8_t *rx_data;
tx_data = (uint8_t*)malloc(n+5);
rx_data = (uint8_t*)malloc(n+5);
tx_data[0] = CMD_FAST_READ;
tx_data[1] = (addr>>16) & 0xFF; // A23-A16
tx_data[2] = (addr>>8) & 0xFF; // A15-A08
tx_data[3] = addr & 0xFF; // A07-A00
tx_data[4] = 0;
spi_write_read_data(tx_data,rx_data,n+5);
memcpy(buf,&rx_data[5],n);
free(tx_data);
free(rx_data);
return n;
}
uint16_t w25q32_page_write( uint16_t inaddr, uint8_t* buf, uint16_t n)
{
uint8_t *tx_data;
uint8_t *rx_data;
tx_data = (uint8_t*)malloc(n+4);
rx_data = (uint8_t*)malloc(n+4);
w25q32_write_enable();
tx_data = (uint8_t*)malloc(n+4);
tx_data[0] = CMD_PAGE_PROGRAM;
tx_data[1] = (inaddr>>16) & 0xff;
tx_data[2] = (inaddr>>8) & 0xff;
tx_data[3] = inaddr & 0xFF;
memcpy(&tx_data[4],buf,n);
spi_write_read_data(tx_data,rx_data,n+4);
while(w25q32_is_busy()) ;
free(tx_data);
free(rx_data);
return 0;
}
void w25q32_write_no_check( uint16_t inaddr, uint8_t* buf, uint16_t n)
{
uint16_t page_remain;
page_remain = 256 - inaddr % 256;
if (n <= page_remain)
page_remain = n;
while (1)
{
/* code */
w25q32_page_write(inaddr,buf,page_remain);
if(n == page_remain)
break;
else
{
buf += page_remain;
inaddr += page_remain;
n -= page_remain;
if (n > 256)
page_remain = 256;
else
page_remain = n;
}
}
}
void w25q32_buffer_write(uint8_t *p_buf,uint16_t inaddr,uint16_t n)
{
uint32_t sec_pos;
uint16_t sec_off;
uint16_t sec_remian;
uint16_t i;
uint8_t w_buff[4096];
sec_pos = inaddr / 4096 ;
sec_off = inaddr % 4096;
sec_remian = 4096 - sec_off;
if (n <= sec_remian)
{
sec_remian = n;
}
while (1)
{
w25q32_read(sec_pos*4096,w_buff,4096);
for(i=0;i<sec_remian;i++)
{
if (w_buff[sec_off + i] != 0xff)
{
break;
}
}
if (i<sec_remian)
{
w25q32_erase_sector(sec_pos);
for(int i=0;i<sec_remian;i++)
{
w_buff[i+sec_off] = p_buf[i];
}
w25q32_write_no_check(sec_pos*4096,w_buff,4096);
}
else
{
w25q32_write_no_check(inaddr,w_buff,4096);
}
if (n == sec_remian)
{
break;
}
else
{
sec_pos++;
sec_off = 0;
p_buf += sec_remian;
inaddr += sec_remian;
n -= sec_remian;
if (n > 4096)
{
sec_remian = 4096;
}
else
{
sec_remian = n;
}
}
}
}
void w25q32_init(void)
{
uint16_t manufacturer_id = 0;
uint16_t jedec_id = 0;
w25q32_read_manufacturer_id(&manufacturer_id);
w25q32_read_jedec_id(&jedec_id);
if (manufacturer_id == W25QXX_TYPE)
{
printf("W25Q32 Init Succdess\r\n");
}
}
#endif //SPI_SLAVE_MODE_INT
w25q32.h
#ifndef __W25Q32_H__
#define __W25Q32_H__
#include "spi.h"
#if SPI_MODE == SPI_MASTER_MODE_POLL
void w25q32_init(void);
uint16_t w25q32_page_write( uint16_t inaddr, uint8_t* buf, uint16_t n) ;
uint16_t w25q32_read(uint32_t addr,uint8_t *buf,uint16_t n);
void w25q32_erase_sector(uint32_t dst_addr) ;
#endif //SPI_MODE == SPI_MASTER_MODE_POLL
#endif //__W25Q32_H__
main函数调用