[AVR]/AVR_EVM2007. 5. 17. 11:28

AVR SPI관련 자료 - ATmega128, ATMega16, ATMega8 (예제 소스코드)

AVR SPI관련 자료 - ATmega128, ATMega16, ATMega8 (예제 소스코드)
AVR에서 SPI제어에 관련된 자료 정리

AVR SPI블록도



AVR ATMega128 SPI 핀맵
SPI핀 찾을것 없이 기록해 두면 편리할것 같다




관련 레지스터
SPSR

• Bit 7 – SPIF: SPI Interrupt Flag
읽을수만 있는 레지스터로 SPI인터럽트 발생 여부를 나타낸다.
• Bit 6 – WCOL: Write COLlision flag
오류 발생을 나타내는 비트
• Bit 5..1 – Res: Reserved Bits
사요하지 않는다.
• Bit 0 – SPI2X: Double SPI Speed Bit
SPI 클럭을 두배러 설정하는 비트

SPCR


• Bit 7 – SPIE: SPI Interrupt Enable
SPI인터럽트 사용여부 결정, 1일때 인터럽트 사용
• Bit 6 – SPE: SPI Enable
SPI 모듈 사용여부 결정. 1일때 SPI 사용.
• Bit 5 – DORD: Data Order
1: LSB 먼저 전송.
0: MSB 먼저 전송
• Bit 4 – MSTR: Master/Slave Select
1: Master SPI mode
0: Slave SPI mode
• Bit 3 – CPOL: Clock Polarity (SPI 모드 설정)
• Bit 2 – CPHA: Clock Phase (SPI 모드 설정)


SPI모드 설정





SPI 모드 설정 소스코드
SPI모드는 디바이스에 따라 변경해야 할 경우가 많으므로 아래 코드와 같이 정의해서 사용한다.
#define SPI0_CPOL_SET()      Sbi(SPCR, BIT3)
#define SPI0_CPHA_SET()      Sbi(SPCR, BIT2)
#define SPI0_CPOL_CLR()      Cbi(SPCR, BIT3)
#define SPI0_CPHA_CLR()      Cbi(SPCR, BIT2)

#define SPI0_MODE0()      SPI0_CPOL_CLR();SPI0_CPHA_CLR()
#define SPI0_MODE1()      SPI0_CPOL_CLR();SPI0_CPHA_SET()
#define SPI0_MODE2()      SPI0_CPOL_SET();SPI0_CPHA_CLR()
#define SPI0_MODE3()      SPI0_CPOL_SET();SPI0_CPHA_SET()


• Bits 1, 0 – SPI클럭 설정


클럭 설정 부분도 아래와 같이 정의 해 두면 편리하게 사용할 수 있다.
#define SPI0_CLK_DIV16()     Cbi(SPCR, BIT1);Sbi(SPCR, BIT0)
#define SPI0_CLK_DIV64()     Sbi(SPCR, BIT1);Cbi(SPCR, BIT0)
#define SPI0_CLK_DIV128()     Sbi(SPCR, BIT1|BIT0)

#define SPI0_CLK_DOULBE()     Sbi(SPSR, BIT0)



AVR SPI통신 초기화 함수
AVR ATMega128, ATMega8의 핀맵이 다르므로 아래와 같이 #if 문으로 정의해 두면 MCU에 따라 유용하게 사용할 수 있다.
void SPI0_Init(void) // SPI 통신 초기화 함수
{
 #if (__MCU_TYPE__ == AVR_TYPE_MEGA128)  
 // setup SPI I/O pins
 Cbi(PORTB, BIT1); // set SCK lo
 Sbi(DDRB, BIT1); // set SCK as output
 
 Sbi(DDRB, BIT2); // set MOSI as output
 Cbi(DDRB, BIT3); // set MISO as input
 
 Sbi(DDRB, BIT0); // SS must be output for Master mode to work
 Sbi(PORTB, BIT0);
 #else if (__MCU_TYPE__ == AVR_TYPE_MEGA8)
 Sbi(PORTB, BIT5); // set SCK lo
 Sbi(DDRB, BIT5); // set SCK as output
 
 Sbi(DDRB, BIT3); // set MOSI as output
 Cbi(DDRB, BIT4); // set MISO as input
 
 Sbi(DDRB, BIT2); // SS must be output for Master mode to work
 Sbi(PORTB, BIT2);
 #endif

 SPI0_ENABLE();
 SPI0_MASTER_MODE();
 
 SPI0_MODE0();
 SPI0_CLK_DOULBE();
 SPI0_CLK_DIV4();
}



SPI 데이터 송/수신 전송 함수
좀더 빠른 처리를 위해 define문으로 정의하는것이 좋다.
#define SPI0_WriteByte(Data)                             SPDR = (Data);  while(!(SPSR & (1<<SPIF)))

#define SPI0_WaitForReceive()                           while(!(SPSR & (1<<SPIF)))

#define SPI0_RxData()       (SPDR)


SPI데이터 수신 함수
보통 SPI Master의 경우 SPI데이터 전송후 수신하는 경우가 많기 때문에 WriteReadByte함수를 만들어 두면 유용하다.
unsigned char SPI0_WriteReadByte(unsigned char Data)
{
    SPI0_WriteByte(Data);
    return SPI0_RxData();
}
Posted by nexp

댓글을 달아 주세요