【CC2640R2F】香瓜CC2640R2F之SPI读写W25Q80

本文最后修改时间:2022年01月08日 10:45

一、本节简介

本节以simple_peripheral工程为例,介绍如何使用SPI读写W25Q80(外部flash)。

二、实验平台

1)CC2640R2F平台

①协议栈版本:CC2640R2 SDK v1.40.00.45

②编译软件:CCS7.3.0.00019

③硬件平台:香瓜CC2640R2F开发板

④仿真器:香瓜XDS100V3下载器

2)外设

①板载在香瓜CC2640R2F开发板底板上的芯片:W25Q80

三、版权声明

1)作者:甜甜的大香瓜

2)声明:喝水不忘挖井人,转载请注明出处。

3)纠错/业务合作:897503845@qq.com

4)香瓜BLE之CC2640R2F群:557278427

5)本文出处:原创连载资料《简单粗暴学蓝牙5》

6)完整开源资料下载地址(电脑端打开):

opengua.taobao.com

7)香瓜CC2640R2F开发板购买链接:

https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4023-16963296339.8.21bfc58419sWKt&id=558653143169

四、实验前提

1、在进行本文步骤前,请先阅读以下章节:

1)《简单粗暴学蓝牙5》的“第一章至第四章”章节​。

2、在进行本文步骤前,请先实现以下章节:

1)《简单粗暴学蓝牙5》的“第三章 软件的安装及使用”章节。

五、基础知识

1、W25Q80是什么?

答: W25Q80是winbond(华邦)公司出的8M bit(也就是1MB)的flash芯片。同系列常用的型号还有W25Q16(16Mb=2MB)、W25Q32(32Mb=4MB)等。

2、W25Q80的基本信息?

答:

如上图,W25Q80一次可写256字节、可4K字节扇区擦除、32K或者64K块擦除、整片擦除。

使用的是SPI接口、2.7V~3.6V电压范围,香瓜购买的是8-pin SOIC 208-mil封装。

如上图,W25Q80的厂商ID是0xEF,设备ID是0x13。这个用于初始化时识别flash芯片用。

六、硬件原理

1、W25Q80芯片引脚图

如上图,W25Q80一共8个脚,其中GND和VCC供电3.3V(范围在2.7V~3.6V)即可,其他4个SPI引脚DO(输出)、DI(输入)、CLK(时钟)、CS(片选)。

WP(写保护)、HOLD(保持输入)这两个引脚本文并没有用到,且“/WP”中的“/”是低电平有效的意思,所以我们本文将WP和HOLD两引脚拉高到VCC即可。

2、W25Q80与香瓜CC2640R2F开发板的对应关系

W25Q80引脚

香瓜CC2640R2F开发板引脚

引脚1(/CS)

DIO_30

引脚2(DO)

DIO_8

引脚3(/WP)

置高到VCC

引脚4(GND)

GND

引脚5(DI)

DIO_9

引脚6(CLK)

DIO_10

引脚7(/HOLD)

置高到VCC

引脚6(VCC)

3.3V

3、硬件原理图

七、实验步骤

1、编写并添加自定义的W25Q80驱动

1)写一个驱动GUA_ExtFlash.c(存放在“……

\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA“路径下)

//**********************************************************************

//name:         GUA_ExtFlash.c

//introduce:    外部flash驱动

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

#include “string.h”

#include <ti/devices/cc26x0r2/driverlib/Ssi.h>

#include <ti/drivers/spi/SPICC26XXDMA.h>

#include <ti/drivers/dma/UDMACC26XX.h>

#include <ti/drivers/SPI.h>

#include “GUA_ExtFlash.h”

/*********************宏定义************************/

//SPI引脚

#define GUA_CC2640R2_SPI0_MISO              IOID_8

#define GUA_CC2640R2_SPI0_MOSI              IOID_9

#define GUA_CC2640R2_SPI0_CLK               IOID_10

#define GUA_CC2640R2_SPI0_CSN               PIN_UNASSIGNED

#define GUA_Spi_flash_CS                    IOID_30

//SPI片选开关宏

#define GUA_FLASH_CS_ON                     0

#define GUA_FLASH_CS_OFF                    1

/* Instruction codes */

#define GUA_BLS_CODE_PROGRAM                0x02 /**< Page Program */

#define GUA_BLS_CODE_READ                   0x03 /**< Read Data */

#define GUA_BLS_CODE_READ_STATUS            0x05 /**< Read Status Register */

#define GUA_BLS_CODE_WRITE_ENABLE           0x06 /**< Write Enable */

#define GUA_BLS_CODE_SECTOR_ERASE           0x20 /**< Sector Erase */

