目录
SPI外设
与I2C外设一样,STM32芯片也集成了专门用于SPI协议通讯的外设。
STM32 的 SPI 外设可用作通讯的主机及从机,支持最高的 SCK 时钟频率为 fpclk/2 (STM32F103 型号的芯片默认fpclk1为36MHz,fpclk2为72MHz。),完全支持 SPI 协议的 4 种模式,数据帧长度可设置为 8 位或 16 位,可设置数据 MSB 先行或 LSB 先行。它还支持双线全双工、双线单向以及单线模式。
STM32F103系列提供了3个SPI,SPI1挂在APB2总线,SPI2/3挂在APB1总线。
其中双线单向模式可以同时使用 MOSI 及 MISO 数据线向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这样速率会受到影响。
用的比较多还是双线全双工模式。
SPI外设框图
因为NSS只有一个,如果需要其他设备的话解决办法就是:
禁用NSS,用GPIO引脚配置通用推挽,让其和SPI相连,用其进行控制SPI
需求描述
基于寄存器操作,使用SPI功能,完成Flash的读写。
硬件电路设计
相关寄存器
SPI_CR1:spi控制寄存器
MSTR:主设备选择
BR:波特率控制
CPOL:时钟极性
CPHA: 时钟相位
DFF:数据帧格式
SSI:内部从设备选择
LSBFIRST:帧格式
SSM:软件从设别管理
SSI:内部从设备管理
SPE:SPI使能
SPI_DR 数据寄存器
16位
SPI_SR:状态寄存器
TXE:发送缓冲为空
RXNE:接收缓冲非空
文字说明:
spi.h
#ifndef __SPI_H__
#define __SPI_H__
#include "stm32f10x.h"
#define CS_HIGH (GPIOC->ODR |= GPIO_ODR_ODR13)
#define CS_LOW (GPIOC->ODR &= ~ GPIO_ODR_ODR13)
void SPI_Init(void);
void SPI_Start(void);
void SPI_Stop(void);
uint8_t SPI_SwapByte(uint8_t byte);
#endif /* __SPI_H__ */
spi.c
#include "spi.h"
void SPI_Init(void){
// 1. GPIOA
// 1.1 先放时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 1.2 PA5 时钟 复用推挽
GPIOA->CRL &= ~GPIO_CRL_CNF5_0;
GPIOA->CRL |= GPIO_CRL_CNF5_1;
GPIOA->CRL |= GPIO_CRL_MODE5;
// 1.3 PA6 输入信号 浮空输入
GPIOA->CRL &= ~GPIO_CRL_CNF6_1;
GPIOA->CRL |= GPIO_CRL_CNF6_0;
GPIOA->CRL &= ~GPIO_CRL_MODE6;
// 1.4 PA7 数据输出 复用推挽
GPIOA->CRL &= ~GPIO_CRL_CNF7_0;
GPIOA->CRL |= GPIO_CRL_CNF7_1;
GPIOA->CRL |= GPIO_CRL_MODE7;
// 2. GPIOC
// 2.1 放GPIOC的时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
CS_HIGH;
// 2.2. PC13 片选使能信号 通用推挽
GPIOC->CRH &= ~GPIO_CRH_CNF13;
GPIOC->CRH |= GPIO_CRH_MODE13;
//配置硬件SPI
//0.1放时钟
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
//0.2 设置DFF位来定义8位或者16位数据格式 当前8位
SPI1->CR1 &= ~SPI_CR1_DFF;
//0.3 设置高位优先
SPI1->CR1 &= ~SPI_CR1_LSBFIRST;
//0.4 工作模式为主模式
SPI1->CR1 |= SPI_CR1_MSTR;
//0.5 波特率的配置 APB2 72M 如果是 000 就是2分频 36M
SPI1->CR1 &= ~SPI_CR1_BR;
//0.6 mode0 模式
SPI1->CR1 &= ~SPI_CR1_CPOL;
SPI1->CR1 &= ~SPI_CR1_CPHA;
//0.7 SSOE 配0 这样的话 会关闭SS引脚的输出 同时 会被迫进入
//多主模式(NSS 会变成一个输入引脚)
SPI1->CR2 &= ~SPI_CR2_SSOE;
//0.8 NSS 进入软件模式
// SSM 配1 那就是NSS信号 由SSI位来决定
SPI1->CR1 |= SPI_CR1_SSM;
// SSI 配1 再多主模式里 一直处于可通讯状态
SPI1->CR1 |= SPI_CR1_SSI;
// 使能位
SPI1->CR1 |= SPI_CR1_SPE;
}
void SPI_Start(void){
CS_LOW;
}
void SPI_Stop(void){
CS_HIGH;
}
uint8_t SPI_SwapByte(uint8_t byte){
while (!(SPI1->SR & SPI_SR_TXE))
{
}
SPI1->DR = byte;
while (!(SPI1->SR & SPI_SR_RXNE))
{
}
uint8_t receive_byte = SPI1->DR;
return receive_byte;
}
W25Q32.h
#include "spi.h"
其他不变
标签:CR1,进阶,void,Flash,STM32,SPI,SPI1,GPIO,CRL From: https://blog.csdn.net/qq_64219867/article/details/144407606