Loading...
Searching...
No Matches
general_spi.c
Go to the documentation of this file.
/**
**************************************************************************
* @file general_spi.c
* @brief Модуль для инициализации SPI.
**************************************************************************
Реализация функций для работы с SPI:
- Инициализация SPI и его линий CLK/MISO/MOSI
- Настройка GPIO для SPI
- Настройка NVIC и тактирования SPI
*************************************************************************/
#include "general_spi.h"
#include "general_gpio.h"
//-------------------------------------------------------------------
//------------------------SPI INIT FUNCTIONS------------------------
/**
* @brief Инициализация SPI с помощью структуры SPI_SettingsTypeDef.
* @param sspi Указатель на структуру с настройками SPI.
* @return HAL status.
* @details
* Инициализирует SPI и его GPIO.
* Настройка аналогична HAL_SPI_Init
* @code
* suart.hspi.Init...
* @endcode
* но дополнительно надо прописать пины CLK/MISO/MOSI @ref SPI_SettingsTypeDef
*/
HAL_StatusTypeDef SPI_Base_Init(SPI_SettingsTypeDef *sspi)
{ // function takes setting structure for init
// check is settings are valid
if(SPI_Check_Init_Struct(sspi) != HAL_OK)
return HAL_ERROR;
SPI_MspInit(&sspi->hspi);
if (HAL_SPI_Init(&sspi->hspi) != HAL_OK)
{
MyLibs_Error_Handler();
return HAL_ERROR;
}
// init gpio from SPISettings structure
SPI_GPIO_Init(sspi);
// // init dma from SPISettings structure if need
// if (sspi->DMAChannel != 0)
// SPI_DMA_Init(&sspi->hspi, sspi->hspi.hdmarx, sspi->DMAChannel, sspi->DMA_CHANNEL_X);
return HAL_OK;
}
/**
* @brief Инициализация GPIO для SPI.
* @param sspi Указатель на структуру с настройками SPI.
*/
void SPI_GPIO_Init(SPI_SettingsTypeDef *sspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// GPIO INIT
GPIO_Clock_Enable(sspi->CLK_GPIOx);
GPIO_Clock_Enable(sspi->MISO_GPIOx);
GPIO_Clock_Enable(sspi->MOSI_GPIOx);
// CLK PIN INIT
GPIO_InitStruct.Pin = sspi->CLK_PIN;
GPIO_InitStruct.Alternate = sspi->CLK_GPIO_AlternageFunc;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(sspi->CLK_GPIOx, &GPIO_InitStruct);
// MISO PIN INIT
GPIO_InitStruct.Pin = sspi->MISO_PIN;
GPIO_InitStruct.Alternate = sspi->MISO_GPIO_AlternageFunc;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(sspi->MISO_GPIOx, &GPIO_InitStruct);
// MOSI PIN INIT
GPIO_InitStruct.Pin = sspi->MOSI_PIN;
GPIO_InitStruct.Alternate = sspi->MOSI_GPIO_AlternageFunc;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(sspi->MOSI_GPIOx, &GPIO_InitStruct);
}
void SPI_DMA_Init(SPI_HandleTypeDef *hspi, DMA_HandleTypeDef *hdma_rx, DMA_Stream_TypeDef *DMAChannel, uint32_t DMA_CHANNEL_X)
{ // function takes spi and dma handlers and dmachannel for spi
// // for now only dma rx is supported, tx maybe later if needed
// // calc defines on boot_project_setup.h
// /* SPI3 DMA Init */
// /* SPI3_RX Init */
//
// hdma_rx->Instance = DMAChannel;
//#if defined(STM32F4xx) // dma channel choose for 407
// hdma_rx->Init.Channel = DMA_CHANNEL_X;
//#endif
// hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY;
// hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE;
// hdma_rx->Init.MemInc = DMA_MINC_ENABLE;
// hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
// hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
// hdma_rx->Init.Mode = DMA_CIRCULAR;
// hdma_rx->Init.Priority = DMA_PRIORITY_LOW;
// if (HAL_DMA_Init(hdma_rx) != HAL_OK)
// {
// MyLibs_Error_Handler();
// }
// __USER_LINKDMA(hspi,hdmarx,hdma_rx);
//
// // __USER_LINKDMA is need because __HAL_LINKDMA is written for global defined hdma_rx
// // so you get error because hal uses . insted of ->
}
/**
* @brief Настройка тактирования и прерываний SPI.
* @param hspi Указатель на хендл SPI.
* @note Чтобы не генерировать функцию с иницилизацией неиспользуемых SPI,
дефайнами @ref SPI_INIT в @ref general_spi.h определяются используемые SPI.
*/
void SPI_MspInit(SPI_HandleTypeDef *hspi) // analog for hal function
{
// rcc, dma and interrupt init for SPIs
// GPIO init was moved to own functions SPI_GPIO_Init
if(0);
#ifdef USE_SPI1
else if(hspi->Instance==SPI1)
{
// /* DMA2 clock enable */
// __HAL_RCC_DMA2_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
#endif // USE_SPI1
#ifdef USE_SPI2
else if(hspi->Instance==SPI2)
{
// /* DMA1 clock enable */
// __HAL_RCC_DMA1_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
/* SPI2 interrupt Init */
HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
}
#endif // USE_SPI2
#ifdef USE_SPI3
else if(hspi->Instance==SPI3)
{
// /* DMA1 clock enable */
// __HAL_RCC_DMA1_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* SPI3 clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
/* SPI3 interrupt Init */
HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI3_IRQn);
}
#endif // USE_SPI3
}
/**
* @brief Деинициализация тактирования и прерываний SPI.
* @param hspi Указатель на хендл SPI.
* @note Чтобы не генерировать функцию с иницилизацией неиспользуемых SPI,
дефайнами @ref SPI_INIT в @ref general_spi.h определяются используемые SPI.
*/
void SPI_MspDeInit(SPI_HandleTypeDef *hspi) // analog for hal function
{
// rcc, dma and interrupt init for SPIs
// GPIO init was moved to own functions SPI_GPIO_Init
if(0);
#ifdef USE_SPI1
else if(hspi->Instance==SPI1)
{
// /* DMA2 clock enable */
// __HAL_RCC_DMA2_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* SPI1 clock reset */
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
}
#endif // USE_SPI1
#ifdef USE_SPI2
else if(hspi->Instance==SPI2)
{
// /* DMA1 clock enable */
// __HAL_RCC_DMA1_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* SPI2 clock reset */
__HAL_RCC_SPI2_FORCE_RESET();
__HAL_RCC_SPI2_RELEASE_RESET();
}
#endif // USE_SPI2
#ifdef USE_SPI3
else if(hspi->Instance==SPI3)
{
// /* DMA1 clock enable */
// __HAL_RCC_DMA1_CLK_ENABLE();
// /* DMA interrupt init */
// HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* SPI3 clock reset */
__HAL_RCC_SPI3_FORCE_RESET();
__HAL_RCC_SPI3_RELEASE_RESET();
}
#endif // USE_SPI3
}
/**
* @brief Проверка корректности структуры инициализации SPI.
* @param sspi Указатель на структуру с настройками SPI.
* @return HAL status.
*/
HAL_StatusTypeDef SPI_Check_Init_Struct(SPI_SettingsTypeDef *sspi)
{
// check is settings are valid
if (!IS_SPI_ALL_INSTANCE(sspi->hspi.Instance))
return HAL_ERROR;
// check init settings
if (!IS_SPI_MODE(sspi->hspi.Init.Mode))
return HAL_ERROR;
if (!IS_SPI_DIRECTION(sspi->hspi.Init.Direction))
return HAL_ERROR;
if (!IS_SPI_DATASIZE(sspi->hspi.Init.DataSize))
return HAL_ERROR;
if (!IS_SPI_BAUDRATE_PRESCALER(sspi->hspi.Init.BaudRatePrescaler))
return HAL_ERROR;
if (!IS_SPI_CPOL(sspi->hspi.Init.CLKPolarity))
return HAL_ERROR;
if (!IS_SPI_CPHA(sspi->hspi.Init.CLKPhase))
return HAL_ERROR;
if (!IS_SPI_NSS(sspi->hspi.Init.NSS))
return HAL_ERROR;
if (!IS_SPI_FIRST_BIT(sspi->hspi.Init.FirstBit))
return HAL_ERROR;
if (!IS_SPI_CRC_CALCULATION(sspi->hspi.Init.CRCCalculation))
return HAL_ERROR;
if (!IS_SPI_CRC_POLYNOMIAL(sspi->hspi.Init.NSS) &&
(sspi->hspi.Init.CRCCalculation != SPI_CRCCALCULATION_DISABLE))
return HAL_ERROR;
if (!IS_SPI_TIMODE(sspi->hspi.Init.TIMode))
return HAL_ERROR;
// check gpio
if (!IS_GPIO_ALL_INSTANCE(sspi->CLK_GPIOx) || !IS_GPIO_ALL_INSTANCE(sspi->MISO_GPIOx) || !IS_GPIO_ALL_INSTANCE(sspi->MOSI_GPIOx))
return HAL_ERROR;
if (!IS_GPIO_PIN(sspi->CLK_PIN) && !IS_GPIO_PIN(sspi->MISO_PIN) && !IS_GPIO_PIN(sspi->MOSI_PIN)) // if both pins arent set up
return HAL_ERROR;
return HAL_OK;
}
general_gpio.h
Заголовочный файл для модуля инициализации портов и работы с ними.
SPI_GPIO_Init
void SPI_GPIO_Init(SPI_SettingsTypeDef *sspi)
Инициализация GPIO для SPI.
Definition general_spi.c:58
general_spi.h
Заголовочный файл для модуля инициализации SPI.
SPI_Base_Init
HAL_StatusTypeDef SPI_Base_Init(SPI_SettingsTypeDef *sspi)
Инициализация SPI с помощью структуры SPI_SettingsTypeDef.
Definition general_spi.c:28
SPI_Check_Init_Struct
HAL_StatusTypeDef SPI_Check_Init_Struct(SPI_SettingsTypeDef *sspi)
Проверка корректности структуры инициализации SPI.
Definition general_spi.c:246
SPI_MspInit
void SPI_MspInit(SPI_HandleTypeDef *hspi)
Настройка тактирования и прерываний SPI.
Definition general_spi.c:127
SPI_MspDeInit
void SPI_MspDeInit(SPI_HandleTypeDef *hspi)
Деинициализация тактирования и прерываний SPI.
Definition general_spi.c:191
GPIO_Clock_Enable
HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx)
Включить тактирование порта GPIO.
Definition general_gpio.c:22
SPI_SettingsTypeDef
Структура настроек SPI.
Definition general_spi.h:105
SPI_SettingsTypeDef::MOSI_GPIOx
GPIO_TypeDef * MOSI_GPIOx
Порт MOSI.
Definition general_spi.h:116
SPI_SettingsTypeDef::MISO_GPIOx
GPIO_TypeDef * MISO_GPIOx
Порт MISO.
Definition general_spi.h:112
SPI_SettingsTypeDef::MISO_PIN
uint32_t MISO_PIN
Пин MISO.
Definition general_spi.h:113
SPI_SettingsTypeDef::CLK_PIN
uint32_t CLK_PIN
Пин CLK.
Definition general_spi.h:109
SPI_SettingsTypeDef::CLK_GPIO_AlternageFunc
uint32_t CLK_GPIO_AlternageFunc
Альтернативная функция для CLK.
Definition general_spi.h:110
SPI_SettingsTypeDef::CLK_GPIOx
GPIO_TypeDef * CLK_GPIOx
Порт CLK.
Definition general_spi.h:108
SPI_SettingsTypeDef::MOSI_PIN
uint32_t MOSI_PIN
Пин MOSI.
Definition general_spi.h:117
SPI_SettingsTypeDef::hspi
SPI_HandleTypeDef hspi
HAL handle SPI.
Definition general_spi.h:106
SPI_SettingsTypeDef::MISO_GPIO_AlternageFunc
uint32_t MISO_GPIO_AlternageFunc
Альтернативная функция для MISO.
Definition general_spi.h:114
SPI_SettingsTypeDef::MOSI_GPIO_AlternageFunc
uint32_t MOSI_GPIO_AlternageFunc
Альтернативная функция для MOSI.
Definition general_spi.h:118