본문 바로가기

Enginius/Firmware

PIC32 - SPI


SPI라 함은 Serial Peripheral Interface가 되겠다.
I2C와 비슷하지만 2 wire를 이용하는 I2C다르게 3-4개의 wire를 이용하지만 전송 속도는 I2C의 최대 수십배에 다른다.


SPI 의 기본 구성의 위의 도면과 같다.
마스터와 슬레이브와는 4개의 wire가 있다. MOSI(Master out Slave in), MISO(Master in Slave out), SCLK, SS(Slave Select).
마스터 IC의 SCLK에 맞춰서 쌍방의 8비트 shift register의 데이타를 교환한다.

SPI의 데이터 송수신은 clock의 edge에서 일어난다. clock의 어떤 상태에서 data 송수신이 일어나는가에 따라서 4개의 모드로 나뉠 수 있다. 




SPI Control Registers

SPIxCON(x는 숫자)
 bit31
     FRMEN: Framed SPI Support bit
     1: Framed SPI Support enable ( nSSx pin used as FSYNC input/output)
     0: Framed SPI Support disable

 bit30
     FRMSYNC: Framed Sync Pulse Directon Control on nSSx pin (Framed SPI Mode 에서만)
     1: Frame sync pulse input (Slave Mode)
     0: Frame sync pulse output (Master Mode)
 
 bit29
     FRMPOL: Framed Sync Polarity bit(Framed SPI Mode 에서만) 
     1: Framed pulse active high
     0: Framed pulse active low
 
 bit28
     MSSEN: Master Mode Slave Select Enable bit
     1: Slave select spi support enable. nSS핀이 tx과정에서 자동으로 구동된다. 극성은 FRMPOL bit에 의해서 정해진다.
 하지만 이 기능은 모든 프로세서에 제공되지는 않는다. 우리가 사용하는 PIC32MX460에서도 지원되지 않는다. 그렇기 때문에 nSS2핀을 강제로 구동시켜야한다. Tx를 하기 전에 low로 내리고, Tx가 완료되고 나서는 High로 올려야 한다.
     0: Framed SPI Support disable
 
 bit26-24
     FRMCNT<2:0>: Framed Sync Pulse Counter bits
     111 = Reserved; do no use
     ....
    000 = 매 data character마다 frame sync pulse를 생성한다. 

 bit23-18
     Reserved: 
 
 bit17
     SPIFE: Framed Sync Pulse Edge Select bit (Framed SPI Mode only)
     1: Frame 동기화 펄스가 처음 비트 클락과 동시에 일어난다.
     0: Frame 동기화  펄스가 처음 비트 클락보다 선행해서 일어난다.
 
 bit16
     ENHBUF: Enhanced Buffer Enable bit
     1: Enhanced Buffer mode를 사용한다.  
     0: Enhanced Buffer mode를 사용하지 않는다. 
 이 mode는 모든 칩에가 가능한 것은 아니다 이 비트는 ON비트가 0일때만 쓸 수 있다. (이 비트를 먼저 바꾸고, ON비트를 1로 해야한다. )
 
 bit15
     ON: SPI perpheral ON bit
     1: SPI를 사용한다.
     0: SPI를 사용하지않느다. 
 
 bit14
     FRZ: Freeze in Debug Exception Mode bit
     1: 디버그 모드에서 멈춤다.
     0: 디버그 모드에서 멈추지 않는다.
 
 bit13
     SIDL: Stop in Idle Mode bit
     1: Idle모드에서 멈춘다. 
     0: Idle 모드에서 계속 동작한다.   

 bit12
     DISSDO: SDOx 핀을 사용하지 않는다.
     1: SDO 핀을 일반 gpio로 사용한다.
     0: SDO 핀을 SPI 모듈에서 제어한다.
 
 bit11-10
     MDOE<32,16>: Framed SPI Support bit
     1x: 32-bit data
     01: 16-bit data
     00. 8-bit data
  
 bit9
     SMP: SPI Data Input Sample Phase bit
     Master mode (MSTEN = 1)
     1: Input data가 data output time 끝에 sample된다.
     0: Input data가 data output time 중간에 sample된다. 
    Slave mode (MSTEN = 0)
     SMP = 0

 bit8
     CKE: SPI Clock Edge Select bit
     1: (CKP bit에 따른) active clock state에서 Idle clock state로 갈 때 output data가 변한다.
     0: (CKP bit에 따른) idle clock state에서 active clock state로 갈 때 output data가 변한다.  

 Framed SPI 모드에서는 CKE를 0으로 해야한다.

 bit7
     SSEN: Slave Select Enable (Slave mode) bit
     1: nSSx 핀이 Slave 모드로 쓰인다.
     0: nSSx 핀이 일반 포트로 쓰인다. 
 
 bit6
     CKP: Clock Polarity Select bit
     1: Actice Low
     0: Active High

