#天空星硬件SPI驱动GD25Q32

本文围绕STM32与GD25Q32芯片展开,介绍了使用方式及接线、操作方法。详细阐述了GD25Q32芯片的特点、内存分配、相关指令,还介绍了SPI协议的概述、模式。最后说明了编程部分,包括读取芯片ID,编写便于移植的SPI和GD25Q32代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、使用方式及接线:

硬件SPI,软件片选CS(PA4)

STM32F407(主机)

GD25Q32(从机)

说明

PA4(SPI1_NSS)

CS(NSS)

片选线

PA5(SPI1_SCK)

CLK

时钟线

PA6(SPI_MISO)

DO(IO1)(MISO)

主机输入从机输出线

PA7(SPI_MOSI)

DI(IO0)(MOSI)

主机输出从机输入线

二、操作:

写入一串数据(嘉立创)

GD25Q32E-Rev1.3 (szlcsc.com)https://atta.szlcsc.com/upload/public/pdf/source/20240402/EEA34CC25AEF519FAE78D6FF38362CF4.pdf

三、GD25Q32简介

1.简介

GD25Q32是一种常见的串行闪存器件,它采用SPI(Serial Peripheral Interface)接口协议,具有高速读写和擦除功能,可用于存储和读取数据。GD25Q32芯片容量为32 Mbit(4 MB),其中名称后的数字代表不同的容量选项。不同的型号和容量选项可以满足不同应用的需求,通常被用于嵌入式设备、存储设备、路由器等高性能电子设备中。

GD25Q32闪存芯片的内存分配是按照扇区(Sector)和块(Block)进行的,每个扇区的大小为4KB,每个块包含16个扇区,即一个块的大小为64KB

2.技术手册

3cd21d3727bf45bc833efbb58ebcbf0d.png 

3.主要参数

芯片容量每颗芯片块数量每个块大小每块扇区数量每个扇区大小
32Mbit(4MB)6464KB164KB

a3d2628bb3314ae3bb69e0f839701ef6.png

3.芯片相关指令

3.1读ID

f11f7af7f71544eca4e79cd76bc19349.png

//读取芯片ID          
//读取设备ID
uint16_t GD25Q32_readID(void)
{
    uint16_t  temp = 0;     
    //将CS端拉低为低电平     
    W25QXX_CS_ON(0);        
    //发送指令90h    
    spi_read_write_byte(0x90);//发送读取ID命令      
    //发送地址  000000H    
    spi_read_write_byte(0x00);             
    spi_read_write_byte(0x00);             
    spi_read_write_byte(0x00); 
        
    //接收数据
    //接收制造商ID
    temp |= spi_read_write_byte(0xFF)<<8;  
    //接收设备ID
    temp |= spi_read_write_byte(0xFF);        
    //恢复CS端为高电平
    W25QXX_CS_ON(1);      
    //返回ID                  
    return temp;
}

3.2写使能

ecaed66ecb72429b980f8271785522f5.png

//发送写使能
void GD25Q32_write_enable(void)   
{
    //拉低CS端为低电平
    W25QXX_CS_ON(0);                          
    //发送指令06h
    spi_read_write_byte(0x06);                  
    //拉高CS端为高电平
    W25QXX_CS_ON(1);
}                                          

 3.3忙碌状态

在GD25Q322的数据手册中,有3个状态寄存器,可以判断当前GD25Q32是否正在传输、写入、读取数据等,我们每一次要对GD25Q32进行操作时,需要先判断GD25Q32是否在忙。如果在忙的状态,我们去操作GD25Q32,很可能会导致数据丢失,并且操作失败。而判断是否忙,是通过状态寄存器1的S0为进行判断,状态寄存器1的地址为0X05。

读取状态寄存器的时序图如下:

  1. 拉低CS端为低电平;

  2. 发送指令05h(0000_0101);

  3. 接收状态寄存器值;

  4. 恢复CS端为高电平;

9d2886385a6c49b199b2d82bb4f37085.png

