반응형

STM32F103 series MCU의 hardware SPI interface를 사용하기 위해서 아래와 같이 GPIO 설정이 필요로 한다.

 

STM32F103RBT6 datasheet

#define GPIO_HW_SPI            GPIOA
#define GPIO_HW_SPI_CS                  GPIO_Pin_4    // NSS PIN
#define GPIO_HW_SPI_SCLK                GPIO_Pin_5    // Clock
#define GPIO_HW_SPI_MISO                GPIO_Pin_6    // Master Input to Slave Output
#define GPIO_HW_SPI_MOSI                GPIO_Pin_7    // Master Output to Slave Input

#define HW_SPI_READ_BIT			0x80
#define HW_SPI_WRITE_BIT		0x00

/* Select hardware SPI: Chip Select pin low  */
#define HW_SPI_CS_LOW()       GPIO_ResetBits(GPIO_HW_SPI, GPIO_HW_SPI_CS)
/* Deselect hardware SPI: Chip Select pin high */
#define HW_SPI_CS_HIGH()      GPIO_SetBits(GPIO_HW_SPI, GPIO_HW_SPI_CS)

void MXM1160_HW_SPI_GPIO_Init(void){

    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable SPI1 and GPIO clocks */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);

    /* Configure SPI1 pins: SCK, MISO and MOSI */
    GPIO_InitStructure.GPIO_Pin   =  GPIO_HW_SPI_SCLK | GPIO_HW_SPI_MOSI | GPIO_HW_SPI_MISO;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIO_HW_SPI, &GPIO_InitStructure);

    /* Configure I/O for the sensor select */
    GPIO_InitStructure.GPIO_Pin   =  GPIO_HW_SPI_CS;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init(GPIO_HW_SPI, &GPIO_InitStructure);

    /* Deselect the hardware SPI : Sensor Select high */
    HW_SPI_CS_HIGH();

    /* SPI1 configuration */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 1;
    SPI_Init(SPI1, &SPI_InitStructure);

    /* Enable SPI1  */
    SPI_Cmd(SPI1, ENABLE);    
}

 

위의 'SPI_InitStructure.SPI_CPOL"와 'SPI_InitStructure.SPI_CPHA'는 사용자 개발 환경과 SPI 통신을 사용하는 slave chip의 통신 모드의 Clock Plarity (CPOL), Clock Phase (CPHA)의 의해 결정되므로 개별적으로 확인하길 바란다.

 

그 다음에 SPI 통신은 양방향 통신이기 때문에 Read / Write command에 따라 dummy byte 등 적절한 array index 관리를 해주면 된다.

 

void  HW_SPI_Multi_TXRX(uint8_t Cmd, uint8_t addr, uint8_t count, uint8_t  *pData)
{
    uint8_t BufferSize = count;
    uint8_t SPI_Dummy_Tx = 0x00;
    uint8_t SPI_Dummy_Rx = 0x00;
	
    // Check the Command mode and Address
    SPI_Dummy_Tx = Cmd | addr;

    HW_SPI_CS_LOW();

    /* Wait for SPIy Tx buffer empty */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    /* Send SPIy data */
    SPI_I2S_SendData(SPI1, SPI_Dummy_Tx);

    /* Wait for SPIy data reception */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    /* Read SPIy received data */
    SPI_Dummy_Rx = SPI_I2S_ReceiveData(SPI1);

    while(count>1){

        /* Wait for SPIy Tx buffer empty */
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        /* Send SPIy data */
        SPI_I2S_SendData(SPI1, pData[BufferSize-count]);

        /* Wait for SPIy data reception */
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
        /* Read SPIy received data */
        if ( Cmd == HW_SPI_READ_BIT ){
            pData[BufferSize-count] = SPI_I2S_ReceiveData(SPI1);
        }
        else{
            SPI_Dummy_Rx = SPI_I2S_ReceiveData(SPI1);
        }			
        count--;
    }

    /* Wait for SPIy Tx buffer empty */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    /* Send SPIy data */
    SPI_I2S_SendData(SPI1, pData[BufferSize-count]);

    /* Wait for SPIy data reception */
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    /* Read SPIy received data */
    if ( Cmd == HW_SPI_READ_BIT ){
        pData[BufferSize-count] = SPI_I2S_ReceiveData(SPI1);
    }
    else{
        SPI_Dummy_Rx = SPI_I2S_ReceiveData(SPI1);
    }
		
    HW_SPI_CS_HIGH();
}

 

마지막으로 SPI 통신의 waveform grpah 관련 자료는 구글링을 하면 되므로, 검색 스킬을 발휘하길 바란다.

 

끝.

반응형

+ Recent posts