WIZnet Developer Forum

W7500P SPI관련문의

SPI로 data를 읽는데 Scope로 보는것과 읽어진값이 다릅니다.
Scope로 파형을 읽어보면 0x65가 보입니다. 그러나 uart로 확인해 보면 0x00이보이고 가끔은 0x65가 보일때도 있습니다. 문제가 뭔지 알수가 없습니다.

int main()
{
    uint8_t i;
    /* External Clock */
    CRG_PLL_InputFrequencySelect(CRG_OCLK);
    /* Set Systme init */
    SystemInit();
	GpioInit();
	S_UART_Init(57600);
    UART_StructInit(&UART_InitStructure);
    /* Configure UART0 */
    /* Retarget functions for GNU Tools for ARM Embedded Processors*/
    /* Configure Uart0 Interrupt Enable*/
    S_UART_ITConfig((UART_IT_FLAG_TXI|UART_IT_FLAG_RXI),ENABLE);
    /* NVIC configuration */
    NVIC_ClearPendingIRQ(UART2_IRQn);
    NVIC_EnableIRQ(UART2_IRQn);
  
    /* SysTick_Config */
    SysTick_Config((GetSystemClock()/1000));

    /* Set WZ_100US Register */
    setTIC100US((GetSystemClock()/10000));
    /* SSP0 Init -- SSP Master */ 
    SSP_StructInit(&SSP0_InitStructure);
    SSP0_InitStructure.SSP_SerialClockRate   = 0;				// 0 10 500KHz
    SSP0_InitStructure.SSP_FrameFormat  = SSP_FrameFormat_MO; // Motorora SPI mode
    SSP0_InitStructure.SSP_CPHA         = SSP_CPHA_1Edge; 
    SSP0_InitStructure.SSP_CPOL         = SSP_CPOL_Low; 
    SSP0_InitStructure.SSP_DataSize 	= SSP_DataSize_8b; 
    //SSP0_InitStructure.SSP_SOD 			= SSP_SOD_RESET;
    SSP0_InitStructure.SSP_NSS          = SSP_NSS_Hard;
    SSP0_InitStructure.SSP_Mode         = SSP_Mode_Master;
    SSP0_InitStructure.SSP_BaudRatePrescaler = 40;					// 40  about 500Khz
    SSP_Init(SSP0,&SSP0_InitStructure);    

    i = read_eeprom(0x0005);     // 실제값은 0x65가 있슴(scope로 확인함)
    printf("r\n rd : %x", i);              // 받아서 보면 값이 0x00이나옴 가끔 0x65가보일때도있슴)
}

void spi_out(byte data)
{
	SSP_SendData(SSP0, data);
	while( SSP_GetFlagStatus(SSP0, SSP_FLAG_BSY) );	
}

byte spi_in(void)
{
	byte data;
	uint16_t retry=0;
	
	GPIO_ResetBits(GPIOB, GPIO_Pin_3); 

	SSP_SendData(SSP0, 0xff);
	while( SSP_GetFlagStatus(SSP0, SSP_FLAG_BSY) );	
       // 위 부분이 없으면 읽기도전에 chip select를 끝내고 나옴
	retry = 10;

	while (SSP_GetFlagStatus (SSP0, SSP_FLAG_RNE) == RESET);
   	data = (byte)SSP_ReceiveData(SSP0);
   	GPIO_SetBits(GPIOB, GPIO_Pin_3);     //scope로 data읽는 시점을 보기위한 단자임

    return data;
}

byte read_eeprom(word add)                                      
{  
	byte data;
	_EepCsLo();
	spi_out(EepCmdRD);
	spi_out((byte)(add >> 8));
	spi_out((byte)(add & 0x00ff));
	data = spi_in();
	_EepCsHi();
        
    return data;
}

GPIOB 3번 Pin이 SPI cs 인가요?
sip_in에서는 cs 설정을 해주는데
spi_out에서는 cs 설정이 없네요
확인 해보시기 바랍니다.

답변 감사합니다.
위에 주석에서 설명한 것처럼 spi cs는 다른핀이고여 GPIOB pin3은 data를 읽는 time을 scope로 확인하기위해 임의의 핀을 설정해서 본것입니다.
spi_in()함수에서 SSP_ReceiveData()이 함수가 동작하는 시점을 보기위한것입니다. 확인결과 읽는 시점은 문제없어 보이고여…
현재 쓰는부분 spi wirite는 문제가 없어서 별도 내용을 추가하진 않은것입니다.
spi cs는 read_eeprom()함수에 있는 _EepCsLo();, _EepCsHi(); 이고여 GPIOB pin1입니다.

SSP BaudRate Prescaler 는 2의 승수 값으로만 설정이 가능합니다.
40으로 설정시 정상적인 동작이 보장되지 않습니다.

#define SSP_BaudRatePrescaler_2 ((uint32_t)0x0002)
#define SSP_BaudRatePrescaler_4 ((uint32_t)0x0004)
#define SSP_BaudRatePrescaler_8 ((uint32_t)0x0008)
#define SSP_BaudRatePrescaler_16 ((uint32_t)0x0010)
#define SSP_BaudRatePrescaler_32 ((uint32_t)0x0020)
#define SSP_BaudRatePrescaler_64 ((uint32_t)0x0040)
#define SSP_BaudRatePrescaler_128 ((uint32_t)0x0080)
#define SSP_BaudRatePrescaler_254 ((uint32_t)0x00FE)

define 되어있는 값들이 있으니 해당값으로 수정하시 거나 0x40으로 수정하시길 바랍니다.

위 말씀하신대로 아래처럼 수정하였으나 결과는 같습니다.
SSP0_InitStructure.SSP_BaudRatePrescaler = SSP_BaudRatePrescaler_64;

RS232로 받은 data를 보여드리면
rd : 65r rd : 0r rd : 0r rd : 0r rd : 65r rd : 0r rd : 0r rd : 0r rd : 0r rd : 0r
실제 0x65 값이 있고 scope로 확인해도 0x65가 확인되는데
data = (byte)SSP_ReceiveData(SSP0); 이 SSP_ReceiveData(SSP0) 함수로 읽는 값이 정상이 아닌것이 이유를 모르겠습니다.

while (SSP_GetFlagStatus (SSP0, SSP_FLAG_RNE) == SET) 으로 변경해주셔야할것 같습니다.
RNE flag는 1인 경우가 Receive FIFO에 데이터가 있는경우입니다.

답변감사합니다.
말씀하신대로
while (SSP_GetFlagStatus (SSP0, SSP_FLAG_RNE) == SET):
이렇게 하면 이부분에서 나오지 못하고 무한루프상태입니다.

추가로 말씀드리면 위 spi_in()함수는 W7500P_FW 예제중
SD_Card_LED중 mmc_sd.c에서
uint8_t bsp_readwritebyte_spi1 (uint8_t tx_data)
{
uint16_t retry=0;
/* Loop while DR register in not emplty /
while (SSP_GetFlagStatus (SSP1, SSP_FLAG_TNF) == RESET)
{
retry++;
if(retry>400)
return 0;
}
/
Send byte through the SPI1 peripheral /
SSP_SendData (SSP1, tx_data);
retry=0;
/
Wait to receive a byte */
while (SSP_GetFlagStatus (SSP1, SSP_FLAG_RNE) == RESET)
{
retry++;

	if(retry>400)
		return 0;
}		
/* Return the byte read from the SPI bus */
return SSP_ReceiveData (SSP1);

}
이부분의 예제를 참고한것입니다.

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.