/**********************************************************
 * 函 数 名 称:GD25Q32_wait_busy
 * 函 数 功 能:检测线路是否繁忙
 * 传 入 参 数:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_wait_busy(void)   
{   
    unsigned char byte = 0;
    do
     { 
        //拉低CS端为低电平
        W25QXX_CS_ON(0); 
        //发送指令05h                           
        spi_read_write_byte(0x05);                
        //接收状态寄存器值
        byte = spi_read_write_byte(0Xff);       
        //恢复CS端为高电平
        W25QXX_CS_ON(1);      
     //判断BUSY位是否为1 如果为1说明在忙,重新读写BUSY位直到为0   
     }while( ( byte & 0x01 ) == 1 );  
}

 3.4扇区擦除

发送写使能->CS拉低->擦除扇区命令(20H)->三字节(24位)地址->CS拉高

326f6c2245bd471da667baf5c1202851.png

/**********************************************************
 * 函 数 名 称:GD25Q32_erase_sector
 * 函 数 功 能:擦除一个扇区
 * 传 入 参 数:addr=擦除的扇区号
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:addr=擦除的扇区号,范围=0~15
**********************************************************/
void GD25Q32_erase_sector(uint32_t addr)   
{
        //计算扇区号,一个扇区4KB=4096
        addr *= 4096;
        GD25Q32_write_enable();  //写使能   
        GD25Q32_wait_busy();     //判断忙,如果忙则一直等待
        //拉低CS端为低电平
        W25QXX_CS_ON(0);  
        //发送指令20h                                     
        spi_read_write_byte(0x20);
        //发送24位扇区地址的高8位                
        spi_read_write_byte((uint8_t)((addr)>>16));      
        //发送24位扇区地址的中8位    
        spi_read_write_byte((uint8_t)((addr)>>8));   
        //发送24位扇区地址的低8位    
        spi_read_write_byte((uint8_t)addr);
        //恢复CS端为高电平  
        W25QXX_CS_ON(1);                  
        //等待擦除完成                                                  
        GD25Q32_wait_busy();   
}

3.5 写入数据

CS拉低--》写入数据命令(0X02)--》3个字节地址(24bit)--》写入至少一个字节--》CS拉高

b9c7d9dae9614579906aa0c4238a5d70.png

