Как реализовать SPI на плате STM32F3 с использованием стандартной периферийной библиотеки?
Я пытаюсь реализовать SPI на плате STM32F3 Discovery, используя стандартную периферийную библиотеку. Я не хочу использовать драйверы HAL (это ограничение). Я не могу понять, чего мне не хватает. Я внедряю SPI в подчиненном режиме. Ниже приведена конфигурация SPI и код в основной функции.
void main() {
/* Initializes the SPI communication */
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_Init(SPIx, &SPI_InitStructure);
/* Initialize the FIFO threshold */
SPI_RxFIFOThresholdConfig(SPIx, SPI_RxFIFOThreshold_QF);
While(1){
// Start SPI transfer
/* DMA channel Rx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(SPIx_RX_DMA_CHANNEL, &DMA_InitStructure);
/* DMA channel Tx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_Init(SPIx_TX_DMA_CHANNEL, &DMA_InitStructure);
/* Enable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);
/* Enable the SPI peripheral */
SPI_Cmd(SPIx, ENABLE);
/* Enable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, ENABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, ENABLE);
/* Wait the SPI DMA transfers complete or time out */
while (DMA_GetFlagStatus(SPIx_RX_DMA_FLAG_TC) == RESET)
{}
TimeOut = USER_TIMEOUT;
while ((DMA_GetFlagStatus(SPIx_TX_DMA_FLAG_TC) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* The BSY flag can be monitored to ensure that the SPI communication is complete.
This is required to avoid corrupting the last transmission before disabling
the SPI or entering the Stop mode. The software must first wait until TXE=1
and then until BSY=0.*/
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* Clear DMA1 global flags */
DMA_ClearFlag(SPIx_TX_DMA_FLAG_GL);
DMA_ClearFlag(SPIx_RX_DMA_FLAG_GL);
/* Disable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, DISABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, DISABLE);
/* Disable the SPI peripheral */
SPI_Cmd(SPIx, DISABLE);
/* Disable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, DISABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, DISABLE);
}}
Конфигурация SPI выглядит следующим образом:
static void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the SPI peripheral */
RCC_APB2PeriphClockCmd(SPIx_CLK, ENABLE);
/* Enable the DMA peripheral */
RCC_AHBPeriphClockCmd(SPI_DMAx_CLK | TIM_DMAx_CLK, ENABLE);
/* Enable the TIM peripheral */
RCC_APB1PeriphClockCmd(TIMx_CLK, ENABLE);
/* Enable SCK, MOSI, MISO and NSS GPIO clocks */
RCC_AHBPeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK |
SPIx_MOSI_GPIO_CLK |
SPIx_NSS_GPIO_CLK , ENABLE);
/* Enable TIM DMA trigger clock */
RCC_AHBPeriphClockCmd(TIMx_TRIGGER_GPIO_CLK, ENABLE);
/* SPI pin mappings */
GPIO_PinAFConfig(SPIx_SCK_GPIO_PORT, SPIx_SCK_SOURCE, SPIx_SCK_AF);
GPIO_PinAFConfig(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_SOURCE, SPIx_MOSI_AF);
GPIO_PinAFConfig(SPIx_MISO_GPIO_PORT, SPIx_MISO_SOURCE, SPIx_MISO_AF);
GPIO_PinAFConfig(SPIx_NSS_GPIO_PORT, SPIx_NSS_SOURCE, SPIx_NSS_AF);
/* TIM capture compare pin mapping */
GPIO_PinAFConfig(TIMx_TRIGGER_GPIO_PORT, TIMx_TRIGGER_SOURCE,
TIMx_TRIGGER_AF);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;
GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStructure);
/* SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MOSI_PIN;
GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MISO_PIN;
GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStructure);
/* SPI NSS pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_NSS_PIN;
GPIO_Init(SPIx_NSS_GPIO_PORT, &GPIO_InitStructure);
/* Configure the TIM channelx capture compare as DMA Trigger */
GPIO_InitStructure.GPIO_Pin = TIMx_TRIGGER_PIN;
GPIO_Init(TIMx_TRIGGER_GPIO_PORT, &GPIO_InitStructure);
/* SPI configuration -------------------------------------------------------
*/
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DATASIZE;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
/* DMA Configuration -------------------------------------------------------
*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
}
Может кто-нибудь сказать мне, где проблема? У меня есть мастер-код в драйверах HAL на другой плате, которая работает нормально (проверено). Так что нет никаких проблем на стороне мастера. Рабская сторона - это проблема.
1 ответ
Ваш код находится в while(1), где вы конфигурируете и инициализируете периферийное устройство SPI. сделать это в отдельной функции и инициализировать и настроить только один раз. Также сначала попробуйте без DMA, а затем снова установите DMA.