STM32F103之SPI硬件读写W25Q64

一、简介

SPI(Serial Peripheral Interface)串行外设接口总线(SPI)最早由Motorola首先提出,采用主从模式(Master—Slave)架构,支持一个或多个Slave设备;广泛应用于MCU和外设模块如E2PROM、ADC、显示驱动器等的连接。

1.1 特点

<1>通信接口特性:全双工、同步、串行
<2>SPI通信接口有4个引脚:MOSI,MISO,SCLK,NSS
       MOSI(Master Out Slave In):主机输出从机输入(发送端口) - USART_TX(相当于)
       MISO(Master In Slave Out):主机输入从机输出(接收端口) - USART_RX(相当于)
       SCLK/SCK/SCL:                  时钟线,时钟信号只能由主机发出---同步
       NSS/CS(Chip Select):         片选引脚(低电平有效,等价于从机的通信开关)
<3>SPI接口支持SPI协议、IIS协议;默认为SPI协议
<4>通信校验:CRC校验(由于短距离传输,干扰信号少,一般不用校验)
<5>8或16位传输帧格式选择、数据低位优先发送或高位优先发送、可编程的时钟极性和相位
<6>硬件SPI的最大的时钟频率、通信速度为18Mhz;有八种预分频系数

1.2 资源 

SPI资源
SM32F103ZET6,SPI接口数量为3个【SPI1,SPI2,SP3】
SPI1->APB2(72MHZ)、SPI2->APB1(36MHZ)、SPI3->APB1(36MHZ)
SPI挂在不同的72MHz/36MHz时钟线上,须经过分频且最后的传输速率不超过18MHz

SPI端口配置

SPI引脚

1.3 框图

主从机连接

主机连接了2个从机
如果主机想要和Slave1进行通信,则只需要在通信前将CS1引脚拉低选中从机1即可通信;
如果主机想要和Slave2进行通信,则只需要在通信前将CS2引脚拉低选中从机2即可通信;
注意:当有多个从机连接一个主机时,由于同一个从机输出连接在一个,如果同时开启会造成冲突,所以当从机未被选中前,从机的MISO引脚必须为高阻态       

系统框图

SPI只有一个移位寄存器,所以数据从移位寄存器移出数据后,也必须移入数据到移位寄存器
当MCU作为主机时
    ①发送的数据从移位寄存器通过MO口发出;同时接受的数据通过MI口进入移位寄存器
当MCU作为从机时
    ② 发送的数据从移位寄存器通过SO口发出;同时接受的数据通过SI口进入移位寄存器      

SPI系统框图

 接发逻辑

当MCU作为主机时 要发送0x78(设置低位先发送),则往发送缓冲区中写入0x78
第一个时钟周期,将0x78的第0位通过MOSI口移出,通过MISO口移入1个bit到移位寄存器
第二个时钟周期,将0x78的第1位通过MOSI口移出,再通过MISO口移入1个bit到移位寄存器
到第八个时钟周期,将0x78的第7位通过MOSI口移出,再通过MISO口移入1个bit到移位寄存器
0x78发送完后,移位寄存器一共接收到8位后,将这八位加载到接收缓冲区

二、时序传输

 根据CPOL位与CPHA位的不同组合会有四种时序逻辑

模式0
CPOL=0,CPHA=0
空闲时时钟为低电平,
在时钟的第一个边沿移入数据(或进行采样输入)
在时钟的第二个边沿移出数据
模式1
CPOL=0,CPHA=1
空闲时时钟为低电平,
在时钟的第一个边沿移出数据,
在时钟的第二个边沿移入数据(或进行采样输入)

模式2

CPOL=1,CPHA=0

空闲时时钟为高电平,
在时钟的第一个边沿移入数据(或进行采样输入)
在时钟的第二个边沿移出数据

模式3

CPOL=1,CPHA=1

