⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 很好的制作AVR32 ICE的资料
💻 C
字号:
/**	\file
	<b>SPI</b><br>
	Autor: Matthias Wei遝r<br>
	Copyright 2005: Matthias Wei遝r<br>
	License: QPL (see license.txt)
	<hr>
*/
#include <iccioavr.h>
#include <eeprom.h>
#include <macros.h>
#include "spi.h"
#include "tools.h"
#include "extern_vars.h"

static unsigned char use_sw_spi = 0;


#if defined(ATMega8)
// HW Normal M8 version
    #define MOSI_SET	PORTB|=BIT(3);
    #define MOSI_CLEAR	PORTB&=~BIT(3);

    #define MISO_IN		(PINB & BIT(4))
    #define SCK_SET     PORTB |= BIT(5);
    #define SCK_CLEAR   PORTB &= ~BIT(5);
    
    #define DDR_MOSI_OUT    DDRB |= BIT(3);
    #define DDR_MOSI_IN     DDRB &= ~BIT(3);NOP();
    #define DDR_SCK_OUT     DDRB |= BIT(5);
    #define DDR_SCK_IN      DDRB &= ~BIT(5);NOP();
    
#elif defined(ATMega16) || defined(ATMega32)
// HW Snail Emluator Kit
    #define MOSI_SET    PORTB |= BIT(5);
    #define MOSI_CLEAR	PORTB &= ~BIT(5);
    
    #define MISO_IN		(PINB & BIT(6))
    #define SCK_SET     PORTB |= BIT(7);
    #define SCK_CLEAR   PORTB &= ~BIT(7);
    
    #define DDR_MOSI_OUT    DDRB |= BIT(5);
    #define DDR_MOSI_IN     DDRB &= ~BIT(5);NOP();
    #define DDR_SCK_OUT     DDRB |= BIT(7);
    #define DDR_SCK_IN      DDRB &= ~BIT(7);NOP();
#endif

void spi_enable(void)
{
  unsigned char i;

  R_RES_ON;
  wait_ms(2);
  
  //PORTB &= BIT3_NEG & BIT5_NEG;	//MOSI and SCK low
  //DDRB |= BIT3_POS | BIT5_POS;	//MOSI and SCK als Ausgang
  MOSI_CLEAR;SCK_CLEAR;
  DDR_MOSI_OUT;DDR_SCK_OUT
  
  if (EEPROMread((int)&eeprom_sck_period) > 64)
    {
      use_sw_spi = 1;  //使用模拟SPI
      SPCR=0x00;
    }
  else
    {
      use_sw_spi = 0;  //使用硬件SPI
      SPCR = 0x51;					//SPI Master /16
      spi_set_speed(EEPROMread((int)&eeprom_sck_period));
    }

  R_RES_OFF;
  for (i=0;i<200;i++) asm("nop");
  R_RES_ON;
  wait_ms(2);

}

void spi_disable(void)
{
  SPCR=0x00;						//SPI aus
  //DDRB &= BIT3_NEG & BIT5_NEG;	//MOSI und SCK als Eingang (hochohmig)
  DDR_MOSI_IN;DDR_SCK_IN;
  R_RES_OFF;
}

void spi_reset(void)
{
  R_RES_OFF;
  wait_ms(2);
  R_RES_ON;
}

