Flash操作注意事项
3.2.1 写入操作
写入操作前,必须先进行写使能
每个数据位只能由1改写为0,不能由0改写为1(成本和技术原因)
写入数据前必须先擦除,擦除后,所有数据位变为1(Flash有专门的擦除命令,操作时仅需要发送擦除命令即可),在Flash中0FFH代表空白
擦除必须按最小擦除单元(在本芯片中,最小的擦除单元是一个扇区Sector)进行
连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入(页缓存器的限制),在写入时,要注意写入的地址范围不能跨越页尾
写入操作结束后,芯片进入忙状态,不响应新的读写操作
3.2.2 读取操作
直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取
在这里插入图片描述

根据读写指令使用ioctl实现flash读写操作

#include <stdint.h>  
#include <unistd.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <getopt.h>  
#include <fcntl.h>  
#include <sys/ioctl.h>  
#include <sys/types.h>
#include <sys/stat.h>

#include <linux/types.h>  
#include <linux/spi/spidev.h>  
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
#define RX_TX_MAX 1024

static void pabort(const char *s)  
{  
    perror(s);  
    abort();  
}  

typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;

static const char *device = "/dev/spidev0.0";  
static unsigned char mode = SPI_MODE_0;  
static unsigned char bits = 8;  
static uint32_t speed = 1000000;  
static uint16_t delay; 
static char* file_name;
static uint32_t number_byte=0;
static unsigned char read_write_flg=0;  //0-read 1-write

int spi_fd;
unsigned char readbuf[1024];
static void dumpstat(const char *name, int fd)
{
    __u8    lsb, bits;
    __u32   mode, speed;

    if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
        perror("SPI rd_mode");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
        perror("SPI rd_lsb_fist");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
        perror("SPI bits_per_word");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
        perror("SPI max_speed_hz");
        return;
    }

    printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
        name, mode, bits, lsb ? "(lsb first) " : "", speed);
}

static void write_en()  
{  
    int ret;
    uint8_t rx[1];   
    uint8_t tx[1] = {  
        0x06,
    };  
    
    struct spi_ioc_transfer tr = {  
        .tx_buf = (unsigned long)tx,  
        .rx_buf = (unsigned long)rx,  
        .len = 1,  
        .delay_usecs = delay,  
        .speed_hz = speed,  
        .bits_per_word = bits,  
    };  
  
    ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);  
    if (ret < 1)  
        pabort("can't send spi message");     
}  
 
static char read_reg1()
{
    int ret;
    uint8_t rx[2];
    uint8_t tx[2]={0x05,0x00,};
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = 2,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
    if (ret < 1)  
        pabort("can't send spi message");   
    return rx[1];
}
static void BlockErase64k(int addr)
{
    int ret;
    uint8_t rx[4];
    uint8_t tx[4]={0xd8,0x00,0x00,0x00,};
    tx[1] = (addr&0xFF0000) >> 16;
    write_en();
    while(read_reg1()&0x01==0x01);
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = 4,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
    while(read_reg1()&0x01==0x01);

    if (ret < 1)  
        pabort("can't send spi message");   
    return ;
}
static void write_data_page(int addr ,char *data,int size)
{
    BlockErase64k(addr);
    int ret;
    int i;
    uint8_t rx[256+4];
    uint8_t tx[256+4]={0x02,0x00,0x00,0x00,};
    tx[1] = (addr&0xFF0000) >> 16;
    tx[2] = (addr&0x00FF00) >> 8;
    tx[3] = (addr&0xFF);
    write_en();
    while(read_reg1()&0x01==0x01);
    for(i = 0; i < size; i++)
    {
        tx[i+4] = data[i];
        printf("write data[%d]:%x\n",i,tx[4+i]);
    }

    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = 4+size,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);

    if (ret < 1)  
        pabort("can't send spi message");  
    while(read_reg1()&0x01==0x01);
    
}
static unsigned char* read_data(int addr ,int size)
{
    int ret;
    int i;
    uint8_t rx[256+4];
    uint8_t tx[4+256]={0x03,0x00,0x00,0x00,};
    tx[1] = (addr&0xFF0000) >> 16;
    tx[2] = (addr&0x00FF00) >> 8;
    tx[3] = (addr&0xFF);

    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = size+4,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);

    if (ret < 1)  
        pabort("can't send spi message"); 
    for(i = 0; i < size;i++){
        readbuf[i] = rx[i+4];
        printf("read data[%d]:%x\n",i,readbuf[i]); 

    }
    printf("read data:%d Byte,first data:%x",size,rx[4]); 
    return readbuf;
}
static char read_id()
{
    int ret;
    uint8_t rx[4];
    uint8_t tx[4]={0x9f,};

    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = 4,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
    if (ret < 1)  
        pabort("can't send spi message"); 
    printf("id:%x %x\n",rx[2],rx[3]);  
    return rx[0];
}

int main (int argc,char*argv[])
{
    int ret;
    char data[4] = {0x01,0x02,0x03,};
    spi_fd = open(device,O_RDWR);
    if(spi_fd < 0)
        pabort("can't open device");
    
    ret = ioctl(spi_fd,SPI_IOC_WR_MODE,&mode);
    if(ret < 0)
        pabort("can't set  device mode");
    
    ret = ioctl(spi_fd,SPI_IOC_RD_BITS_PER_WORD,&bits);
    if(ret < 0)
        pabort("can't set  device mode");

    ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);  
    if (ret == -1)  
        pabort("can't set max speed hz");
    printf("spi mode: %d\n", mode);  
    printf("bits per word: %d\n", bits);  
    printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); 
    read_id();
    write_data_page(0x000000,data,4);
    read_data(0x000000,4);
}

接线
[图片]

运行结果
在这里插入图片描述

借鉴代码:https://blog.csdn.net/xiaopanpanpanpan/article/details/79869753?ops_request_misc=%257B%2522request%255Fid%2522%253A%25222EC85752-85F1-4EE7-9FBB-437665631911%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=2EC85752-85F1-4EE7-9FBB-437665631911&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-79869753-null-null.142v100pc_search_result_base2&utm_term=%E6%A0%91%E8%8E%93%E6%B4%BE%20w25q64&spm=1018.2226.3001.4187

更多推荐