#define GUA_BLS_CODE_MDID                   0x90 /**< Manufacturer Device ID */

#define GUA_BLS_CODE_DP                     0xB9 /**< Power down */

#define GUA_BLS_CODE_RDP                    0xAB /**< Power standby */

/* Erase instructions */

#define GUA_BLS_CODE_ERASE_4K               0x20 /**< Sector Erase */

#define GUA_BLS_CODE_ERASE_32K              0x52

#define GUA_BLS_CODE_ERASE_64K              0xD8

#define GUA_BLS_CODE_ERASE_ALL              0xC7 /**< Mass Erase */

/* Bitmasks of the status register */

#define GUA_BLS_STATUS_SRWD_BM              0x80

#define GUA_BLS_STATUS_BP_BM                0x0C

#define GUA_BLS_STATUS_WEL_BM               0x02

#define GUA_BLS_STATUS_WIP_BM               0x01

#define GUA_BLS_STATUS_BIT_BUSY             0x01 /**< Busy bit of the status register */

/* Part specific constants */

#define GUA_BLS_PROGRAM_PAGE_SIZE           256

#define GUA_BLS_ERASE_SECTOR_SIZE           4096

/* Manufacturer IDs */

#define GUA_MF_MACRONIX                     0xC2

#define GUA_MF_WINBOND                      0xEF

typedef enum GUA_CC2640R2_SPIName {

GUA_CC2640R2_SPI0 = 0,

GUA_CC2640R2_SPICOUNT

} GUA_CC2640R2_SPIName;

SPICC26XXDMA_Object GUA_spiCC26XXDMAObjects[GUA_CC2640R2_SPICOUNT];

//SPI速度4M

#define GUA_SPI_BIT_RATE                    4000000

//flash每页大小4K

#define GUA_EXT_FLASH_PAGE_SIZE             4096

/*********************内部变量************************/

const SPICC26XXDMA_HWAttrsV1 GUA_spiCC26XXDMAHWAttrs[GUA_CC2640R2_SPICOUNT] = {

{

        .baseAddr           = SSI0_BASE,

        .intNum             = INT_SSI0_COMB,

        .intPriority        = ~0,

        .swiPriority        = 0,

        .powerMngrId        = PowerCC26XX_PERIPH_SSI0,

        .defaultTxBufValue  = 0,

        .rxChannelBitMask   = 1<<UDMA_CHAN_SSI0_RX,

        .txChannelBitMask   = 1<<UDMA_CHAN_SSI0_TX,

        .mosiPin            = GUA_CC2640R2_SPI0_MOSI,

        .misoPin            = GUA_CC2640R2_SPI0_MISO,

        .clkPin             = GUA_CC2640R2_SPI0_CLK,

        .csnPin             = GUA_CC2640R2_SPI0_CSN

}

};

const SPI_Config GUA_SPI_config[GUA_CC2640R2_SPICOUNT] = {

{

         .fxnTablePtr = &SPICC26XXDMA_fxnTable,

         .object      = &GUA_spiCC26XXDMAObjects[GUA_CC2640R2_SPI0],

         .hwAttrs     = &GUA_spiCC26XXDMAHWAttrs[GUA_CC2640R2_SPI0]

},

};

const uint_least8_t GUA_SPI_count = GUA_CC2640R2_SPICOUNT;

static PIN_Config GUA_BoardFlashPinTable[] =

{

GUA_Spi_flash_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MIN, /* Ext. flash chip select */

PIN_TERMINATE

};

static PIN_Handle GUA_hFlashPin = NULL;

static PIN_State GUA_pinState;

// Supported flash devices

static GUA_ExtFlashInfo_t GUA_flashInfo[] =

{

{

        .manfId = GUA_MF_MACRONIX,  // Macronics

        .devId = 0x15,              // MX25R1635F

        .deviceSize = 0x200000      // 2 Mbyte (16 Mbit)

},

{

        .manfId = GUA_MF_MACRONIX,  // Macronics

        .devId = 0x14,              // MX25R8035F

        .deviceSize = 0x100000      // 1 Mbyte (8 Mbit)

},

{

        .manfId = GUA_MF_WINBOND,   // WinBond

        .devId = 0x13,              // W25Q80DV

        .deviceSize = 0x100000      // 1 Mbyte (8 Mbit)

},

{

        .manfId = GUA_MF_WINBOND,   // WinBond

        .devId = 0x12,              // W25X40CL

        .deviceSize = 0x080000      // 512 Kbyte (4 Mbit)

},

{

        .manfId = GUA_MF_WINBOND,   // WinBond

        .devId = 0x11,              // W25X20CL

        .deviceSize = 0x040000      // 256 Kbyte (2 Mbit)

},

{

        .manfId = 0x0,

        .devId = 0x0,

        .deviceSize = 0x0

}

};

