32

框架-SPI四种模式+通用设备驱动实现

 3 years ago
source link: http://www.cnblogs.com/lizhuming/p/13907267.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

目录

前言

  • 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. 标号1:NSS信号线由高变低,是SPI通讯的起始信号。
      2. 标号6:NSS信号由低变高,是SPI通讯的停止信号。
  • 简单时序图 7RbAnmN.png!mobile

  • 模式时序图 vamiu2.png!mobile

SPI四种模式 **

  • 四种模式由 CPOLCPHA 组合区分
  • 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的 上升沿 被采样

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);
	}
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK