[W7500] SPI 통신할때 포트 관련 문의입니다.

W7500 SPI 통신 할 때 SE_CLK 설정 하고 오실로스코프로 파형을 찍어보는데 1만 계속 인가되네요…

제가 PB_01 포트로

GPIO_InitDef.GPIO_Pin = GPIO_Pin_1;
GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOB, &GPIO_InitDef);
PAD_AFConfig(PAD_PB,GPIO_Pin_1 , PAD_AF0); (normal function 으로 setting 했습니다)

이렇게 포트 설정을 하고,

GPIO_SetBits(GPIOB, GPIO_Pin_1)
GPIO_ResetBits(GPIOB, GPIO_Pin_1) 로 clk 를 만들어서 보내면 되는거 아닌가요 ??

data send 함수는

void SPI_Send_16(unsigned long data)
{
unsigned char Bit_Cnt;
unsigned int SendBuf;
SendBuf = data;
for (Bit_Cnt = 0; Bit_Cnt < 16; Bit_Cnt++)
{
if ( SendBuf & 0x00000001)
{
SetBitSpiPort ;
}
else
{

ResetBitSpiPort;
					 }
					 SetSpiClk;
					 SendBuf = SendBuf >>1;
         ResetSpiClk;						 
		 }

}

식으로 만들어서 Main 에서는

while(1)
{
SPI_Send_16(0x00000000);
Latch_Enable(); // Latch는 PC_06 을 1us delay를 두고 토글 시켰습니다.
}
이런식으로 사용 했습니다.

그러면 16비트

아래 링크에 답변 드렸습니다.

감사합니다 :slight_smile:

안녕하세요 :smile:
WIZnet 연구원 정찬미입니다.

질문1
저희 예제 소스가 잘못 구현되어있습니다.
실수가 있었던것 같습니다. 추후 수정하도록 하겠습니다.
SPI 최대 Clock는 24MHZ 이며, 20MHz 이하로 사용하는것을 권장드립니다.
Clock 설정은 CR0레지스터의 [15:8] bit(SCR)을 이용해 할 수 있습니다.

질문2.


datasheet v110의 92page image입니다.
single transfer의 경우 특정 구간에서만 nSSPOE가 Low되어있고, continuous transfers의 경우 계속 Low 되어있음을 확인 할 수 있습니다.

말씀하신 W7500의 SD카드 예제 기준으로 말씀드리면,
read, write함수의 처음과 마지막에 MSD_CS_ENABLE(); MSD_CS_DISABLE(); 를 사용하고 있습니다.
MSD_CS_DISABLE();함수를 통신을 끝낼때만 작성해주시면 될것 같습니다.

질문3.
질문이 잘 이해가 가지않습니다. 좀더 자세히 말씀해주세요

더문의 사항이 있으시면 답글 달아주세요.
감사합니다.

안녕하세요.

System클럭을 기준으로 SSP 클럭 분주하는 예제는 따로 없습니다만,
간단하게 만들어 아래와 같이 첨부드립니다.

#include "W7500x_ssp.h"
#include "W7500x_crg.h"

SSP_InitTypeDef SSP0_InitStructure;
uint16_t send_data = 0x0102;

int main()
{
    /* System clock */
    SystemInit();

    /* Select source clock  */
    CRG_PLL_InputFrequencySelect(CRG_OCLK); //External Clock

    /* Update FOUT, PLL_FCR */
    *(volatile uint32_t *)(0x41001014) = 0x0060100; //clock setting 48MHz
    //*(volatile uint32_t *)(0x41001014) = 0x0050100; //clock setting 40MHz
    
    /* Set SSP source clock & prescale */
    //CRG_SSPCLK_SourceSelect(CRG_MCLK);
    //CRG_SSPCLK_SetPrescale(CRG_PREDIV1);

    /* SSP0 Init -- SSP Master */ 
    SSP_StructInit(&SSP0_InitStructure);
    SSP0_InitStructure.SSP_FrameFormat  = SSP_FrameFormat_TI; // SPI mode
    SSP0_InitStructure.SSP_DataSize = SSP_DataSize_16b;
    SSP0_InitStructure.SSP_BaudRatePrescaler = (uint32_t)0x0002; //SSP_BaudRatePrescaler_2;
    SSP_Init(SSP0,&SSP0_InitStructure);

    while (1) {
        SSP_SendData(SSP0, send_data);
    }
}

ssp 분주비 관련된 define이 수정이 필요한 상태라서,
위 코드처럼 직접 HEX값으로 지정하였습니다.

PLL의 경우는 위에 미리 만들어둔 48Mhz나 40Mhz 라인을 사용하셔도 되며, SystemInit()함수나 SystemCoreClockUpdate() 함수를 통해서도 변경 가능하십니다.