/**********************************************************
 * 函 数 名 称:GD25Q32_write
 * 函 数 功 能:写数据到GD25Q32进行保存
 * 传 入 参 数:buffer=写入的数据内容        addr=写入地址        numbyte=写入数据的长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_write(uint8_t* buffer, uint32_t addr, uint16_t numbyte)
{    
    unsigned int i = 0;
    //擦除扇区数据
    GD25Q32_erase_sector(addr/4096);
    //写使能 
    GD25Q32_write_enable();  
    //忙检测  
    GD25Q32_wait_busy();    
    //写入数据
    //拉低CS端为低电平
    W25QXX_CS_ON(0);         
    //发送指令02h                              
    spi_read_write_byte(0x02);                 
    //发送写入的24位地址中的高8位   
    spi_read_write_byte((uint8_t)((addr)>>16));  
    //发送写入的24位地址中的中8位
    spi_read_write_byte((uint8_t)((addr)>>8));   
    //发送写入的24位地址中的低8位
    spi_read_write_byte((uint8_t)addr);   
    //根据写入的字节长度连续写入数据buffer
    for(i=0;i<numbyte;i++)
    {
        spi_read_write_byte(buffer[i]);  
    }
    //恢复CS端为高电平
    W25QXX_CS_ON(1);
    //忙检测 
    GD25Q32_wait_busy();      
}

3.6读取数据

CS拉低-》发送读取命令0X03-》发送24位地址

dc49be4ee0e74327a36ee22d6875198f.png

/**********************************************************
 * 函 数 名 称:GD25Q32_read
 * 函 数 功 能:读取GD25Q32的数据
 * 传 入 参 数:buffer=读出数据的保存地址  read_addr=读取地址   read_length=读去长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_read(uint8_t* buffer,uint32_t read_addr,uint16_t read_length)   
{ 
        uint16_t i;                   
        //拉低CS端为低电平
        W25QXX_CS_ON(0);    
        //发送指令03h        
        spi_read_write_byte(0x03);  
        //发送24位读取数据地址的高8位                         
        spi_read_write_byte((uint8_t)((read_addr)>>16));     
        //发送24位读取数据地址的中8位      
        spi_read_write_byte((uint8_t)((read_addr)>>8));   
        //发送24位读取数据地址的低8位
        spi_read_write_byte((uint8_t)read_addr);   
        //根据读取长度读取出地址保存到buffer中
        for(i=0;i<read_length;i++)
        { 
            buffer[i]= spi_read_write_byte(0XFF);  
        }
        //恢复CS端为高电平
        W25QXX_CS_ON(1);                                    
}

四、SPI介绍 

1.上面所述的FLASH芯片的SPI模式

7bc2f27112564653b11e191720f580ce.png

2.SPI概述 

 

在SPI协议中,主设备是通信的发起方和控制方,而从设备则是被动接收和响应主设备的命令和数据。主设备通过时钟信号来同步数据传输,同时使用多个双向数据线来实现数据的传输和接收。

SPI协议是一种全双工通信方式,意味着主设备和从设备可以同时发送和接收数据。它还使用一种选择信号(通常称为片选或使能信号),用于选择与主设备进行通信的特定从设备。

3.SPI模式

SPI协议定义了多种传输模式,也称为SPI模式或时序模式,用于控制数据在时钟信号下的传输顺序和数据采样方式。SPI的传输模式主要由两个参数决定:时钟极性 (CKPL) 和相位 (CKPH)。 时钟极性 (CKPL):时钟极性定义了时钟信号在空闲状态时的电平。

CKPL = 0:时钟信号在空闲状态时为低电平。

CKPL = 1:时钟信号在空闲状态时为高电平。

时钟相位 (CKPH):相位定义了数据采样和更新发生在时钟信号的哪个边沿上。

CKPH = 0:数据采样发生在时钟的第一个边沿,数据更新发生在第二个边沿。

CKPH = 1:数据采样发生在时钟的第二个边沿,数据更新发生在第一个边沿。

以下是常见的SPI模式:

  1. 模式0(CKPL=0,CKPH=0):

- 时钟极性(Clock Polarity)为0,表示时钟空闲状态为低电平。

- 时钟相位(Clock Phase)为0,表示数据在时钟信号的第一个边沿(时钟上升沿)进行采样和稳定。

  1. 模式1(CKPL=0,CKPH=1):

- 时钟极性为0,时钟空闲状态为低电平。

- 时钟相位为1,数据在时钟信号的第二个边沿(时钟下降沿)进行采样和稳定。

  1. 模式2(CKPL=1,CKPH=0):

- 时钟极性为1,时钟空闲状态为高电平。

- 时钟相位为0,数据在时钟信号的第一个边沿(时钟下降沿)进行采样和稳定。

  1. 模式3(CKPL=1,CKPH=1):

- 时钟极性为1,时钟空闲状态为高电平。

- 时钟相位为1,数据在时钟信号的第二个边沿(时钟上升沿)进行采样和稳定。

 GD25Q32手册中指出模式0和模式3都是支持的,如下配置即为模式三

dbdfc5c664ee425eb83bfe348bd15a51.png

 五、编程

1.先读取ID,我贴的GD25Q32ESIG芯片ID为C815

bbbb0d0519d048c69ebbac905b03aa7e.png

/*
 * 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
 * 开发板官网:www.lckfb.com
 * 技术支持常驻论坛,任何技术问题欢迎随时交流学习
 * 立创论坛:club.szlcsc.com
 * 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
 * 不靠卖板赚钱,以培养中国工程师为己任
 */
#include "board.h"
#include "bsp_uart.h"
#include "stdio.h"
#include "sys.h"

#define CS_HIGH GPIO_SetBits(GPIOA,GPIO_Pin_4)
#define CS_LOW GPIO_ResetBits(GPIOA,GPIO_Pin_4)
/*
 *初始化SPI的GPIO
 *PA4--SPI1_NSS
 *PA5--SPI1_SCK
 *PA6--SPI1_MISO
 *PA7--SPI1_MOSI
 */
void SpiGpio_Init(void)
{
//1.1复用GPIO
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);
//1.2初始化GPIO PA4 PA5 PA6 PA7
	GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

	/*配置MISO*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*配置MOSI*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*配置CS*/	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
//1.3拉高CS
  CS_HIGH;
}

/*
 *初始化SPI1
 */
void Spi_Init(void)
{
	//2.1初始化gpio
   SpiGpio_Init();
	//2.2配置Spi
	SPI_InitTypeDef SPI_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
	SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;  //84MHZ/4=21MHZ
	SPI_InitStruct.SPI_CPHA=SPI_CPHA_2Edge; //第二个边沿有效
	SPI_InitStruct.SPI_CPOL=SPI_CPOL_High;  //高电平有效
	SPI_InitStruct.SPI_CRCPolynomial= 7;     
	SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b; //单位数据大小1个字节
	SPI_InitStruct.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工
	SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;  //高位先行
	SPI_InitStruct.SPI_Mode=SPI_Mode_Master; //主机
	SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;   //软件选择CS
	SPI_Init(SPI1,&SPI_InitStruct);
	SPI_Cmd(SPI1,ENABLE);
}

