软件模拟SPI接口程序代码(4种模式)

    关注、星标公众号,直达精彩内容

来源:技术让梦想更伟大

整理:李肖遥


SPI传输模式

SPI总线传输一共有4种模式,这4种模式分别由时钟极性(CPOL)和时钟相位(CPHA)来定义。

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为例:SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据),在SCK的下降沿切换数据线的数据。



◐在时钟的第1个上升沿(游标1处)(采样点)

  MOSI上数据为1,则在此边沿从机采样(提取)数据为1,采样点在MOSI数据线的中间。

  MISO上数据为0,则在此边沿主机采样(提取)数据为0,采样点在MISO数据线的中间。


◐在时钟的第1个下降沿(游标2处)(切换点)

  MOSI上数据由1切换为0,,数据在时钟下降沿时切换数据。

  MISO上数据由0切换为1,,数据在时钟下降沿时切换数据。


◐在时钟的第2~8个上升沿(采样点),主机在MISO上采样数据,从机在MOSI上采样数据。


◐在时钟的第2~8个下降沿(切换点),主机在MISO上切换数据,从机在MOSI上切换数据


/* 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;          else                                MOSI_L;          write_dat <<= 1;        delay_us(1);          SCK_H;         read_dat <<= 1;          if( MISO )             read_dat++;     delay_us(1);        SCK_L;         __nop();    }      return read_dat;}  /* CPOL=0,CPHA=1, MSB first */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;   //若最到位为低,则输出低    }    byte <<= 1;     // 低一位移位到最高位    delay_us(1);    SCK_L;     //拉低时钟    Temp <<= 1;     //数据左移     if(MISO)      Temp++;     //若从从机接收到高电平,数据自加一    delay_us(1);   }  return (Temp);     //返回数据} /* CPOL=1,CPHA=0, MSB first */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);     //返回数据}  /* CPOL = 1, CPHA = 1, MSB first */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;} 

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。

点击下面图片,有星球具体介绍,新用户有新人优惠券,老用户半价优惠,期待大家一起学习一起进步。


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。