// Flash information

static GUA_ExtFlashInfo_t *pGUA_flashInfo = NULL;

static GUA_U8 GUA_infoBuf[2];

// SPI interface

static SPI_Handle GUA_spiHandle = NULL;

static SPI_Params GUA_spiParams;

/*********************内部函数************************/

static int GUA_Spi_write(const GUA_U8 *pGUA_buf, size_t GUA_length);

static int GUA_Spi_read(GUA_U8 *pGUA_buf, size_t GUA_length);

static bool GUA_Spi_open(GUA_U32 GUA_bitRate);

static void GUA_Spi_close(void);

static void GUA_Spi_flash(void);

static void GUA_extFlashSelect(void);

static void GUA_extFlashDeselect(void);

static bool GUA_extFlashPowerDown(void);

static bool GUA_extFlashPowerStandby(void);

static bool GUA_ExtFlash_readInfo(void);

static bool GUA_extFlashVerifyPart(void);

static int GUA_ExtFlash_waitReady(void);

static int GUA_ExtFlash_powerDown(void);

static int GUA_ExtFlash_writeEnable(void);

//**********************************************************************

//name:         GUA_Spi_write

//introduce:    SPI设备

//parameter:    pGUA_buf:写缓存

//              GUA_len:数据长度

//return:       如果操作正常,返回0;反之返回1

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static int GUA_Spi_write(const GUA_U8 *pGUA_buf, size_t GUA_len)

{

SPI_Transaction masterTransaction;

masterTransaction.count  = GUA_len;

masterTransaction.txBuf  = (void*)pGUA_buf;

masterTransaction.arg    = NULL;

masterTransaction.rxBuf  = NULL;

return SPI_transfer(GUA_spiHandle, &masterTransaction) ? 0 : -1;

}

//**********************************************************************

//name:         GUA_Spi_read

//introduce:    SPI设备

//parameter:    pGUA_buf:读缓存

//              GUA_len:数据长度

//return:       如果操作正常,返回0;反之返回1

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static int GUA_Spi_read(GUA_U8 *pGUA_buf, size_t GUA_len)

{

SPI_Transaction masterTransaction;

masterTransaction.count = GUA_len;

masterTransaction.txBuf = NULL;

masterTransaction.arg = NULL;

masterTransaction.rxBuf = pGUA_buf;

return SPI_transfer(GUA_spiHandle, &masterTransaction) ? 0 : -1;

}

//**********************************************************************

//name:         GUA_Spi_open

//introduce:    打开SPI

//parameter:    GUA_bitRate:要设置的SPI速度

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static bool GUA_Spi_open(GUA_U32 GUA_bitRate)

{

/*  Configure SPI as master */

SPI_Params_init(&GUA_spiParams);

GUA_spiParams.bitRate = GUA_bitRate;

GUA_spiParams.mode = SPI_MASTER;

GUA_spiParams.transferMode = SPI_MODE_BLOCKING;

/* Attempt to open SPI. */

GUA_spiHandle = SPI_open(GUA_CC2640R2_SPI0, &GUA_spiParams);

return GUA_spiHandle != NULL;

}

//**********************************************************************

//name:         GUA_Spi_close

//introduce:    关闭SPI

//parameter:    none

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static void GUA_Spi_close(void)

{

if (GUA_spiHandle != NULL)

{

        // Close the RTOS driver

        SPI_close(GUA_spiHandle);

        GUA_spiHandle = NULL;

}

}

//**********************************************************************

//name:         GUA_Spi_flash

//introduce:    把没用的垃圾数据处理掉

//parameter:    none

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static void GUA_Spi_flash(void)

{

/* make sure SPI hardware module is done  */

while(SSIBusy(((SPICC26XXDMA_HWAttrsV1*)GUA_spiHandle->hwAttrs)->baseAddr))

{ };

}

//**********************************************************************

//name:         GUA_extFlashSelect

//introduce:    片选引脚选择外部flash

//parameter:    none

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static void GUA_extFlashSelect(void)

{

PIN_setOutputValue(GUA_hFlashPin, GUA_Spi_flash_CS, GUA_FLASH_CS_ON);

}

//**********************************************************************

//name:         GUA_extFlashDeselect

//introduce:    取消片选引脚选择外部flash

//parameter:    none

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static void GUA_extFlashDeselect(void)

{

PIN_setOutputValue(GUA_hFlashPin, GUA_Spi_flash_CS, GUA_FLASH_CS_OFF);

}

//**********************************************************************

//name:         GUA_extFlashPowerDown

