2022-05-20 05:05 AM
I can't get a data transfer over the SPI bus with my currently implemented code. I can see the CLK and CS but there is no output via MISO (only zeros are probably transferred). If I execute a transmission manually via "LL_SPI_TransmitData16", I can see this via an oscilloscope.
The send should be triggered by an interrupt from a timer. The data come from 4 Channles of the ADC1s.
If you need more data, feel free to report. This is my first entry. :)
Many greetings
Used board: STM32G071C8Ux
SPI-Configuration:
uint16_t SPI2_TX_BUFF[4] = { 0 };
/* SPI2 init function */
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 */
/* 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_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]);
//enable DMA Channel
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_SPI_EnableDMAReq_TX(SPI2);
//enable SPI2
LL_SPI_Enable(SPI2);
}
ADC1: Memory settings with DMA settings
LL_DMA_SetDataLength(DMA1, ADC1_DMA_CHANNEL, ADC1_BUFFER_LENGTH);
LL_DMA_SetPeriphAddress(DMA1, ADC1_DMA_CHANNEL, LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA));
//LL_DMA_SetMemoryAddress(DMA1, ADC1_DMA_CHANNEL, (uint32_t)&adc1_values);
LL_DMA_SetMemoryAddress(DMA1, ADC1_DMA_CHANNEL, (uint32_t) &SPI2_TX_BUFF[0]);
//LL_DMA_EnableIT_HT(DMA1, ADC1_DMA_CHANNEL);
LL_DMA_EnableIT_TC(DMA1, ADC1_DMA_CHANNEL);
LL_DMA_EnableIT_TE(DMA1, ADC1_DMA_CHANNEL);
LL_DMA_EnableChannel(DMA1, ADC1_DMA_CHANNEL);
LL_ADC_Enable(ADC1);
while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0);
LL_ADC_REG_StartConversion(ADC1);
Timer2 Interrupt:
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);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_TIM_ClearFlag_UPDATE(TIM2);
/* USER CODE END TIM2_IRQn 0 */
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
}
2022-05-25 12:35 AM
The solution was simpler than expected but easier to overlook. The initialization sequence has initialized the timer, which serves as a trigger, too early. This leads to problems.