SPI 总线协议详解与实现

1 篇文章 0 订阅

一,SPI概括:

SPI是串行外设接口(Serial Peripheral
Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。(引用百度百科)
SPI也有三线制,适用于单向传输。

SPI协议是由Motorola首先在其MC68HCXX系列处理器上定义的。

二,SPI 接口 原理 缺陷:

四线制物理接口:
三线制只是少了SS/CS接口,不能一对多。
在这里插入图片描述

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS/SS(片选)。

(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS/SS – Chip Select,从设备使能信号,由主设备控制。
(引用百度百科)

SPI缺点:没有指定的流控制,没有应答机制确认是否接收到数据

三 SPI协议:

SPI协议根据片选线(CS/SS)区分从设备,因此4线和3线的区别就在于此。

在这里插入图片描述
SPI协议根据CPOL和CPHA不同,有四种通讯方式。

时钟极性(CPOL)指通讯设备处于空闲状态(SPI开始通讯前、CS/SS线无效)时,SCK的状态。
时钟相位(CPHA)指数据的采样时刻位于SCK的偶数边沿采样还是奇数边沿采样。

CPOL:时钟极性选择,为0时SPI总线空闲为低电平,为1时SPI总线空闲为高电(0/1)
CPHA:时钟相位选择,为0时在SCK第一个跳变沿采样,为1时在SCK第二个跳变沿采样(0/1)

注意:不要认为是上升沿采集数据,下降沿发送数据

spi协议时序图(4种情况)
在这里插入图片描述
所以对于的code有四种写法,按实际需求去写。
注意:所有操作需要先拉低对应的片选线(CS/SS)

数据的传输方向一般是高位开始,实际编写操作看需求。
SPI协议有硬件实现和软件模拟两种方式。

//默认一对一

/*
函数功能:SPI底层时序
时序图的第一种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
     u8 i=0,rx_data=0;
     SCK=0;
     for(i=0;i<8;i++)
     {
         SCK=0;
         if(tx_data&0x80)MOSI=1;
         else MOSI=0;
         SCK=1;
         tx_data<<=1;
       
         rx_data<<=1;
         if(MISO)rx_data|=0x01;
     }
     SCK=0;
     return rx_data;
}

/*
函数功能:SPI底层时序
时序图的第二种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
	u8 i=0,rx_data=0;
	 SCK=0;
	for(i=0;i<8;i++)
	{
		SCK=1;
		if(tx_data&0x80)MOSI=1;
		else MOSI=0;
		SCK=0;
		tx_data<<=1;
		
		rx_data<<=1;
		if(MISO)rx_data|=0x01;
	}
	 SCK=0;
	return rx_data;
}
/*
函数功能:SPI底层时序
时序图的第三种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
	u8 i=0,rx_data=0;
	 SCK=1;
	for(i=0;i<8;i++)
	{
		SCK=1;
		if(tx_data&0x80)MOSI=1;
		else MOSI=0;
		SCK=0;
		tx_data<<=1;
		
		rx_data<<=1;
		if(MISO)rx_data|=0x01;
	}
	 SCK=1;
	return rx_data;
}
/*
函数功能:SPI底层时序
时序图的第四种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
	u8 i=0,rx_data=0;
	 SCK=1;
	for(i=0;i<8;i++)
	{
		SCK=0;
		if(tx_data&0x80)MOSI=1;
		else MOSI=0;
		SCK=1;
		tx_data<<=1;
		
		rx_data<<=1;
		if(MISO)rx_data|=0x01;
	}
	 SCK=1;
	return rx_data;
}

示例:
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值