你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32C0评测】驱动SPI_Flash:W25Q128

[复制链接]
lugl 发布时间:2025-5-5 16:41

【前言】

虽然stm32c092rct6的flash是大尺寸,但是如果需要放置其他大容易的文件,比如文件系统等,spi_flash还是一个重要的补充,这篇文章将分享如何驱动W25Q128。

1、w25q128:

image.png

他是最大支持104MHz的时钟总线,我们的spi的时钟总线,最大是48MHz因此是可以完全可以适配的。

2、选择sp1做为输出接口,CS片选设置为PA8,在stm32cubeMX中配置如下:

image.png

3、移植开源的spi_flash代码如下:

#include "spi_flash.h"

extern SPI_HandleTypeDef hspi1;

uint8_t spiflash_sector_buf[SPIF_SECTOR_SIZE];


uint8_t spi1_writedat(uint8_t txdata)
{
    uint8_t rxdata;
    HAL_SPI_TransmitReceive(&hspi1, &txdata, &rxdata, 1, 1000);
    return rxdata;
}

void init_spi(void)
{
    FLASH_CS_HIGH();
    spi1_writedat(0xFF);
}

/**
  * @brief  spi configuration.
  * @param  none
  * @retval none
  */
void spiflash_init(void)
{
    init_spi();
}

/**
  * @brief  write data to flash
  * @param  pbuffer: the pointer for data buffer
  * @param  write_addr: the address where the data is written
  * @param  length: buffer length
  * @retval none
  */
void spiflash_write(uint8_t *pbuffer, uint32_t write_addr, uint32_t length)
{
  uint32_t sector_pos;
  uint16_t sector_offset;
  uint16_t sector_remain;
  uint16_t index;
  uint8_t *spiflash_buf;
  spiflash_buf = spiflash_sector_buf;

  /* sector address */
  sector_pos = write_addr / SPIF_SECTOR_SIZE;

  /* address offset in a sector */
  sector_offset = write_addr % SPIF_SECTOR_SIZE;

  /* the remain in a sector */
  sector_remain = SPIF_SECTOR_SIZE - sector_offset;
  if(length <= sector_remain)
  {
    /* smaller than a sector size */
    sector_remain = length;
  }
  while(1)
  {
    /* read a sector */
    spiflash_read(spiflash_buf, sector_pos * SPIF_SECTOR_SIZE, SPIF_SECTOR_SIZE);

    /* validate the read erea */
    for(index = 0; index < sector_remain; index++)
    {
      if(spiflash_buf[sector_offset + index] != 0xFF)
      {
        /* there are some data not equal 0xff, so this secotr needs erased */
        break;
      }
    }
    if(index < sector_remain)
    {
      /* erase the sector */
      spiflash_sector_erase(sector_pos);

      /* copy the write data */
      for(index = 0; index < sector_remain; index++)
      {
        spiflash_buf[index + sector_offset] = pbuffer[index];
      }
      spiflash_write_nocheck(spiflash_buf, sector_pos * SPIF_SECTOR_SIZE, SPIF_SECTOR_SIZE); /* program the sector */
    }
    else
    {
      /* write directly in the erased area */
      spiflash_write_nocheck(pbuffer, write_addr, sector_remain);
    }
    if(length == sector_remain)
    {
      /* write end */
      break;
    }
    else
    {
      /* go on writing */
      sector_pos++;
      sector_offset = 0;

      pbuffer += sector_remain;
      write_addr += sector_remain;
      length -= sector_remain;
      if(length > SPIF_SECTOR_SIZE)
      {
        /* could not write the remain data in the next sector */
        sector_remain = SPIF_SECTOR_SIZE;
      }
      else
      {
        /* could write the remain data in the next sector */
        sector_remain = length;
      }
    }
  }
}

/**
  * @brief  read data from flash
  * @param  pbuffer: the pointer for data buffer
  * @param  read_addr: the address where the data is read
  * @param  length: buffer length
  * @retval none
  */
void spiflash_read(uint8_t *pbuffer, uint32_t read_addr, uint32_t length)
{
  FLASH_CS_LOW();
  spi_byte_write(SPIF_READDATA); /* send instruction */
  spi_byte_write((uint8_t)((read_addr) >> 16)); /* send 24-bit address */
  spi_byte_write((uint8_t)((read_addr) >> 8));
  spi_byte_write((uint8_t)read_addr);
  spi_bytes_read(pbuffer, length);
  FLASH_CS_HIGH();
}

在spi_flash.h中定义片选如下:

#define FLASH_CS_HIGH()                 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET)
#define FLASH_CS_LOW()                  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET)

3、在主程序中添加初始化与测试代码:

  /* USER CODE BEGIN 2 */
        spiflash_init();

        flash_id_index = spiflash_read_id();
        if(flash_id_index !=0xEF17)
        {
            printf("flash id check error!\r\n");
        }
        else
        {
            printf("flash id check success! id: %x\r\n", flash_id_index);
        }
        printf("Write Data: ");
        for(i = 0; i < SPI_BUF_SIZE; i++)
        {
            tx_buffer[i] = 255-i;
            printf("%x ", tx_buffer[i]);
        }

        spiflash_sector_erase(FLASH_TEST_ADDR / SPIF_SECTOR_SIZE);
        spiflash_write(tx_buffer, FLASH_TEST_ADDR, SPI_BUF_SIZE);
        spiflash_read(rx_buffer, FLASH_TEST_ADDR, SPI_BUF_SIZE);
        printf("\r\n ");
        printf("Read Data: ");
        for(i = 0; i < SPI_BUF_SIZE; i++)
        {
            printf("%x ", rx_buffer[i]);
        }
  /* USER CODE END 2 */

实现效果,使用串口查看写入与写出:

image.png

可见初始化,写入、写出是对的。到此成功的驱动了spi的flash w25q128。

image.png
收藏 评论0 发布时间:2025-5-5 16:41

举报

0个回答

所属标签

ST中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版