//introduce:    让设备进入低功耗模式,不能访问数据,只能读取寄存器状态

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static bool GUA_extFlashPowerDown(void)

{

GUA_U8 GUA_cmd;

bool GUA_success;

GUA_cmd = GUA_BLS_CODE_DP;

GUA_extFlashSelect();

GUA_success = GUA_Spi_write(&GUA_cmd, sizeof(GUA_cmd)) == 0;

GUA_extFlashDeselect();

return GUA_success;

}

//**********************************************************************

//name:         GUA_extFlashPowerStandby

//introduce:    退出低功耗模式

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static bool GUA_extFlashPowerStandby(void)

{

GUA_U8 GUA_cmd;

bool GUA_success;

GUA_cmd = GUA_BLS_CODE_RDP;

GUA_extFlashSelect();

GUA_success = GUA_Spi_write(&GUA_cmd, sizeof(GUA_cmd)) == 0;

GUA_extFlashDeselect();

if(GUA_success)

{

        if(GUA_ExtFlash_waitReady() != 0)

        {

            GUA_success = false;

        }

}

return GUA_success;

}

//**********************************************************************

//name:         GUA_ExtFlash_readInfo

//introduce:    flash信息(厂商ID和设备ID

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static bool GUA_ExtFlash_readInfo(void)

{

const GUA_U8 GUA_wbuf[] = {GUA_BLS_CODE_MDID, 0xFF, 0xFF, 0x00};

GUA_extFlashSelect();

int GUA_ret = GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

if(GUA_ret)

{

        GUA_extFlashDeselect();

        return false;

}

GUA_ret = GUA_Spi_read(GUA_infoBuf, sizeof(GUA_infoBuf));

GUA_extFlashDeselect();

return GUA_ret == 0;

}

//**********************************************************************

//name:         GUA_extFlashVerifyPart

//introduce:    校验flash芯片是否是驱动支持的flash

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static bool GUA_extFlashVerifyPart(void)

{

if(!GUA_ExtFlash_readInfo())

{

        return false;

}

pGUA_flashInfo = GUA_flashInfo;

while(pGUA_flashInfo->deviceSize > 0)

{

        if(GUA_infoBuf[0] == pGUA_flashInfo->manfId && GUA_infoBuf[1] == pGUA_flashInfo->devId)

        {

            break;

        }

        pGUA_flashInfo++;

}

return pGUA_flashInfo->deviceSize > 0;

}

//**********************************************************************

//name:         GUA_ExtFlash_waitReady

//introduce:    等待当前擦除、编程的操作结束

//parameter:    none

//return:       如果操作正常,返回0;反之返回非0

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static int GUA_ExtFlash_waitReady(void)

{

const GUA_U8 GUA_wbuf[1] = {GUA_BLS_CODE_READ_STATUS};

int GUA_ret;

/* Throw away all garbage */

GUA_extFlashSelect();

GUA_Spi_flash();

GUA_extFlashDeselect();

for(;;)

{

        GUA_U8 GUA_buf;

        GUA_extFlashSelect();

        GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

        GUA_ret = GUA_Spi_read(&GUA_buf, sizeof(GUA_buf));

        GUA_extFlashDeselect();

        if(GUA_ret)

        {

            /* Error */

            return -2;

        }

        if(!(GUA_buf & GUA_BLS_STATUS_BIT_BUSY))

        {

            /* Now ready */

            break;

        }

}

return 0;

}

//**********************************************************************

//name:         GUA_ExtFlash_powerDown

//introduce:    等待进入低功耗模式

//parameter:    none

//return:       如果操作正常,返回0;反之返回非0

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static int GUA_ExtFlash_powerDown(void)

{

GUA_U8 GUA_i;

GUA_i = 0;

while(GUA_i < 10)

{

        if(!GUA_ExtFlash_readInfo())

        {

            return 0;

        }

        GUA_i++;

}

return -1;

}

//**********************************************************************

//name:         GUA_ExtFlash_writeEnable

//introduce:    启动写操作

//parameter:    none

//return:       如果操作正常,返回0;反之返回非0

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

static int GUA_ExtFlash_writeEnable(void)

{

const GUA_U8 GUA_wbuf[] = {GUA_BLS_CODE_WRITE_ENABLE};

GUA_extFlashSelect();

int GUA_ret = GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf));

GUA_extFlashDeselect();

if(GUA_ret)

{

        return -3;

}

return 0;

}

//**********************************************************************

//name:         GUA_ExtFlash_open

//introduce:    初始化flash

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

bool GUA_ExtFlash_open(void)

