STM32学习------SPI笔记【寄存器版】

								1.介绍
								2. 模拟SPI
							    3. 硬件SPI

一、介绍
简述:
1)通常 SPI 通信要求 4 根线,分别是 MOSI(主机输出从机输入), MISO(主机输入从机输出), CLK(时钟线), CS(片选线)
2)当发送和接受数据的工作都准备好了,只要有时钟 CLK,就发送数据,没有时钟就不发送,而且一个时钟周期发送一位(bit)数据,所以发送数据的快慢由时钟频率来控制。
3)至于时钟和数据的相位没有特别严格的要求(而 IIC 中,数据的变化只能在 SCL 是低电平的时候发生), SPI数据的变化是一个时钟周期一次,这样的方法来传输数据就简单多了。我们可以根据需求对时钟的极性和相位做调整,看看是在时钟上升沿还是下降沿来发送数据,还有停止发送时时钟的极性,是保持高电平还是低电平。
4)另外在多机通信时, SPI 只是简单的通过一个片选信号(拉低电平选择)来选择哪个设备占用总线,但是 IIC 是通过发送从设备地址来自动选择的。(简介来自某手册说明)

SPI有四种时序模式:
STM32学习------SPI笔记【寄存器版】_第1张图片
SPI工作原理,方便自己就用了原子哥的原话:
1)硬件上为4根线。
2)主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。
3)串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。
4)外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。
STM32学习------SPI笔记【寄存器版】_第2张图片

在当第一次接触SPI协议的时候,还是练习OLED时,当时总感觉这东西太难了,看不懂时序,不清楚原理。但是在学习过IIC之后,感觉SPI比起IIC来说很简洁明了了,IIC模拟起来复杂,硬件配置也不是那么轻松。总之,对于现在的我来说,都不是很轻松。

二、模拟SPI
比起来IIC,SPI代码真是简洁了许多。模拟SPI只需要简单初始化用到的IO再根据时序图来实现发送接收数据即可。

/*
#define SPI_SCK pbout(13)
#define SPI_MOSI pbout(15)
#define SPI_MISO pbin(14)
*/
/*
SPI_SCK:PB13(SPI2)
SPI_MOSI:PB15,
SPI_MISO:PB14
片选脚(CS)不用初始化,因为片选脚属于需要SPI控制的芯片自身。可以在驱动芯片时定义CS引脚
*/
void SPI_Init(void)
{
	RCC->APB2ENR |= 1<<3;
	GPIOB->CRH &= 0x000fffff;
	GPIOB->CRH |= 0x38300000;
	SPI_SCK = 1;//空闲电平为高
}

/*
读写一个字节,因为全双工同时发收
txdata
配置的时序图为模式3,即CPOL=1,CPHA=1
*/
u8 SPI_ReadWriteOneData(u8 txdata)
{
	u8 rxdata=0;
	u8 i=0;
	for(i=0;i<8;i++)
	{
		SPI_SCK=0;
		if(txdata&0x80)SPI_MOSI=1;//发送数据格式为高位在前,八位。当发送的某一位为1时,对MOSI赋1.
		else SPI_MOSI=0;//主机采样为第二个边沿,为上升沿,所以主机发送数据时为下降沿
		txdata<<=1;
		SPI_SCK=1;
		//上升沿时读取从机发送过来的数据
		rxdata<<=1;
		if(SPI_MISO)rxdata |= 0x01;
	}
	return rxdata;
}

三、硬件SPI
硬件SPI也很好理解,唯一难理解的就是NSS(SPI_CR1)脚管理。

/*
SPI硬件时序配置初始化
Hardware:硬件
pb13:sp2_sck
pb14:miso
pb15:mosi
*/
void HWSPI_Init(void)
{
	RCC->APB2ENR |= 1<<3;
	GPIOB->CRH &= 0x000fffff;
	GPIOB->CRH |= 0xb8b00000;
	RCC->APB1ENR |= 1<<14;//开启rcc时钟
	RCC->APB1RSTR |= 1<<14;
	RCC->APB1RSTR &=~(1<<14);
	SPI2->CR1 |= 0x3<<8;
//8,9位:启动软件NSS管理(也就是允许用程序控制片选脚)。当配置MCU为主模式(MSTR=1),SSOE=0时,NSS为低的话则会进入主模式失败
//而进入从模式。所以必须拉高。
//一旦使能SSOE位,NSS引脚也可以作为输出引脚,并在SPI处于主模式时将NSS拉低;此时,所有的SPI设备,如果它们的NSS引脚连接
//到主设备的NSS引脚,则会检测到低电平,如果它们被设置为NSS硬件模式,就会自动进入从设备状态。(中文手册23.3.1)

	SPI2->CR1 |= 1<<1;//SCK空闲电平为高
	SPI2->CR1 |= 1<<0;//数据采样从第二个边沿开始
	SPI2->CR1 |= 1<<2;//配置为主设备
	
	SPI2->CR1 |= 1<<6;//使能SPI
	HWSPI_ReadWriteOneByte(0xff);
	
}


/*发送和接收数据(8位)*/
u8 HWSPI_ReadWriteOneByte(u8 data)
{
	u32 i=0;
	while(!(SPI2->SR & 1<<1))//等待发送缓冲区空
	{
		i++;
		if(i>0xfffe)return 0;//超时,发生错误
	}
	SPI2->DR = data;
	i=0;
	while(!(SPI2->SR & 1<<0))//等待接收缓冲区非空
	{
		i++;
		if(i>0xfffe)return 0;
	}
	return SPI2->DR;
}

目前只学习了硬件SPI的主模式,好多强大的功能同样没有学习到,所有只能记录到这了。才疏学浅,惭愧惭愧~

你可能感兴趣的:(单片机学习笔记)