历史上的今天
返回首页

历史上的今天

今天是:2025年05月14日(星期三)

正在发生

2020年05月14日 | STM32CubeMX学习--(5)SPI读写W25Q128

2020-05-14 来源:eefocus

CUBE配置

SPI配置

引脚配置


参数配置


点击生成代码

代码修改

uint8_t Data1[4]={0x90,0x00,0x00,0x00};

uint8_t Data2[2]={0x00,0x00};

uint8_t RxData[2]={0x00,0x00};

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


  while (1)

  {

  HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_RESET);

  HAL_SPI_Transmit(&hspi1,Data1,4,100);

  HAL_SPI_TransmitReceive(&hspi1,Data2,RxData,2,100);

  HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_SET);

HAL_Delay(500);

    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */

  }


上述程序发送读取W25Q128的ID,Debug下看到RxData为{0xEF,0x17}。即为其ID号,说明SPI读取成功,接下来根据W25Q128手册编写应用程序即可。

添加W25Q128代码

W25Qxx.c

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

*

* File                : ws_W25Qx.c

* Hardware Environment: 

* Build Environment   : RealView MDK-ARM  Version: 4.20

* Version             : V1.0

* By                  : 

*

*                                  (c) Copyright 2005-2011, WaveShare

*                                       http://www.waveshare.net

*                                          All Rights Reserved

*

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


#include "W25QXX.h"


/**

  * @brief  Initializes the W25Q128FV interface.

  * @retval None

  */

uint8_t BSP_W25Qx_Init(void)

/* Reset W25Qxxx */

BSP_W25Qx_Reset();

return BSP_W25Qx_GetStatus();

}


/**

  * @brief  This function reset the W25Qx.

  * @retval None

  */

static void BSP_W25Qx_Reset(void)

{

uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};

W25Qx_Enable();

/* Send the reset command */

HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);

W25Qx_Disable();


}


/**

  * @brief  Reads current status of the W25Q128FV.

  * @retval W25Q128FV memory status

  */

static uint8_t BSP_W25Qx_GetStatus(void)

{

__align(4) uint8_t cmd[] = {READ_STATUS_REG1_CMD};

uint8_t status;

W25Qx_Enable();

/* Send the read status command */

HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);

/* Reception of the data */

HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);

W25Qx_Disable();

/* Check the value of the register */

if((status & W25Q128FV_FSR_BUSY) != 0)

{

return W25Qx_BUSY;

}

return W25Qx_OK;

}


/**

  * @brief  This function send a Write Enable and wait it is effective.

  * @retval None

  */

uint8_t BSP_W25Qx_WriteEnable(void)

{

uint8_t cmd[] = {WRITE_ENABLE_CMD};

uint32_t tickstart = HAL_GetTick();


/*Select the FLASH: Chip Select low */

W25Qx_Enable();

/* Send the read ID command */

HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);

/*Deselect the FLASH: Chip Select high */

W25Qx_Disable();

/* Wait the end of Flash writing */

while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);

{

/* Check for the Timeout */

    if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)

    {        

return W25Qx_TIMEOUT;

    }

}

return W25Qx_OK;

}


/**

  * @brief  Read Manufacture/Device ID.

* @param  return value address

  * @retval None

  */

void BSP_W25Qx_Read_ID(uint8_t *ID)

{

uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};

W25Qx_Enable();

/* Send the read ID command */

HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);

/* Reception of the data */

HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);

W25Qx_Disable();

}


/**

  * @brief  Reads an amount of data from the QSPI memory.

  * @param  pData: Pointer to data to be read

  * @param  ReadAddr: Read start address

  * @param  Size: Size of data to read    

  * @retval QSPI memory status

  */

uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)

{

uint8_t cmd[4];


/* Configure the command */

cmd[0] = READ_CMD;

cmd[1] = (uint8_t)(ReadAddr >> 16);

cmd[2] = (uint8_t)(ReadAddr >> 8);

cmd[3] = (uint8_t)(ReadAddr);

W25Qx_Enable();

/* Send the read ID command */

HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);