/*
 *spi发送一个字节
 */
uint8_t spi_read_write_byte(uint8_t dat)
{
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);  //等待发送完毕
	SPI_I2S_SendData(SPI1,dat);
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET); //等待接收到数据
	return SPI_I2S_ReceiveData(SPI1);
}

/*
 *获取芯片ID和设备ID
 */
uint16_t GD25Q32_readID(void)
{
uint16_t id=0;     //要做移位操作必须初始化!!!
CS_LOW;
spi_read_write_byte(0x90);  //读芯片ID指令
spi_read_write_byte(0x00);
spi_read_write_byte(0x00);
spi_read_write_byte(0x00);	
id |= spi_read_write_byte(0xff)<<8;
id |= spi_read_write_byte(0xff);
CS_HIGH;
return id;
}

int main(void)
{

        board_init();
        uart1_init(115200);
	    Spi_Init();

        while(1)
        {       
			    printf("man_id is %X",GD25Q32_readID());
                delay_ms(1000);
        }
}

 2.spi编写为便于移植

spi.c


#include "spi.h"

/*
 *初始化SPI的GPIO
 *PA4--SPI1_NSS
 *PA5--SPI1_SCK
 *PA6--SPI1_MISO
 *PA7--SPI1_MOSI
 */
void SpiGpio_Init(void)
{
//1.1复用GPIO
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);
//1.2初始化GPIO PA4 PA5 PA6 PA7
	GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

	/*配置MISO*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*配置MOSI*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*配置CS*/	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
//1.3拉高CS
  CS_HIGH;
}

/*
 *初始化SPI1
 */
void Spi_Init(void)
{
	//2.1初始化gpio
   SpiGpio_Init();
	//2.2配置Spi
	SPI_InitTypeDef SPI_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
	SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;  //84MHZ/4=21MHZ
	SPI_InitStruct.SPI_CPHA=SPI_CPHA_2Edge; //第二个边沿有效
	SPI_InitStruct.SPI_CPOL=SPI_CPOL_High;  //空闲状态为高电平
	SPI_InitStruct.SPI_CRCPolynomial= 7;     
	SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b; //单位数据大小1个字节
	SPI_InitStruct.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工
	SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;  //高位先行
	SPI_InitStruct.SPI_Mode=SPI_Mode_Master; //主机
	SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;   //软件选择CS
	SPI_Init(SPI1,&SPI_InitStruct);
	SPI_Cmd(SPI1,ENABLE);
}

/*
 *spi发送一个字节
 */
uint8_t spi_read_write_byte(uint8_t dat)
{
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);  //等待发送完毕
	SPI_I2S_SendData(SPI1,dat);
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET); //等待接收到数据
	return SPI_I2S_ReceiveData(SPI1);
}

spi.h 

#ifndef _SPI_H
#define _SPI_H
#include "board.h"

#define CS_HIGH GPIO_SetBits(GPIOA,GPIO_Pin_4)
#define CS_LOW GPIO_ResetBits(GPIOA,GPIO_Pin_4)

void SpiGpio_Init(void);
void Spi_Init(void);
uint8_t spi_read_write_byte(uint8_t dat);

#endif

 3.gd25q32

gd25q32.c

#include "gd25q32.h"
#include "spi.h"

/*
 *获取芯片ID和设备ID
 */
uint16_t GD25Q32_readID(void)
{
uint16_t id=0;     //要做移位操作必须初始化!!!
CS_LOW;
spi_read_write_byte(0x90);  //读芯片ID指令
spi_read_write_byte(0x00);
spi_read_write_byte(0x00);
spi_read_write_byte(0x00);	
id |= spi_read_write_byte(0xff)<<8;
id |= spi_read_write_byte(0xff);
CS_HIGH;
return id;
}

//发送写使能
void GD25Q32_write_enable(void)   
{
    //拉低CS端为低电平
    CS_LOW;                          
    //发送指令06h
    spi_read_write_byte(0x06);                  
    //拉高CS端为高电平
    CS_HIGH;
}

