stm32固件库SPI操作

发布者:SereneVoyage最新更新时间:2025-01-15 来源: jianshu关键字:stm32  固件库  SPI操作 手机看文章 扫描二维码
随时随地手机看文章

野火25Q128.JPG

'''
/* Private typedef -----------------------------------------------------------*/
//#define  sFLASH_ID                       0xEF3015     //W25X16
//#define  sFLASH_ID                       0xEF4015     //W25Q16
//#define  sFLASH_ID                        0XEF4017     //W25Q64


define  sFLASH_ID                       0XEF4018     //W25Q128

//#define SPI_FLASH_PageSize            4096

define SPI_FLASH_PageSize              256

define SPI_FLASH_PerWritePageSize      256

/* Private define ------------------------------------------------------------/
/命令定义-开头*******************************/

define W25X_WriteEnable              0x06

define W25X_WriteDisable             0x04

define W25X_ReadStatusReg          0x05

define W25X_WriteStatusReg       0x01

define W25X_ReadData                   0x03

define W25X_FastReadData             0x0B

define W25X_FastReadDual             0x3B

define W25X_PageProgram              0x02

define W25X_BlockErase               0xD8

define W25X_SectorErase              0x20

define W25X_ChipErase                0xC7

define W25X_PowerDown                0xB9

define W25X_ReleasePowerDown     0xAB

define W25X_DeviceID                   0xAB

define W25X_ManufactDeviceID       0x90

define W25X_JedecDeviceID          0x9F

define WIP_Flag                  0x01  /* Write In Progress (WIP) flag */

define Dummy_Byte                0xFF

/*命令定义-结尾*******************************/

/*SPI接口定义-开头****************************/

define FLASH_SPI                           SPI1

define FLASH_SPI_CLK                       RCC_APB2Periph_SPI1

define FLASH_SPI_CLK_INIT                  RCC_APB2PeriphClockCmd

define FLASH_SPI_SCK_PIN                   GPIO_Pin_3

define FLASH_SPI_SCK_GPIO_PORT             GPIOB

define FLASH_SPI_SCK_GPIO_CLK              RCC_AHB1Periph_GPIOB

define FLASH_SPI_SCK_PINSOURCE             GPIO_PinSource3

define FLASH_SPI_SCK_AF                    GPIO_AF_SPI1

define FLASH_SPI_MISO_PIN                  GPIO_Pin_4

define FLASH_SPI_MISO_GPIO_PORT            GPIOB

define FLASH_SPI_MISO_GPIO_CLK             RCC_AHB1Periph_GPIOB

define FLASH_SPI_MISO_PINSOURCE            GPIO_PinSource4

define FLASH_SPI_MISO_AF                   GPIO_AF_SPI1

define FLASH_SPI_MOSI_PIN                  GPIO_Pin_5

define FLASH_SPI_MOSI_GPIO_PORT            GPIOB

define FLASH_SPI_MOSI_GPIO_CLK             RCC_AHB1Periph_GPIOB

define FLASH_SPI_MOSI_PINSOURCE            GPIO_PinSource5

define FLASH_SPI_MOSI_AF                   GPIO_AF_SPI1

define FLASH_CS_PIN                        GPIO_Pin_6

define FLASH_CS_GPIO_PORT                  GPIOG

define FLASH_CS_GPIO_CLK                   RCC_AHB1Periph_GPIOG

define SPI_FLASH_CS_LOW()      {FLASH_CS_GPIO_PORT->BSRRH=FLASH_CS_PIN;}

define SPI_FLASH_CS_HIGH()     {FLASH_CS_GPIO_PORT->BSRRL=FLASH_CS_PIN;}

/*SPI接口定义-结尾****************************/

/等待超时时间/

define SPIT_FLAG_TIMEOUT         ((uint32_t)0x1000)

define SPIT_LONG_TIMEOUT         ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))

/信息输出/


define FLASH_DEBUG_ON         1

define FLASH_INFO(fmt,arg...)           printf('<<-FLASH-INFO->> 'fmt'n',##arg)

define FLASH_ERROR(fmt,arg...)          printf('<<-FLASH-ERROR->> 'fmt'n',##arg)

define FLASH_DEBUG(fmt,arg...)          do{

if(FLASH_DEBUG_ON)

printf('<<-FLASH-DEBUG->> [%d]'fmt'n',__LINE__, ##arg);

}while(0)


==============================
static __IO uint32_t  SPITimeout = SPIT_LONG_TIMEOUT;

static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);

/**

  • @brief  SPI_FLASH初始化

  • @param  无

  • @retval 无
    */
    void SPI_FLASH_Init(void)
    {
    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

/* 使能 FLASH_SPI 及GPIO 时钟 /
/!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO,
SPI_FLASH_SPI_MISO_GPIO,SPI_FLASH_SPI_SCK_GPIO 时钟使能 */
RCC_AHB1PeriphClockCmd (FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK|FLASH_SPI_MOSI_GPIO_CLK|FLASH_CS_GPIO_CLK, ENABLE);

/*!< SPI_FLASH_SPI 时钟使能 */
FLASH_SPI_CLK_INIT(FLASH_SPI_CLK, ENABLE);

//设置引脚复用
GPIO_PinAFConfig(FLASH_SPI_SCK_GPIO_PORT,FLASH_SPI_SCK_PINSOURCE,FLASH_SPI_SCK_AF);
GPIO_PinAFConfig(FLASH_SPI_MISO_GPIO_PORT,FLASH_SPI_MISO_PINSOURCE,FLASH_SPI_MISO_AF);
GPIO_PinAFConfig(FLASH_SPI_MOSI_GPIO_PORT,FLASH_SPI_MOSI_PINSOURCE,FLASH_SPI_MOSI_AF);

/*!< 配置 SPI_FLASH_SPI 引脚: SCK */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);


/*!< 配置 SPI_FLASH_SPI 引脚: MISO */

GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);


/*!< 配置 SPI_FLASH_SPI 引脚: MOSI */

GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);


/*!< 配置 SPI_FLASH_SPI 引脚: CS */

GPIO_InitStructure.GPIO_Pin = FLASH_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(FLASH_CS_GPIO_PORT, &GPIO_InitStructure);

/* 停止信号 FLASH: CS引脚高电平*/
SPI_FLASH_CS_HIGH();

/* FLASH_SPI 模式配置 */
// FLASH芯片 支持SPI模式0及模式3,据此设置CPOL CPHA
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(FLASH_SPI, &SPI_InitStructure);

/* 使能 FLASH_SPI  */
SPI_Cmd(FLASH_SPI, ENABLE);

}

/**

  • @brief  擦除FLASH扇区

  • @param  SectorAddr:要擦除的扇区地址

  • @retval 无
    /
    void SPI_FLASH_SectorErase(u32 SectorAddr)
    {
    / 发送FLASH写使能命令 /
    SPI_FLASH_WriteEnable();
    SPI_FLASH_WaitForWriteEnd();
    / 擦除扇区 /
    / 选择FLASH: CS低电平 /
    SPI_FLASH_CS_LOW();
    / 发送扇区擦除指令/
    SPI_FLASH_SendByte(W25X_SectorErase);
    /发送擦除扇区地址的高位/
    SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
    / 发送擦除扇区地址的中位 /
    SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
    / 发送擦除扇区地址的低位 /
    SPI_FLASH_SendByte(SectorAddr & 0xFF);
    / 停止信号 FLASH: CS 高电平 /
    SPI_FLASH_CS_HIGH();
    / 等待擦除完毕*/
    SPI_FLASH_WaitForWriteEnd();
    }

/**

  • @brief  擦除FLASH扇区,整片擦除

  • @param  无

  • @retval 无
    /
    void SPI_FLASH_BulkErase(void)
    {
    / 发送FLASH写使能命令 */
    SPI_FLASH_WriteEnable();

/* 整块 Erase /
/ 选择FLASH: CS低电平 /
SPI_FLASH_CS_LOW();
/ 发送整块擦除指令/
SPI_FLASH_SendByte(W25X_ChipErase);
/ 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();

/* 等待擦除完毕*/
SPI_FLASH_WaitForWriteEnd();
}

/**

  • @brief  对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区

  • @param  pBuffer,要写入数据的指针

  • @param WriteAddr,写入地址

  • @param  NumByteToWrite,写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize

  • @retval 无
    /
    void SPI_FLASH_PageWrite(u8 pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    {
    /* 发送FLASH写使能命令 */
    SPI_FLASH_WriteEnable();

/* 选择FLASH: CS低电平 /
SPI_FLASH_CS_LOW();
/ 写页写指令/
SPI_FLASH_SendByte(W25X_PageProgram);
/发送写地址的高位/
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/发送写地址的中位/
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/发送写地址的低位*/
SPI_FLASH_SendByte(WriteAddr & 0xFF);

if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
{
NumByteToWrite = SPI_FLASH_PerWritePageSize;
FLASH_ERROR('SPI_FLASH_PageWrite too large!');
}

/* 写入数据/
while (NumByteToWrite--)
{
/ 发送当前要写入的字节数据 /
SPI_FLASH_SendByte(pBuffer);
/* 指向下一字节数据 */
pBuffer++;
}

/* 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();

/* 等待写入完毕*/
SPI_FLASH_WaitForWriteEnd();
}

/**

  • @brief  对FLASH写入数据,调用本函数写入数据前需要先擦除扇区

  • @param  pBuffer,要写入数据的指针

  • @param  WriteAddr,写入地址

  • @param  NumByteToWrite,写入数据长度

  • @retval 无
    /
    void SPI_FLASH_BufferWrite(u8 pBuffer, u32 WriteAddr, u16 NumByteToWrite)
    {
    u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

    /mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0/
    Addr = WriteAddr % SPI_FLASH_PageSize;

    /差count个数据值,刚好可以对齐到页地址/
    count = SPI_FLASH_PageSize - Addr;
    /计算出要写多少整数页/
    NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
    /mod运算求余,计算出剩余不满一页的字节数/
    NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

    /* Addr=0,则WriteAddr 刚好按页对齐 aligned  /
    if (Addr == 0)
    {
    / NumByteToWrite < SPI_FLASH_PageSize /
    if (NumOfPage == 0)
    {
    SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
    }
    else / NumByteToWrite > SPI_FLASH_PageSize /
    {
    /先把整数页都写了*/
    while (NumOfPage--)
    {
    SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
    WriteAddr +=  SPI_FLASH_PageSize;
    pBuffer += SPI_FLASH_PageSize;
    }

[1] [2]
关键字:stm32  固件库  SPI操作 引用地址:stm32固件库SPI操作

上一篇:STM32一文通(5) 中断概览
下一篇:L1 Keil5-MDK创建STM32工程

推荐阅读最新更新时间:2026-03-13 11:12

stm32固件库SPI操作
野火25Q128.JPG ''' /* Private typedef -----------------------------------------------------------*/ //#define sFLASH_ID 0xEF3015 //W25X16 //#define sFLASH_ID 0xEF4015 //W25Q16 //#define sFLASH_ID 0XEF4017 //W25Q64 define sFLASH_ID 0XEF4018 //W25Q128 //#d
[单片机]
STM32自学之SPI的DMA操作(寄存器级)
STM32自学之SPI的DMA操作(寄存器级) 一、实验目标 学会配置STM32的SPI寄存器和DMA寄存器,实现STM32的SPI1与SPI2通信功能,每次发送一字节数据,并可多次发送,如果接收的数据正确,则点亮LED灯。之后看可以利用DMA来实现什么功能~~~ 二、实验目的 加入DMA的SPI通信相对于普通SPI通信有什么好处?ST给SPI加了DMA功能出于什么目的?我觉得这是很重要的一个问题,一直边学习边想。以下是我的看法: 减少CPU负荷?我想这应该是DMA最主要的功能,可是对于SPI通信来说,其实大部分时候我们需要根据发送的指令- 目标器件的应答来决定下一个指令,所以此时CPU还是需要一直等待每次通信的结束。而且
[单片机]
<font color='red'>STM32</font>自学之<font color='red'>SPI</font>的DMA<font color='red'>操作</font>(寄存器级)
STM32使用SPI总线对外部Flash的操作
标开发板:原子 STM32F103RBT6 SPI: 四根线 MISO, MOSI, SCLK, CS 是高速,全双工,通信总线。读写同时进行,如果只想写,只需忽略读。 如果要读,只需发送一个空字节来引发从机的传输。 FLASH:W25X16 STM32 下面SPI 使用步骤: 1。初始化片选 CS 2. 初始化 MISO, MOSI, SCLK 3. 初始化 SPI_InitStructure 结构体 4. SPI_Cmd(SPI1, ENABLE); //使能SPI外设 5. SPIx_ReadWriteByte(0xff);//启动传输 STM32 下面 Flash 操作步骤
[单片机]
初识STM32固件库——我们认为管件库应该是什么样子的
一、STM32固件库文件分析 汇编编写的启动文件startup_stm32f10x_hd.s 设置堆栈指针 设置PC指 初始化中断向量表 配置系统时钟 对用C库函数 __main最终去到C的世界 时钟配置文件 system_stm32f10x.c:将外部时钟HSE=8M,经过PLL倍频为72M 外设相关的(xx:GPIO UART I2C SPI FSMC) stm32f10x.h:实现内核之外的外设寄存器映射 stm32f10x_xx.h存放外设的初始化结构体、外设初始化结构体成员的参数列表、外设固件库的函数声明 stm32f10x_xx.c外设驱动函数库文件 内和相关的 core_c
[单片机]
STM32系列MCU,写寄存器Or利用固件库
写在开头的话: 最近心血来潮,打算重新捡起老本行,结果发现很多都忘记了。干脆重新开始学习,并做个从零开始的笔记了。 STM32系列MCU STM32系列芯片包括F0/F1/F2/F3/F4/F7/L0/L1/L4/H7等系列芯片芯片。不同系列的芯片适用于不同的应用场景。F0/L0基于ARM Cortex®-M0,F1/F2/L1系列基于ARM Cortex®-M3,F3/F4/L4系列基于ARM Cortex®-M4,F7/H7基于ARM Cortex®-M7。L系列表示超低功耗,H表示超高性能(对应就是高功耗了),F就是个折中方案了,性能不错,功耗也不高。 其他的先不管,F1系列芯片主要分类如下: ·超值型STM32F100
[单片机]
<font color='red'>STM32</font>系列MCU,写寄存器Or利用<font color='red'>固件库</font>
基于STM32调用固件库实现点灯
相信学过单片机的同学,对于调库这个操作都不陌生,大多数人都是从调别人的库阶段过来的。 今天看到一个评论说,如果只会调库,到了公司后会发现自己啥都不是。其实这话说的一点也不假,如果只会调库的话,你的单片机水平还停留在C语言阶段,并不能称为真正的单片机开发。 但我们要有这么一个概念:调库是自己编写的开始,如果上来就给你讲寄存器这些,我相信很多初学者都接收不了、理解不了这写寄存器到底在干啥。可是,如果从调别人库开始学习单片机,我们就会对单片机有个初始概念,对于后面的学习非常有帮助。 所以,今天我们就来看一下如何从调库工程师成为真正的开发工程师。 1. 什么是调库? 如果你通过机构的培训视频,比如野火的STM32单片机开
[单片机]
基于<font color='red'>STM32</font>调用<font color='red'>固件库</font>实现点灯
STM32固件库使用USART
1.USART的配置 (1)关键结构体 GPIO_InitTypeDef USART_InitTypeDef NVIC_InitTypeDef//用于接收的中断 1.1USART的TX在PA9,RX在PA10. 2.时钟线 2.1 USART时钟挂载在APB2上 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//配时钟 3.代码段 3.1(单发送) void usart_init(void){ GPIO_InitTypeDef gpio_
[单片机]
STM32固件库实现按键控制
前言 使用固件库实现按键控制LED 一、原理图 从按键的原理图可知,这些按键在没有被按下的时候,GPIO 引脚的输入状态为低电平(按键所在的电路不通,引脚接地),当按键按下时,GPIO 引脚的输入状态为高电平(按键所在的电路导通,引脚接到电源)。只要我们检测引脚的输入电平,即可判断按键是否被按下。 电容的作用:利用电容充放电的延时,消除了波纹,起到消抖功能。 二、软件设计 在“工程”上新建“bsp_key.c”及“bsp_key.h”文件,这些文件不属于STM32 标准库的内容,是由我们自己根据应用需要编写的,编程步骤如下: 使能 GPIO 端口时钟; 初始化 GPIO 目标引脚为输入模式(浮空输入); 编写简
[单片机]
<font color='red'>STM32</font><font color='red'>固件库</font>实现按键控制
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved