框架-SPI四种模式+通用设备驱动实现
前言
- SPI 介绍为搜集百度资料+个人理解
 - 其余为原创(有误请指正)
 - 集四种模式于一身
 
笔录草稿
SPI介绍
SPI 协议简介
- SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。
 - 是一个环形总线结构
- 由 ss(cs)、sck、sdi、sdo 构成
 - 其时序主要是在 sck 的控制下,两个双向移位寄存器进行数据交换。
 
 
物理线说明
- SS
- 从设备选择信号线,常称为片选信号线,也称为NSS、CS。
 - 用于选择从机。
 
 - SCK (Serial Clock)
- 时钟信号线
 - 用于通讯数据同步。
 
 - MOSI (Master Output, Slave Input)
- 主设备输出/从设备输入引脚。
 - 主机发出,从机接收。
 
 - MISO (Master Input,,Slave Output)
- 主设备输入/从设备输出引脚。
 - 从机发出,主机接收。
 
 
- SS
 SPI 四种模式
- 请移步到下面章节学习
 
SPI的协议层
- SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节。
 - 基本通讯过程
 - 图解
- 标号1:NSS信号线由高变低,是SPI通讯的起始信号。
 - 标号6:NSS信号由低变高,是SPI通讯的停止信号。
 
 
简单时序图

模式时序图

SPI四种模式 **
- 四种模式由 CPOL 和 CPHA 组合区分
 - CPOL
- 时钟极性
 - 是指SPI通讯设备处于空闲状态时,SCK信号线的电平信号
 - 为 0 时
- SCK 空闲状态为 低电平
 
 - 为 1 时
- SCK 空闲状态为 高电平
 
 
 - CPHA
- 时钟相位
 - 是指数据的采样的时刻
 - 为 0 时
- MOSI或MISO数据线上的信号将会在SCK时钟线的“奇数边沿”被采样。(即是第一个边沿)
 - 这种模式适合那种从设备一旦被片选后就输出数据到MISO线上。
 
 - 为 1 时
- 数据线在SCK的“偶数边沿”采样。(即是第二个边沿)
 - 这种模式适合那种从设备被片选后还需要一个时钟才能 输出数据到MISO线上。
 
 
 - 四种模式(CPOL, CPHA)
- 模式 0:(0, 0)
- SCK空闲为 低电平,数据在SCK的 上升沿 被采样
 
 - 模式 1:(0, 1)
- SCK空闲为 低电平,数据在SCK的 下降沿 被采样
 
 - 模式 2:(1, 0)
- SCK空闲为 高电平,数据在SCK的 下降沿 被采样
 
 - 模式 3:(1, 1)
- SCK空闲为 高电平,数据在SCK的 上升沿 被采样
 
 
 - 模式 0:(0, 0)
 
SPI 驱动框架 **
框架
- 实现方法参考 I2C设备驱动拆解
 - 自己先在写出四种模式的读写时序,便会发现以下规律
 - 读写的逻辑差不多都一样,只是 SCK 信号线出现的位置及高低电平会因不同模式而不同。(这里我就不分别写出4种模式的单独实现了,直接上规律表,然后实现统一的源码)
 
| R/W | CPOL | CPHA | 位置1-SCK | 位置2-SCK | 位置3-SCK | 位置4-SCK | 
|---|---|---|---|---|---|---|
| R | 0 | 0 | X | 0 | 1 | 0 | 
| R | 0 | 1 | X | 1 | 0 | 0 | 
| R | 1 | 0 | X | 1 | 0 | 1 | 
| R | 1 | 1 | X | 0 | 1 | 1 | 
| - | - | - | - | - | - | - | 
| W | 0 | 0 | X | 0 | 1 | 0 | 
| W | 0 | 1 | 0 | 1 | 0 | X | 
| W | 1 | 0 | X | 1 | 0 | 1 | 
| W | 1 | 1 | 1 | 0 | 1 | X | 
由上规律得出 支持四种模式的 SPI 读写源码
- SPI 写函数
 
/**
  * @brief  SPI 写函数
  * @param
  * @retval
  * @author lzm
  */
void spiWriteOneByte(eSPI_ID id, unsigned char data)
{
	unsigned char i;
	const spi_t * spi = &spiDriverElem[id];
    // 位置1
	if(spi->CPHA){
		spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
	}
	for(i=0; i<8; i++)
	{
        // 位置2
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
		if(data & 0x80){
			spiMosiOutHi(spi);
		}
		else{
			spiMosiOutLo(spi);
		}
		data <<= 1;
		spi->delayUsFun(spi->readDelayUsCnt);
        // 位置3
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
	}
    // 位置4
	if(!(spi->CPHA)){
		spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
	}
}
- SPI 读函数
 
/**
  * @brief  SPI 读函数
  * @param
  * @retval
  * @author lzm
  */
unsigned char spiReadOneByte(eSPI_ID id)
{
	unsigned char i;
	unsigned char ret;
	const spi_t * spi = &spiDriverElem[id];
    // 位置1
	for(i=0; i<8; i++)
	{
        // 位置2
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
		ret <<= 1;
		if(spiMisoIn(spi))
			ret |= 0x01;
		else
			ret &= 0xfe;
		spi->delayUsFun(spi->readDelayUsCnt);
        // 位置3
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
	}
    // 位置4
	spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
	return ret;
}
- SPI 读写函数
 
/**
  * @brief  SPI 读写一体函数
  * @param
  * @retval
  * @author lzm
  */