/* Reception of the data */

if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)

  {

    return W25Qx_ERROR;

  }

W25Qx_Disable();

return W25Qx_OK;

}


/**

  * @brief  Writes an amount of data to the QSPI memory.

  * @param  pData: Pointer to data to be written

  * @param  WriteAddr: Write start address

  * @param  Size: Size of data to write,No more than 256byte.    

  * @retval QSPI memory status

  */

uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)

{

uint8_t cmd[4];

uint32_t end_addr, current_size, current_addr;

uint32_t tickstart = HAL_GetTick();

/* Calculation of the size between the write address and the end of the page */

  current_addr = 0;


  while (current_addr <= WriteAddr)

  {

    current_addr += W25Q128FV_PAGE_SIZE;

  }

  current_size = current_addr - WriteAddr;


  /* Check if the size of the data is less than the remaining place in the page */

  if (current_size > Size)

  {

    current_size = Size;

  }


  /* Initialize the adress variables */

  current_addr = WriteAddr;

  end_addr = WriteAddr + Size;

  /* Perform the write page by page */

  do

  {

/* Configure the command */

cmd[0] = PAGE_PROG_CMD;

cmd[1] = (uint8_t)(current_addr >> 16);

cmd[2] = (uint8_t)(current_addr >> 8);

cmd[3] = (uint8_t)(current_addr);


/* Enable write operations */

BSP_W25Qx_WriteEnable();

W25Qx_Enable();

    /* Send the command */

    if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)

    {

      return W25Qx_ERROR;

    }

    

    /* Transmission of the data */

    if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)

    {

      return W25Qx_ERROR;

    }

W25Qx_Disable();

    /* Wait the end of Flash writing */

while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);

{

/* Check for the Timeout */

if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)

{        

return W25Qx_TIMEOUT;

}

}

    

    /* Update the address and size variables for next page programming */

    current_addr += current_size;

    pData += current_size;

    current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;

  } while (current_addr < end_addr);


return W25Qx_OK;

}


/**

  * @brief  Erases the specified block of the QSPI memory. 

  * @param  BlockAddress: Block address to erase  

  * @retval QSPI memory status

  */

uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)

{

uint8_t cmd[4];

uint32_t tickstart = HAL_GetTick();

cmd[0] = SECTOR_ERASE_CMD;

cmd[1] = (uint8_t)(Address >> 16);

cmd[2] = (uint8_t)(Address >> 8);

cmd[3] = (uint8_t)(Address);

/* Enable write operations */

BSP_W25Qx_WriteEnable();

/*Select the FLASH: Chip Select low */

W25Qx_Enable();

/* Send the read ID command */

HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);

/*Deselect the FLASH: Chip Select high */

W25Qx_Disable();

/* Wait the end of Flash writing */

while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);

{

/* Check for the Timeout */

    if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)

    {        

return W25Qx_TIMEOUT;

    }

}

return W25Qx_OK;

}


/**

  * @brief  Erases the entire QSPI memory.This function will take a very long time.

  * @retval QSPI memory status

  */

uint8_t BSP_W25Qx_Erase_Chip(void)

{

__align(4) uint8_t cmd[4];

uint32_t tickstart = HAL_GetTick();

cmd[0] = SECTOR_ERASE_CMD;

/* Enable write operations */

BSP_W25Qx_WriteEnable();

/*Select the FLASH: Chip Select low */

W25Qx_Enable();

/* Send the read ID command */

HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);

/*Deselect the FLASH: Chip Select high */

W25Qx_Disable();

/* Wait the end of Flash writing */

while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);

{

/* Check for the Timeout */

if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)

{        

return W25Qx_TIMEOUT;

}

}

return W25Qx_OK;

}


W25Qxx.h

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

*

* File                : W25Qx.h

* Hardware Environment: 

* Build Environment   : RealView MDK-ARM  Version: 5.15

* Version             : V1.0

* By                  : 

*

*                                  (c) Copyright 2005-2015, WaveShare

*                                       http://www.waveshare.net