추가로, SSP에서 사용할 소스클럭과 그에 대한 분주비를 선택할 수 있는 내용도 주석으로 추가해두었습니다. 필요에 따라 사용하시면 되겠습니다.


자체 테스트 결과,
8Mhz 외부 클럭을 PLL을 통해 48Mhz로 만들고,
SSP 분주비를 통해 24Mhz가 출력되는 것을 확인하였습니다.
다만, 칩 팀에서는 20Mhz 이하로 사용할 것을 권하고 있습니다.

CS의 경우는 어떤 SPI 장비와 통신을 할 것인지 선택하는 기능입니다.
따라서 이 것에 의해서 클럭이 지속적으로 발생하지는 않습니다.
(다만, 여러 Slave와 사용할 때는 신경써야 하는 부분입니다)

그리고, 기본적으로 SPI에서 마스터는 데이터 전송이 끝나면 클럭을 내보내지 않습니다.

Transmission may continue for any number of clock cycles. When complete, the master stops toggling the clock signal, and typically deselects the slave. - Wikipedia


제가 보기에는, 저희 예제에 설정되어 있는 모드(모토로라)를 그대로 사용하셔서 발생한 이슈 같습니다.
TI사의 경우, TI만의 포맷을 사용할 수도 있습니다.

직접 문의주실 때, TI사의 제품(ADS1248)을 사용한다고 하셨고,
이 제품에서는 연속된 통신을 할 때, SCLK가 주기적으로 발생해야 한다고 하셨습니다.

따라서 이 경우는 W7500의 SSP 모드를 TI로 변경하셔야 합니다.
TI 포맷과 관련한 W7500에 대한 내용은 W7500 레퍼런스 메뉴얼 p.459의 Figure57, Figure58을 참조해주세요.

우선 직전에 올린 코드도 TI 모드로 수정하였습니다.

1 Like

현재 보내고 있는 코드를 보여주실 수 있나요?

8bit만 보내실거면 위 함수를 사용하실 때 주의하셔야 합니다.
위 함수는 16bit 파라미터를 받고 있으며, SPI에서는 이 중에 8bit만큼만 전송합니다.

추가로 함수를 사용하시고 또 함수를 사용하시면,
현재처럼 고속의 속도에서는 함수를 호출하고 다른 처리를 하는 과정에서 시간이 소요됩니다.

만약 시스템 클럭의 절반의 속도로 SPI 클럭을 내고 있다면 이는 당연한 현상임을 이해하실 것입니다.

따라서 이 경우는 함수를 별도로 만드셔서 SSPx_DR에 전송하고자 하는 데이터를 8bit씩 반복하여 입력하는 방식으로 진행하셔야 합니다.
혹은 SSP클럭의 속도를 더 낮추시면 됩니다.

추가로, TI ADS1248이 어떠한 요구조건을 가지고 있는지는 알 수 없으나,
SPI는 기본적으로 동기 통신입니다.
따라서, 클럭간의 시간 제한만 충족시킨다면 데이터 전송에는 지장이 없음을 참조해주시길 바랍니다.

어떤 메일로 보내셨나요?
Forum에서는 제 메일이 공개되어 있지 않기때문에 어디로 전송하셨는지 알 수 없습니다.
( 제 메일에는 새로운 메일이 없습니다 )

재전송이 가능하시다면, support@wiznet.io 로 메일 주시길 바랍니다.

답변에 앞서 말씀드리면,
ioLibrary의 경우, 기본 API만을 제공하기때문에 나머지 내용들은 유저가 직접 작성해야 합니다.

사용하시는 칩이 표준 SPI를 사용한다면, 모토로라 모드를 사용하셔야 됩니다.
이 때, 클럭이 연속되는 것처럼 보이지 않는 것은 모토로라 프로토콜에 의한 것입니다
(연속되게 전송하여도 아래와 같이 나오는 것은 프로토콜에 의한 당연한 현상입니다)

참고로 위처럼 전송하기 위해서는 별도로 함수를 구성하셔야 됩니다.
원래 응용 함수를 제공하지는 않지만 테스트에서 만들어 사용했던 것을 공유드립니다.

void SSP_SendBuffer(SSP_TypeDef* SSPx, uint16_t* data, uint16_t len)
{
	/* Check the parameters */
	assert_param(IS_SSP_ALL_PERIPH(SSPx));

	for(uint8_t i=0; i<len; i++)
	{
            while(SSP_GetFlagStatus(SSPx, SSP_FLAG_BSY));
            SSPx->DR = data[i];
	}
}