unsigned char spiRWOneByte(eSPI_ID id, unsigned char data)
{
	unsigned char i;
	unsigned char ret;
	const spi_t * spi = &spiDriverElem[id];
    // 位置1
	if(spi->CPHA){
		spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
	}
	for(i=0; i<8; i++)
	{
        // 位置2
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
		if(data & 0x80){
			spiMosiOutHi(spi);
		}
		else{
			spiMosiOutLo(spi);
		}
		data <<= 1;
		spi->delayUsFun(spi->readDelayUsCnt);
        // 位置3
		spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
		ret <<= 1;
		if(spiMisoIn(spi))
			ret |= 0x01;
		else
			ret &= 0xfe;
		spi->delayUsFun(spi->readDelayUsCnt);
	}
    // 位置4
	if(!(spi->CPHA)){
		spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
	}
}
												
											框架-SPI四种模式+通用设备驱动实现的更多相关文章
- 【框架】SPI四种模式+通用设备驱动实现-源码
		
目录 前言 bsp_spi.c bsp_spi.h bsp_flash.c bsp_flash.h 前言 SPI 介绍为搜集百度资料+个人理解 其余为原创(有误请指正) 集四种模式于一身 demo 采 ...
 - 小知识:SPI四种模式区别【转】
		
转自:http://home.eeworld.com.cn/my/space-uid-80086-blogid-119198.html spi四种模式SPI的相位(CPHA)和极性(CPOL)分别可以 ...
 - SPI 四种模式
		
SPI时钟极性CPOL, = 0表示在没有数据传输时为低电平,= 1表示没有数据传输时为高电平. SPI时钟相位CPHA,= 0表示时钟的第一个沿更新数据.第二个沿锁存数据,= 1表示时钟的第一个沿锁 ...
 - Asp.net的sessionState四种模式配置方案
		
sessionState节点的配置 web.config关于sessionState节点的配置方案,sessionState有四种模式:off,inProc,StateServer,SqlServer ...
 - 大量数据也不在话下,Spring Batch并行处理四种模式初探
		
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Spring相关文章:Springboot-Cloud 前面写了一篇文章<通过例子讲解Spring Batch入门,优 ...
 - Hibernate 查询MatchMode的四种模式
		
Hibernate 查询MatchMode的四种模式 MatchMode.START:字符串在最前面的位置.相当于"like 'key%'" MatchMode.END:字符串在最 ...
 - Android 文件访问权限的四种模式
		
Linux文件的访问权限* 在Android中,每一个应用是一个独立的用户* drwxrwxrwx* 第1位:d表示文件夹,-表示文件* 第2-4位:rwx,表示这个文件的拥有者(创建这个文件的应用) ...
 - 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
		
一. AES对称加密: AES加密 分组 二. 分组密码的填充 分组密码的填充 e.g.: PKCS#5填充方式 三. 流密码: 四. 分组密码加密中的四种模式: 3.1 ECB模式 优点: 1. ...
 - OAuth2简易实战(一)-四种模式
		
1. OAuth2简易实战(一)-四种模式 1.1. 授权码授权模式(Authorization code Grant) 1.1.1. 流程图 1.1.2. 授权服务器配置 配置授权服务器中 clie ...
 
随机推荐
- 使用jsonify返回json数据
			
from flask import Flask, jsonify app = Flask(__name__) json_data = [ {"name":"json&qu ...
 - (转载)Altium Designer 17 (AD17)
			
转载自:http://blog.csdn.net/qq_29350001/article/details/52199356 以前是使用DXP2004来画图的,后来转行.想来已经有一年半的时间没有画过了 ...
 - vue下history模式刷新后404错误解决
			
官方说明文档: https://router.vuejs.org/zh/g... 一. 实测 Linux 系统 Apache 配置: 更改站点配置文件即可,我这里在 Directory 标签后面添加了 ...
 - 使用C#创建WebService实例
			
新增WebService专案 更改服务程式名称 重命名程式名称 Service1.asmx 修改为 TestService.asmx 此时下面的cs代表文件也会跟着修改,但可发现,代码中的类名并没有跟 ...
 - linux 基础语法
			
1.linux常用命令 1.1 系统命令 runlevel # 查看当前的运行级别systemctl status sshd # 开启网络服务功能 ...
 - mysqldump 5.7
			
简介 mysqldump是官方自带的文本格式备份工具,简单实用,一般在Mysql安装目录的bin目录下.备份文件默认是SQL格式,它由一系列语句例如CREATE TABLE.INSERT等组成.mys ...
 - jquery,Datatables插件使用,做根据【日期段】筛选数据的功能  jsp
			
时间格式为yyyymmdd,通过转换为int类型进行比较大小 画面: jsp代码: 1 //日期显示控件,使用h-ui框架 2 3 <div class="text-c"& ...
 - _1_html_框架
			
创:18_3_2017修:20_3_2017 什么是html? --超文本标记语言 --告诉浏览器内容的语义 html页面的框架是什么? <!DOCTYPE html> <!--DT ...
 - Python-临时文件文件模块-tempfile
			
案例: 某项目中,从传感器中获得采集数据,每收集到1G的数据后做是数据分析,最终只保留数据分析的结果,收集到的数据放在内存中,将会消耗大量内存,我们希望把这些数据放到一个临时的文件中 临时文件不能命名 ...
 - CF538B Quasi Binary 思维题
			
题目描述 给出一个数 \(n\),你需要将 \(n\) 写成若干个数的和,其中每个数的十进制表示中仅包含\(0\)和\(1\). 问最少需要多少个数 输入输出格式 输入格式: 一行 一个数 \(n(1 ...