STM32F103 驱动SPI的串行FLASH

STM32F103C8T6 最小系统开发板驱动SPI串行FLASH

1. 硬件设计

1.1 最小系统开发板

STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,非常适合嵌入式开发。在本项目中,我们将使用STM32F103C8T6开发板与SPI串行FLASH进行通信。为了连接SPI串行FLASH,以下是连接方式:

STM32F103C8T6 引脚 串行FLASH 引脚 描述
PA5 SCK SPI时钟线
PA6 MISO SPI数据输入线
PA7 MOSI SPI数据输出线
PA4 CS SPI片选线
GND GND 地线
3.3V VCC 电源线

1.2 SPI协议原理

SPI(Serial Peripheral Interface)是一种同步串行通信协议,通常用于与外部设备(如串行FLASH存储器)进行数据交换。SPI协议通过四根线来传输数据:

  • SCK(Serial Clock):由主设备提供的时钟信号,用于同步数据传输。
  • MISO(Master In Slave Out):主设备接收数据的线,通常从外设向主设备传输数据。
  • MOSI(Master Out Slave In):主设备发送数据的线,通常从主设备传输数据到外设。
  • CS(Chip Select):选择目标设备,通常低电平激活。

本项目使用SPI协议与串行FLASH进行数据读写。

2. 软件设计

2.1 开发环境

  • 开发工具:STM32CubeMX、Keil uVision 5
  • 下载工具:ST-Link V2(用于将程序烧录到STM32开发板)
  • 固件库:STM32Cube HAL库

2.2 STM32CubeMX配置

  1. 打开STM32CubeMX,选择STM32F103C8T6芯片。
  2. 配置时钟、GPIO、SPI等外设:
    • 配置PA5为SPI时钟(SCK)。
    • 配置PA6为SPI数据输入(MISO)。
    • 配置PA7为SPI数据输出(MOSI)。
    • 配置PA4为SPI片选(CS)。
  3. 配置SPI为主模式,数据位宽为8位,时钟极性和相位根据串行FLASH的要求设置。
  4. 生成代码并打开Keil uVision 5。

2.3 驱动SPI串行FLASH的步骤

2.3.1 初始化SPI

首先,使用HAL_SPI_Init()函数初始化SPI外设:

/* SPI初始化代码 */
SPI_HandleTypeDef hspi1;

void SPI_Init(void)
{
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;
    HAL_SPI_Init(&hspi1);
}

2.3.2 SPI发送函数

接下来,定义一个函数来通过SPI发送数据。由于串行FLASH使用SPI进行通信,我们将创建一个发送数据的函数:

void SPI_Transmit(uint8_t* data, uint16_t size)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);  // 选择SPI外设(低电平激活)
    HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY);    // 发送数据
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);    // 取消选择SPI外设(高电平)
}

2.3.3 读取串行FLASH

为了读取串行FLASH中的数据,我们需要定义读取操作。这通常通过发送读取命令和地址,然后接收返回的数据实现:

void SPI_Receive(uint8_t* buffer, uint16_t size)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);  // 选择SPI外设(低电平激活)
    HAL_SPI_Receive(&hspi1, buffer, size, HAL_MAX_DELAY);   // 接收数据
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);    // 取消选择SPI外设(高电平)
}

2.3.4 读取FLASH ID

串行FLASH通常提供一个读取设备ID的命令。我们可以通过发送设备ID命令并接收返回的数据来验证与FLASH的通信:

void SPI_ReadFlashID(void)
{
    uint8_t cmd[1] = {0x9F};  // 读取Flash ID命令
    uint8_t id[3];

    SPI_Transmit(cmd, 1);      // 发送读取ID命令
    SPI_Receive(id, 3);        // 接收FLASH ID
    printf("Flash ID: %X %X %X\n", id[0], id[1], id[2]);
}

3. 示例代码

3.1 完整示例

#include "stm32f1xx_hal.h"
#include "main.h"

SPI_HandleTypeDef hspi1;

void SPI_Init(void);
void SPI_Transmit(uint8_t* data, uint16_t size);
void SPI_Receive(uint8_t* buffer, uint16_t size);
void SPI_ReadFlashID(void);

int main(void)
{
    HAL_Init();
    SPI_Init();

    SPI_ReadFlashID();

    while (1)
    {
        // 循环操作,进行其他串行FLASH操作
    }
}

3.2 注释

  1. SPI初始化:通过HAL_SPI_Init()函数初始化SPI,设置为主模式,数据位宽为8位,时钟极性和相位配置为与串行FLASH匹配。
  2. 发送和接收数据:使用HAL_SPI_Transmit()HAL_SPI_Receive()函数来发送和接收数据。通过SPI接口与串行FLASH进行通信。
  3. 读取FLASH ID:使用标准的读取ID命令(0x9F),读取串行FLASH的ID并输出。

4. 下载工具

stlink

使用ST-Link V2将程序烧录到STM32F103C8T6开发板。通过ST-Link V2调试接口连接到开发板,并使用Keil uVision 5的下载功能将程序烧录到微控制器中。

5. 结语

本博客介绍了如何使用STM32F103C8T6最小系统开发板和HAL固件库,通过SPI协议驱动串行FLASH存储器。通过详细的硬件连接、SPI协议原理、软件设计和示例代码,您可以实现与串行FLASH的基本通信。希望本博客对您的项目开发有所帮助。

posted @ 2025-02-07 15:33  jeikerxiao  阅读(261)  评论(0)    收藏  举报