bit5
     MSTEN: Framed SPI Support bit
     1: Master mode
     0: Slave mode

 bit4
     Reserved:  

 bit3-2
     STXISEL<1:0>: SPI Transmit Buffer Empty Interrupt Mode bits (TX가 다 끝났다는 EVENT)
     11: 버퍼가 가득 차지 않았을 때 SPI_TBE_EVENT가 set 된다.
     10: 버퍼가 절반 이하로 비었을 때 SPI_TBE_EVENT가 set된다. 
     01: 버퍼가 비었을 때 SPI_TBE_EVENT가 set된다.
     00: Tx가 끝났을 때 SPI_TBE_EVENT가 set된다.

 
 bit1-0
     RTXISEL<1:0>: SPI Receive Buffer Full Interrupt Mode bits (RX가 다 끝났다는 EVENT)
     11: 버퍼가 가득 찼을 때 SPI_RBF_EVENT가 set 된다.
     10: 버퍼가 절반 이상 찾을 때 SPI_RBF_EVENT가 set된다. 
     01: 버퍼가 비지 않았을 때 SPI_RBF_EVENT가 set된다.
     00: Rx가 끝났을 때 SPI_RBF_EVENT가 set된다.



SPI2BRG
 : SPI Baud Rate Register 
  SPI freq = Fpb / (2 * (SPI2BRG+1))
 [ 960kHz = 8000000 / (2 * (40+1)) ]


void Init_spi()
{
//	SpiInitDevice(2, 1, 1, 1);    	// initialize the SPI channel 2 as master, frame master
//	initSEE();				//explorer16에서 eeprom 테스트 	

	SPI2CONbits.ON		= 1;		// 킨다. 
	SPI2CONbits.FRZ		= 0;
	SPI2CONbits.SIDL		= 0;
	SPI2CONbits.DISSDO	= 0;
	SPI2CONbits.MODE32 	= 0;
	SPI2CONbits.MODE16	= 1;
	SPI2CONbits.SMP		= 0;		//한 주기 클럭 중간에서 데이터 출력 위상 설정
	SPI2CONbits.CKE		= 1;		// 0: Idle에서 active로 갈 때 data transaction 1: 반대
	SPI2CONbits.SSEN	= 1;		// Slave select enable
	SPI2CONbits.CKP		= 0;		// 0: active high 1: 반대
	SPI2CONbits.MSTEN	= 1;
	
	SPI2STATbits.SPIROV	= 0;		//수신 오버플로우 초기화

	#define SPI2_BAUD    40		// clock divider Fpb/(2 * (40+1)) = 960KHz
	SPI2BRG = SPI2_BAUD;			// select clock speed(960KHz)
	
	AUDIO_RESET = 1;
	
	nSS2 = 1;
}

int writeSPI2( int i)
{
	nSS2 = 0;

	//myprintf("SPI: 0x%X\r\n", i);
	SPI2BUF = i;                  	// write to buffer for TX
	while( !SPI2STATbits.SPIRBF); // wait for transfer complete


	nSS2 = 1;
	return SPI2BUF;               // read the received value
}



'Enginius > Firmware' 카테고리의 다른 글

PIC32 - UART  (2) 2010.04.13
PIC32 - TIMER  (0) 2010.04.13
PIC32 - PWM  (0) 2010.02.19
PIC32 - Input Capture  (0) 2010.02.19
PID 제어  (1) 2010.02.18