{

bool GUA_f;

GUA_hFlashPin = PIN_open(&GUA_pinState, GUA_BoardFlashPinTable);

if(GUA_hFlashPin == NULL)

{

        return false;

}

/* Initialise SPI. Subsequent calls will do nothing. */

SPI_init();

/* Make sure SPI is available */

GUA_f = GUA_Spi_open(GUA_SPI_BIT_RATE);

if (GUA_f)

{

        /* Put the part is standby mode */

        GUA_f = GUA_extFlashPowerStandby();

        if(GUA_f)

        {

            /* Verify manufacturer and device ID */

            GUA_f = GUA_extFlashVerifyPart();

        }

        if(!GUA_f)

        {

            GUA_ExtFlash_close();

        }

}

return GUA_f;

}

//**********************************************************************

//name:         GUA_ExtFlash_close

//introduce:    关闭flash

//parameter:    none

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

void GUA_ExtFlash_close(void)

{

if(GUA_hFlashPin != NULL)

{

        // Put the part in low power mode

        GUA_extFlashPowerDown();

        if(pGUA_flashInfo->manfId == GUA_MF_WINBOND)

        {

            GUA_ExtFlash_powerDown();

        }

        /* Make sure SPI lines have a defined state */

        GUA_Spi_close();

        PIN_close(GUA_hFlashPin);

        GUA_hFlashPin = NULL;

}

}

//**********************************************************************

//name:         GUA_ExtFlash_read

//introduce:    flash

//parameter:    GUA_offset:偏移地址

//              GUA_length:数据长度

//              pGUA_buf:接收缓存区

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

bool GUA_ExtFlash_read(size_t GUA_offset, size_t GUA_length, GUA_U8 *pGUA_buf)

