STM32F407作为ST公司推出的高性能MCU,广泛应用于嵌入式系统的开发。它集成了丰富的外设接口,其中SPI(Serial Peripheral Interface)作为一种常见的高速串行通信协议,广泛应用于与传感器、存储设备等外设的通信。本文将详细介绍STM32F407的SPI通信功能及其代码实现。
实现功能本文将以SPI通信为例,实现STM32F407与外部SPI设备的通信,通过SPI接口向设备发送数据并接收返回的数据。本文的硬件连接以STM32F407与SPI Flash存储芯片W25Q64为例,演示如何与存储器进行数据读写。
硬件连接- STM32F407 MCU
- W25Q64 SPI Flash存储芯片
- SPI接口线:MISO、MOSI、SCK、CS
SPI的四根信号线分别与STM32的SPI引脚连接,CS作为片选信号,由GPIO控制。
软件开发环境- 开发工具:Keil uVision 5
- 编程语言:C语言
- 固件库:STM32 HAL库
代码实现#include "stm32f4xx_hal.h"
#include "spi.h"
#include "gpio.h"
// W25Q64 指令定义
#define WRITE_ENABLE 0x06
#define READ_DATA 0x03
#define WRITE_DATA 0x02
#define SECTOR_ERASE 0x20
#define W25Q64_CS_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
#define W25Q64_CS_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
// SPI发送一字节数据
void SPI_SendByte(uint8_t data)
{
HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
}
// SPI接收一字节数据
uint8_t SPI_ReceiveByte(void)
{
uint8_t data;
HAL_SPI_Receive(&hspi1, &data, 1, HAL_MAX_DELAY);
return data;
}
// 写使能
void W25Q64_WriteEnable(void)
{
W25Q64_CS_LOW();
SPI_SendByte(WRITE_ENABLE);
W25Q64_CS_HIGH();
}
// 读取数据
void W25Q64_ReadData(uint32_t addr, uint8_t* buffer, uint16_t len)
{
W25Q64_CS_LOW();
SPI_SendByte(READ_DATA);
SPI_SendByte((addr >> 16) & 0xFF);
SPI_SendByte((addr >> 8) & 0xFF);
SPI_SendByte(addr & 0xFF);
HAL_SPI_Receive(&hspi1, buffer, len, HAL_MAX_DELAY);
W25Q64_CS_HIGH();
}
// 写数据
void W25Q64_WriteData(uint32_t addr, uint8_t* buffer, uint16_t len)
{
W25Q64_WriteEnable();
W25Q64_CS_LOW();
SPI_SendByte(WRITE_DATA);
SPI_SendByte((addr >> 16) & 0xFF);
SPI_SendByte((addr >> 8) & 0xFF);
SPI_SendByte(addr & 0xFF);
HAL_SPI_Transmit(&hspi1, buffer, len, HAL_MAX_DELAY);
W25Q64_CS_HIGH();
}
void MX_SPI1_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;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置CS引脚
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 片选置高
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
uint8_t data_to_write[] = {0x12, 0x34, 0x56, 0x78};
uint8_t data_to_read[4];
// 写入数据到Flash存储器
W25Q64_WriteData(0x000000, data_to_write, sizeof(data_to_write));
// 读取数据
W25Q64_ReadData(0x000000, data_to_read, sizeof(data_to_read));
while (1)
{
// 可以在此处检查读取的数据
}
}
代码说明- SPI通信配置:代码通过HAL_SPI_Init配置SPI通信的模式、时钟频率等参数。在通信时,通过HAL_SPI_Transmit和HAL_SPI_Receive分别实现数据的发送和接收。
- Flash读写操作:通过W25Q64的读写指令,与存储器进行数据交互。写入数据前需调用W25Q64_WriteEnable函数启用写操作,数据读写以字节为单位。
- GPIO控制:CS(片选)引脚通过GPIO控制,用于指示当前的SPI操作。在每次操作前,将CS拉低,操作结束后将其拉高。
功能扩展- 数据校验:在写入数据后,可以实现CRC校验,确保数据的完整性。
- 多设备通信:SPI总线上可以挂载多个设备,只需为每个设备分配独立的CS引脚。
- 高速传输:可以调整SPI的波特率设置,实现更高速的数据传输,适用于大数据量的存储场景。
- 深度睡眠模式:STM32支持低功耗模式,可以在空闲时进入睡眠模式,进一步降低功耗。
总结STM32F407凭借其高性能和丰富的外设接口,特别是SPI接口,能够轻松与各种外部设备进行通信。本次例程通过SPI与W25Q64 Flash存储芯片的通信实现了数据的读写操作,展示了STM32的强大功能。开发者可以在此基础上,进一步扩展应用至多设备通信、数据校验等高级功能。
|