AVR单片机IO口模拟SPI四种模式的程序
来源: 芯艺
本站广告
  ENC28J60+uIP DHCP动态获取IP及UDP广播服务端示例
  ENC28J60+uIP 基于TCP的MODBUS IO示例
  C720H5上实现MODBUS远程IO
  ENC28J60+uIP HTTP GET方式将温度数据上传到web服务器
  FM1702读写S50(也叫M1)卡相关资料

时钟相位(CPHA)和时钟极性(CPOL)的不同组合使得SPI传输有了4种方式

如果CPOL =0,SCK 引脚在空闲状态保持低电平;
如果CPOL =1,SCK 引脚在空闲状态保持高电平

时序图如下:


//IO端口定义
#define SPI_SCK  PC0
#define SPI_MOSI PC1
#define SPI_MISO PC2
#define SPI_DDR  DDRC
#define SPI_PORT PROTC
#define SPI_PIN   PINC

//端口操作符定义
#define SCK_SET SPI_PORT|=_BV(SPI_SCK)
#define SCK_CLR SPI_PORT&=~_BV(SPI-SCK)

#define MOSI_SET SPI_PORT|=_BV(SPI_MOSI)
#define MOSI_CLR SPI_PORT&=~_BV(SPI_MOSI)

#define MISO_PIN PINC&_BV(SPI_MISO)

#define DELAY_BUS   //如需要延时,用延时函数替代此符号

//模式1:CPOL=1 CPHA=1
void spi_init(void)
{
  SCK_SET;
  SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);
}
uint8_t spi_readwrite_byte(uint8_t data)
{
  uint8_t i,ret=0;
  
  for(i=0;i<8;i++)
  {
    //下降沿模拟
    if(data&0x80)//设置输出
      MOSI_SET;
    else
      MOSI_CLR;
    SCK_CRL;//SCK产生下降沿  
      
    DELAY_BUS;
    
    //上升沿模拟
    ret<<=1;
    if(MISO_PIN)//读数据
      ret|=1;
    SCK_SET; //SCK产生上升沿
    data<<=1;
    
    DELAY_BUS;
  }
  
  return ret;
}

//模式2:CPOL=0 CPHA=1
void spi_init(void)
{
  SCK_CLR;
  SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);
}
uint8_t spi_readwrite_byte(uint8_t data)
{
  uint8_t i,ret=0;
  
  for(i=0;i<8;i++)
  {
    //上升沿模拟
    if(data&0x80)//设置输出
      MOSI_SET;
    else
      MOSI_CLR;
    SCK_SET;//SCK产生上升沿  
      
    DELAY_BUS;
    
    //下降沿模拟
    ret<<=1;
    if(MISO_PIN)//读数据
      ret|=1;
    SCK_CLR; //SCK产生下降沿
    data<<=1;
    
    DELAY_BUS;
  }
  
  return ret;
}

//模式3:CPOL=1 CPHA=0
void spi_init(void)
{
  SCK_SET;
  SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);
}
uint8_t spi_readwrite_byte(uint8_t data)
{
  uint8_t i,ret=0;
  
  //设置好输出口
  if(data&0x80)
    MOSI_SET;
  else
    MOSI_CLR;
  for(i=0;i<8;i++)
  {
    DELAY_BUS;
    
    //下降沿模拟
    ret<<=1;
    if(MISO_PIN)//读数据
      ret|=1;
    SCK_CRL;//SCK产生下降沿
    
    DELAY_BUS;
    
    //上升沿模拟
    data<<=1;
    if(data&0x80)//设置输出
      MOSI_SET;
    else
      MOSI_CLR;
    SCK_SET; //SCK产生上升沿
  }
  
  return ret;
}

//模式4:CPOL=0 CPHA=0 
void spi_init(void)
{
  SCK_CLR;
  SPI_DDR|=_BV(SPI_MOSI)|_BV(SPI_SCK);
}
uint8_t spi_readwrite_byte(uint8_t data)
{
  uint8_t i,ret=0;
  
  //设置好输出口
  if(data&0x80)
    MOSI_SET;
  else
    MOSI_CLR;
  for(i=0;i<8;i++)
  {
    DELAY_BUS;
    
    //上升沿模拟
    ret<<=1;
    if(MISO_PIN)//读数据
      ret|=1;
    SCK_SET;//SCK产生上升沿
    
    DELAY_BUS;
    
    //下降沿模拟
    data<<=1;
    if(data&0x80)//设置输出
      MOSI_SET;
    else
      MOSI_CLR;
    SCK_CLR; //SCK产生下降沿
  }
  
  return ret;
}




声明:芯艺工作室(http://www.chipart.cn)保留所有权力,转载请注明出处!

芯艺工作室    蒙ICP备06005492号

Copyright© 2004-2020 ChipArt Studio All Rights Reserved