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()
#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)
#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();
}
{
#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)
#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();
}
{
SPI0_WriteByte(Data);
return SPI0_RxData();
}
출처 : http://nexp.tistory.com/1047
'AVR(AT90CAN128)공부' 카테고리의 다른 글
K5 스마트 코너링 램프 모듈 제작 (28) | 2011.12.08 |
---|---|
요즘 가지고 노는놈 (13) | 2011.08.25 |
KOBD 방식의 배터리센서 전류 모니터링 (11) | 2011.06.13 |
KOBD 방식의 미션오일온도 게이지(표시기) (7) | 2011.06.13 |
분배저항(전압분배) / 병렬저항 계산기 (0) | 2011.06.10 |