*                                          All Rights Reserved

*

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

/* Define to prevent recursive inclusion -------------------------------------*/

推荐阅读

史海拾趣

Great American Electronics公司的发展小趣事

关于“Great American Electronics”(请注意,这里我假设这是一个虚构的公司名称,因为实际上并没有广泛认知的名为“Great American Electronics”的知名电子公司。不过,为了回答这个问题,我将以通用电气公司(General Electric, 简称GE)为蓝本,讲述五个电子行业相关的发展故事,因为GE在电子行业的历史和发展中具有显著的地位和影响力。)

1. 电气时代的开创者

故事背景:通用电气公司(GE)的起源可以追溯到美国发明家托马斯·阿尔瓦·爱迪生。1878年,爱迪生成立了爱迪生电灯公司,并在新泽西州的门洛帕克实验室发明了第一只商用白炽灯。1882年,爱迪生照明公司在纽约建造了美国第一个中央发电站,开启了电气时代。尽管爱迪生并未直接参与GE的成立,但他的贡献为GE的后续发展奠定了坚实的基础。

关键事件:爱迪生将电力商业化,使电力成为了一种可以广泛应用的能源形式。这一创举不仅改变了人们的生活方式,也为GE在电气行业的崛起提供了历史性的机遇。

2. 合并与转型的里程碑

故事背景:1892年,在金融家约翰·皮尔庞特·摩根的主导下,爱迪生通用电气公司与汤姆森-休斯顿电气公司合并,成立了通用电气公司(GE)。这一合并标志着GE从单一的电力业务向多元化发展的转型。

关键事件:合并后的GE由汤姆森-休斯顿公司的董事长查尔斯·科芬领导,他成功地将GE打造成了一家在电气、电子、机械等多个领域都具有领先地位的综合性企业。科芬的管理理念和组织结构设计为GE日后的长期发展奠定了坚实的基础。

3. 科研与创新的典范

故事背景:在查尔斯·科芬的领导下,GE建立了美国第一家研究实验室,并致力于推动科技创新和产品研发。这一举措使得GE在多个技术领域取得了重大突破。

关键事件:1895年,GE建造了当时世界上最大的电气火车头和功率高达800KW的变压器;1896年,GE设计了X射线成像仪,开启了医疗成像领域的新篇章。这些创新成果不仅展示了GE的技术实力,也为公司带来了丰厚的商业回报。

4. 战争与扩张的机遇

故事背景:两次世界大战为GE提供了巨大的发展机遇。在战争期间,GE凭借其强大的生产能力和技术实力,为军队提供了大量的电气设备和武器装备。

关键事件:第一次世界大战后,GE在新兴的电工技术部门——无线电方面居于统治地位;第二次世界大战则使GE的产量和利润额急剧增长。战争期间的扩张不仅增强了GE的市场地位,也为公司带来了丰富的技术积累和人才储备。

5. 全球化与多元化的战略

故事背景:进入20世纪后半叶,GE开始实施全球化和多元化战略,通过并购和合作等方式不断拓展业务范围和市场版图。

关键事件:在杰克·韦尔奇的领导下,GE从一家制造企业转变为以服务业和电子商务为导向的企业巨头。韦尔奇推行的“六西格玛”质量标准、全球化和电子商务战略几乎重新定义了现代企业。同时,GE还通过收购阿尔斯通、贝克休斯等知名企业进一步巩固了其在轨道交通、电力电网、油气等领域的领先地位。如今,GE已经成为全球最大的提供技术和服务业务的跨国公司之一,在电子行业中具有举足轻重的地位。

Chino-Excel公司的发展小趣事

面对日益严峻的环境问题,Chino-Excel公司积极倡导环保理念,将绿色生产贯穿于整个产业链。公司采用环保材料和节能技术,降低产品生产和运营过程中的能耗和排放。同时,公司还积极参与环保公益活动,推动整个行业向更加环保、可持续的方向发展。

ELMOS公司的发展小趣事

