• stm32 操作W25Q256 W25Q16 spi flash


    硬件连接

    本函数库来自正点原子官方,本人稍作修改和添加注释

    W25Q16 2M Byte

    在这里插入图片描述

    W25Q256 32M Byte

    在这里插入图片描述

    spi 配置

    2022-7-27 经过测试

    1. 华邦的 W25Q256JV 32M 字节 容量的spi flash没有问题 spi配置是 上升沿采集数据 —> CPOL =0 CPOA=0 或者是 CPOL=1 CPOA=1 hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
    2. 华邦的 W25Q16JVSSIQ 2M 字节 容量的spi flash没有问题

    第1种配置

    在这里插入图片描述

    第2种配置

    在这里插入图片描述

    测试代码

    1. 需要修改CS片选引脚
    2. 需要选着spi外设

    头文件

    /**
     ****************************************************************************************************
     * @file        norflash.h
     * @author      正点原子团队(ALIENTEK)
     * @version     V1.0
     * @date        2021-10-26
     * @brief       NOR FLASH(25QXX) 驱动代码
     * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
     ****************************************************************************************************
     * @attention
     *
     * 实验平台:正点原子 F407电机开发板
     * 在线视频:www.yuanzige.com
     * 技术论坛:http://www.openedv.com/forum.php
     * 公司网址:www.alientek.com
     * 购买地址:zhengdianyuanzi.tmall.com
     *
     * 修改说明
     * V1.0 20211026
     * 第一次发布
     *
     ****************************************************************************************************
     */
    
    #ifndef __norflash_H
    #define __norflash_H
    
    #include "main.h"
    
    
    /*
    	2022-7-27 经过测试 华邦的 W25Q256JV   32M 字节 容量的spi flash没有问题  spi配置是  上升沿采集数据 ---> CPOL =0 CPOA=0  或者是 CPOL=1 CPOA=1   hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
    										华邦的  W25Q16JVSSIQ 2M 字节 容量的spi flash没有问题 
    	
    */
    
    
    
    
    
    
    /* SPI总线速度设置 */
    #define SPI_SPEED_2         0
    #define SPI_SPEED_4         1
    #define SPI_SPEED_8         2
    #define SPI_SPEED_16        3
    #define SPI_SPEED_32        4
    #define SPI_SPEED_64        5
    #define SPI_SPEED_128       6
    #define SPI_SPEED_256       7
    
    
    /******************************************************************************************/
    /* NORFLASH 片选 引脚 定义 */
    
    #define NORFLASH_CS_GPIO_PORT           GPIOA
    #define NORFLASH_CS_GPIO_PIN            GPIO_PIN_2
    #define NORFLASH_CS_GPIO_CLK_ENABLE()   do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PI口时钟使能 */
    
    /******************************************************************************************/
    //spi外设选择
    extern SPI_HandleTypeDef hspi1;
    #define HSPI hspi1
    
    /* NORFLASH 片选信号 */
    #define NORFLASH_CS(x)      do{ x ? \
                                      HAL_GPIO_WritePin(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN, GPIO_PIN_SET) : \
                                      HAL_GPIO_WritePin(NORFLASH_CS_GPIO_PORT, NORFLASH_CS_GPIO_PIN, GPIO_PIN_RESET); \
                                }while(0)
    
    /* FLASH芯片列表 */
    #define W25Q80      0XEF13          /* W25Q80   芯片ID */
    #define W25Q16      0XEF14          /* W25Q16   芯片ID */
    #define W25Q32      0XEF15          /* W25Q32   芯片ID */
    #define W25Q64      0XEF16          /* W25Q64   芯片ID */
    #define W25Q128     0XEF17          /* W25Q128  芯片ID */
    #define W25Q256     0XEF18          /* W25Q256  芯片ID */
    #define BY25Q64     0X6816          /* BY25Q64  芯片ID */
    #define BY25Q128    0X6817          /* BY25Q128 芯片ID */
    #define NM25Q64     0X5216          /* NM25Q64  芯片ID */
    #define NM25Q128    0X5217          /* NM25Q128 芯片ID */
    
    extern uint16_t norflash_TYPE;      /* 定义FLASH芯片型号 */
     
    /* 指令表 */
    #define FLASH_WriteEnable           0x06 
    #define FLASH_WriteDisable          0x04 
    #define FLASH_ReadStatusReg1        0x05 
    #define FLASH_ReadStatusReg2        0x35 
    #define FLASH_ReadStatusReg3        0x15 
    #define FLASH_WriteStatusReg1       0x01 
    #define FLASH_WriteStatusReg2       0x31 
    #define FLASH_WriteStatusReg3       0x11 
    #define FLASH_ReadData              0x03 
    #define FLASH_FastReadData          0x0B 
    #define FLASH_FastReadDual          0x3B 
    #define FLASH_FastReadQuad          0xEB  
    #define FLASH_PageProgram           0x02 
    #define FLASH_PageProgramQuad       0x32 
    #define FLASH_BlockErase            0xD8 
    #define FLASH_SectorErase           0x20 
    #define FLASH_ChipErase             0xC7 
    #define FLASH_PowerDown             0xB9 
    #define FLASH_ReleasePowerDown      0xAB 
    #define FLASH_DeviceID              0xAB 
    #define FLASH_ManufactDeviceID      0x90 
    #define FLASH_JedecDeviceID         0x9F 
    #define FLASH_Enable4ByteAddr       0xB7
    #define FLASH_Exit4ByteAddr         0xE9
    #define FLASH_SetReadParam          0xC0 
    #define FLASH_EnterQPIMode          0x38
    #define FLASH_ExitQPIMode           0xFF
    
    /* 静态函数 */
    static void norflash_wait_busy(void);               /* 等待空闲 */
    static void norflash_send_address(uint32_t address);/* 发送地址 */
    static void norflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen);    /* 写入page */
    static void norflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen); /* 写flash,不带擦除 */
    
    /* 普通函数 */
    void norflash_init(void);                   /* 初始化25QXX */
    uint16_t norflash_read_id(void);            /* 读取FLASH ID */
    void norflash_write_enable(void);           /* 写使能 */
    uint8_t norflash_read_sr(uint8_t regno);    /* 读取状态寄存器 */
    void norflash_write_sr(uint8_t regno,uint8_t sr);   /* 写状态寄存器 */
    
    void norflash_erase_chip(void);             /* 整片擦除 */
    void norflash_erase_sector(uint32_t saddr); /* 扇区擦除 */
    void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen);     /* 读取flash */
    void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen);    /* 写入flash */
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    源文件

    1. 需要移植 spi读写函数
    uint8_t spi2_read_write_byte(uint8_t send_data)
    
    • 1
    1. 需要移植spi速度修改函数—也可以不修改–非必要
    void spi2_set_speed(uint8_t speed)
    
    • 1

    spi flash操作库源文件

    /**
     ****************************************************************************************************
     * @file        norflash.c
     * @author      正点原子团队(ALIENTEK)
     * @version     V1.0
     * @date        2021-10-26
     * @brief       NOR FLASH(25QXX) 驱动代码
     * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
     ****************************************************************************************************
     * @attention
     *
     * 实验平台:正点原子 F407电机开发板
     * 在线视频:www.yuanzige.com
     * 技术论坛:http://www.openedv.com/forum.php
     * 公司网址:www.alientek.com
     * 购买地址:zhengdianyuanzi.tmall.com
     *
     * 修改说明
     * V1.0 20211026
     * 第一次发布
     *
     ****************************************************************************************************
     */
    
    
    #include "norflash.h"
    #include "stdio.h"
    
    uint16_t g_norflash_type = NM25Q128;     /* 默认是NM25Q128 */
    /*需要移植的代码:spi数据收发函数*/
    uint8_t spi2_read_write_byte(uint8_t send_data)
    {
        uint8_t recv_data;
        HAL_SPI_TransmitReceive(&HSPI, &send_data, &recv_data, 1, 0xffff);
        return recv_data;
    }
    /**
    * @brief SPI2 速度设置函数
    * @note SPI2 时钟选择来自 APB1, 即 PCLK1, 为 42Mhz
    * SPI 速度 = PCLK1 / 2^(speed + 1)
    * @param speed : SPI2 时钟分频系数
    取值为 SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_2 256
    * @retval 无
    */
    void spi2_set_speed(uint8_t speed)
    {
        assert_param(IS_SPI_BAUDRATE_PRESCALER(speed));/* 判断有效性 */
        __HAL_SPI_DISABLE(&HSPI); /* 关闭 SPI */
        HSPI.Instance->CR1 &= 0xFFC7; /* 位 3-5 清零,用来设置波特率 */
        HSPI.Instance->CR1 |= speed << 3; /* 设置 SPI 速度 */
        __HAL_SPI_ENABLE(&HSPI); /* 使能 SPI */
    }
    
    /**
     * @brief       初始化SPI NOR FLASH
     * @param       无
     * @retval      无
     */
    void norflash_init(void)
    {
    
        spi2_set_speed(SPI_SPEED_4);            /* SPI2 切换到高速状态 21Mhz */
    		uint8_t temp=0;
        g_norflash_type = norflash_read_id();   /* 读取FLASH ID. */
    
        if (g_norflash_type == W25Q256)         /* SPI FLASH为W25Q256, 必须使能4字节地址模式 */
        {
            temp = norflash_read_sr(3);         /* 读取状态寄存器3,判断地址模式 */
    
            if ((temp & 0x01) == 0)             /* 如果不是4字节地址模式,则进入4字节地址模式 */
            {
                norflash_write_enable();        /* 写使能 */
                temp |= 1 << 1;                 /* ADP=1, 上电4位地址模式 */
                norflash_write_sr(3, temp);     /* 写SR3 */
    
                NORFLASH_CS(0);
                spi2_read_write_byte(FLASH_Enable4ByteAddr);    /* 使能4字节地址指令 */
                NORFLASH_CS(1);
            }
        }
    
       // printf("ID:%x\r\n", g_norflash_type);
    }
    
    /**
     * @brief       等待空闲
     * @param       无
     * @retval      无
     */
    static void norflash_wait_busy(void)
    {
        while ((norflash_read_sr(1) & 0x01) == 0x01);   /* 等待BUSY位清空 */
    }
    
    /**
     * @brief       25QXX写使能
     *   @note      将S1寄存器的WEL置位
     * @param       无
     * @retval      无
     */
    void norflash_write_enable(void)
    {
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_WriteEnable);   /* 发送写使能 */
        NORFLASH_CS(1);
    }
    
    /**
     * @brief       25QXX发送地址
     *   @note      根据芯片型号的不同, 发送24ibt / 32bit地址
     * @param       address : 要发送的地址
     * @retval      无
     */
    static void norflash_send_address(uint32_t address)
    {
        if (g_norflash_type == W25Q256) /* 只有W25Q256支持4字节地址模式 */
        {
            spi2_read_write_byte((uint8_t)((address) >> 24)); /* 发送 bit31 ~ bit24 地址 */
        }
    
        spi2_read_write_byte((uint8_t)((address) >> 16));   /* 发送 bit23 ~ bit16 地址 */
        spi2_read_write_byte((uint8_t)((address) >> 8));    /* 发送 bit15 ~ bit8  地址 */
        spi2_read_write_byte((uint8_t)address);             /* 发送 bit7  ~ bit0  地址 */
    }
    
    /**
     * @brief       读取25QXX的状态寄存器,25QXX一共有3个状态寄存器
     *   @note      状态寄存器1:
     *              BIT7  6   5   4   3   2   1   0
     *              SPR   RV  TB BP2 BP1 BP0 WEL BUSY
     *              SPR:默认0,状态寄存器保护位,配合WP使用
     *              TB,BP2,BP1,BP0:FLASH区域写保护设置
     *              WEL:写使能锁定
     *              BUSY:忙标记位(1,忙;0,空闲)
     *              默认:0x00
     *
     *              状态寄存器2:
     *              BIT7  6   5   4   3   2   1   0
     *              SUS   CMP LB3 LB2 LB1 (R) QE  SRP1
     *
     *              状态寄存器3:
     *              BIT7      6    5    4   3   2   1   0
     *              HOLD/RST  DRV1 DRV0 (R) (R) WPS ADP ADS
     *
     * @param       regno: 状态寄存器号,范:1~3
     * @retval      状态寄存器值
     */
    uint8_t norflash_read_sr(uint8_t regno)
    {
        uint8_t byte = 0, command = 0;
    
        switch (regno)
        {
            case 1:
                command = FLASH_ReadStatusReg1;  /* 读状态寄存器1指令 */
                break;
    
            case 2:
                command = FLASH_ReadStatusReg2;  /* 读状态寄存器2指令 */
                break;
    
            case 3:
                command = FLASH_ReadStatusReg3;  /* 读状态寄存器3指令 */
                break;
    
            default:
                command = FLASH_ReadStatusReg1;
                break;
        }
    
        NORFLASH_CS(0);
        spi2_read_write_byte(command);      /* 发送读寄存器命令 */
        byte = spi2_read_write_byte(0xFF);  /* 读取一个字节 */
        NORFLASH_CS(1);
    
        return byte;
    }
    
    /**
     * @brief       写25QXX状态寄存器
     *   @note      寄存器说明见norflash_read_sr函数说明
     * @param       regno: 状态寄存器号,范:1~3
     * @param       sr   : 要写入状态寄存器的值
     * @retval      无
     */
    void norflash_write_sr(uint8_t regno, uint8_t sr)
    {
        uint8_t command = 0;
    
        switch (regno)
        {
            case 1:
                command = FLASH_WriteStatusReg1;  /* 写状态寄存器1指令 */
                break;
    
            case 2:
                command = FLASH_WriteStatusReg2;  /* 写状态寄存器2指令 */
                break;
    
            case 3:
                command = FLASH_WriteStatusReg3;  /* 写状态寄存器3指令 */
                break;
    
            default:
                command = FLASH_WriteStatusReg1;
                break;
        }
    
        NORFLASH_CS(0);
        spi2_read_write_byte(command);  /* 发送读寄存器命令 */
        spi2_read_write_byte(sr);       /* 写入一个字节 */
        NORFLASH_CS(1);
    }
    
    /**
     * @brief       读取芯片ID
     * @param       无
     * @retval      FLASH芯片ID
     *   @note      芯片ID列表见: norflash.h, 芯片列表部分
     */
    uint16_t norflash_read_id(void)
    {
        uint16_t deviceid;
    
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_ManufactDeviceID);   /* 发送读 ID 命令 */
        spi2_read_write_byte(0);    /* 写入一个字节 */
        spi2_read_write_byte(0);
        spi2_read_write_byte(0);
        deviceid = spi2_read_write_byte(0xFF) << 8;     /* 读取高8位字节 */
        deviceid |= spi2_read_write_byte(0xFF);         /* 读取低8位字节 */
        NORFLASH_CS(1);
    
        return deviceid;
    }
    
    /**
     * @brief       读取SPI FLASH
     *   @note      在指定地址开始读取指定长度的数据
     * @param       pbuf    : 数据存储区
     * @param       addr    : 开始读取的地址(最大32bit)
     * @param       datalen : 要读取的字节数(最大65535)
     * @retval      无
     */
    void norflash_read(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
    {
        uint16_t i;
    
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_ReadData);       /* 发送读取命令 */
        norflash_send_address(addr);                /* 发送地址 */
    
        for (i = 0; i < datalen; i++)
        {
            pbuf[i] = spi2_read_write_byte(0xFF);   /* 循环读取 */
        }
    
        NORFLASH_CS(1);
    }
    
    /**
     * @brief       SPI在一页(0~65535)内写入少于256个字节的数据
     *   @note      在指定地址开始写入最大256字节的数据
     * @param       pbuf    : 数据存储区
     * @param       addr    : 开始写入的地址(最大32bit)
     * @param       datalen : 要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
     * @retval      无
     */
    static void norflash_write_page(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
    {
        uint16_t i;
    
        norflash_write_enable();    /* 写使能 */
    
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_PageProgram);    /* 发送写页命令 */
        norflash_send_address(addr);                /* 发送地址 */
    
        for (i = 0; i < datalen; i++)
        {
            spi2_read_write_byte(pbuf[i]);          /* 循环读取 */
        }
    
        NORFLASH_CS(1);
        norflash_wait_busy();       /* 等待写入结束 */
    }
    
    /**
     * @brief       无检验写SPI FLASH
     *   @note      必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
     *              具有自动换页功能
     *              在指定地址开始写入指定长度的数据,但是要确保地址不越界!
     *
     * @param       pbuf    : 数据存储区
     * @param       addr    : 开始写入的地址(最大32bit)
     * @param       datalen : 要写入的字节数(最大65535)
     * @retval      无
     */
    static void norflash_write_nocheck(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
    {
        uint16_t pageremain;
        pageremain = 256 - addr % 256;  /* 单页剩余的字节数 */
    
        if (datalen <= pageremain)      /* 不大于256个字节 */
        {
            pageremain = datalen;
        }
    
        while (1)
        {
            /* 当写入字节比页内剩余地址还少的时候, 一次性写完
             * 当写入直接比页内剩余地址还多的时候, 先写完整个页内剩余地址, 然后根据剩余长度进行不同处理
             */
            norflash_write_page(pbuf, addr, pageremain);
    
            if (datalen == pageremain)      /* 写入结束了 */
            {
                break;
            }
            else     /* datalen > pageremain */
            {
                pbuf += pageremain;         /* pbuf指针地址偏移,前面已经写了pageremain字节 */
                addr += pageremain;         /* 写地址偏移,前面已经写了pageremain字节 */
                datalen -= pageremain;      /* 写入总长度减去已经写入了的字节数 */
    
                if (datalen > 256)          /* 剩余数据还大于一页,可以一次写一页 */
                {
                    pageremain = 256;       /* 一次可以写入256个字节 */
                }
                else     /* 剩余数据小于一页,可以一次写完 */
                {
                    pageremain = datalen;   /* 不够256个字节了 */
                }
            }
        }
    }
    
    /**
     * @brief       写SPI FLASH
     *   @note      在指定地址开始写入指定长度的数据, 该函数带擦除操作!
     *              SPI FLASH 一般是: 256个字节为一个Page, 4Kbytes为一个Sector, 16个扇区为1个Block
     *              擦除的最小单位为Sector.
     *
     * @param       pbuf    : 数据存储区
     * @param       addr    : 开始写入的地址(最大32bit)
     * @param       datalen : 要写入的字节数(最大65535)
     * @retval      无
     */
    uint8_t g_norflash_buf[4096];   /* 扇区缓存 */
    
    void norflash_write(uint8_t *pbuf, uint32_t addr, uint16_t datalen)
    {
        uint32_t secpos;
        uint16_t secoff;
        uint16_t secremain;
        uint16_t i;
        uint8_t *norflash_buf;
    
        norflash_buf = g_norflash_buf;
        secpos = addr / 4096;       /* 扇区地址 */
        secoff = addr % 4096;       /* 在扇区内的偏移 */
        secremain = 4096 - secoff;  /* 扇区剩余空间大小 */
    
        //printf("ad:%X,nb:%X\r\n", addr, datalen); /* 测试用 */
        if (datalen <= secremain)
        {
            secremain = datalen;    /* 不大于4096个字节 */
        }
    
        while (1)
        {
            norflash_read(norflash_buf, secpos * 4096, 4096);   /* 读出整个扇区的内容 */
    
            for (i = 0; i < secremain; i++)   /* 校验数据 */
            {
                if (norflash_buf[secoff + i] != 0XFF)
                {
                    break;      /* 需要擦除, 直接退出for循环 */
                }
            }
    
            if (i < secremain)   /* 需要擦除 */
            {
                norflash_erase_sector(secpos);  /* 擦除这个扇区 */
    
                for (i = 0; i < secremain; i++)   /* 复制 */
                {
                    norflash_buf[i + secoff] = pbuf[i];
                }
    
                norflash_write_nocheck(norflash_buf, secpos * 4096, 4096);  /* 写入整个扇区 */
            }
            else        /* 写已经擦除了的,直接写入扇区剩余区间. */
            {
                norflash_write_nocheck(pbuf, addr, secremain);  /* 直接写扇区 */
            }
    
            if (datalen == secremain)
            {
                break;  /* 写入结束了 */
            }
            else        /* 写入未结束 */
            {
                secpos++;               /* 扇区地址增1 */
                secoff = 0;             /* 偏移位置为0 */
    
                pbuf += secremain;      /* 指针偏移 */
                addr += secremain;      /* 写地址偏移 */
                datalen -= secremain;   /* 字节数递减 */
    
                if (datalen > 4096)
                {
                    secremain = 4096;   /* 下一个扇区还是写不完 */
                }
                else
                {
                    secremain = datalen;/* 下一个扇区可以写完了 */
                }
            }
        }
    }
    
    /**
     * @brief       擦除整个芯片
     *   @note      等待时间超长...
     * @param       无
     * @retval      无
     */
    void norflash_erase_chip(void)
    {
        norflash_write_enable();    /* 写使能 */
        norflash_wait_busy();       /* 等待空闲 */
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_ChipErase);  /* 发送读寄存器命令 */
        NORFLASH_CS(1);
        norflash_wait_busy();       /* 等待芯片擦除结束 */
    }
    
    /**
     * @brief       擦除一个扇区
     *   @note      注意,这里是扇区地址,不是字节地址!!
     *              擦除一个扇区的最少时间:150ms
     *
     * @param       saddr : 扇区地址 根据实际容量设置
     * @retval      无
     */
    void norflash_erase_sector(uint32_t saddr)
    {
        //printf("fe:%x\r\n", saddr);   /* 监视falsh擦除情况,测试用 */
        saddr *= 4096;
        norflash_write_enable();        /* 写使能 */
        norflash_wait_busy();           /* 等待空闲 */
    
        NORFLASH_CS(0);
        spi2_read_write_byte(FLASH_SectorErase);    /* 发送写页命令 */
        norflash_send_address(saddr);   /* 发送地址 */
        NORFLASH_CS(1);
        norflash_wait_busy();           /* 等待扇区擦除完成 */
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460

    测试使用函数

    重定向printf函数

    /* 重定向printf函数 */
    int fputc(int ch, FILE *f)
    {
        HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 0xffff);
        return ch;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    spi flash 测试函数

    
    void spi_flash_test()
    {
        int x = 0;
        norflash_init();
        uint8_t buf[256];
    
        for(x = 0; x < 256; x++)buf[x] = x;
    
        norflash_write(buf, 0, 256);
        memset(buf, 0, 256);
        norflash_read(buf, 0, 256);
    
        for(x = 0; x < 256; x++)
        {
            if(buf[x] != x)break;
        }
    
        if(x != 256)
        {
            printf("spi flash test fail\r\n");
        }
        else
        {
            printf("spi flash test ok\r\n");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    计算机网络性能指标——时延,时延带宽积,RTT和利用率
    Python学习记录——이십이 Bytes和字符集编码
    Spire.XLS for C++操作方法
    【ES实战】ES上的安全性运行方式
    面试题:集群高并发环境下如何保证分布式唯一全局ID生成?
    学生HTML个人网页作业作品 简单的IT技术个人简历模板html下载 简单个人网页设计作业 静态HTML个人博客主页
    基于STM32单片机一氧化碳(CO)气体监控系统proteus仿真设计
    并查集的学习
    Java大厂面试题第2季
    Chat2DB下载、以及AI功能使用
  • 原文地址:https://blog.csdn.net/u010261063/article/details/126022334