通信协议--软件模拟SPI

文章目录

  • 一、SPI简介
  • 二、SPI传输模式
  • 模式0
  • 模式1
  • 模式2
  • 模式3

一、SPI简介

SPI的通信原理很简单,一般主从方式工作,这种模式通常有一个主设备和一个或多个从设备,通常采用的是4根线,它们是MISO(数据输入,针对主机来说)、MOSI(数据输出,针对主机来说)、SCLK(时钟,主机产生)、CS/SS(片选,一般由主机发送或者直接使能,通常为低电平有效)
通信协议--软件模拟SPI_第1张图片

SCK:时钟信号,由主设备产生,所以主设备SCK信号为输出模式,从设备的SCK信号为输入模式。

CS:使能信号,由主设备控制从设备,,所以主设备CS信号为输出模式,从设备的CS信号为输入模式。

MOSI:主设备数据输出,从设备数据输入,所以主设备MOSI信号为输出模式,从设备的MOSI信号为输入模式。

MISO:主设备数据输入,从设备数据输出,所以主设备MISO信号为输入模式,从设备的MISO信号为输出模式。

SPI作为全双工的的串行通信协议,数据传输时高位在前,低位在后。主机和从机公用由主机产生的SCK信号,所以在每个时钟周期内主机和从机有1bit的数据交换(因为MOSI和MISO数据线上的数据都是在时钟的边沿处被采样)。如下图:
通信协议--软件模拟SPI_第2张图片
SPI协议规定数据采样是在SCK的上升沿或下降沿时刻(由SPI模式决定,下面会说到),观察上图,在SCK的边沿处(上升沿或下降沿),主机会在MISO数据线上采样(接收来从机的数据),从机会在MOSI数据线上采样(接收来自主机的数据),所以每个时钟周期中会有一bit的数据交换。
在这里插入图片描述

二、SPI传输模式

SPI总线传输一共有4种模式,这4种模式分别由时钟极性(CPOL)和时钟相位(CPHA)来定义。
通信协议--软件模拟SPI_第3张图片通信协议--软件模拟SPI_第4张图片

CPOL:规定了SCK时钟信号空闲状态的电平

CPHA:规定了数据是在SCK时钟的上升沿还是下降沿被采样

模式0:CPOL=0,CPHA =0 SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据)

模式1:CPOL=0,CPHA =1 SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据)

模式2:CPOL=1,CPHA =0 SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据)

模式3:CPOL=1,CPHA =1 SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据)

模式0

CPOL=0,CPHA =0 SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据),下降沿切换数据
通信协议--软件模拟SPI_第5张图片
写入传入的数据,返回读取的数据

/* CPOL = 0, CPHA = 0, MSB first */
uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )
{
    uint8_t i, read_dat;//--用来保存读取的数据
    //--空闲电平是低电平,所以第一次写数据不需要拉低时钟线
    for( i = 0; i < 8; i++ )
    {
    //--------------写数据------------------
        if( write_dat & 0x80 )//--从高字节写入
            MOSI_H;  //--如果是1,拉高MOSI线
        else                    
            MOSI_L;  //--如果是0,拉低MOSI线
        write_dat <<= 1; //--更新最高为数据
        
        delay_us(1);	
    //---------------读数据----------------------    
        SCK_H;       //--拉高时钟线,准备采样数据
        read_dat <<= 1;  //--高位左移,接收下一位,
        if( MISO ) //--如果是1
            read_dat++; //--最低位保存1,否则就是0
		delay_us(1);
        SCK_L; //--拉低时钟线准备下一次写入
        __nop();
    }
    return read_dat;
}

模式1

模式1:CPOL=0,CPHA =1 SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据),上升沿改变数据
通信协议--软件模拟SPI_第6张图片

uint8_t SOFT_SPI_RW_MODE1(uint8_t byte) 
{
    uint8_t i,Temp=0;
	for(i=0;i<8;i++)     // 循环8次
	{
	//----------------写数据------------------
		SCK_H;     //拉高时钟(上升沿改变数据)
		if(byte&0x80)
			MOSI_H;  //若最到位为高,则输出高
		else      
			MOSI_L;   //若最到位为低,则输出低
			
		delay_us(1);
   //----------------读数据-------------------
		byte <<= 1;     // 低一位移位到最高位
		SCK_L;     //拉低时钟(下降沿采样数据)
		Temp <<= 1;     //数据左移
		if(MISO)
			Temp++;     //若从从机接收到高电平,数据自加一
		delay_us(1);
 
	}
	return (Temp);     //返回数据
}

模式2

模式2:CPOL=1,CPHA =0 SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据),上升沿改变数据
通信协议--软件模拟SPI_第7张图片

uint8_t SOFT_SPI_RW_MODE2(uint8_t byte) 
{
    uint8_t i,Temp=0;
	for(i=0;i<8;i++)     // 循环8次
	{
	//----------------写数据-------------------
	   //--上升沿改变数据,空闲电平为高电平,
		if(byte&0x80)
			MOSI_H;  //若最到位为高,则输出高
		else      
			MOSI_L;   //若最到位为低,则输出低
		byte <<= 1;     // 低一位移位到最高位
		
		delay_us(1);
	//--------------读数据---------------------	
		SCK_L;     //拉低时钟(下降沿采样数据)
		Temp <<= 1;     //数据左移
		if(MISO)
			Temp++;     //若从从机接收到高电平,数据自加一
		delay_us(1);
		SCK_H;     //拉高时钟(为下一次下数据做准备)
	}
	return (Temp);     //返回数据
}

模式3

模式3:CPOL=1,CPHA =1 SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据),下降沿改变数据
通信协议--软件模拟SPI_第8张图片

uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
    //--------------写数据-----------------
		SCK_L; //--空闲电平为高电平,下降沿改变数据,所以拉低时钟线
        if( write_dat & 0x80 )
            MOSI_H;  
        else                    
            MOSI_L;  
        write_dat <<= 1;
        
        delay_us(1);	
    //--------------读数据-----------------
        SCK_H; //--上升沿采样数据,所以拉高时钟线
        read_dat <<= 1;  
        if( MISO ) 
            read_dat++; 
		delay_us(1);
        __nop();
    }
    return read_dat;
}

你可能感兴趣的:(#,通信协议,嵌入式,单片机,stm32,通信协议,spi)