/**********************************************************
 * 函 数 名 称:GD25Q32_wait_busy
 * 函 数 功 能:检测线路是否繁忙
 * 传 入 参 数:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_wait_busy(void)   
{   
    unsigned char byte = 0;
    do
     { 
        //拉低CS端为低电平
        CS_LOW; 
        //发送指令05h                           
        spi_read_write_byte(0x05);                
        //接收状态寄存器值
        byte = spi_read_write_byte(0Xff);       
        //恢复CS端为高电平
        CS_HIGH;      
     //判断BUSY位是否为1 如果为1说明在忙,重新读写BUSY位直到为0   
     }while( ( byte & 0x01 ) == 1 );  
}

/**********************************************************
 * 函 数 名 称:GD25Q32_erase_sector
 * 函 数 功 能:擦除一个扇区
 * 传 入 参 数:addr=擦除的扇区号
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:addr=擦除的扇区号,范围=0~15
**********************************************************/
void GD25Q32_erase_sector(uint32_t addr)   
{
        //计算扇区号,一个扇区4KB=4096
        addr *= 4096;
        GD25Q32_write_enable();  //写使能   
        GD25Q32_wait_busy();     //判断忙,如果忙则一直等待
        //拉低CS端为低电平
        CS_LOW;  
        //发送指令20h                                     
        spi_read_write_byte(0x20);
        //发送24位扇区地址的高8位                
        spi_read_write_byte((uint8_t)((addr)>>16));      
        //发送24位扇区地址的中8位    
        spi_read_write_byte((uint8_t)((addr)>>8));   
        //发送24位扇区地址的低8位    
        spi_read_write_byte((uint8_t)addr);
        //恢复CS端为高电平  
        CS_HIGH;                  
        //等待擦除完成                                                  
        GD25Q32_wait_busy();   
}

/**********************************************************
 * 函 数 名 称:GD25Q32_write
 * 函 数 功 能:写数据到GD25Q32进行保存
 * 传 入 参 数:buffer=写入的数据内容        addr=写入地址        numbyte=写入数据的长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_write(uint8_t* buffer, uint32_t addr, uint16_t numbyte)
{    
    unsigned int i = 0;
    //擦除扇区数据
    GD25Q32_erase_sector(addr/4096);
    //写使能 
    GD25Q32_write_enable();  
    //忙检测  
    GD25Q32_wait_busy();    
    //写入数据
    //拉低CS端为低电平
    CS_LOW;         
    //发送指令02h                              
    spi_read_write_byte(0x02);                 
    //发送写入的24位地址中的高8位   
    spi_read_write_byte((uint8_t)((addr)>>16));  
    //发送写入的24位地址中的中8位
    spi_read_write_byte((uint8_t)((addr)>>8));   
    //发送写入的24位地址中的低8位
    spi_read_write_byte((uint8_t)addr);   
    //根据写入的字节长度连续写入数据buffer
    for(i=0;i<numbyte;i++)
    {
        spi_read_write_byte(buffer[i]);  
    }
    //恢复CS端为高电平
    CS_HIGH;
    //忙检测 
    GD25Q32_wait_busy();      
}

/**********************************************************
 * 函 数 名 称:GD25Q32_read
 * 函 数 功 能:读取GD25Q32的数据
 * 传 入 参 数:buffer=读出数据的保存地址  read_addr=读取地址   read_length=读去长度
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
**********************************************************/
void GD25Q32_read(uint8_t* buffer,uint32_t read_addr,uint16_t read_length)   
{ 
        uint16_t i;                   
        //拉低CS端为低电平
        CS_LOW;    
        //发送指令03h        
        spi_read_write_byte(0x03);  
        //发送24位读取数据地址的高8位                         
        spi_read_write_byte((uint8_t)((read_addr)>>16));     
        //发送24位读取数据地址的中8位      
        spi_read_write_byte((uint8_t)((read_addr)>>8));   
        //发送24位读取数据地址的低8位
        spi_read_write_byte((uint8_t)read_addr);   
        //根据读取长度读取出地址保存到buffer中
        for(i=0;i<read_length;i++)
        { 
            buffer[i]= spi_read_write_byte(0XFF);  
        }
        //恢复CS端为高电平
        CS_HIGH;                                    
}

gd25q32.h

#ifndef _GD25Q32_H
#define _GD25Q32_H
#include "gd25q32.h"
#include "board.h"

uint16_t GD25Q32_readID(void);
void GD25Q32_write_enable(void);
void GD25Q32_wait_busy(void);
void GD25Q32_erase_sector(uint32_t addr);
void GD25Q32_write(uint8_t* buffer, uint32_t addr, uint16_t numbyte);
void GD25Q32_read(uint8_t* buffer,uint32_t read_addr,uint16_t read_length);

#endif

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值