{

GUA_U8 GUA_wbuf[4];

/* Wait till previous erase/program operation completes */

int GUA_ret = GUA_ExtFlash_waitReady();

if(GUA_ret)

{

        return false;

}

/* SPI is driven with very low frequency (1MHz < 33MHz fR spec)

* in this temporary implementation.

* and hence it is not necessary to use fast read. */

GUA_wbuf[0] = GUA_BLS_CODE_READ;

GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

GUA_wbuf[3] = GUA_offset & 0xff;

GUA_extFlashSelect();

if(GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

{

        /* failure */

        GUA_extFlashDeselect();

        return false;

}

GUA_ret = GUA_Spi_read(pGUA_buf, GUA_length);

GUA_extFlashDeselect();

return GUA_ret == 0;

}

//**********************************************************************

//name:         GUA_ExtFlash_write

//introduce:    flash

//parameter:    GUA_offset:偏移地址

//              GUA_length:数据长度

//              pGUA_buf:发送缓存区

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

bool GUA_ExtFlash_write(size_t GUA_offset, size_t GUA_length, const GUA_U8 *pGUA_buf)

{

GUA_U8 GUA_wbuf[4];

while(GUA_length > 0)

{

        /* Wait till previous erase/program operation completes */

        int GUA_ret = GUA_ExtFlash_waitReady();

        if(GUA_ret)

        {

            return false;

        }

        GUA_ret = GUA_ExtFlash_writeEnable();

        if (GUA_ret)

        {

            return false;

        }

        size_t GUA_ilen; /* interim GUA_length per instruction */

        GUA_ilen = GUA_BLS_PROGRAM_PAGE_SIZE – (GUA_offset % GUA_BLS_PROGRAM_PAGE_SIZE);

        if (GUA_length < GUA_ilen)

        {

            GUA_ilen = GUA_length;

        }

        GUA_wbuf[0] = GUA_BLS_CODE_PROGRAM;

        GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

        GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

        GUA_wbuf[3] = GUA_offset & 0xff;

        GUA_offset += GUA_ilen;

        GUA_length -= GUA_ilen;

        /* Up to 100ns CS hold time (which is not clear

        * whether it’s application only in between reads)

        * is not imposed here since above instructions

        * should be enough to delay

        * as much. */

        GUA_extFlashSelect();

        if (GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

        {

            /* failure */

            GUA_extFlashDeselect();

            return false;

        }

        if (GUA_Spi_write(pGUA_buf, GUA_ilen))

        {

            /* failure */

            GUA_extFlashDeselect();

            return false;

        }

        pGUA_buf += GUA_ilen;

        GUA_extFlashDeselect();

}

return true;

}

//**********************************************************************

//name:         GUA_ExtFlash_erase

//introduce:    擦除flash

//parameter:    GUA_offset:偏移地址

//              GUA_length:数据长度

//              pGUA_buf:发送缓存区

//return:       如果操作正常,返回true;反之返回false

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

bool GUA_ExtFlash_erase(size_t GUA_offset, size_t GUA_length)

{

/* Note that Block erase might be more efficient when the floor map

* is well planned for OTA but to simplify for the temporary implementation,

* sector erase is used blindly. */

GUA_U8 GUA_wbuf[4];

size_t GUA_i, GUA_numsectors;

GUA_wbuf[0] = GUA_BLS_CODE_SECTOR_ERASE;

{

        size_t GUA_endoffset = GUA_offset + GUA_length – 1;

        GUA_offset = (GUA_offset / GUA_BLS_ERASE_SECTOR_SIZE) * GUA_BLS_ERASE_SECTOR_SIZE;

        GUA_numsectors = (GUA_endoffset – GUA_offset + GUA_BLS_ERASE_SECTOR_SIZE – 1) /

            GUA_BLS_ERASE_SECTOR_SIZE;

}

for(GUA_i = 0; GUA_i < GUA_numsectors; GUA_i++)

{

        /* Wait till previous erase/program operation completes */

        int GUA_ret = GUA_ExtFlash_waitReady();

        if(GUA_ret)

        {

            return false;

        }

        GUA_ret = GUA_ExtFlash_writeEnable();

        if(GUA_ret)

        {

            return false;

        }

        GUA_wbuf[1] = (GUA_offset >> 16) & 0xff;

        GUA_wbuf[2] = (GUA_offset >> 8) & 0xff;

        GUA_wbuf[3] = GUA_offset & 0xff;

        GUA_extFlashSelect();

        if(GUA_Spi_write(GUA_wbuf, sizeof(GUA_wbuf)))

        {

            /* failure */

            GUA_extFlashDeselect();

            return false;

        }

        GUA_extFlashDeselect();

        GUA_offset += GUA_BLS_ERASE_SECTOR_SIZE;

}

return true;

}

//**********************************************************************

//name:         GUA_ExtFlash_info

//introduce:    获取当前连接的外部flash的信息

//parameter:    none

//return:       ExtFlashInfo_t(包含设备内存大小、厂商ID、设备ID)

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

GUA_ExtFlashInfo_t *GUA_ExtFlash_info(void)

{

return pGUA_flashInfo;

}

2)写一个驱动头文件GUA_ExtFlash.h(存放在“……

\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\simple_peripheral\src\app\GUA“路径下)

//**********************************************************************

//name:         GUA_ExtFlash.h

//introduce:    外部flash驱动的头文件

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLECC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.08.02

//**********************************************************************

#ifndef GUA_EXT_FLASH_H

#define GUA_EXT_FLASH_H

//头文件

#include <stdlib.h>

#include <stdbool.h>

/*********************宏定义************************/

//类型宏

#ifndef GUA_C

typedef char GUA_C;

#endif

#ifndef GUA_U8

typedef unsigned char GUA_U8;

#endif

#ifndef GUA_8

typedef signed char GUA_8;

#endif

#ifndef GUA_U16

typedef unsigned short GUA_U16;

#endif

#ifndef GUA_16

typedef signed short GUA_16;

#endif

#ifndef GUA_U32

typedef unsigned long GUA_U32;

#endif

#ifndef GUA_32

typedef signed long GUA_32;

#endif

#ifndef GUA_U64

typedef unsigned long long GUA_U64;

#endif

#ifndef GUA_64

typedef signed long long GUA_64;

#endif

/*********************外部变量************************/

//设备信息结构体

typedef struct

{

GUA_U32 deviceSize; // bytes

GUA_U8 manfId;      // manufacturer ID

GUA_U8 devId;       // device ID

} GUA_ExtFlashInfo_t;

/*********************函数声明************************/

extern bool GUA_ExtFlash_open(void);

extern void GUA_ExtFlash_close(void);

extern bool GUA_ExtFlash_read(size_t GUA_offset, size_t GUA_length, GUA_U8 *pGUA_buf);

extern bool GUA_ExtFlash_write(size_t GUA_offset, size_t GUA_length, const GUA_U8 *pGUA_buf);

extern bool GUA_ExtFlash_erase(size_t GUA_offset, size_t GUA_length);

extern GUA_ExtFlashInfo_t *GUA_ExtFlash_info(void);

#endif

3、工程中添加驱动文件GUA_ExtFlash.c、GUA_ExtFlash.h

注:拖拽至CCS工程的Application文件夹下

添加文件过程中,选项选择如下

4、应用层调用

1)添加头文件(simple_peripheral.c中)

//GUA

#include “GUA_ ExtFlash.h”

//GUA

2)添加测试代码(simple_peripheral.c的SimpleBLEPeripheral_init函数末尾中)

//GUA

GUA_U32 GUA_offset = 0x012233;

GUA_U8 GUA_write_buf[7] = {‘o’,’p’,’e’,’n’,’g’,’u’,’a’};

GUA_U8 GUA_read_buf[7] = {0};