空闲时时钟为高电平,
在时钟的第一个边沿移出数据,
在时钟的第二个边沿移入数据(或进行采样输入)

 模式0:CPOL=0,CPHA=0时序图(最常用)

 对于模式0,时钟空闲时为低电平,规定高位发送
对于CPHA=0,则第一个上升沿主机输入数据,但是想要输入数据就必须先要发送数据,所以说当SS为下降沿时主机通过MOSI发送高位数据 ,从机通过MOSI发送高位数据;当SCK第一个时钟沿时主机通过MOSI发送高位数据 ,从机通过MOSI发送高位数据

 模式1:CPOL=0,CPHA=1时序图

对于模式1,时钟空闲时为低电平,规定高位发送
当上升沿时,主机通过MOSI发送高位数据 ,从机通过MOSI发送高位数据
当下升沿时,主机通过MISO进行采样接收数据 ,从机通过MISO进行采样接收数据

主模式、全双工、连续传输

在这里重点需要看两个关键的标志位发送寄存器为空标志位(TXE),接收标志位非空标志位(RXNE)
当TXE=1时,说明发送缓冲区为空,表示可以发数据了;这时0xF1进入发送缓冲区,发送缓冲区的0xF1进入移位寄存器,此时发送缓冲区又变为空,这时0xF2可以进入发送缓冲区等待移位寄存器变为空;当0xF1输出完时,相应的主机也接收完了,此时的接收缓冲区为非空,当RXNE=1,时表示可以读数据了

/****************************
*@brief   SPI数据交换
*@param  void
*@return   void
*@note     void
*@time  2025-6-29
******************************/
int8_t HardWare_SPI_Dataswap(uint8_t Send_Data)
{
	
	while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==0) ;//TXE=1时,说明发送缓冲区为空,表示可以发数据了
	SPI_I2S_SendData(SPI2, Send_Data)                      ;

	while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==0);//RXNE=1时,说明接受缓冲区为非空,表示可以读数据了
	
	return SPI_I2S_ReceiveData(SPI2)                       ; 
}

 三、 硬件SPI读写W25Q64

虽然W25Q64可支持SPI最大频率为80MHz,但开发板的硬件SPI支持的最大速率为18MHz;软件模式SPI的引脚与硬件SPI引脚配置不同

/****************************
*@brief    SPI引脚初始化
*@param  void
*@return   void
*@note     
    PB13->CLK推挽复用输出
 		PB14->MISO->DO浮空或上拉
		PB12->CS  软件控制,推挽输出
		PB15->MOSI->DI推挽复用输出
   
		36MHz
*@time  2025-6-29
******************************/
void HardWare_SPI_Init(void)
{
	/*1.打开IO引脚、SPI2时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
	
	/*2.引脚模式配置*/
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP                    ;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15             ;//输出配置为推挽复用输出
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz                  ;
	GPIO_Init(GPIOB,&GPIO_InitStruct)                            ;
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU                      ;//输入配置为浮空输入
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14                         ;
	GPIO_Init(GPIOB,&GPIO_InitStruct)                            ;
	
	/*3.SPI初始化*/
	SPI_InitTypeDef SPI_InitStruct;
  SPI_InitStruct.SPI_BaudRatePrescaler  =SPI_BaudRatePrescaler_2         ;//二分频,18MHz
	SPI_InitStruct.SPI_CPHA               =SPI_CPHA_1Edge                  ;
	SPI_InitStruct.SPI_CPOL               =SPI_CPOL_Low                    ;//模式0
	SPI_InitStruct.SPI_CRCPolynomial      =0x0007                          ;
	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); 
	
	/*4.使能*/
  SPI_Cmd(SPI2,ENABLE);
	
	/*5.片选信号配置*/
	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)                            ;
	
	/*6.CS默认为高电平*/
	 GPIO_WriteBit( GPIOB,GPIO_Pin_12,(BitAction)SET)            ;
}

 完整的代码在我的资源下载,代码部分有跨页写入

 四、软件模拟SPI

 软件模拟就放在下个文章了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值