【STM32-学习笔记-9-】SPI通信

SPI通信

Ⅰ、SPI通信概述

SPISerial Peripheral Interface,串行外设接口)是一种高速、全双工、同步的通信总线,广泛应用于嵌入式系统与外围设备间的短距离通信。SPI由摩托罗拉公司在20世纪80年代中期开发,后逐渐发展成为行业规范。它采用主从模式,通常由一个主设备(Master)和一个或多个从设备(Slave)组成。主设备负责控制通信过程,包括时钟信号的生成、从设备的选择以及数据的发送与接收

1、SPI技术规格

  • SPI四根通信线
    • SCK(Serial Clock):时钟信号线,由主设备产生,用于同步数据传输
    • MOSI(Master Output, Slave Input):主设备输出、从设备输入的数据线
    • MISO(Master Input, Slave Output):主设备输入、从设备输出的数据线
    • CS/SS(Chip Select/Slave Select):从设备选择信号线,用于主设备选择与其通信的从设备(默认1
  • 工作模式:SPI有四种工作模式,由CPOL(时钟极性)和CPHA(时钟相位)定义。这决定了数据采样和发送的时钟边沿
  • 数据帧格式:通常为8位或16位,可以配置为MSB(高位在前)或LSB(低位在前)。
  • 传输速率:SPI支持较高的数据传输速率,通常能达到甚至超过10M/bps
  • 通信特点:全双工通信,可以同时发送和接收数据;同步通信,使用时钟信号来同步数据传输;连接简单,硬件结构简单
2、SPI应用
  • 存储器芯片:如EEPROM、SRAM、SPI Flash等,用于数据的高速读写和存储
  • 传感器:用于与各种传感器进行通信,获取传感器数据
  • 显示器:如液晶显示器和OLED显示器,传输图像数据和控制信号
  • 通信模块:如无线模块等,用于数据传输
  • 其他外设:如ADC、DAC等

3、硬件电路

image-20250108163022842

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起

  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚

  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

移位示意图

image-20250108170335243

Ⅱ、SPI时序基本单元

①、起始条件

SS从高电平切换到低电平

image-20250108170847890

②、终止条件

SS从低电平切换到高电平

image-20250108170914447

③、交换一个字节(模式0)

  • CPOL(时钟极性)=0:空闲状态时,SCK为低电平
  • CPHA(时钟相位)=0:SCK第一个边沿移入数据,第二个边沿移出数据
    • 由于SCK第一个边沿就要移入数据,因此在SCK之前,就要先将数据移出

image-20250108171658293

④、交换一个字节(模式1)

CPOL(时钟极性)=0:空闲状态时,SCK为低电平

CPHA(时钟相位)=1:SCK第一个边沿移出数据,第二个边沿移入数据

    • SCK上升沿时,MOSI和MISO都将数据移至数据寄存器中
    • 直到SCK下降沿时,
      • 主机移入数据寄存器中的最高位数据“B7”移入从机的最低位;
      • 从机移入数据寄存器中的最高位数据“B7”移入主机的最低位,从而完成数据交换

image-20250108171827304

⑤、交换一个字节(模式2)

CPOL(时钟极性)=1:空闲状态时,SCK为高电平

CPHA(时钟相位)=0:SCK第一个边沿移入数据,第二个边沿移出数据

image-20250108171910609

⑥、交换一个字节(模式3)

CPOL(时钟极性)=1:空闲状态时,SCK为高电平

CPHA(时钟相位)=1:SCK第一个边沿移出数据,第二个边沿移入数据

image-20250108171941946

Ⅲ、SPI时序

①、发送指令

  • 向SS指定的设备,发送指令(0x06)

image-20250108174857750

②、指定地址写

  • 向SS指定的设备,发送写指令(0x02),随后在指定地址(Address[23:0])下,写入指定数据(Data

image-20250110110128634

③、指定地址读

  • 向SS指定的设备,发送读指令(0x03),随后在指定地址(Address[23:0])下,读取从机数据(Data

image-20250110110155463

Ⅳ、W25Q64 - Nor Flash(闪存)

image-20250108175316341

①、硬件电路

image-20250109111414536

②、W25Q64框图

image-20250109112639477

  • W25Q64闪存芯片中有8Mbyte闪存空间,这些空间被划分为128Block 0~Block 127),每个块占有64kb

  • 每个块又被分成16扇区Sector 0~Sector 15),每个扇区占有4kb

  • 扇区又可以划分成16个,每页占有256byte

请添加图片描述

③、Flash操作注意事项

  • 写入操作时:

    • 写入操作前,必须先进行写使能
    • 每个数据位只能由1改写为0,不能由0改写为1
    • 写入数据前必须先擦除,擦除后,所有数据位变为1
    • 擦除必须按最小擦除单元进行(擦除所有、擦除块、擦除扇区)
    • 连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入
    • 写入操作结束后,芯片进入忙状态,不响应新的读写操作
  • 读取操作时:

    • 直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

④、指令表

image-20250109152616615

⑤、电气特性表

image-20250109154933784

⑥、软件模拟SPI

#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
//模拟SPI
//输出:>SS:	PA4
//输出:>SCK:	PA5
//输出:>MOSI:	PA7
//输入:>MISO:	PA6

void MySPI_W_SS(uint8_t BitValue) {
   
	GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}
void MySPI_W_SCK(uint8_t BitValue) {
   
	GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}
void MySPI_W_MOSI(uint8_t BitValue) {
   
	GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}
uint8_t MySPI_R_MISO(void) {
   
	return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}


void MySPI_Init(void)
{
   
	//初始化GPIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//配置默认电平
	MySPI_W_SS(1);
	MySPI_W_SCK(0);//使用SPI模式0
}

//起始条件-----SS从高电平切换到低电平
void MySPI_Start(void)
{
   
	MySPI_W_SS(0);
}

//终止条件-----SS从低电平切换到高电平
void MySPI_Stop(void)
{
   
	MySPI_W_SS(1);
}


//交换一个字节(模式0)
uint8_t MySPI_SwapByte_Mod0(uint8_t ByteSend)
{
   
	uint8_t	ByteReceive = 0;
	uint8_t	i = 0;
	for(i = 0;i < 8;i++)
	{
   
		MySPI_W_MOSI(ByteSend & (0x80 >> i));
		MySPI_W_SCK(1);
		if(MySPI_R_MISO() == 1) {
   ByteReceive |= 0x80 >> i;}
		MySPI_W_SCK(0);
	}
	return ByteReceive;
}
方法2:使用移位模型
//uint8_t MySPI_SwapByte_Mod0(uint8_t ByteSend)
//{
   
//	uint8_t	ByteReceive = 0;
//	uint8_t	i = 0;
//	for(i = 0;i < 8;i++)
//	{
   
//		MySPI_W_MOSI(ByteSend & 0x80);
//		ByteSend <<= 1
//		MySPI_W_SCK(1);
//		if(MySPI_R_MISO() == 1) {ByteSend |= 0x01;}
//		MySPI_W_SCK(0);
//	}
//	return ByteSend;
//}

//交换一个字节(模式1)
uint8_t MySPI_SwapByte_Mod1(uint8_t ByteSend)
{
   
	uint8_t	ByteReceive = 0;
	uint8_t	i = 0;
	for(i = 0;i < 8;i++)
	{
   
		MySPI_W_SCK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值