框架-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)主设备输入/从设备输出引脚 。 从机发出 , 主机接收 。
- SPI 四种模式请移步到下面章节学习
- SPI的协议层SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节 。 基本通讯过程图解标号1:NSS信号线由高变低 , 是SPI通讯的起始信号 。 标号6:NSS信号由低变高 , 是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的 上升沿 被采样
- 实现方法参考I2C设备驱动拆解
- 自己先在写出四种模式的读写时序 , 便会发现以下规律
- 读写的逻辑差不多都一样 , 只是 SCK 信号线出现的位置及高低电平会因不同模式而不同 。 ( 这里我就不分别写出4种模式的单独实现了 , 直接上规律表 , 然后实现统一的源码 )
文章插图
由上规律得出 支持四种模式的 SPI 读写源码
- SPI 写函数
/*** @briefSPI 写函数* @param* @retval* @author lzm*/void spiWriteOneByte(eSPI_ID id, unsigned char data){ unsigned char i; const spi_t * spi =// 位置1 if(spi->CPHA){spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL); }for(i=0; i<8; i++) {// 位置2spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));if(data}else{spiMosiOutLo(spi);}data <<= 1;spi->delayUsFun(spi->readDelayUsCnt);// 位置3spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA)); }// 位置4 if(!(spi->CPHA)){spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL); }}
- SPI 读函数
/*** @briefSPI 读函数* @param* @retval* @author lzm*/unsigned char spiReadOneByte(eSPI_ID id){ unsigned char i; unsigned char ret; const spi_t * spi =// 位置1for(i=0; i<8; i++) {// 位置2spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));ret <<= 1;if(spiMisoIn(spi))ret |= 0x01;elseretspi->delayUsFun(spi->readDelayUsCnt);// 位置3spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA)); }// 位置4 spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL); return ret;}
- SPI 读写函数
/*** @briefSPI 读写一体函数* @param* @retval* @author lzm*/unsigned char spiRWOneByte(eSPI_ID id, unsigned char data){ unsigned char i; unsigned char ret; const spi_t * spi =// 位置1 if(spi->CPHA){spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL); }for(i=0; i<8; i++) {// 位置2spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));if(data}else{spiMosiOutLo(spi);}data <<= 1;spi->delayUsFun(spi->readDelayUsCnt);// 位置3spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));ret <<= 1;if(spiMisoIn(spi))ret |= 0x01;elseretspi->delayUsFun(spi->readDelayUsCnt); }// 位置4 if(!(spi->CPHA)){spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL); }}
【框架-SPI四种模式+通用设备驱动实现】本文作者:李柱明本文链接:- 手机|OPPO手机该如何截屏?四种最简单的方法已汇总!
- 空间|垃圾文件正在吞噬你的C盘空间用这四种方法,还你一个干净的C盘
- 5G|想入手iPhone 12吗?如果你是这四种人,我劝你还是放弃吧!
- 框架|三种数据分析思维框架的构建方法
- 整理:常见的Java开发框架有哪些,看过,就赶紧收藏吧
- Martian框架发布 3.0.3 版本,Redis分布式锁
- 在Linux系统中安装深度学习框架Pytorch
- 案例:如何使用接口测试框架Karate创建一个API测试?
- 常用的NIO框架-Netty
- countif函数的四种另类经典用法,我不说没人告诉你