cancel
Showing results for 
Search instead for 
Did you mean: 

About S2LP with STM32F103VCT

Son, Dong-Seong
Associate III

Hello everyone,

I’m trying to control an S2-LP QTR via SPI1 on an STM32F103VCT.

I completed the initial setup and configured the radio to 420 MHz.

I then wrote a routine to transmit periodically, but I’m not seeing any RF output on the antenna pin.

Below is the code I’m using for the S2-LP QTR. Any ideas what might be going wrong?

 
 
void S2LP_Init(void)
{
	// 1 : SDN pin LOW -> Enter operating mode
    S2LP_SDN_LOW();   // SDN LOW → 동작모드
    HAL_Delay(10);

    // 2 :  soft reset (SRES)
//    S2LP_SoftReset();
    S2LP_SetCommand(CMD_SRES);

    // 3 : Setting XO/ RCO
    // Disable digital clock divider -> digital clock = fxo
	S2LP_WriteReg(XO_RCO_CONF1_ADDR, PD_CLKDIV_REGMASK);
    S2LP_WriteReg(XO_RCO_CONF0_ADDR, EXT_REF_REGMASK | GM_CONF_REGMASK);

    // 4 : SMPS power management configuration
    // 4-1 : internal smps
//    S2LP_WriteReg(PM_CONF4_ADDR, 0x00);
    // PM_CONF0: SET_SMPS_LVL = 011b → 1.4V (HPM), SLEEP_MODE_SEL=0
//    S2LP_WriteReg(PM_CONF0_ADDR, SET_SMPS_LVL_REGMASK);  // :contentReference[oaicite:3]{index=3}
    // PM_CONF1: default (battery level detection enabled, SMPS level mode in TX)
//    S2LP_WriteReg(PM_CONF1_ADDR, BATTERY_LVL_EN_REGMASK | SET_BLD_TH_REGMASK);         // :contentReference[oaicite:4]{index=4}

    // 4-2 : external smps
    S2LP_WriteReg(PM_CONF4_ADDR, EXT_SMPS_REGMASK);

    // 5 : Setting GPIO
    S2LP_WriteReg(S2LP_GPIO0_CONF, (GPIO_Digi_Out_TX_FIFO_Empty<<GPIO_SELECT_BIT) 	| (GPIO_DigitalOutputLow<<GPIO_MODE));  // GPIO0: TX FIFO Almost Empty
    S2LP_WriteReg(S2LP_GPIO1_CONF, (GPIO_Digi_Out_RX_Data_Out<<GPIO_SELECT_BIT) 	| (GPIO_DigitalOutputLow<<GPIO_MODE));  // GPIO1: RX data ready
    S2LP_WriteReg(S2LP_GPIO2_CONF, 0x00);  // GPIO2: NIRQ
    S2LP_WriteReg(S2LP_GPIO3_CONF, 0x00);  // GPIO3: LOW

    // 6 : Data rate setting (e.g., datarate in bps)
    // mantissa/exponent Calculation : DataRate = fdig * M / 2^E
    uint64_t tmp = (uint64_t)datarate << 28;
    uint32_t dr_mant = (uint32_t)(tmp / fxo);
    uint8_t  dr_exp  = (dr_mant >> 28) & 0x0F;
    uint16_t dr_man  = (uint16_t)(dr_mant & 0x0FFF);
    S2LP_WriteReg(MOD4_ADDR, (uint8_t)(dr_man >> 8));   // DATARATE_M[15:8] :contentReference[oaicite:5]{index=5}
    S2LP_WriteReg(MOD3_ADDR, (uint8_t)(dr_man & 0xFF)); // DATARATE_M[7:0]  :contentReference[oaicite:6]{index=6}
    // MOD2: upper 4 bits = modulation type (2-GFSK BT=0.5 → 0xA), lower 4 bits = dr_exp
    S2LP_WriteReg(MOD2_ADDR, (0xA << 4) | dr_exp);

    // 7 : FDEV: frequency deviation setting (e.g., 20 kHz)
    uint32_t fdev = 20000;
    tmp = (uint64_t)fdev << 18;
    uint32_t fdv_mant = (uint32_t)(tmp / fxo);
    uint8_t  fdv_exp  = (fdv_mant >> 8) & 0x0F;
    uint8_t  fdv_man  = (uint8_t)(fdv_mant & 0xFF);
    S2LP_WriteReg(MOD0_ADDR, fdv_man);                 // FDEV_M :contentReference[oaicite:7]{index=7}
    // CONST_MAP: default = 0, lower 4 bits = fdv_exp
    S2LP_WriteReg(MOD1_ADDR, (0 << 4) | fdv_exp);      // CONST_MAP+FDEV_E :contentReference[oaicite:8]{index=8}

    HAL_Delay(1);
    S2LP_WriteReg(PA_POWER8_ADDR, 80);			// +10dBm
    S2LP_WriteReg(PA_POWER7_ADDR, 76);			//  +8dBm
    S2LP_WriteReg(PA_POWER6_ADDR, 72);			//  +6dBm
    S2LP_WriteReg(PA_POWER5_ADDR, 68);			//  +4dBm
    S2LP_WriteReg(PA_POWER4_ADDR, 64);			//  +2dBm
    S2LP_WriteReg(PA_POWER3_ADDR, 60);			//  +0dBm
    S2LP_WriteReg(PA_POWER2_ADDR, 56);			//  -2dBm
    S2LP_WriteReg(PA_POWER1_ADDR, 52);			//  -4dBm
}