추가로, 8bit 단위로 전송할 때에는, 아래와 같이 데이터시트(SSPxDR)에 나와 있는 내용을 주의해주세요.

You must right-justify data when the SSP0 is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies.

더불어, 제가 첨부한 이미지와 비교하여 아래 내용에 대해 답변 드리면,

간격의 차이는 CPU클럭과 SPI클럭의 차이로 인해 발생하는 것입니다.
코드가 동작 중에 CPU클럭과 SPI클럭이 각각 얼마나 진행되는지 비교해보시면 바로 이해하시리라 판단됩니다.

데이터와 상관없이 계속 마스터의 클럭이 발생해야한다는 것인가요? (이는 표준 SPI가 아닙니다)
어떤 의도인지는 알 수 없지만, Ti칩에서 데이터시트에 명시되어 있는건가요?

만약 그렇다면, SPI페리가 아닌 일반 GPIO로 클럭을 생성하셔야 합니다.

연속된 데이터에서도 중간에 클럭이 로우로 떨어지는 이유는 모토로라 표준 프로토콜에 의한 것입니다.
정말 Ti칩이 표준 프로토콜을 요구하고 있는 것인지 이를 변형한 내용을 요구하는 것인지에 대해서는 TI측에 문의해서 확실히 하시는게 좋다고 판단됩니다.
후자의 경우는, 표준 모토로라 프로토콜을 사용하는 페리로는 안되므로 사용자가 직접 커스터마이징 해야합니다.

먼저 질문드리고 싶은 것이 있습니다.
이전에 드린 방식으로는 ADS1248과 통신 자체가 안되시는건가요?
일반적인 SPI라면, 클럭의 연속 유무(몇 클럭 차이 수준)에 따라 통신이 안되지는 않습니다.
사용하시는 ADS1248의 요구사항이 다르다면 모르겠지만, 일반적으로는 그러합니다.


모토로라 프로토콜 특성상 각 전송마다 클럭 로우 구간이 발생합니다.
(물론 이는 기본 값이며, SPO와 SPH에 따라 달라집니다)

Cortex M0를 사용한다고 해서 무조건 같은 Peri IP를 사용하지는 않습니다.
따라서 시중의 m0가 올려주신 파형이 나온다고해서 W7500에서 나오는 것은 아닙니다.

질문자님과는 반대의 경우로 위 파형을 일반적인 형태로 만들기 위한 이슈도 있는데, 필요하시다면 아래 링크를 참조해주세요.
STMicroelectronics사 Cortex-M0에서의 기괴한 SPI 동작


추가로 오픈하드웨어에서 사용되는 몇가지 라이브러리를 첨부하니 참조해보시길 바랍니다. 이 중 mbed의 경우는 W7500 위키 보드에도 적용할 수 있습니다.

ADS1248에서 SSPCLKOUT polarity, SSPCLKOUT phase에 대한 설정값을 특별히 요구한 것이 있나요?
이 것에 따라 작동 방식이 달라집니다. (자세한 내용은 여기를 참조)

혹시 통신이 안되신다면 이 부분을 다시 확인해주세요.

필요하다면, 요구사항에 맞게 이부분도 레지스터에 적용해주셔야 합니다. 위에서 보내드렸던 코드는 둘다 0입니다.


추가로 아래는 W7500에서 사용하고 있는 SSP입니다.
ARM SSP이며, 모든 세부 내용은 이 곳에 나와 있습니다.
ARM PrimeCell® Synchronous Serial Port (PL022) Technical Reference Manual

물론, 칩 인터페이스에 의해 다소 차이는 있을 수 있지만 기본 특성은 동일하므로 위 내용에서 벗어나는 것은 사용할 수 없습니다.

W7500이 8bit Command를 전송하여, ADS1248에서 24bit 데이터 출력은 된다는 말씀이신가요?

ADS1248 방식 자체가 마스터의 커맨드에 의한 요청과 상관없이 클럭만 맞춰주면 데이터를 내보내는 형태인가요?

제가 보기엔, SPI특성에 의한 이슈보다는 ADS1248에 대한 어플리케이션 구현 이슈 같습니다. ADS1248 데이터시트와 위에 링크드린 GitHub코드를 참조하셔서 코드를 작성해보시는게 좋을 것 같습니다.

만약, 어플리케이션 구현을 ADS1248에 맞게 하셨다면,
우선은 Ti사에 구현하신 형태로 통신하는게 맞는지 문의해보시는 것이 좋다고 판단됩니다.
추가로, 그 클럭에 대한 문의를 해보시고, "무조건 연속적으로 발생해야만 통신이 된다."라고 가이드를 해야지만, W7500의 SSP 특성에 대해 더 논의하는게 의미 있을 것 같습니다.