bool GUA_flash_Ret;

//初始化flash

GUA_flash_Ret = GUA_ExtFlash_open();

if(GUA_flash_Ret == true)

{

        //擦除flash

        GUA_flash_Ret = GUA_ExtFlash_erase(GUA_offset, sizeof(GUA_write_buf));

        if(GUA_flash_Ret == true)

        {

            //flash

            GUA_flash_Ret = GUA_ExtFlash_write(GUA_offset, sizeof(GUA_write_buf), GUA_write_buf);

            if(GUA_flash_Ret == true)

            {

                //flash

                GUA_flash_Ret = GUA_ExtFlash_read(GUA_offset, sizeof(GUA_read_buf), GUA_read_buf);

                if(GUA_flash_Ret == true)

                {

                    //读正确后关flash

                    GUA_ExtFlash_close();

                }

            }

        }

}

//GUA

上述代码,先将0x012233地址擦除7个字节,再写入7个字节“opengua”,再读出7个字节,判断是否读出的是“opengua”,以此来判断是否有正常写入。

八、注意事项

1、W25Q80的内存大小是1M,也就是0x100000,所以读、写、擦除的范围就是0~0x100000。

2、在写入之前,需要先擦除,否则会写入不成功。

3、本文驱动会与《香瓜CC2640R2F之LCD》冲突,因为都是使用SPI。如果只是想检测flash是否良好,可以在oled启动之前,测试一下flash再关闭。思路如下

//flash测试代码

//……

//oled初始化代码

//……

//GUA

//oled显示flash的好坏

if(GUA_flash_Ret == true)

{

        GUA_LCD_WriteString(“flash OK”, GUA_LCD_LINE7);

}

else

{

        GUA_LCD_WriteString(“flash error”, GUA_LCD_LINE7);

}

//GUA

九、实验结果

仿真并设置断点,查看读出的flash数据

可见读出的是“opengua”,与写入的数据一样,表示读写正常。

因此,实验成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/66347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光谱相机如何还原色彩

多光谱通道采集 光谱相机设有多个不同波段的光谱通道&#xff0c;可精确记录每个波长的光强信息。如 8 到 16 个甚至更多的光谱通道&#xff0c;每个通道负责特定波长范围的光信息记录。这使得相机能分辨出不同光谱组合产生的相同颜色感知&#xff0c;而传统相机的传感器通常只…

C# 获取PDF文档中的字体信息(字体名、大小、颜色、样式等

在设计和出版行业中&#xff0c;字体的选择和使用对最终作品的质量有着重要影响。然而&#xff0c;有时我们可能会遇到包含未知字体的PDF文件&#xff0c;这使得我们无法准确地复制或修改文档。获取PDF中的字体信息可以解决这个问题&#xff0c;让我们能够更好地处理这些文件。…

Shell正则表达式与文本处理三剑客(grep、sed、awk)

一、正则表达式 Shell正则表达式分为两种&#xff1a; 基础正则表达式&#xff1a;BRE&#xff08;basic regular express&#xff09; 扩展正则表达式&#xff1a;ERE&#xff08;extend regular express&#xff09;&#xff0c;扩展的表达式有、?、|和() 1.1 基本正则表…

arcgis提取不规则栅格数据的矢量边界

效果 1、准备数据 栅格数据:dem或者dsm 2、栅格重分类 分成两类即可 3、新建线面图层 在目录下选择预先准备好的文件夹,点击右键,选择“新建”→“Shapefile”,新建一个Shapefile文件。 在弹出的“新建Shapefile”对话框内“名称”命名为“折线”,“要素类型”选…

阿里云通义实验室自然语言处理方向负责人黄非:通义灵码2.0,迈入 Agentic AI

通义灵码是基于阿里巴巴通义大模型研发的AI 智能编码助手&#xff0c;在通义灵码 1.0 时代&#xff0c;我们针对代码的生成、补全和问答&#xff0c;通过高效果、低时延&#xff0c;研发出了国内最受欢迎的编码助手。 在通义灵码 2.0 发布会上&#xff0c;阿里云通义实验室自然…

Open3D 最小二乘拟合平面(直接求解法)【2025最新版】

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 博客长期更新,本文最近更新时间为:2025年1月18日。 一、算法原理 平面方程的一般表达式为:

超标量处理器设计2-cache

1. cache 介绍 影响Cache缺失的情况有3种&#xff1a; Compulsory: 第一次被访问的指令或者数据肯定不会在cache中&#xff0c;需要通过预取来减少这种缺失Capcity: Cache容量越大&#xff0c;缺失就可以更少, 程序频繁使用的三个数据来源于3个set&#xff0c; 但是&#xff…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…