void S2LP_SetFrequency(float freqMHz)
{
    const float fXO = 25.0f;             // 25 MHz crystal
    const uint8_t BS = 8;        // SYNT3 bit4 = 1 for middle band
    const uint8_t BSbit = BS_REGMASK;

    // 28-bit N = freqRF × 2^20 / fXO
    uint32_t N = (uint32_t)((freqMHz * BS * (1 << 20)) / fXO);

    // 분해
    uint8_t synt3 = ((N >> 24) & 0x0F) | BSbit;
    uint8_t synt2 =  (N >> 16) & 0xFF;
    uint8_t synt1 =  (N >>  8) & 0xFF;
    uint8_t synt0 =   N        & 0xFF;

    // 올바른 레지스터에 쓰기
    S2LP_WriteReg(SYNT3_ADDR, synt3);   // 0x05, SYNT3(PLL_CP_ISEL|BS|N[27:24])
    S2LP_WriteReg(SYNT2_ADDR, synt2);   // 0x06, N[23:16]
    S2LP_WriteReg(SYNT1_ADDR, synt1);   // 0x07, N[15:8]
    S2LP_WriteReg(SYNT0_ADDR, synt0);   // 0x08, N[7:0]

    S2LP_SetCommand(CMD_RCO_CALIB);		// Start (or re-start) the RCO calibration
    S2LP_SetCommand(CMD_LOCKTX);
    S2LP_SetCommand(CMD_LOCKRX);
}

void S2LP_SetOutputPower(uint8_t level_index)
{
    // 인덱스 범위 체크
    if(level_index > 7) {
    	level_index = 7;
    }

    // PA_POWER0: HPM(최대 dBm) 모드 + 램핑 사용 + level 인덱스
    uint8_t pa0 = PA_MAXDBM_REGMASK       // bit6 = 1 → HPM 모드
                | PA_RAMP_EN_REGMASK     // bit5 = 1 → 램핑 사용
                | (level_index & PA_LEVEL_MAX_IDX_REGMASK);
    S2LP_WriteReg(PA_POWER0_ADDR, pa0);

    // PA_CONFIG1: 선형 모드 + FIR 필터링
    uint8_t pa1 = LIN_NLOG_REGMASK        // bit4 = 1 → 선형 모드
                | FIR_EN_REGMASK;        // bit1 = 1 → FIR 사용
    S2LP_WriteReg(PA_CONFIG1_ADDR, pa1);
}

void S2LP_SendPacket(uint8_t* data, uint8_t length)
{
	S2LP_SetCommand(CMD_READY);
    S2LP_SetCommand(CMD_FLUSHTXFIFO);

    S2LP_WriteReg(PCKTLEN1_ADDR, (length >> 8) & 0xFF); // PCKTLEN
    S2LP_WriteReg(PCKTLEN0_ADDR, length        & 0xFF);   // SYNC config

    // FIFO write
    S2LP_CSN_LOW();
    uint8_t cmd = CMD_WRITE_FIFO;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 		HAL_MAX_DELAY);
    HAL_SPI_Transmit(&hspi1, data, length, 	HAL_MAX_DELAY);
    S2LP_CSN_HIGH();

    // Start TX
    S2LP_SetCommand(CMD_TX);

    while ((S2LP_ReadReg(MC_STATE1_ADDR) & (1<<7)) == 0) {
        HAL_Delay(1);
    }

    S2LP_SetCommand(CMD_READY);
    S2LP_SetCommand(CMD_FLUSHRXFIFO);

    S2LP_SetCommand(CMD_RX);
}


void S2LP_StartRx(void) {
    S2LP_WriteReg(0x3E, 64); // 예상 최대 수신길이
    uint8_t rx_cmd = 0x61;   // RX Command
    S2LP_CSN_LOW();
    HAL_SPI_Transmit(&hspi1, &rx_cmd, 1, HAL_MAX_DELAY);
    S2LP_CSN_HIGH();
}

uint8_t S2LP_IsRxReceived(void)
{
    // GPIO1을 NIRQ로 설정했다면 해당 핀 인터럽트 확인
    return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET;
}

void S2LP_ReadReceivedData(uint8_t* buffer, uint8_t length) {
    uint8_t cmd = 0x77;
    S2LP_CSN_LOW();
    HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);
    HAL_SPI_Receive(&hspi1, buffer, length, HAL_MAX_DELAY);
    S2LP_CSN_HIGH();
}


static uint8_t S2LP_ReadReg(uint8_t addr)
{
    uint8_t tx[2] = {0x01, addr};
    uint8_t rx[1];

    S2LP_CSN_LOW();
    HAL_SPI_Transmit(&hspi1, 	tx, 2, HAL_MAX_DELAY);
    HAL_SPI_Receive(&hspi1, 	rx, 1, HAL_MAX_DELAY);
    S2LP_CSN_HIGH();

    return rx[0];

}

static void S2LP_WriteReg(uint8_t addr, uint8_t val)
{
    uint8_t tx[3] = {0x00, addr, val};
    S2LP_CSN_LOW();
    HAL_SPI_Transmit(&hspi1, tx, 3, HAL_MAX_DELAY);
    S2LP_CSN_HIGH();
}

static void S2LP_SetCommand(uint8_t cmd)
{
    S2LP_CSN_LOW();               // CSN low start
    HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);
    S2LP_CSN_HIGH();              // CSN high terminate
    HAL_Delay(1);                 // standby reset
}
 
Schematic is below
SonDongSeong_0-1749466815822.png

I would appreciate it if you could let me know which parts might be incorrect.

0 REPLIES 0