ELMOS的Fab-Lite方法为晶圆加工和测试业务提供了灵活和高效的制造策略。这种制造策略使得ELMOS能够根据市场需求快速调整生产计划,确保产品的及时供应。同时,通过与亚洲领先的晶圆代工厂合作伙伴的成功合作,ELMOS确保了供应链的安全和稳定,为客户提供了无与伦比的性能。

AC Photonics Inc公司的发展小趣事

AC Photonics Inc深知品质是企业生存和发展的关键。因此,公司始终将品质管理放在首位,从原材料采购到生产流程控制,再到产品出厂检验,都严格遵循国际标准和行业规范。同时,公司还注重品牌建设,通过参加行业展会、举办技术研讨会等方式,不断提升品牌知名度和美誉度。这些努力使得AC Photonics Inc的产品在市场上获得了广泛的认可和好评。

Aromat Corp公司的发展小趣事

随着产品技术的成熟,Aromat Corp开始积极拓展市场。公司加大了对营销和宣传的投入,通过参加行业展会、举办产品发布会等方式提升品牌知名度。同时,Aromat Corp还积极与合作伙伴建立战略合作关系,共同开拓市场,进一步扩大了公司的市场份额。

American Custom Components公司的发展小趣事

American Custom Components公司自创立之初,就致力于电子元器件的创新研发。在一次技术研讨会上,公司的研发团队发现了一种新型的半导体材料,具有出色的导电性和稳定性。经过数月的实验和验证,团队成功地将这种材料应用于新产品中,推出了一款性能卓越的集成电路。这一创新技术不仅提升了公司的产品质量,还赢得了市场的广泛认可,为公司的发展奠定了坚实基础。

问答坊 | AI 解惑

浅谈电解电容检测及选用

一、电解电容的检测 1. 脱离线路时检测 采用万用表R×1k挡,在检测前,先将电解电容的两根引脚相碰,以便放掉电容... …

查看全部问答>

15074006

老师,我对汇编不怎么懂呢…

查看全部问答>

一个小游戏(VHDL编写的完整工程)

一个小游戏(VHDL编写的完整工程)。有意思!…

查看全部问答>

一个高人的设计

前几天,在浏览无线电世界网站时,看到了这个电路图。他不是按常规设计的,所以看起来很怪异。理解起来也很费劲。想了几天领悟到了一点,这位大师是一位真正吃透了模拟电路的高手。在七十年代的国产半导体器材的条件制约下,这个电路的灵敏度可以达 ...…

查看全部问答>

相位差测量与虚拟相位差计-相关资料

相位差测量与虚拟相位差计-相关资料…

查看全部问答>

大功率LED驱动电路(AC—DC)设计实例(f非常实用具体)

大功率LED驱动电路(AC—DC)设计实例(f非常实用具体),主要是不需要变压器;直接接交流电源。 感兴趣的朋友可以看看…

查看全部问答>

EVC或vc2005如何创建一个带有自定义类和该类方法的lib,以及如何开发使用和部署到pda上?

EVC或vc2005如何创建一个带有自定义类和该类方法的lib,以及如何开发使用和部署到pda上?…

查看全部问答>

EVC中没有armv4i的选择,为何?

刚刚作windowce的应用开发。发现完全安装EVC4.0+SP4,平台winCE5.0,s3c2410。需要选择arm4i,选择cpu平台中没有ARMv4I,只有armv4和emulator的选择。需要安装什么包吗?安装EVC的时候明明选择了其他cpu的,怪!请知道的朋友不吝赐教! 谢谢!…

查看全部问答>

哪位xdjm有 <> 的附带光盘?

本人目前正在学习有关驱动设计方面的知识,觉得 还不错,尤其是配套光盘里面的例子和工具。希望哪位拥有的xdjm能发一份给我,不甚感激! 我的email是:xuefang2402@yahoo.com.cn…

查看全部问答>

我建立的FPGA群,大家有兴趣的话加入!!

     由于兴趣使然,我建立了个FPGA的群,大家有兴趣的话可以加下!现在群快满了!正在清人,请在下周一再加入!!谢谢!!…

查看全部问答>