cancel
Showing results for 
Search instead for 
Did you mean: 

How to configure the NSS with software

MHeid.4
Associate

I have the problem that I don't get the NSS configured correctly on my SPI transmission. I should get according to reference Manuel a NSS signal that switches just before the first bit and just after the last bit. I send several different data one after the other using the command LL_SPI_TransmitData16. For me now NSS should be permanently low as long as I send data directly one after the other.

But for me the NSS signal toggles also in between, respectively always then, when a send process is finished.

Configuration:

void spi2_init(void)
{
 
  /* USER CODE BEGIN SPI2_Init 0 */
 
  /* USER CODE END SPI2_Init 0 */
 
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
 
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
 
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
  /**SPI2 GPIO Configuration
  PB12   ------> SPI2_NSS
  PB13   ------> SPI2_SCK
  PB14   ------> SPI2_MISO
  PB15   ------> SPI2_MOSI
  */
  GPIO_InitStruct.Pin = S_CS_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(S_CS_GPIO_Port, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = S_SCLK_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(S_SCLK_GPIO_Port, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = S_MISO_F_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(S_MISO_F_GPIO_Port, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = S_MOSI_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(S_MOSI_GPIO_Port, &GPIO_InitStruct);
 
  /* SPI2 DMA Init */
 
  //spi12_dmatest();
 
    /* SPI2_TX Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMAMUX_REQ_SPI2_TX);
 
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
 
  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PRIORITY_HIGH);
 
  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MODE_NORMAL);
 
  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PERIPH_NOINCREMENT);
 
  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MEMORY_INCREMENT);
 
  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PDATAALIGN_HALFWORD);
 
  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_HALFWORD);
 
 
//  /* SPI2_RX Init */
//  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_7, LL_DMAMUX_REQ_SPI2_RX);
//
//  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
//
//  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PRIORITY_HIGH);
//
//  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MODE_NORMAL);
//
//  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PERIPH_NOINCREMENT);
//
//  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MEMORY_INCREMENT);
//
//  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PDATAALIGN_HALFWORD);
//
//  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MDATAALIGN_HALFWORD);
 
 
  /* SPI2 interrupt Init */
  NVIC_SetPriority(SPI2_IRQn, 3);
  NVIC_EnableIRQ(SPI2_IRQn);
 
  /* USER CODE BEGIN SPI2_Init 1 */
  LL_SPI_Disable(SPI2);
  /* USER CODE END SPI2_Init 1 */
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_HARD_OUTPUT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_ENABLE;
  SPI_InitStruct.CRCPoly = 0xED2F;
  LL_SPI_Init(SPI2, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_SetCRCWidth(SPI2, LL_SPI_CRC_16BIT);
  LL_SPI_EnableNSSPulseMgt(SPI2);
  //LL_SPI_SetNSSMode(SPI2, 1);
 
  LL_SPI_EnableCRC(SPI2);
 
  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, SPI2TxBufferSize);
  LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_4, LL_SPI_DMA_GetRegAddr(SPI2));
  LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_4, (uint32_t) &SPI2_TX_BUFF[0]);
 
  //LL_SPI_EnableDMAReq_TX(SPI2);
 
  //enable SPI2
  LL_SPI_Enable(SPI2);
  //enable DMA Channel
  LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
}

Sending process:

void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */
	LED_Red_toggle();
	LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
	LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, SPI2TxBufferSize);
 
 
	//RAW for U_SEC
	while (LL_SPI_GetTxFIFOLevel(SPI2) > 2);
	//LL_SPI_TransmitData16(SPI2, 50);
	LL_SPI_TransmitData16(SPI2, SPI2_TX_BUFF[0]);
 
	//RAW for I_ch_a
	while (LL_SPI_GetTxFIFOLevel(SPI2) > 2);
	//LL_SPI_TransmitData16(SPI2, 100);
	LL_SPI_TransmitData16(SPI2, SPI2_TX_BUFF[1]);
 
	//RAW for I_ch_b
	while (LL_SPI_GetTxFIFOLevel(SPI2) > 2);
	//LL_SPI_TransmitData16(SPI2, 200);
	LL_SPI_TransmitData16(SPI2, SPI2_TX_BUFF[2]);
 
	//RAW for U_SEC_FILTERT
	while (LL_SPI_GetTxFIFOLevel(SPI2) > 2);
	//LL_SPI_TransmitData16(SPI2, 300);
	LL_SPI_TransmitData16(SPI2, SPI2_TX_BUFF[3]);
 
	while (LL_SPI_GetTxFIFOLevel(SPI2) > 2);
	LL_SPI_SetCRCNext(SPI2);
 
 
	adc1_raw();
	LL_TIM_ClearFlag_UPDATE(TIM2);
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
  /* USER CODE END TIM2_IRQn 0 */
  /* USER CODE BEGIN TIM2_IRQn 1 */
 
  /* USER CODE END TIM2_IRQn 1 */
}

1 REPLY 1
MasterT
Senior III

NSS is driven based on SPI configuration word size - 16-bits in this case. If you need to send more bits (24-32-40) and SPI for this iCPU (what exactly ?) doesn't support - the only option is software NSS. Drive NSS as common GPIO output in software.