vscode的安装与使用

下载 地址&#xff1a;https://code.visualstudio.com/ 安装 修改安装路径&#xff08;不要有中文&#xff09; 点击下一步&#xff0c;创建桌面快捷方式&#xff0c;等待安装 安装中文插件 可以根据自己的需要安装python和Jupyter插件

浅谈云计算19 | OpenStack管理模块 (上)

OpenStack管理模块&#xff08;上&#xff09; 一、操作界面管理架构二、认证管理2.1 定义与作用2.2 认证原理与流程2.2.1 认证机制原理2.2.2 用户认证流程 三、镜像管理3.1 定义与功能3.2 镜像服务架构3.3 工作原理与流程3.3.1 镜像存储原理3.3.2 镜像检索流程 四、计算管理4.…

彩色图像面积计算一般方法及MATLAB实现

一、引言 在数字图像处理中&#xff0c;经常需要获取感兴趣区域的面积属性&#xff0c;下面给出图像处理的一般步骤。 1.读入的彩色图像 2.将彩色图像转化为灰度图像 3.灰度图像转化为二值图像 4.区域标记 5.对每个区域的面积进行计算和显示 二、程序代码 %面积计算 cle…

分布式理解

分布式 如何理解分布式 狭义的分布是指&#xff0c;指多台PC在地理位置上分布在不同的地方。 分布式系统 分布式系**统&#xff1a;**多个能独立运行的计算机&#xff08;称为结点&#xff09;组成。各个结点利用计算机网络进行信息传递&#xff0c;从而实现共同的“目标或者任…

Red Hat8:搭建FTP服务器

目录 一、匿名FTP访问 1、新建挂载文件 2、挂载 3、关闭防火墙 4、搭建yum源 5、安装VSFTPD 6、 打开配置文件 7、设置配置文件如下几个参数 8、重启vsftpd服务 9、进入图形化界面配置网络 10、查看IP地址 11、安装ftp服务 12、遇到拒绝连接 13、测试 二、本地…

Re78 读论文:GPT-4 Technical Report

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名&#xff1a;GPT-4 Technical Report 官方博客&#xff1a;GPT-4 | OpenAI appendix懒得看了。 文章目录 1. 模型训练过程心得2. scaling law3. 实验结果减少风险 1. 模型训练过程心得 模型结构还…

推荐单通道有刷直流电机驱动芯片AT8236

单通道直流有刷电机驱动芯片AT8236 描述应用特点型号选择典型应用原理图管脚列表推荐工作条件 atT A 25C电气特性 atT A 25C,V M 24VH桥控制电流控制死区时间休眠模式过流保护 (OCP)过温保护 (TSD)欠压锁定保护(UVLO) PCB 版图建议典型应用示例 描述 AT8236是一款直流有刷电机…

聚铭网络6款产品入选CCIA《网络安全专用产品指南》

近日&#xff0c;中国网络安全产业联盟CCIA正式发布《网络安全专用产品指南》&#xff08;第二版&#xff09;&#xff08;以下简称《指南》&#xff09;。聚铭网络凭借突出技术优势、创新能力以及市场积累&#xff0c;旗下安全产品成功入选防火墙、网络安全审计、日志分析、网…

将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(1)

问题 项目里使用了 AzureBlob 存储了用户上传的各种资源文件&#xff0c;近期 AzureBlob 的流量费用增长很快&#xff0c;想通过分析Blob的日志&#xff0c;获取一些可用的信息&#xff0c;所以有了这个需求&#xff1a;将存储账户的日志&#xff08;读写&#xff0c;审计&…

ESP32S3基于espidf接入网络获取NTP时间

ESP32S3基于espidf接入网络获取NTP时间 &#x1f4cc; 相关篇《ESP32S3基于espidf接入网络配置介绍》&#x1f4cd;官方相关SNTP 时间同步介绍文档&#xff1a;https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-reference/system/system_time.html?highli…

【蓝桥杯选拔赛真题63】C++奇数 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解

目录 C++奇数 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、运行结果 五、考点分析 七、推荐资料 C++奇数 第十四届蓝桥杯青少年创意编程大赛C++选拔赛真题 一、题目要求 1、编程实现 给定两个正整数N和M(10≤N<M≤10000),请找出N到M…

(学习总结20)C++11 可变参数模版、lambda表达式、包装器与部分新内容添加

C11 可变参数模版、lambda表达式、包装器与部分新内容添加 一、可变参数模版基本语法及原理包扩展emplace系列接口 二、lambda表达式lambda表达式语法捕捉列表lambda的原理lambda的应用 三、包装器bindfunction 四、部分新内容添加新的类功能1.默认的移动构造和移动赋值2.声明时…