/**
	Stellt die Geschwindigkeit des SPI-Busses ein (bei f=8MHz)
	0:	/2		4MHz	--SPI2X
	1	/4		2MHz
	2:	/8		1MHz	--SPI2X
	3	/16		500kHz
	4:	/32		250kHz	--SPI2X
	5	/64		125kHz
	6:	/128	62,5kHz

	weitere Geschwindigkeiten geplant
	-> dann per Software-SPI
*/
void spi_set_speed(unsigned char s)
{
#if F_CPU <= 8000000
  if ((s==0)||(s==2)||(s==4)) SPSR|=1;
  else SPSR&=0xFE;

  switch (s)
    {
    case 0:
    case 1:
      SPCR&=0xFC;
      break;
    case 2:
    case 3:
      SPCR&=0xFC;
      SPCR|=0x01;
      break;
    case 4:
    case 5:
      SPCR&=0xFC;
      SPCR|=0x02;
      break;
    case 6:
      SPCR|=0x03;
      break;
    default:		//Wenn Wert ung黮tig ganz langsam
      SPCR|=0x03;
      break;
    }
#else
/**
	Stellt die Geschwindigkeit des SPI-Busses ein (bei f=16MHz)
	0:	/4		4MHz
	1	/8		2MHz        -SPI2X
	2:	/16		1MHz
	3	/32		500kHz      -SPI2X
	4:	/64		250kHz
	5	/128	125kHz      -SPI2X
	6:	/128	62,5kHz

	weitere Geschwindigkeiten geplant
	-> dann per Software-SPI
*/
    if ((s==1)||(s==3)) 
    {
        SPSR|=1;
    }
    else 
    {
        SPSR&=0xFE;
    }
    
    switch (s)
    {
        case 0:
            SPCR&=0xFC;
            break;
        case 1:
            SPCR&=0xFC;
            SPCR|=0x01;
            break;
        case 2:
            SPCR&=0xFC;
            SPCR|=0x01;
            break;
        case 3:
            SPCR&=0xFC;
            SPCR|=0x02;
            break;
        case 4:
            SPCR&=0xFC;
            SPCR|=0x02;
            break;
        case 5:
            SPCR|=0x03;
            break;
        case 6:
            SPCR|=0x03;
            break;
        default:		//Wenn Wert ung黮tig ganz langsam
            SPCR|=0x03;
            break;
    }

#endif
}

void spi_clock_pulse(void)  //模拟SPI时钟
{
  if (!use_sw_spi)
    {
      SPCR&=BIT6_NEG;		//SPI 使能关闭
    }

  SCK_SET
  //PORTB|=BIT5_POS;	//SPI SCK impuls
  wait_ms(2);
  //PORTB&=BIT5_NEG;
  SCK_CLEAR
  
  if (!use_sw_spi)
    {
      SPCR|=BIT6_POS;		//SPI 使能
    }
}

/**
	Does a 8 bit transfer over the SPI-Interface
	and gives back the byte received

	@param	d	the byte to be transmitted

	@return		the byte received
*/
unsigned char spi_transfer_8(unsigned char d)
{
  if (!use_sw_spi)
    {
      SPDR=d;
      while (!(SPSR&0x80));

      return SPDR;
    }
  else
    {
      unsigned char result=0,i;
      volatile unsigned int j;

      for (i = 0; i < 8; i++)
        {
          if (d&0x80)
            {
              MOSI_SET;
            }
          else
            {
              MOSI_CLEAR;
            }
          d<<=1;
          result<<=1;
          
          #if F_CPU < 8000000
          for (j = 0; j < 18; j++) asm ("nop");
          #else
          for (j = 0; j < 36; j++) asm ("nop");
          #endif
          SCK_SET
          //PORTB|=BIT5_POS; //sck 
          if (MISO_IN)
            {
              result|=1;
            }
          #if F_CPU < 8000000
          for (j = 0; j < 18; j++) asm ("nop");
          #else
          for (j = 0; j < 36; j++) asm ("nop");
          #endif
          //PORTB&=BIT5_NEG;
          SCK_CLEAR
        }
      MOSI_CLEAR;

      return result;
    }
}

/**
	Does a 16 bit transfer over the SPI-Interface
	and gives back the last byte received

	@param	d	the int to be transmitted

	@return		the last byte received
*/
unsigned char spi_transfer_16(unsigned int d)
{
  spi_transfer_8((d>>8)&0xFF);
  return spi_transfer_8(d&0xFF);
}

/**
	Does a 32 bit transfer over the SPI-Interface
	and gives back the last byte received

	@param	d	the long to be transmitted

	@return		the last byte received
*/
unsigned char spi_transfer_32(unsigned long d)
{
  spi_transfer_8((d>>24)&0xFF);
  spi_transfer_8((d>>16)&0xFF);
  spi_transfer_8((d>>8)&0xFF);
  return spi_transfer_8(d&0xFF);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -