stm32使用SPI写W25Q32

SPI.h

#ifndef __SPI_H
#define __SPI_H


#include "stm32f10x.h"

#define SPI_CS_H GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define SPI_CS_L GPIO_ResetBits(GPIOB, GPIO_Pin_12)

#define SPI_SCK_H GPIO_SetBits(GPIOB, GPIO_Pin_13)
#define SPI_SCK_L GPIO_ResetBits(GPIOB, GPIO_Pin_13)

#define SPI_MISO_H GPIO_SetBits(GPIOB, GPIO_Pin_14)
#define SPI_MISO_L GPIO_ResetBits(GPIOB, GPIO_Pin_14)

#define SPI_MOSI_H GPIO_SetBits(GPIOB, GPIO_Pin_15)
#define SPI_MOSI_L GPIO_ResetBits(GPIOB, GPIO_Pin_15)

#define READDATALENGTH 255

void SPI_GPIO_Init(void);
uint8_t SPI_WriteRead_Byte(uint8_t byte);



void Write_Enable(void);
void Write_Disable(void);
uint8_t Read_StatusR1(void);
uint8_t* Read_Data(uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t num2read);


void Page_Program(uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t *data);
void Sector_Erase(void);

#endif

SPI.C

#include "spi.h"



void SPI_GPIO_Init(void)
{
    
    //SPI2-NSS PB12:PIN25 --CS
    //SPI2-SCK PB13:PIN26
    //SPI2-MISO PB14:PIN27     W25Q32:DO
    //SPI2-MOSI PB15:PIN28     W25Q32:DI

    GPIO_InitTypeDef    GPIO_InitStruct;  
    SPI_InitTypeDef    SPI_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStruct);
    SPI_CS_H;
//    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
//    
//    GPIO_Init(GPIOB, &GPIO_InitStruct);

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStruct.SPI_CRCPolynomial = 7;
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
    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;

    SPI_Init(SPI2, &SPI_InitStruct);

    SPI_Cmd(SPI2, ENABLE);


}

uint8_t SPI_WriteRead_Byte(uint8_t byte)
{
    SPI_I2S_SendData(SPI2, byte);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    return SPI_I2S_ReceiveData(SPI2);
}

void Write_Enable(void)
{
    SPI_CS_L;
    SPI_WriteRead_Byte(0x06); //set WEL bit 1
    SPI_CS_H;

}

//一般不需要调用,编程或是擦除操作,WEL会自动清零
void Write_Disable(void)
{
    SPI_CS_L;
    SPI_WriteRead_Byte(0x04); //set WEL bit 0
    SPI_CS_H;
}

//判断忙标志
uint8_t Read_StatusR1(void)
{
     uint8_t res = 0;

     SPI_CS_L;
     SPI_WriteRead_Byte(0x05); //S0 BUSY bit 1: busy ;    S0 BUSY bit 0: free ;
     res = SPI_WriteRead_Byte(0x05);

     SPI_CS_H;
     if((res & 0x01)== 0x01)
     {
         return 1;
     }
     else
     {
         return 0;
     }
}

//读1/2个字节数据
uint8_t* Read_Data(uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t num2read)
{
    
    
    static uint8_t res[READDATALENGTH] = {0};

    uint8_t i = 0;

    SPI_CS_L;
    SPI_WriteRead_Byte(0x03);
    SPI_WriteRead_Byte(addr2);
    SPI_WriteRead_Byte(addr1);
    SPI_WriteRead_Byte(addr0);

    for(i = 0; i < num2read; i ++)
    {
        res[i] = SPI_WriteRead_Byte(0xff);    
    }
    
    SPI_CS_H;
    return res;
}

void Page_Program(uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t *data)
{
      Write_Enable();
      SPI_CS_L;
      SPI_WriteRead_Byte(0x02);//02H页写

      SPI_WriteRead_Byte(addr2);//设定写入数据的起始地址
      SPI_WriteRead_Byte(addr1);
      SPI_WriteRead_Byte(addr0);

//      SPI_WriteRead_Byte(data[0]);//1个字节数据
//      SPI_WriteRead_Byte(data[1]);

      while(*data != '\0')
      {
              SPI_WriteRead_Byte(*data);
            data ++;
      }
      SPI_CS_H;
}

void Sector_Erase(void)
{
    Write_Enable();
    SPI_CS_L;
    SPI_WriteRead_Byte(0x20);//20H扇区擦除

    SPI_WriteRead_Byte(0x00);//擦除的数据的起始地址
    SPI_WriteRead_Byte(0x00);
    SPI_WriteRead_Byte(0x00);

    SPI_CS_H;
}

MAIN.C

#include "stm32f10x.h"
#include "spi.h"

uint8_t val[4] = {0};
uint8_t *p;
//uint8_t send[4] = {0xa8, 0x8a, 0x55, 0xaa};
uint8_t *send = "hello, world";

int main(void)
{
    SPI_GPIO_Init();

    SPI_CS_L;
    
    SPI_WriteRead_Byte(0X90);
    SPI_WriteRead_Byte(0X90);
    SPI_WriteRead_Byte(0X90);
    SPI_WriteRead_Byte(0X00);
    val[0] = SPI_WriteRead_Byte(0X90);
    val[1] = SPI_WriteRead_Byte(0X90);
    
    SPI_CS_H;    

    Sector_Erase();
    while(Read_StatusR1());

    Page_Program(0x0, 0x0, 0x0, send);
    while(Read_StatusR1());

    p = Read_Data(0x0, 0x0, 0x0, 12);
    

    while(1);
}

主要学习数组作为参数传递,函数返回数组

posted @ 2025-11-11 20:19  了解2号  阅读(0)  评论(0)    收藏  举报