ch39f 驱动成功

This commit is contained in:
2026-07-15 20:14:54 +08:00
parent 9943b410f4
commit c8c7ec0992
21 changed files with 17994 additions and 32 deletions

File diff suppressed because one or more lines are too long

1366
CH395F.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,733 @@
/**
******************************************************************************
* @file stm32f4xx_hal_spi.h
* @author MCD Application Team
* @brief Header file of SPI HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32F4xx_HAL_SPI_H
#define STM32F4xx_HAL_SPI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @addtogroup SPI
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup SPI_Exported_Types SPI Exported Types
* @{
*/
/**
* @brief SPI Configuration Structure definition
*/
typedef struct
{
uint32_t Mode; /*!< Specifies the SPI operating mode.
This parameter can be a value of @ref SPI_Mode */
uint32_t Direction; /*!< Specifies the SPI bidirectional mode state.
This parameter can be a value of @ref SPI_Direction */
uint32_t DataSize; /*!< Specifies the SPI data size.
This parameter can be a value of @ref SPI_Data_Size */
uint32_t CLKPolarity; /*!< Specifies the serial clock steady state.
This parameter can be a value of @ref SPI_Clock_Polarity */
uint32_t CLKPhase; /*!< Specifies the clock active edge for the bit capture.
This parameter can be a value of @ref SPI_Clock_Phase */
uint32_t NSS; /*!< Specifies whether the NSS signal is managed by
hardware (NSS pin) or by software using the SSI bit.
This parameter can be a value of @ref SPI_Slave_Select_management */
uint32_t BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be
used to configure the transmit and receive SCK clock.
This parameter can be a value of @ref SPI_BaudRate_Prescaler
@note The communication clock is derived from the master
clock. The slave clock does not need to be set. */
uint32_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit.
This parameter can be a value of @ref SPI_MSB_LSB_transmission */
uint32_t TIMode; /*!< Specifies if the TI mode is enabled or not.
This parameter can be a value of @ref SPI_TI_mode */
uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not.
This parameter can be a value of @ref SPI_CRC_Calculation */
uint32_t CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation.
This parameter must be an odd number between Min_Data = 1 and Max_Data = 65535 */
} SPI_InitTypeDef;
/**
* @brief HAL SPI State structure definition
*/
typedef enum
{
HAL_SPI_STATE_RESET = 0x00U, /*!< Peripheral not Initialized */
HAL_SPI_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */
HAL_SPI_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */
HAL_SPI_STATE_BUSY_TX = 0x03U, /*!< Data Transmission process is ongoing */
HAL_SPI_STATE_BUSY_RX = 0x04U, /*!< Data Reception process is ongoing */
HAL_SPI_STATE_BUSY_TX_RX = 0x05U, /*!< Data Transmission and Reception process is ongoing */
HAL_SPI_STATE_ERROR = 0x06U, /*!< SPI error state */
HAL_SPI_STATE_ABORT = 0x07U /*!< SPI abort is ongoing */
} HAL_SPI_StateTypeDef;
/**
* @brief SPI handle Structure definition
*/
typedef struct __SPI_HandleTypeDef
{
SPI_TypeDef *Instance; /*!< SPI registers base address */
SPI_InitTypeDef Init; /*!< SPI communication parameters */
const uint8_t *pTxBuffPtr; /*!< Pointer to SPI Tx transfer Buffer */
uint16_t TxXferSize; /*!< SPI Tx Transfer size */
__IO uint16_t TxXferCount; /*!< SPI Tx Transfer Counter */
uint8_t *pRxBuffPtr; /*!< Pointer to SPI Rx transfer Buffer */
uint16_t RxXferSize; /*!< SPI Rx Transfer size */
__IO uint16_t RxXferCount; /*!< SPI Rx Transfer Counter */
void (*RxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Rx ISR */
void (*TxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Tx ISR */
DMA_HandleTypeDef *hdmatx; /*!< SPI Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< SPI Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /*!< Locking object */
__IO HAL_SPI_StateTypeDef State; /*!< SPI communication state */
__IO uint32_t ErrorCode; /*!< SPI Error code */
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Completed callback */
void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Completed callback */
void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Completed callback */
void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Half Completed callback */
void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Half Completed callback */
void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Half Completed callback */
void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Error callback */
void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Abort callback */
void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp Init callback */
void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp DeInit callback */
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
} SPI_HandleTypeDef;
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
/**
* @brief HAL SPI Callback ID enumeration definition
*/
typedef enum
{
HAL_SPI_TX_COMPLETE_CB_ID = 0x00U, /*!< SPI Tx Completed callback ID */
HAL_SPI_RX_COMPLETE_CB_ID = 0x01U, /*!< SPI Rx Completed callback ID */
HAL_SPI_TX_RX_COMPLETE_CB_ID = 0x02U, /*!< SPI TxRx Completed callback ID */
HAL_SPI_TX_HALF_COMPLETE_CB_ID = 0x03U, /*!< SPI Tx Half Completed callback ID */
HAL_SPI_RX_HALF_COMPLETE_CB_ID = 0x04U, /*!< SPI Rx Half Completed callback ID */
HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID = 0x05U, /*!< SPI TxRx Half Completed callback ID */
HAL_SPI_ERROR_CB_ID = 0x06U, /*!< SPI Error callback ID */
HAL_SPI_ABORT_CB_ID = 0x07U, /*!< SPI Abort callback ID */
HAL_SPI_MSPINIT_CB_ID = 0x08U, /*!< SPI Msp Init callback ID */
HAL_SPI_MSPDEINIT_CB_ID = 0x09U /*!< SPI Msp DeInit callback ID */
} HAL_SPI_CallbackIDTypeDef;
/**
* @brief HAL SPI Callback pointer definition
*/
typedef void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi); /*!< pointer to an SPI callback function */
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup SPI_Exported_Constants SPI Exported Constants
* @{
*/
/** @defgroup SPI_Error_Code SPI Error Code
* @{
*/
#define HAL_SPI_ERROR_NONE (0x00000000U) /*!< No error */
#define HAL_SPI_ERROR_MODF (0x00000001U) /*!< MODF error */
#define HAL_SPI_ERROR_CRC (0x00000002U) /*!< CRC error */
#define HAL_SPI_ERROR_OVR (0x00000004U) /*!< OVR error */
#define HAL_SPI_ERROR_FRE (0x00000008U) /*!< FRE error */
#define HAL_SPI_ERROR_DMA (0x00000010U) /*!< DMA transfer error */
#define HAL_SPI_ERROR_FLAG (0x00000020U) /*!< Error on RXNE/TXE/BSY Flag */
#define HAL_SPI_ERROR_ABORT (0x00000040U) /*!< Error during SPI Abort procedure */
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
#define HAL_SPI_ERROR_INVALID_CALLBACK (0x00000080U) /*!< Invalid Callback error */
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup SPI_Mode SPI Mode
* @{
*/
#define SPI_MODE_SLAVE (0x00000000U)
#define SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI)
/**
* @}
*/
/** @defgroup SPI_Direction SPI Direction Mode
* @{
*/
#define SPI_DIRECTION_2LINES (0x00000000U)
#define SPI_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY
#define SPI_DIRECTION_1LINE SPI_CR1_BIDIMODE
/**
* @}
*/
/** @defgroup SPI_Data_Size SPI Data Size
* @{
*/
#define SPI_DATASIZE_8BIT (0x00000000U)
#define SPI_DATASIZE_16BIT SPI_CR1_DFF
/**
* @}
*/
/** @defgroup SPI_Clock_Polarity SPI Clock Polarity
* @{
*/
#define SPI_POLARITY_LOW (0x00000000U)
#define SPI_POLARITY_HIGH SPI_CR1_CPOL
/**
* @}
*/
/** @defgroup SPI_Clock_Phase SPI Clock Phase
* @{
*/
#define SPI_PHASE_1EDGE (0x00000000U)
#define SPI_PHASE_2EDGE SPI_CR1_CPHA
/**
* @}
*/
/** @defgroup SPI_Slave_Select_management SPI Slave Select Management
* @{
*/
#define SPI_NSS_SOFT SPI_CR1_SSM
#define SPI_NSS_HARD_INPUT (0x00000000U)
#define SPI_NSS_HARD_OUTPUT (SPI_CR2_SSOE << 16U)
/**
* @}
*/
/** @defgroup SPI_BaudRate_Prescaler SPI BaudRate Prescaler
* @{
*/
#define SPI_BAUDRATEPRESCALER_2 (0x00000000U)
#define SPI_BAUDRATEPRESCALER_4 (SPI_CR1_BR_0)
#define SPI_BAUDRATEPRESCALER_8 (SPI_CR1_BR_1)
#define SPI_BAUDRATEPRESCALER_16 (SPI_CR1_BR_1 | SPI_CR1_BR_0)
#define SPI_BAUDRATEPRESCALER_32 (SPI_CR1_BR_2)
#define SPI_BAUDRATEPRESCALER_64 (SPI_CR1_BR_2 | SPI_CR1_BR_0)
#define SPI_BAUDRATEPRESCALER_128 (SPI_CR1_BR_2 | SPI_CR1_BR_1)
#define SPI_BAUDRATEPRESCALER_256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
/**
* @}
*/
/** @defgroup SPI_MSB_LSB_transmission SPI MSB LSB Transmission
* @{
*/
#define SPI_FIRSTBIT_MSB (0x00000000U)
#define SPI_FIRSTBIT_LSB SPI_CR1_LSBFIRST
/**
* @}
*/
/** @defgroup SPI_TI_mode SPI TI Mode
* @{
*/
#define SPI_TIMODE_DISABLE (0x00000000U)
#define SPI_TIMODE_ENABLE SPI_CR2_FRF
/**
* @}
*/
/** @defgroup SPI_CRC_Calculation SPI CRC Calculation
* @{
*/
#define SPI_CRCCALCULATION_DISABLE (0x00000000U)
#define SPI_CRCCALCULATION_ENABLE SPI_CR1_CRCEN
/**
* @}
*/
/** @defgroup SPI_Interrupt_definition SPI Interrupt Definition
* @{
*/
#define SPI_IT_TXE SPI_CR2_TXEIE
#define SPI_IT_RXNE SPI_CR2_RXNEIE
#define SPI_IT_ERR SPI_CR2_ERRIE
/**
* @}
*/
/** @defgroup SPI_Flags_definition SPI Flags Definition
* @{
*/
#define SPI_FLAG_RXNE SPI_SR_RXNE /* SPI status flag: Rx buffer not empty flag */
#define SPI_FLAG_TXE SPI_SR_TXE /* SPI status flag: Tx buffer empty flag */
#define SPI_FLAG_BSY SPI_SR_BSY /* SPI status flag: Busy flag */
#define SPI_FLAG_CRCERR SPI_SR_CRCERR /* SPI Error flag: CRC error flag */
#define SPI_FLAG_MODF SPI_SR_MODF /* SPI Error flag: Mode fault flag */
#define SPI_FLAG_OVR SPI_SR_OVR /* SPI Error flag: Overrun flag */
#define SPI_FLAG_FRE SPI_SR_FRE /* SPI Error flag: TI mode frame format error flag */
#define SPI_FLAG_MASK (SPI_SR_RXNE | SPI_SR_TXE | SPI_SR_BSY | SPI_SR_CRCERR\
| SPI_SR_MODF | SPI_SR_OVR | SPI_SR_FRE)
/**
* @}
*/
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup SPI_Exported_Macros SPI Exported Macros
* @{
*/
/** @brief Reset SPI handle state.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) \
do{ \
(__HANDLE__)->State = HAL_SPI_STATE_RESET; \
(__HANDLE__)->MspInitCallback = NULL; \
(__HANDLE__)->MspDeInitCallback = NULL; \
} while(0)
#else
#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPI_STATE_RESET)
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
/** @brief Enable the specified SPI interrupts.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @param __INTERRUPT__ specifies the interrupt source to enable.
* This parameter can be one of the following values:
* @arg SPI_IT_TXE: Tx buffer empty interrupt enable
* @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
* @arg SPI_IT_ERR: Error interrupt enable
* @retval None
*/
#define __HAL_SPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__))
/** @brief Disable the specified SPI interrupts.
* @param __HANDLE__ specifies the SPI handle.
* This parameter can be SPIx where x: 1, 2, or 3 to select the SPI peripheral.
* @param __INTERRUPT__ specifies the interrupt source to disable.
* This parameter can be one of the following values:
* @arg SPI_IT_TXE: Tx buffer empty interrupt enable
* @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
* @arg SPI_IT_ERR: Error interrupt enable
* @retval None
*/
#define __HAL_SPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__))
/** @brief Check whether the specified SPI interrupt source is enabled or not.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @param __INTERRUPT__ specifies the SPI interrupt source to check.
* This parameter can be one of the following values:
* @arg SPI_IT_TXE: Tx buffer empty interrupt enable
* @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
* @arg SPI_IT_ERR: Error interrupt enable
* @retval The new state of __IT__ (TRUE or FALSE).
*/
#define __HAL_SPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\
& (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET)
/** @brief Check whether the specified SPI flag is set or not.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg SPI_FLAG_RXNE: Receive buffer not empty flag
* @arg SPI_FLAG_TXE: Transmit buffer empty flag
* @arg SPI_FLAG_CRCERR: CRC error flag
* @arg SPI_FLAG_MODF: Mode fault flag
* @arg SPI_FLAG_OVR: Overrun flag
* @arg SPI_FLAG_BSY: Busy flag
* @arg SPI_FLAG_FRE: Frame format error flag
* @retval The new state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__))
/** @brief Clear the SPI CRCERR pending flag.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_CLEAR_CRCERRFLAG(__HANDLE__) ((__HANDLE__)->Instance->SR = (uint16_t)(~SPI_FLAG_CRCERR))
/** @brief Clear the SPI MODF pending flag.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg_modf = 0x00U; \
tmpreg_modf = (__HANDLE__)->Instance->SR; \
CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE); \
UNUSED(tmpreg_modf); \
} while(0U)
/** @brief Clear the SPI OVR pending flag.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg_ovr = 0x00U; \
tmpreg_ovr = (__HANDLE__)->Instance->DR; \
tmpreg_ovr = (__HANDLE__)->Instance->SR; \
UNUSED(tmpreg_ovr); \
} while(0U)
/** @brief Clear the SPI FRE pending flag.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_CLEAR_FREFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg_fre = 0x00U; \
tmpreg_fre = (__HANDLE__)->Instance->SR; \
UNUSED(tmpreg_fre); \
} while(0U)
/** @brief Enable the SPI peripheral.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE)
/** @brief Disable the SPI peripheral.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define __HAL_SPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE)
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup SPI_Private_Macros SPI Private Macros
* @{
*/
/** @brief Set the SPI transmit-only mode.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define SPI_1LINE_TX(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE)
/** @brief Set the SPI receive-only mode.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define SPI_1LINE_RX(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE)
/** @brief Reset the CRC calculation of the SPI.
* @param __HANDLE__ specifies the SPI Handle.
* This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
* @retval None
*/
#define SPI_RESET_CRC(__HANDLE__) \
do{ \
CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \
SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \
} while(0U)
/** @brief Check whether the specified SPI flag is set or not.
* @param __SR__ copy of SPI SR register.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg SPI_FLAG_RXNE: Receive buffer not empty flag
* @arg SPI_FLAG_TXE: Transmit buffer empty flag
* @arg SPI_FLAG_CRCERR: CRC error flag
* @arg SPI_FLAG_MODF: Mode fault flag
* @arg SPI_FLAG_OVR: Overrun flag
* @arg SPI_FLAG_BSY: Busy flag
* @arg SPI_FLAG_FRE: Frame format error flag
* @retval SET or RESET.
*/
#define SPI_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__) & ((__FLAG__) & SPI_FLAG_MASK)) == \
((__FLAG__) & SPI_FLAG_MASK)) ? SET : RESET)
/** @brief Check whether the specified SPI Interrupt is set or not.
* @param __CR2__ copy of SPI CR2 register.
* @param __INTERRUPT__ specifies the SPI interrupt source to check.
* This parameter can be one of the following values:
* @arg SPI_IT_TXE: Tx buffer empty interrupt enable
* @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
* @arg SPI_IT_ERR: Error interrupt enable
* @retval SET or RESET.
*/
#define SPI_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__) & (__INTERRUPT__)) == \
(__INTERRUPT__)) ? SET : RESET)
/** @brief Checks if SPI Mode parameter is in allowed range.
* @param __MODE__ specifies the SPI Mode.
* This parameter can be a value of @ref SPI_Mode
* @retval None
*/
#define IS_SPI_MODE(__MODE__) (((__MODE__) == SPI_MODE_SLAVE) || \
((__MODE__) == SPI_MODE_MASTER))
/** @brief Checks if SPI Direction Mode parameter is in allowed range.
* @param __MODE__ specifies the SPI Direction Mode.
* This parameter can be a value of @ref SPI_Direction
* @retval None
*/
#define IS_SPI_DIRECTION(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \
((__MODE__) == SPI_DIRECTION_2LINES_RXONLY) || \
((__MODE__) == SPI_DIRECTION_1LINE))
/** @brief Checks if SPI Direction Mode parameter is 2 lines.
* @param __MODE__ specifies the SPI Direction Mode.
* @retval None
*/
#define IS_SPI_DIRECTION_2LINES(__MODE__) ((__MODE__) == SPI_DIRECTION_2LINES)
/** @brief Checks if SPI Direction Mode parameter is 1 or 2 lines.
* @param __MODE__ specifies the SPI Direction Mode.
* @retval None
*/
#define IS_SPI_DIRECTION_2LINES_OR_1LINE(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \
((__MODE__) == SPI_DIRECTION_1LINE))
/** @brief Checks if SPI Data Size parameter is in allowed range.
* @param __DATASIZE__ specifies the SPI Data Size.
* This parameter can be a value of @ref SPI_Data_Size
* @retval None
*/
#define IS_SPI_DATASIZE(__DATASIZE__) (((__DATASIZE__) == SPI_DATASIZE_16BIT) || \
((__DATASIZE__) == SPI_DATASIZE_8BIT))
/** @brief Checks if SPI Serial clock steady state parameter is in allowed range.
* @param __CPOL__ specifies the SPI serial clock steady state.
* This parameter can be a value of @ref SPI_Clock_Polarity
* @retval None
*/
#define IS_SPI_CPOL(__CPOL__) (((__CPOL__) == SPI_POLARITY_LOW) || \
((__CPOL__) == SPI_POLARITY_HIGH))
/** @brief Checks if SPI Clock Phase parameter is in allowed range.
* @param __CPHA__ specifies the SPI Clock Phase.
* This parameter can be a value of @ref SPI_Clock_Phase
* @retval None
*/
#define IS_SPI_CPHA(__CPHA__) (((__CPHA__) == SPI_PHASE_1EDGE) || \
((__CPHA__) == SPI_PHASE_2EDGE))
/** @brief Checks if SPI Slave Select parameter is in allowed range.
* @param __NSS__ specifies the SPI Slave Select management parameter.
* This parameter can be a value of @ref SPI_Slave_Select_management
* @retval None
*/
#define IS_SPI_NSS(__NSS__) (((__NSS__) == SPI_NSS_SOFT) || \
((__NSS__) == SPI_NSS_HARD_INPUT) || \
((__NSS__) == SPI_NSS_HARD_OUTPUT))
/** @brief Checks if SPI Baudrate prescaler parameter is in allowed range.
* @param __PRESCALER__ specifies the SPI Baudrate prescaler.
* This parameter can be a value of @ref SPI_BaudRate_Prescaler
* @retval None
*/
#define IS_SPI_BAUDRATE_PRESCALER(__PRESCALER__) (((__PRESCALER__) == SPI_BAUDRATEPRESCALER_2) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_4) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_8) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_16) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_32) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_64) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_128) || \
((__PRESCALER__) == SPI_BAUDRATEPRESCALER_256))
/** @brief Checks if SPI MSB LSB transmission parameter is in allowed range.
* @param __BIT__ specifies the SPI MSB LSB transmission (whether data transfer starts from MSB or LSB bit).
* This parameter can be a value of @ref SPI_MSB_LSB_transmission
* @retval None
*/
#define IS_SPI_FIRST_BIT(__BIT__) (((__BIT__) == SPI_FIRSTBIT_MSB) || \
((__BIT__) == SPI_FIRSTBIT_LSB))
/** @brief Checks if SPI TI mode parameter is in allowed range.
* @param __MODE__ specifies the SPI TI mode.
* This parameter can be a value of @ref SPI_TI_mode
* @retval None
*/
#define IS_SPI_TIMODE(__MODE__) (((__MODE__) == SPI_TIMODE_DISABLE) || \
((__MODE__) == SPI_TIMODE_ENABLE))
/** @brief Checks if SPI CRC calculation enabled state is in allowed range.
* @param __CALCULATION__ specifies the SPI CRC calculation enable state.
* This parameter can be a value of @ref SPI_CRC_Calculation
* @retval None
*/
#define IS_SPI_CRC_CALCULATION(__CALCULATION__) (((__CALCULATION__) == SPI_CRCCALCULATION_DISABLE) || \
((__CALCULATION__) == SPI_CRCCALCULATION_ENABLE))
/** @brief Checks if SPI polynomial value to be used for the CRC calculation, is in allowed range.
* @param __POLYNOMIAL__ specifies the SPI polynomial value to be used for the CRC calculation.
* This parameter must be a number between Min_Data = 0 and Max_Data = 65535
* @retval None
*/
#define IS_SPI_CRC_POLYNOMIAL(__POLYNOMIAL__) (((__POLYNOMIAL__) >= 0x1U) && \
((__POLYNOMIAL__) <= 0xFFFFU) && \
(((__POLYNOMIAL__)&0x1U) != 0U))
/** @brief Checks if DMA handle is valid.
* @param __HANDLE__ specifies a DMA Handle.
* @retval None
*/
#define IS_SPI_DMA_HANDLE(__HANDLE__) ((__HANDLE__) != NULL)
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup SPI_Exported_Functions
* @{
*/
/** @addtogroup SPI_Exported_Functions_Group1
* @{
*/
/* Initialization/de-initialization functions ********************************/
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi);
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi);
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi);
/* Callbacks Register/UnRegister functions ***********************************/
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
pSPI_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID);
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
/**
* @}
*/
/** @addtogroup SPI_Exported_Functions_Group2
* @{
*/
/* I/O operation functions ***************************************************/
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size);
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size);
HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi);
HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi);
HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi);
/* Transfer Abort functions */
HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi);
HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi);
void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi);
/**
* @}
*/
/** @addtogroup SPI_Exported_Functions_Group3
* @{
*/
/* Peripheral State and Error functions ***************************************/
HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi);
uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32F4xx_HAL_SPI_H */

View File

@@ -0,0 +1,909 @@
/**
******************************************************************************
* @file stm32f4xx_hal_uart.h
* @author MCD Application Team
* @brief Header file of UART HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_UART_H
#define __STM32F4xx_HAL_UART_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @addtogroup UART
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup UART_Exported_Types UART Exported Types
* @{
*/
/**
* @brief UART Init Structure definition
*/
typedef struct
{
uint32_t BaudRate; /*!< This member configures the UART communication baud rate.
The baud rate is computed using the following formula:
- IntegerDivider = ((PCLKx) / (8 * (OVR8+1) * (huart->Init.BaudRate)))
- FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8 * (OVR8+1)) + 0.5
Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */
uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.
This parameter can be a value of @ref UART_Word_Length */
uint32_t StopBits; /*!< Specifies the number of stop bits transmitted.
This parameter can be a value of @ref UART_Stop_Bits */
uint32_t Parity; /*!< Specifies the parity mode.
This parameter can be a value of @ref UART_Parity
@note When parity is enabled, the computed parity is inserted
at the MSB position of the transmitted data (9th bit when
the word length is set to 9 data bits; 8th bit when the
word length is set to 8 data bits). */
uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
This parameter can be a value of @ref UART_Mode */
uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled or disabled.
This parameter can be a value of @ref UART_Hardware_Flow_Control */
uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).
This parameter can be a value of @ref UART_Over_Sampling */
} UART_InitTypeDef;
/**
* @brief HAL UART State structures definition
* @note HAL UART State value is a combination of 2 different substates: gState and RxState.
* - gState contains UART state information related to global Handle management
* and also information related to Tx operations.
* gState value coding follow below described bitmap :
* b7-b6 Error information
* 00 : No Error
* 01 : (Not Used)
* 10 : Timeout
* 11 : Error
* b5 Peripheral initialization status
* 0 : Reset (Peripheral not initialized)
* 1 : Init done (Peripheral initialized. HAL UART Init function already called)
* b4-b3 (not used)
* xx : Should be set to 00
* b2 Intrinsic process state
* 0 : Ready
* 1 : Busy (Peripheral busy with some configuration or internal operations)
* b1 (not used)
* x : Should be set to 0
* b0 Tx state
* 0 : Ready (no Tx operation ongoing)
* 1 : Busy (Tx operation ongoing)
* - RxState contains information related to Rx operations.
* RxState value coding follow below described bitmap :
* b7-b6 (not used)
* xx : Should be set to 00
* b5 Peripheral initialization status
* 0 : Reset (Peripheral not initialized)
* 1 : Init done (Peripheral initialized)
* b4-b2 (not used)
* xxx : Should be set to 000
* b1 Rx state
* 0 : Ready (no Rx operation ongoing)
* 1 : Busy (Rx operation ongoing)
* b0 (not used)
* x : Should be set to 0.
*/
typedef enum
{
HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized
Value is allowed for gState and RxState */
HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use
Value is allowed for gState and RxState */
HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing
Value is allowed for gState only */
HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing
Value is allowed for gState only */
HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing
Value is allowed for RxState only */
HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing
Not to be used for neither gState nor RxState.
Value is result of combination (Or) between gState and RxState values */
HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state
Value is allowed for gState only */
HAL_UART_STATE_ERROR = 0xE0U /*!< Error
Value is allowed for gState only */
} HAL_UART_StateTypeDef;
/**
* @brief HAL UART Reception type definition
* @note HAL UART Reception type value aims to identify which type of Reception is ongoing.
* This parameter can be a value of @ref UART_Reception_Type_Values :
* HAL_UART_RECEPTION_STANDARD = 0x00U,
* HAL_UART_RECEPTION_TOIDLE = 0x01U,
*/
typedef uint32_t HAL_UART_RxTypeTypeDef;
/**
* @brief HAL UART Rx Event type definition
* @note HAL UART Rx Event type value aims to identify which type of Event has occurred
* leading to call of the RxEvent callback.
* This parameter can be a value of @ref UART_RxEvent_Type_Values :
* HAL_UART_RXEVENT_TC = 0x00U,
* HAL_UART_RXEVENT_HT = 0x01U,
* HAL_UART_RXEVENT_IDLE = 0x02U,
*/
typedef uint32_t HAL_UART_RxEventTypeTypeDef;
/**
* @brief UART handle Structure definition
*/
typedef struct __UART_HandleTypeDef
{
USART_TypeDef *Instance; /*!< UART registers base address */
UART_InitTypeDef Init; /*!< UART communication parameters */
const uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */
uint16_t TxXferSize; /*!< UART Tx Transfer size */
__IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */
uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */
uint16_t RxXferSize; /*!< UART Rx Transfer size */
__IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */
__IO HAL_UART_RxTypeTypeDef ReceptionType; /*!< Type of ongoing reception */
__IO HAL_UART_RxEventTypeTypeDef RxEventType; /*!< Type of Rx Event */
DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /*!< Locking object */
__IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management
and also related to Tx operations.
This parameter can be a value of @ref HAL_UART_StateTypeDef */
__IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations.
This parameter can be a value of @ref HAL_UART_StateTypeDef */
__IO uint32_t ErrorCode; /*!< UART Error code */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
void (* TxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Half Complete Callback */
void (* TxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Tx Complete Callback */
void (* RxHalfCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Half Complete Callback */
void (* RxCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Rx Complete Callback */
void (* ErrorCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Error Callback */
void (* AbortCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Complete Callback */
void (* AbortTransmitCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Transmit Complete Callback */
void (* AbortReceiveCpltCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Abort Receive Complete Callback */
void (* WakeupCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Wakeup Callback */
void (* RxEventCallback)(struct __UART_HandleTypeDef *huart, uint16_t Pos); /*!< UART Reception Event Callback */
void (* MspInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp Init callback */
void (* MspDeInitCallback)(struct __UART_HandleTypeDef *huart); /*!< UART Msp DeInit callback */
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
} UART_HandleTypeDef;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/**
* @brief HAL UART Callback ID enumeration definition
*/
typedef enum
{
HAL_UART_TX_HALFCOMPLETE_CB_ID = 0x00U, /*!< UART Tx Half Complete Callback ID */
HAL_UART_TX_COMPLETE_CB_ID = 0x01U, /*!< UART Tx Complete Callback ID */
HAL_UART_RX_HALFCOMPLETE_CB_ID = 0x02U, /*!< UART Rx Half Complete Callback ID */
HAL_UART_RX_COMPLETE_CB_ID = 0x03U, /*!< UART Rx Complete Callback ID */
HAL_UART_ERROR_CB_ID = 0x04U, /*!< UART Error Callback ID */
HAL_UART_ABORT_COMPLETE_CB_ID = 0x05U, /*!< UART Abort Complete Callback ID */
HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID = 0x06U, /*!< UART Abort Transmit Complete Callback ID */
HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID = 0x07U, /*!< UART Abort Receive Complete Callback ID */
HAL_UART_WAKEUP_CB_ID = 0x08U, /*!< UART Wakeup Callback ID */
HAL_UART_MSPINIT_CB_ID = 0x0BU, /*!< UART MspInit callback ID */
HAL_UART_MSPDEINIT_CB_ID = 0x0CU /*!< UART MspDeInit callback ID */
} HAL_UART_CallbackIDTypeDef;
/**
* @brief HAL UART Callback pointer definition
*/
typedef void (*pUART_CallbackTypeDef)(UART_HandleTypeDef *huart); /*!< pointer to an UART callback function */
typedef void (*pUART_RxEventCallbackTypeDef)(struct __UART_HandleTypeDef *huart, uint16_t Pos); /*!< pointer to a UART Rx Event specific callback function */
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup UART_Exported_Constants UART Exported Constants
* @{
*/
/** @defgroup UART_Error_Code UART Error Code
* @{
*/
#define HAL_UART_ERROR_NONE 0x00000000U /*!< No error */
#define HAL_UART_ERROR_PE 0x00000001U /*!< Parity error */
#define HAL_UART_ERROR_NE 0x00000002U /*!< Noise error */
#define HAL_UART_ERROR_FE 0x00000004U /*!< Frame error */
#define HAL_UART_ERROR_ORE 0x00000008U /*!< Overrun error */
#define HAL_UART_ERROR_DMA 0x00000010U /*!< DMA transfer error */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
#define HAL_UART_ERROR_INVALID_CALLBACK 0x00000020U /*!< Invalid Callback error */
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup UART_Word_Length UART Word Length
* @{
*/
#define UART_WORDLENGTH_8B 0x00000000U
#define UART_WORDLENGTH_9B ((uint32_t)USART_CR1_M)
/**
* @}
*/
/** @defgroup UART_Stop_Bits UART Number of Stop Bits
* @{
*/
#define UART_STOPBITS_1 0x00000000U
#define UART_STOPBITS_2 ((uint32_t)USART_CR2_STOP_1)
/**
* @}
*/
/** @defgroup UART_Parity UART Parity
* @{
*/
#define UART_PARITY_NONE 0x00000000U
#define UART_PARITY_EVEN ((uint32_t)USART_CR1_PCE)
#define UART_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS))
/**
* @}
*/
/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control
* @{
*/
#define UART_HWCONTROL_NONE 0x00000000U
#define UART_HWCONTROL_RTS ((uint32_t)USART_CR3_RTSE)
#define UART_HWCONTROL_CTS ((uint32_t)USART_CR3_CTSE)
#define UART_HWCONTROL_RTS_CTS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE))
/**
* @}
*/
/** @defgroup UART_Mode UART Transfer Mode
* @{
*/
#define UART_MODE_RX ((uint32_t)USART_CR1_RE)
#define UART_MODE_TX ((uint32_t)USART_CR1_TE)
#define UART_MODE_TX_RX ((uint32_t)(USART_CR1_TE | USART_CR1_RE))
/**
* @}
*/
/** @defgroup UART_State UART State
* @{
*/
#define UART_STATE_DISABLE 0x00000000U
#define UART_STATE_ENABLE ((uint32_t)USART_CR1_UE)
/**
* @}
*/
/** @defgroup UART_Over_Sampling UART Over Sampling
* @{
*/
#define UART_OVERSAMPLING_16 0x00000000U
#define UART_OVERSAMPLING_8 ((uint32_t)USART_CR1_OVER8)
/**
* @}
*/
/** @defgroup UART_LIN_Break_Detection_Length UART LIN Break Detection Length
* @{
*/
#define UART_LINBREAKDETECTLENGTH_10B 0x00000000U
#define UART_LINBREAKDETECTLENGTH_11B ((uint32_t)USART_CR2_LBDL)
/**
* @}
*/
/** @defgroup UART_WakeUp_functions UART Wakeup Functions
* @{
*/
#define UART_WAKEUPMETHOD_IDLELINE 0x00000000U
#define UART_WAKEUPMETHOD_ADDRESSMARK ((uint32_t)USART_CR1_WAKE)
/**
* @}
*/
/** @defgroup UART_Flags UART FLags
* Elements values convention: 0xXXXX
* - 0xXXXX : Flag mask in the SR register
* @{
*/
#define UART_FLAG_CTS ((uint32_t)USART_SR_CTS)
#define UART_FLAG_LBD ((uint32_t)USART_SR_LBD)
#define UART_FLAG_TXE ((uint32_t)USART_SR_TXE)
#define UART_FLAG_TC ((uint32_t)USART_SR_TC)
#define UART_FLAG_RXNE ((uint32_t)USART_SR_RXNE)
#define UART_FLAG_IDLE ((uint32_t)USART_SR_IDLE)
#define UART_FLAG_ORE ((uint32_t)USART_SR_ORE)
#define UART_FLAG_NE ((uint32_t)USART_SR_NE)
#define UART_FLAG_FE ((uint32_t)USART_SR_FE)
#define UART_FLAG_PE ((uint32_t)USART_SR_PE)
/**
* @}
*/
/** @defgroup UART_Interrupt_definition UART Interrupt Definitions
* Elements values convention: 0xY000XXXX
* - XXXX : Interrupt mask (16 bits) in the Y register
* - Y : Interrupt source register (2bits)
* - 0001: CR1 register
* - 0010: CR2 register
* - 0011: CR3 register
* @{
*/
#define UART_IT_PE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_PEIE))
#define UART_IT_TXE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE))
#define UART_IT_TC ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_TCIE))
#define UART_IT_RXNE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE))
#define UART_IT_IDLE ((uint32_t)(UART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE))
#define UART_IT_LBD ((uint32_t)(UART_CR2_REG_INDEX << 28U | USART_CR2_LBDIE))
#define UART_IT_CTS ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_CTSIE))
#define UART_IT_ERR ((uint32_t)(UART_CR3_REG_INDEX << 28U | USART_CR3_EIE))
/**
* @}
*/
/** @defgroup UART_Reception_Type_Values UART Reception type values
* @{
*/
#define HAL_UART_RECEPTION_STANDARD (0x00000000U) /*!< Standard reception */
#define HAL_UART_RECEPTION_TOIDLE (0x00000001U) /*!< Reception till completion or IDLE event */
/**
* @}
*/
/** @defgroup UART_RxEvent_Type_Values UART RxEvent type values
* @{
*/
#define HAL_UART_RXEVENT_TC (0x00000000U) /*!< RxEvent linked to Transfer Complete event */
#define HAL_UART_RXEVENT_HT (0x00000001U) /*!< RxEvent linked to Half Transfer event */
#define HAL_UART_RXEVENT_IDLE (0x00000002U)
/**
* @}
*/
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/** @defgroup UART_Exported_Macros UART Exported Macros
* @{
*/
/** @brief Reset UART handle gstate & RxState
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \
(__HANDLE__)->gState = HAL_UART_STATE_RESET; \
(__HANDLE__)->RxState = HAL_UART_STATE_RESET; \
(__HANDLE__)->MspInitCallback = NULL; \
(__HANDLE__)->MspDeInitCallback = NULL; \
} while(0U)
#else
#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \
(__HANDLE__)->gState = HAL_UART_STATE_RESET; \
(__HANDLE__)->RxState = HAL_UART_STATE_RESET; \
} while(0U)
#endif /*USE_HAL_UART_REGISTER_CALLBACKS */
/** @brief Flushes the UART DR register
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
*/
#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR)
/** @brief Checks whether the specified UART flag is set or not.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5)
* @arg UART_FLAG_LBD: LIN Break detection flag
* @arg UART_FLAG_TXE: Transmit data register empty flag
* @arg UART_FLAG_TC: Transmission Complete flag
* @arg UART_FLAG_RXNE: Receive data register not empty flag
* @arg UART_FLAG_IDLE: Idle Line detection flag
* @arg UART_FLAG_ORE: Overrun Error flag
* @arg UART_FLAG_NE: Noise Error flag
* @arg UART_FLAG_FE: Framing Error flag
* @arg UART_FLAG_PE: Parity Error flag
* @retval The new state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__))
/** @brief Clears the specified UART pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __FLAG__ specifies the flag to check.
* This parameter can be any combination of the following values:
* @arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5).
* @arg UART_FLAG_LBD: LIN Break detection flag.
* @arg UART_FLAG_TC: Transmission Complete flag.
* @arg UART_FLAG_RXNE: Receive data register not empty flag.
*
* @note PE (Parity error), FE (Framing error), NE (Noise error), ORE (Overrun
* error) and IDLE (Idle line detected) flags are cleared by software
* sequence: a read operation to USART_SR register followed by a read
* operation to USART_DR register.
* @note RXNE flag can be also cleared by a read to the USART_DR register.
* @note TC flag can be also cleared by software sequence: a read operation to
* USART_SR register followed by a write operation to USART_DR register.
* @note TXE flag is cleared only by a write to the USART_DR register.
*
* @retval None
*/
#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__))
/** @brief Clears the UART PE pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) \
do{ \
__IO uint32_t tmpreg = 0x00U; \
tmpreg = (__HANDLE__)->Instance->SR; \
tmpreg = (__HANDLE__)->Instance->DR; \
UNUSED(tmpreg); \
} while(0U)
/** @brief Clears the UART FE pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)
/** @brief Clears the UART NE pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)
/** @brief Clears the UART ORE pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)
/** @brief Clears the UART IDLE pending flag.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @retval None
*/
#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)
/** @brief Enable the specified UART interrupt.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __INTERRUPT__ specifies the UART interrupt source to enable.
* This parameter can be one of the following values:
* @arg UART_IT_CTS: CTS change interrupt
* @arg UART_IT_LBD: LIN Break detection interrupt
* @arg UART_IT_TXE: Transmit Data Register empty interrupt
* @arg UART_IT_TC: Transmission complete interrupt
* @arg UART_IT_RXNE: Receive Data register not empty interrupt
* @arg UART_IT_IDLE: Idle line detection interrupt
* @arg UART_IT_PE: Parity Error interrupt
* @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @retval None
*/
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
/** @brief Disable the specified UART interrupt.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __INTERRUPT__ specifies the UART interrupt source to disable.
* This parameter can be one of the following values:
* @arg UART_IT_CTS: CTS change interrupt
* @arg UART_IT_LBD: LIN Break detection interrupt
* @arg UART_IT_TXE: Transmit Data Register empty interrupt
* @arg UART_IT_TC: Transmission complete interrupt
* @arg UART_IT_RXNE: Receive Data register not empty interrupt
* @arg UART_IT_IDLE: Idle line detection interrupt
* @arg UART_IT_PE: Parity Error interrupt
* @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @retval None
*/
#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK)))
/** @brief Checks whether the specified UART interrupt source is enabled or not.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __IT__ specifies the UART interrupt source to check.
* This parameter can be one of the following values:
* @arg UART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
* @arg UART_IT_LBD: LIN Break detection interrupt
* @arg UART_IT_TXE: Transmit Data Register empty interrupt
* @arg UART_IT_TC: Transmission complete interrupt
* @arg UART_IT_RXNE: Receive Data register not empty interrupt
* @arg UART_IT_IDLE: Idle line detection interrupt
* @arg UART_IT_ERR: Error interrupt
* @retval The new state of __IT__ (TRUE or FALSE).
*/
#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == UART_CR1_REG_INDEX)? (__HANDLE__)->Instance->CR1:(((((uint32_t)(__IT__)) >> 28U) == UART_CR2_REG_INDEX)? \
(__HANDLE__)->Instance->CR2 : (__HANDLE__)->Instance->CR3)) & (((uint32_t)(__IT__)) & UART_IT_MASK))
/** @brief Enable CTS flow control
* @note This macro allows to enable CTS hardware flow control for a given UART instance,
* without need to call HAL_UART_Init() function.
* As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
* @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need
* for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
* - UART instance should have already been initialised (through call of HAL_UART_Init() )
* - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__))
* and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)).
* @param __HANDLE__ specifies the UART Handle.
* The Handle Instance can be any USARTx (supporting the HW Flow control feature).
* It is used to select the USART peripheral (USART availability and x value depending on device).
* @retval None
*/
#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \
do{ \
ATOMIC_SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \
(__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \
} while(0U)
/** @brief Disable CTS flow control
* @note This macro allows to disable CTS hardware flow control for a given UART instance,
* without need to call HAL_UART_Init() function.
* As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
* @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need
* for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
* - UART instance should have already been initialised (through call of HAL_UART_Init() )
* - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__))
* and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)).
* @param __HANDLE__ specifies the UART Handle.
* The Handle Instance can be any USARTx (supporting the HW Flow control feature).
* It is used to select the USART peripheral (USART availability and x value depending on device).
* @retval None
*/
#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \
do{ \
ATOMIC_CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \
(__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \
} while(0U)
/** @brief Enable RTS flow control
* This macro allows to enable RTS hardware flow control for a given UART instance,
* without need to call HAL_UART_Init() function.
* As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
* @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need
* for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
* - UART instance should have already been initialised (through call of HAL_UART_Init() )
* - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__))
* and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)).
* @param __HANDLE__ specifies the UART Handle.
* The Handle Instance can be any USARTx (supporting the HW Flow control feature).
* It is used to select the USART peripheral (USART availability and x value depending on device).
* @retval None
*/
#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \
do{ \
ATOMIC_SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \
(__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \
} while(0U)
/** @brief Disable RTS flow control
* This macro allows to disable RTS hardware flow control for a given UART instance,
* without need to call HAL_UART_Init() function.
* As involving direct access to UART registers, usage of this macro should be fully endorsed by user.
* @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need
* for USART instance Deinit/Init, following conditions for macro call should be fulfilled :
* - UART instance should have already been initialised (through call of HAL_UART_Init() )
* - macro could only be called when corresponding UART instance is disabled (i.e __HAL_UART_DISABLE(__HANDLE__))
* and should be followed by an Enable macro (i.e __HAL_UART_ENABLE(__HANDLE__)).
* @param __HANDLE__ specifies the UART Handle.
* The Handle Instance can be any USARTx (supporting the HW Flow control feature).
* It is used to select the USART peripheral (USART availability and x value depending on device).
* @retval None
*/
#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \
do{ \
ATOMIC_CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\
(__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \
} while(0U)
/** @brief Macro to enable the UART's one bit sample method
* @param __HANDLE__ specifies the UART Handle.
* @retval None
*/
#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT)
/** @brief Macro to disable the UART's one bit sample method
* @param __HANDLE__ specifies the UART Handle.
* @retval None
*/
#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3\
&= (uint16_t)~((uint16_t)USART_CR3_ONEBIT))
/** @brief Enable UART
* @param __HANDLE__ specifies the UART Handle.
* @retval None
*/
#define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE)
/** @brief Disable UART
* @param __HANDLE__ specifies the UART Handle.
* @retval None
*/
#define __HAL_UART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE)
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup UART_Exported_Functions
* @{
*/
/** @addtogroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
/* Initialization/de-initialization functions **********************************/
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength);
HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod);
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart);
void HAL_UART_MspInit(UART_HandleTypeDef *huart);
void HAL_UART_MspDeInit(UART_HandleTypeDef *huart);
/* Callbacks Register/UnRegister functions ***********************************/
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID,
pUART_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID);
HAL_StatusTypeDef HAL_UART_RegisterRxEventCallback(UART_HandleTypeDef *huart, pUART_RxEventCallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_UART_UnRegisterRxEventCallback(UART_HandleTypeDef *huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
/**
* @}
*/
/** @addtogroup UART_Exported_Functions_Group2 IO operation functions
* @{
*/
/* IO operation functions *******************************************************/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
uint32_t Timeout);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart);
/* Transfer Abort functions */
HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart);
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);
/**
* @}
*/
/** @addtogroup UART_Exported_Functions_Group3
* @{
*/
/* Peripheral Control functions ************************************************/
HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart);
/**
* @}
*/
/** @addtogroup UART_Exported_Functions_Group4
* @{
*/
/* Peripheral State functions **************************************************/
HAL_UART_StateTypeDef HAL_UART_GetState(const UART_HandleTypeDef *huart);
uint32_t HAL_UART_GetError(const UART_HandleTypeDef *huart);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup UART_Private_Constants UART Private Constants
* @{
*/
/** @brief UART interruptions flag mask
*
*/
#define UART_IT_MASK 0x0000FFFFU
#define UART_CR1_REG_INDEX 1U
#define UART_CR2_REG_INDEX 2U
#define UART_CR3_REG_INDEX 3U
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup UART_Private_Macros UART Private Macros
* @{
*/
#define IS_UART_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B) || \
((LENGTH) == UART_WORDLENGTH_9B))
#define IS_UART_LIN_WORD_LENGTH(LENGTH) (((LENGTH) == UART_WORDLENGTH_8B))
#define IS_UART_STOPBITS(STOPBITS) (((STOPBITS) == UART_STOPBITS_1) || \
((STOPBITS) == UART_STOPBITS_2))
#define IS_UART_PARITY(PARITY) (((PARITY) == UART_PARITY_NONE) || \
((PARITY) == UART_PARITY_EVEN) || \
((PARITY) == UART_PARITY_ODD))
#define IS_UART_HARDWARE_FLOW_CONTROL(CONTROL)\
(((CONTROL) == UART_HWCONTROL_NONE) || \
((CONTROL) == UART_HWCONTROL_RTS) || \
((CONTROL) == UART_HWCONTROL_CTS) || \
((CONTROL) == UART_HWCONTROL_RTS_CTS))
#define IS_UART_MODE(MODE) ((((MODE) & 0x0000FFF3U) == 0x00U) && ((MODE) != 0x00U))
#define IS_UART_STATE(STATE) (((STATE) == UART_STATE_DISABLE) || \
((STATE) == UART_STATE_ENABLE))
#define IS_UART_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16) || \
((SAMPLING) == UART_OVERSAMPLING_8))
#define IS_UART_LIN_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16))
#define IS_UART_LIN_BREAK_DETECT_LENGTH(LENGTH) (((LENGTH) == UART_LINBREAKDETECTLENGTH_10B) || \
((LENGTH) == UART_LINBREAKDETECTLENGTH_11B))
#define IS_UART_WAKEUPMETHOD(WAKEUP) (((WAKEUP) == UART_WAKEUPMETHOD_IDLELINE) || \
((WAKEUP) == UART_WAKEUPMETHOD_ADDRESSMARK))
#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) <= 10500000U)
#define IS_UART_ADDRESS(ADDRESS) ((ADDRESS) <= 0x0FU)
#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(4U*((uint64_t)(_BAUD_)))))
#define UART_DIVMANT_SAMPLING16(_PCLK_, _BAUD_) (UART_DIV_SAMPLING16((_PCLK_), (_BAUD_))/100U)
#define UART_DIVFRAQ_SAMPLING16(_PCLK_, _BAUD_) ((((UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) * 100U)) * 16U)\
+ 50U) / 100U)
/* UART BRR = mantissa + overflow + fraction
= (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */
#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_) ((UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) << 4U) + \
(UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0xF0U) + \
(UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0x0FU))
#define UART_DIV_SAMPLING8(_PCLK_, _BAUD_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(2U*((uint64_t)(_BAUD_)))))
#define UART_DIVMANT_SAMPLING8(_PCLK_, _BAUD_) (UART_DIV_SAMPLING8((_PCLK_), (_BAUD_))/100U)
#define UART_DIVFRAQ_SAMPLING8(_PCLK_, _BAUD_) ((((UART_DIV_SAMPLING8((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) * 100U)) * 8U)\
+ 50U) / 100U)
/* UART BRR = mantissa + overflow + fraction
= (UART DIVMANT << 4) + ((UART DIVFRAQ & 0xF8) << 1) + (UART DIVFRAQ & 0x07U) */
#define UART_BRR_SAMPLING8(_PCLK_, _BAUD_) ((UART_DIVMANT_SAMPLING8((_PCLK_), (_BAUD_)) << 4U) + \
((UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0xF8U) << 1U) + \
(UART_DIVFRAQ_SAMPLING8((_PCLK_), (_BAUD_)) & 0x07U))
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup UART_Private_Functions UART Private Functions
* @{
*/
HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_UART_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

495
Inc/ch395f.h Normal file
View File

@@ -0,0 +1,495 @@
/*
* 模块名称CH395F SPI Ethernet Protocol Stack Driver
* 模块功能CH395F 以太网协议栈芯片 SPI 驱动提供网络初始化、Socket 管理、
* 数据收发等功能。命令码参考 CH395 手册 v2.2 Table 5-1
* 适用平台STM32F4 系列SPI2 接口)
* 作者:王建锋
* 创建日期2026-06-06
* 修改记录:
* 2026-06-06 王建锋 创建初始版本,按代码规范重构
*/
#ifndef __CH395F_H
#define __CH395F_H
/*
* 头文件包含区 - 仅包含本模块必需的头文件
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/*
* 宏定义区 - SPI 命令码(来自 CH395 手册 v2.2 Table 5-1
*/
/* 无输入数据,无输出数据 */
#define CH395F_CMD_RESET_ALL 0x05U
#define CH395F_CMD_ENTER_SLEEP 0x03U
/* 无输入数据1 字节输出 */
#define CH395F_CMD_GET_IC_VER 0x01U
#define CH395F_CMD_GET_CMD_STATUS 0x2CU
#define CH395F_CMD_GET_GLOB_INT_STATUS 0x29U
#define CH395F_CMD_GET_GLOB_INT_STATUS_ALL 0x19U
#define CH395F_CMD_GET_PHY_STATUS 0x26U
#define CH395F_CMD_GET_DHCP_STATUS 0x42U
/* 无输入数据6 字节输出 */
#define CH395F_CMD_GET_MAC_ADDR 0x40U
/* 无输入数据20 字节输出 */
#define CH395F_CMD_GET_IP_INF 0x43U
/* 1 字节输入,无输出数据 */
#define CH395F_CMD_SET_PHY 0x20U
#define CH395F_CMD_PING_ENABLE 0x3FU
#define CH395F_CMD_DHCP_ENABLE 0x41U
#define CH395F_CMD_SET_RETRAN_COUNT 0x2AU
/* 1 字节输入1 字节输出 */
#define CH395F_CMD_CHECK_EXIST 0x06U
#define CH395F_CMD_SET_FUN_PARA 0x55U
/* 2 字节输入,无输出数据 */
#define CH395F_CMD_SET_TTL 0x51U
#define CH395F_CMD_SET_ARP 0x44U
/* 3 字节输入,无输出数据 */
#define CH395F_CMD_SET_BAUDRATE 0x02U
#define CH395F_CMD_SET_RETRAN_PERIOD 0x2BU
/* 4 字节输入,无输出数据 */
#define CH395F_CMD_SET_IP_ADDR 0x22U
#define CH395F_CMD_SET_GWIP_ADDR 0x23U
#define CH395F_CMD_SET_MASK_ADDR 0x24U
/* 6 字节输入,无输出数据 */
#define CH395F_CMD_SET_MAC_ADDR 0x21U
/* 初始化命令(仅写入,执行时间较长) */
#define CH395F_CMD_INIT_CH395 0x27U
/* Socket 命令 */
/* 1 字节输入socket 索引),无输出数据 */
#define CH395F_CMD_CLOSE_SOCKET_SN 0x3DU
#define CH395F_CMD_OPEN_SOCKET_SN 0x35U
#define CH395F_CMD_TCP_LISTEN_SN 0x36U
#define CH395F_CMD_TCP_CONNECT_SN 0x37U
#define CH395F_CMD_TCP_DISCONNECT_SN 0x38U
#define CH395F_CMD_CLEAR_RECV_BUF_SN 0x2EU
/* 1 字节输入1 字节输出socket 索引) */
#define CH395F_CMD_GET_INT_STATUS_SN 0x30U
#define CH395F_CMD_GET_SOCKET_STATUS_SN 0x2FU
/* 1 字节输入2 字节输出 */
#define CH395F_CMD_GET_RECV_LEN_SN 0x3BU
/* 2 字节输入,无输出数据 */
#define CH395F_CMD_SET_PROTO_TYPE_SN 0x34U
#define CH395F_CMD_SET_IPRAW_PRO_SN 0x3EU
/* 3 字节输入,无输出数据 */
#define CH395F_CMD_SET_DES_PORT_SN 0x32U
#define CH395F_CMD_SET_SOUR_PORT_SN 0x33U
/* 5 字节输入无输出数据socket + 4 字节 IP */
#define CH395F_CMD_SET_IP_ADDR_SN 0x31U
/* 1 字节输入6 字节输出socket 索引 -> 远程 IP + 端口) */
#define CH395F_CMD_GET_REMOT_IPP_SN 0x2DU
/* 3 字节输入 + 数据输出socket + 长度) */
#define CH395F_CMD_READ_RECV_BUF_SN 0x3CU
/* 3 字节输入 + 数据输入socket + 长度 + 数据) */
#define CH395F_CMD_WRITE_SEND_BUF_SN 0x39U
/* 其他命令 */
#define CH395F_CMD_SET_TCP_MSS 0x50U
#define CH395F_CMD_SET_RECV_BUF 0x52U
#define CH395F_CMD_SET_SEND_BUF 0x53U
#define CH395F_CMD_SET_KEEPALIVE_IDLE 0x56U
#define CH395F_CMD_SET_KEEPALIVE_INTVL 0x57U
#define CH395F_CMD_SET_KEEPALIVE_CNT 0x58U
#define CH395F_CMD_SET_KEEPALIVE_SN 0x59U
#define CH395F_CMD_EEPROM_ERASE 0xE9U
#define CH395F_CMD_EEPROM_WRITE 0xEAU
#define CH395F_CMD_EEPROM_READ 0xEBU
#define CH395F_CMD_READ_GPIO_REG 0xECH
#define CH395F_CMD_WRITE_GPIO_REG 0xEDU
/*
* CH395 错误码(来自手册 CH395INC.H 引用)
*/
#define CH395F_ERR_SUCCESS 0x00U
#define CH395F_ERR_BUSY 0x01U
#define CH395F_ERR_CMD 0x02U
#define CH395F_ERR_MAC 0x03U
#define CH395F_ERR_PHY 0x04U
#define CH395F_ERR_IP_CONFLI 0x05U
#define CH395F_ERR_SOCK 0x06U
#define CH395F_ERR_SOCK_BUSY 0x07U
#define CH395F_ERR_SOCK_CLOSED 0x08U
#define CH395F_ERR_SOCK_ERR 0x09U
#define CH395F_ERR_UNKNOW 0xFFU
/*
* PHY 状态码
*/
#define CH395F_PHY_DISCONN 0x01U /* PHY 断开连接 */
#define CH395F_PHY_10M_FULL 0x02U /* 10M 全双工 */
#define CH395F_PHY_10M_HALF 0x04U /* 10M 半双工 */
#define CH395F_PHY_100M_FULL 0x08U /* 100M 全双工 */
#define CH395F_PHY_100M_HALF 0x10U /* 100M 半双工 */
#define CH395F_PHY_AUTO_NEGOTIATE 0x20U /* 自动协商 */
/*
* 协议类型
*/
#define CH395F_PROTO_TYPE_IP_RAW 0x00U
#define CH395F_PROTO_TYPE_MAC_RAW 0x01U
#define CH395F_PROTO_TYPE_UDP 0x02U
#define CH395F_PROTO_TYPE_TCP 0x03U
/*
* Socket 状态
*/
#define CH395F_SOCKET_CLOSED 0x00U
#define CH395F_SOCKET_OPEN 0x05U
/*
* TCP 状态
*/
#define CH395F_TCP_CLOSED 0x00U
#define CH395F_TCP_LISTEN 0x01U
#define CH395F_TCP_SYN_SENT 0x02U
#define CH395F_TCP_SYN_RCVD 0x03U
#define CH395F_TCP_ESTABLISHED 0x04U
#define CH395F_TCP_FIN_WAIT_1 0x05U
#define CH395F_TCP_FIN_WAIT_2 0x06U
#define CH395F_TCP_CLOSE_WAIT 0x07U
#define CH395F_TCP_CLOSING 0x08U
#define CH395F_TCP_LAST_ACK 0x09U
#define CH395F_TCP_TIME_WAIT 0x0AU
/*
* 全局中断状态位
*/
#define CH395F_GINT_STAT_UNREACH 0x01U
#define CH395F_GINT_STAT_IP_CONFLI 0x02U
#define CH395F_GINT_STAT_PHY_CHANGE 0x04U
#define CH395F_GINT_STAT_DHCP 0x08U
#define CH395F_GINT_STAT_SOCK0 0x10U
#define CH395F_GINT_STAT_SOCK1 0x20U
#define CH395F_GINT_STAT_SOCK2 0x40U
#define CH395F_GINT_STAT_SOCK3 0x80U
/*
* Socket 中断状态位
*/
#define CH395F_SINT_STAT_CONNECT 0x01U
#define CH395F_SINT_STAT_DISCONNECT 0x02U
#define CH395F_SINT_STAT_SEND_OK 0x04U
#define CH395F_SINT_STAT_SENBUF_FREE 0x08U
#define CH395F_SINT_STAT_RECV_OK 0x10U
#define CH395F_SINT_STAT_DISCARD 0x20U
#define CH395F_SINT_STAT_SOCK_TIMEOUT 0x40U
/*
* 类型定义区 - 驱动返回码
*/
typedef enum {
CH395F_STATUS_OK = 0,
CH395F_STATUS_ERROR = -1,
CH395F_STATUS_TIMEOUT = -2,
CH395F_STATUS_NOT_DETECTED = -3
} ch395f_status_t;
/*
* 函数声明区 - SPI 基础事务层
*/
/*
* 函数功能:向 CH395 写入命令字节
* 入口参数cmd - 命令码 uint8_t 0x00 - 0xFF
* 返回值:命令码回显值 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
* 函数说明SPI 模式下命令与数据之间无需间隔
*/
uint8_t ch395f_write_cmd(uint8_t cmd);
/*
* 函数功能:向 CH395 写入数据字节
* 入口参数data - 数据字节 uint8_t 0x00 - 0xFF
* 返回值:数据回显值 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
*/
uint8_t ch395f_write_data(uint8_t data);
/*
* 函数功能:从 CH395 读取数据字节
* 返回值:接收到的数据字节 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
*/
uint8_t ch395f_read_data(void);
/*
* 函数声明区 - 芯片检测与版本
*/
/*
* 函数功能:检测 CH395 芯片是否存在且通信正常
* 返回值CH395F_STATUS_OK - 检测到芯片CH395F_STATUS_NOT_DETECTED - 未检测到
* 限定条件SPI2 已正确初始化
* 函数说明:发送 CMD_CHECK_EXIST (0x06) 及测试字节 0x57
* 芯片应返回按位取反值 0xA8
*/
ch395f_status_t ch395f_check_exist(void);
/*
* 函数功能:读取 CH395 芯片版本号
* 返回值版本字节bit5:0 为版本号uint8_t
* 限定条件:芯片已通过 ch395f_check_exist() 检测
*/
uint8_t ch395f_get_version(void);
/*
* 函数声明区 - 初始化
*/
/*
* 函数功能:软件复位 CH395
* 返回值CH395F_STATUS_OK
* 限定条件SPI2 已正确初始化
* 函数说明:复位耗时约 15msTE0函数内部已包含延时
*/
ch395f_status_t ch395f_reset(void);
/*
* 函数功能:查询命令执行状态
* 返回值状态字节CH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...uint8_t
* 限定条件:仅在长执行命令(如初始化)后调用
*/
uint8_t ch395f_get_cmd_status(void);
/*
* 函数功能:初始化 CH395包含 MAC、PHY、TCP/IP 协议栈)
* 返回值CH395F_STATUS_OK - 成功CH395F_STATUS_TIMEOUT - 超时失败
* 限定条件:芯片已通过 ch395f_reset() 复位
* 函数说明:阻塞等待初始化完成或超时(典型 5msTE1
*/
ch395f_status_t ch395f_init(void);
/*
* 函数声明区 - 网络参数配置
*/
/*
* 函数功能:设置 CH395 IP 地址(低字节在前)
* 入口参数p_ip - 4 字节 IP 地址指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_ip_addr(uint8_t *p_ip);
/*
* 函数功能:设置网关 IP 地址(低字节在前)
* 入口参数p_gwip - 4 字节网关 IP 指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_gwip_addr(uint8_t *p_gwip);
/*
* 函数功能:设置子网掩码(低字节在前)
* 入口参数p_mask - 4 字节子网掩码指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_mask_addr(uint8_t *p_mask);
/*
* 函数功能:设置 MAC 地址(低字节在前,存储于 EEPROM
* 入口参数p_mac - 6 字节 MAC 地址指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
* 函数说明:执行耗时约 30usTE5
*/
void ch395f_set_mac_addr(uint8_t *p_mac);
/*
* 函数功能:从 CH395 读取 MAC 地址
* 出口参数p_mac - 6 字节 MAC 地址缓冲区指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_get_mac_addr(uint8_t *p_mac);
/*
* 函数功能:读取 IP 信息IP + 掩码 + DNS共 20 字节)
* 出口参数p_buf - 20 字节缓冲区指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_get_ip_inf(uint8_t *p_buf);
/*
* 函数声明区 - PHY 管理
*/
/*
* 函数功能:获取 PHY 连接状态
* 返回值PHY 状态码CH395F_PHY_DISCONN、CH395F_PHY_10M_FULL 等uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_phy_status(void);
/*
* 函数功能:设置 PHY 连接模式
* 入口参数phystat - 连接模式码 uint8_t 0x20 = 自动协商
* 限定条件:芯片已初始化
*/
void ch395f_set_phy(uint8_t phystat);
/*
* 函数声明区 - DHCP
*/
/*
* 函数功能:启用/禁用 DHCP
* 入口参数enable - 1 启用0 禁用 uint8_t
* 限定条件:芯片已初始化
*/
void ch395f_set_dhcp(uint8_t enable);
/*
* 函数功能:获取 DHCP 状态
* 返回值0 = 成功,非零 = 错误/超时 uint8_t
* 限定条件:芯片已初始化且 DHCP 已启用
*/
uint8_t ch395f_get_dhcp_status(void);
/*
* 函数声明区 - Socket 管理
*/
/*
* 函数功能:设置 Socket 协议类型
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* proto - 协议类型 uint8_t CH395F_PROTO_TYPE_xxx
* 限定条件Socket 未打开
*/
void ch395f_set_proto_type(uint8_t sock, uint8_t proto);
/*
* 函数功能:设置 Socket 目标 IP 地址
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_ip - 4 字节目标 IP 指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip);
/*
* 函数功能:设置 Socket 目标端口(小端序)
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* port - 目标端口 uint16_t
* 限定条件:无
*/
void ch395f_set_des_port(uint8_t sock, uint16_t port);
/*
* 函数功能:设置 Socket 源端口(小端序)
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* port - 源端口 uint16_t
* 限定条件:无
*/
void ch395f_set_sour_port(uint8_t sock, uint16_t port);
/*
* 函数功能:打开 Socket
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件:协议类型、目标 IP、端口已设置
*/
void ch395f_open_socket(uint8_t sock);
/*
* 函数功能:关闭 Socket
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开
*/
void ch395f_close_socket(uint8_t sock);
/*
* 函数功能:启动 TCP 监听模式
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开且协议类型为 TCP
*/
void ch395f_tcp_listen(uint8_t sock);
/*
* 函数功能:启动 TCP 连接
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开且协议类型为 TCP
*/
void ch395f_tcp_connect(uint8_t sock);
/*
* 函数功能:断开 TCP 连接
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件TCP 已建立连接
*/
void ch395f_tcp_disconnect(uint8_t sock);
/*
* 函数声明区 - Socket 数据传输
*/
/*
* 函数功能:向 Socket 发送缓冲区写入数据
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_data - 数据指针 uint8_t*
* len - 数据长度 uint16_t
* 限定条件:指针非空,长度大于 0TCP 已连接或 UDP 已打开
*/
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len);
/*
* 函数功能:从 Socket 接收缓冲区读取数据
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_data - 输出缓冲区指针 uint8_t*
* len - 待读取数据长度 uint16_t
* 限定条件:指针非空,长度大于 0接收缓冲区有数据
*/
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len);
/*
* 函数功能:获取 Socket 接收缓冲区数据长度
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 返回值:接收数据长度 uint16_t
* 限定条件Socket 已打开
*/
uint16_t ch395f_get_recv_len(uint8_t sock);
/*
* 函数声明区 - 中断状态
*/
/*
* 函数功能:获取全局中断状态
* 返回值:中断状态字节 uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_glob_int_status(void);
/*
* 函数功能:获取 Socket 中断状态
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 返回值Socket 中断状态字节 uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_sock_int_status(uint8_t sock);
#ifdef __cplusplus
}
#endif
#endif /* __CH395F_H */

View File

@@ -61,6 +61,26 @@ void Error_Handler(void);
#define LED1_GPIO_Port GPIOC
#define LED2_Pin GPIO_PIN_5
#define LED2_GPIO_Port GPIOC
#define LED3_Pin GPIO_PIN_1
#define LED3_GPIO_Port GPIOB
#define LED4_Pin GPIO_PIN_2
#define LED4_GPIO_Port GPIOB
#define LED5_Pin GPIO_PIN_11
#define LED5_GPIO_Port GPIOF
#define LED6_Pin GPIO_PIN_12
#define LED6_GPIO_Port GPIOF
#define CH395_SCS_Pin GPIO_PIN_12
#define CH395_SCS_GPIO_Port GPIOB
#define CH395F_SCK_Pin GPIO_PIN_13
#define CH395F_SCK_GPIO_Port GPIOB
#define CH395F_SDO_Pin GPIO_PIN_14
#define CH395F_SDO_GPIO_Port GPIOB
#define CH395F_SDOB15_Pin GPIO_PIN_15
#define CH395F_SDOB15_GPIO_Port GPIOB
#define ST_TX0_Pin GPIO_PIN_9
#define ST_TX0_GPIO_Port GPIOA
#define ST_RX0_Pin GPIO_PIN_10
#define ST_RX0_GPIO_Port GPIOA
/* USER CODE BEGIN Private defines */

52
Inc/spi.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.h
* @brief This file contains all the function prototypes for
* the spi.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_H__
#define __SPI_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern SPI_HandleTypeDef hspi2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_SPI2_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __SPI_H__ */

View File

@@ -62,9 +62,9 @@
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
#define HAL_SPI_MODULE_ENABLED
/* #define HAL_TIM_MODULE_ENABLED */
/* #define HAL_UART_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */

52
Inc/usart.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

View File

@@ -16,7 +16,7 @@
<TargetCommonOption>
<Device>STM32F407ZGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.0.0</PackID>
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001BFFF) IRAM2(0x2001C000-0x2001FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec>
@@ -48,7 +48,7 @@
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>STM32F407-Demo\</OutputDirectory>
<OutputDirectory>.\STM32F407-Demo\</OutputDirectory>
<OutputName>STM32F407-Demo</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
@@ -134,11 +134,11 @@
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4101</DriverSelection>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2V8M.DLL</Flash2>
<Flash3></Flash3>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
@@ -190,7 +190,7 @@
<hadIRAM2>1</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>
<useUlib>0</useUlib>
<useUlib>1</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
@@ -207,7 +207,7 @@
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>1</Ir2Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
@@ -404,6 +404,123 @@
<FileType>1</FileType>
<FilePath>../Src/gpio.c</FilePath>
</File>
<File>
<FileName>spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/spi.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>usart.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/usart.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>ch395f.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/ch395f.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_it.c</FileName>
<FileType>1</FileType>
@@ -419,6 +536,62 @@
<Group>
<GroupName>Drivers/STM32F4xx_HAL_Driver</GroupName>
<Files>
<File>
<FileName>stm32f4xx_hal_spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f4xx_hal_rcc.c</FileName>
<FileType>1</FileType>
@@ -484,6 +657,62 @@
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c</FilePath>
</File>
<File>
<FileName>stm32f4xx_hal_uart.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
</Files>
</Group>
<Group>
@@ -506,8 +735,8 @@
<RTE>
<apis/>
<components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="4.3.0" condition="CMSIS Core">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="4.5.0"/>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.5.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0"/>
<targetInfos>
<targetInfo name="STM32F407-Demo"/>
</targetInfos>

View File

@@ -9,18 +9,30 @@ Mcu.CPN=STM32F407ZGT6
Mcu.Family=STM32F4
Mcu.IP0=NVIC
Mcu.IP1=RCC
Mcu.IP2=SYS
Mcu.IPNb=3
Mcu.IP2=SPI2
Mcu.IP3=SYS
Mcu.IP4=USART1
Mcu.IPNb=5
Mcu.Name=STM32F407Z(E-G)Tx
Mcu.Package=LQFP144
Mcu.Pin0=PH0-OSC_IN
Mcu.Pin1=PH1-OSC_OUT
Mcu.Pin10=PB14
Mcu.Pin11=PB15
Mcu.Pin12=PA9
Mcu.Pin13=PA10
Mcu.Pin14=PA13
Mcu.Pin15=PA14
Mcu.Pin16=VP_SYS_VS_Systick
Mcu.Pin2=PC4
Mcu.Pin3=PC5
Mcu.Pin4=PA13
Mcu.Pin5=PA14
Mcu.Pin6=VP_SYS_VS_Systick
Mcu.PinsNb=7
Mcu.Pin4=PB1
Mcu.Pin5=PB2
Mcu.Pin6=PF11
Mcu.Pin7=PF12
Mcu.Pin8=PB12
Mcu.Pin9=PB13
Mcu.PinsNb=17
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F407ZGTx
@@ -37,10 +49,56 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA10.GPIOParameters=GPIO_PuPd,GPIO_Label
PA10.GPIO_Label=ST_RX0
PA10.GPIO_PuPd=GPIO_PULLUP
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA9.GPIOParameters=GPIO_Label
PA9.GPIO_Label=ST_TX0
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB1.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PB1.GPIO_Label=LED3
PB1.GPIO_PuPd=GPIO_PULLUP
PB1.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PB1.Locked=true
PB1.PinState=GPIO_PIN_SET
PB1.Signal=GPIO_Output
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PB12.GPIO_Label=CH395_SCS
PB12.GPIO_PuPd=GPIO_NOPULL
PB12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PB12.Locked=true
PB12.PinState=GPIO_PIN_SET
PB12.Signal=GPIO_Output
PB13.GPIOParameters=GPIO_Label
PB13.GPIO_Label=CH395F_SCK
PB13.Locked=true
PB13.Mode=Full_Duplex_Master
PB13.Signal=SPI2_SCK
PB14.GPIOParameters=GPIO_PuPd,GPIO_Label
PB14.GPIO_Label=CH395F_SDO
PB14.GPIO_PuPd=GPIO_PULLUP
PB14.Locked=true
PB14.Mode=Full_Duplex_Master
PB14.Signal=SPI2_MISO
PB15.GPIOParameters=GPIO_Label
PB15.GPIO_Label=CH395F_SDO
PB15.Locked=true
PB15.Mode=Full_Duplex_Master
PB15.Signal=SPI2_MOSI
PB2.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PB2.GPIO_Label=LED4
PB2.GPIO_PuPd=GPIO_PULLUP
PB2.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PB2.Locked=true
PB2.PinState=GPIO_PIN_SET
PB2.Signal=GPIO_Output
PC4.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PC4.GPIO_Label=LED1
PC4.GPIO_PuPd=GPIO_PULLUP
@@ -63,6 +121,20 @@ PCC.PartNumber=STM32F407ZGTx
PCC.Series=STM32F4
PCC.Temperature=25
PCC.Vdd=3.3
PF11.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PF11.GPIO_Label=LED5
PF11.GPIO_PuPd=GPIO_PULLUP
PF11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PF11.Locked=true
PF11.PinState=GPIO_PIN_SET
PF11.Signal=GPIO_Output
PF12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
PF12.GPIO_Label=LED6
PF12.GPIO_PuPd=GPIO_PULLUP
PF12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
PF12.Locked=true
PF12.PinState=GPIO_PIN_SET
PF12.Signal=GPIO_Output
PH0-OSC_IN.Mode=HSE-External-Oscillator
PH0-OSC_IN.Signal=RCC_OSC_IN
PH1-OSC_OUT.Mode=HSE-External-Oscillator
@@ -100,7 +172,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_USART1_UART_Init-USART1-false-HAL-true,4-MX_SPI2_Init-SPI2-false-HAL-true
RCC.48MHZClocksFreq_Value=84000000
RCC.AHBFreq_Value=168000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4
@@ -117,7 +189,8 @@ RCC.HCLKFreq_Value=168000000
RCC.HSE_VALUE=8000000
RCC.HSI_VALUE=16000000
RCC.I2SClocksFreq_Value=192000000
RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
RCC.LSE_VALUE=32768
RCC.LSI_VALUE=32000
RCC.MCO2PinFreq_Value=168000000
RCC.PLLCLKFreq_Value=168000000
@@ -133,6 +206,13 @@ RCC.VCOI2SOutputFreq_Value=384000000
RCC.VCOInputFreq_Value=2000000
RCC.VCOOutputFreq_Value=336000000
RCC.VcooutputI2S=192000000
SPI2.CalculateBaudRate=21.0 MBits/s
SPI2.Direction=SPI_DIRECTION_2LINES
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate
SPI2.Mode=SPI_MODE_MASTER
SPI2.VirtualType=VM_MASTER
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
board=custom

918
Src/ch395f.c Normal file
View File

@@ -0,0 +1,918 @@
/*
* 模块名称CH395F SPI Ethernet Protocol Stack Driver
* 模块功能CH395F 以太网协议栈芯片 SPI 驱动实现,提供芯片检测、初始化、
* 网络参数配置、PHY 管理、DHCP、Socket 管理及数据收发功能
* 适用平台STM32F4 系列SPI2 接口)
* 作者:王建锋
* 创建日期2026-03-14
* 修改记录:
* 2026-03-14 王建锋 创建初始版本,按代码规范重构
*/
/* 头文件包含区 - 先包含本模块头文件,再包含依赖头文件 */
#include "ch395f.h"
#include "spi.h"
#include <string.h>
/*
* 私有宏定义区
*/
#define CH395F_CHECK_EXIST_TEST_DATA 0x57U /* 芯片检测测试字节 */
#define CH395F_RESET_DELAY_MS 20U /* 复位后等待延时ms */
#define CH395F_INIT_TIMEOUT_MS 500U /* 初始化超时时间ms */
#define CH395F_SPI_BEGIN_DELAY_MS 1U /* SPI 事务开始延时ms */
/*
* 私有函数声明区
*/
static void ch395f_spi_begin(void);
static void ch395f_spi_end(void);
/*
* 私有函数实现区
*/
/*
* 函数功能:开始 SPI 事务CS 拉高 -> 拉低)
* 函数说明:手册要求 SPI 模式下字节间无需间隔
*/
static void ch395f_spi_begin(void)
{
/* CS 先拉高,确保空闲状态 */
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
HAL_Delay(CH395F_SPI_BEGIN_DELAY_MS);
/* CS 拉低,启动事务 */
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_RESET);
}
/*
* 函数功能:结束 SPI 事务CS 拉高)
*/
static void ch395f_spi_end(void)
{
/* CS 拉高,结束事务 */
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
}
/*
* 公共函数实现区
*/
/*
* 函数功能:向 CH395 写入命令字节
* 入口参数cmd - 命令码 uint8_t 0x00 - 0xFF
* 返回值:命令码回显值 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
* 函数说明SPI 模式下命令与数据之间无需间隔
*/
uint8_t ch395f_write_cmd(uint8_t cmd)
{
uint8_t rx_data;
/* 通过 SPI 发送命令并接收回显 */
HAL_SPI_TransmitReceive(&hspi2, &cmd, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:向 CH395 写入数据字节
* 入口参数data - 数据字节 uint8_t 0x00 - 0xFF
* 返回值:数据回显值 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
*/
uint8_t ch395f_write_data(uint8_t data)
{
uint8_t rx_data;
/* 通过 SPI 发送数据并接收回显 */
HAL_SPI_TransmitReceive(&hspi2, &data, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:从 CH395 读取数据字节
* 返回值:接收到的数据字节 uint8_t
* 限定条件:需在 ch395f_spi_begin() 和 ch395f_spi_end() 之间调用
*/
uint8_t ch395f_read_data(void)
{
uint8_t tx_dummy = 0xFFU;
uint8_t rx_data;
/* 发送 0xFF 作为时钟源,读取芯片返回的数据 */
HAL_SPI_TransmitReceive(&hspi2, &tx_dummy, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:检测 CH395 芯片是否存在且通信正常
* 返回值CH395F_STATUS_OK - 检测到芯片CH395F_STATUS_NOT_DETECTED - 未检测到
* 限定条件SPI2 已正确初始化
* 函数说明:发送 CMD_CHECK_EXIST (0x06) 及测试字节 0x57
* 芯片应返回按位取反值 0xA8
*/
ch395f_status_t ch395f_check_exist(void)
{
uint8_t test_data = CH395F_CHECK_EXIST_TEST_DATA;
uint8_t reply_data;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送检测命令 */
ch395f_write_cmd(CH395F_CMD_CHECK_EXIST);
/* 发送测试数据 */
ch395f_write_data(test_data);
/* 读取芯片回复 */
reply_data = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
/* 验证回复是否为测试数据的按位取反 */
if (reply_data == (uint8_t)(~test_data))
{
return CH395F_STATUS_OK;
}
return CH395F_STATUS_NOT_DETECTED;
}
/*
* 函数功能:读取 CH395 芯片版本号
* 返回值版本字节bit5:0 为版本号uint8_t
* 限定条件:芯片已通过 ch395f_check_exist() 检测
*/
uint8_t ch395f_get_version(void)
{
uint8_t version;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送版本读取命令 */
ch395f_write_cmd(CH395F_CMD_GET_IC_VER);
/* 读取版本号 */
version = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return version;
}
/*
* 函数功能:软件复位 CH395
* 返回值CH395F_STATUS_OK
* 限定条件SPI2 已正确初始化
* 函数说明:复位耗时约 15msTE0函数内部已包含延时
*/
ch395f_status_t ch395f_reset(void)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送复位命令 */
ch395f_write_cmd(CH395F_CMD_RESET_ALL);
/* 结束 SPI 事务 */
ch395f_spi_end();
/* 等待复位完成TE0 = 15ms 典型值,等待 20ms */
HAL_Delay(CH395F_RESET_DELAY_MS);
return CH395F_STATUS_OK;
}
/*
* 函数功能:查询命令执行状态
* 返回值状态字节CH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...uint8_t
* 限定条件:仅在长执行命令(如初始化)后调用
*/
uint8_t ch395f_get_cmd_status(void)
{
uint8_t status;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送状态查询命令 */
ch395f_write_cmd(CH395F_CMD_GET_CMD_STATUS);
/* 读取状态字节 */
status = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:初始化 CH395包含 MAC、PHY、TCP/IP 协议栈)
* 返回值CH395F_STATUS_OK - 成功CH395F_STATUS_TIMEOUT - 超时失败
* 限定条件:芯片已通过 ch395f_reset() 复位
* 函数说明:阻塞等待初始化完成或超时(典型 5msTE1
*/
ch395f_status_t ch395f_init(void)
{
uint8_t status;
uint32_t retry_count = 0U;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送初始化命令 */
ch395f_write_cmd(CH395F_CMD_INIT_CH395);
/* 结束 SPI 事务 */
ch395f_spi_end();
/* 轮询等待初始化完成 */
while (1)
{
/* 每次轮询延时 1ms */
HAL_Delay(1U);
/* 查询命令执行状态 */
status = ch395f_get_cmd_status();
/* 状态非 BUSY 表示执行完毕 */
if (status != CH395F_ERR_BUSY)
{
break;
}
/* 超时判断 */
if (++retry_count > CH395F_INIT_TIMEOUT_MS)
{
return CH395F_STATUS_TIMEOUT;
}
}
/* 返回最终执行结果 */
if (status == CH395F_ERR_SUCCESS)
{
return CH395F_STATUS_OK;
}
return CH395F_STATUS_ERROR;
}
/*
* 函数功能:设置 CH395 IP 地址(低字节在前)
* 入口参数p_ip - 4 字节 IP 地址指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_ip_addr(uint8_t *p_ip)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_ip == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置 IP 命令 */
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR);
/* 逐字节发送 IP 地址 */
for (i = 0; i < 4; i++)
{
ch395f_write_data(p_ip[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置网关 IP 地址(低字节在前)
* 入口参数p_gwip - 4 字节网关 IP 指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_gwip_addr(uint8_t *p_gwip)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_gwip == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置网关命令 */
ch395f_write_cmd(CH395F_CMD_SET_GWIP_ADDR);
/* 逐字节发送网关 IP */
for (i = 0; i < 4; i++)
{
ch395f_write_data(p_gwip[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置子网掩码(低字节在前)
* 入口参数p_mask - 4 字节子网掩码指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
*/
void ch395f_set_mask_addr(uint8_t *p_mask)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_mask == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置掩码命令 */
ch395f_write_cmd(CH395F_CMD_SET_MASK_ADDR);
/* 逐字节发送子网掩码 */
for (i = 0; i < 4; i++)
{
ch395f_write_data(p_mask[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置 MAC 地址(低字节在前,存储于 EEPROM
* 入口参数p_mac - 6 字节 MAC 地址指针 uint8_t*
* 限定条件:指针非空,芯片已初始化
* 函数说明:执行耗时约 30usTE5
*/
void ch395f_set_mac_addr(uint8_t *p_mac)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_mac == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置 MAC 命令 */
ch395f_write_cmd(CH395F_CMD_SET_MAC_ADDR);
/* 逐字节发送 MAC 地址 */
for (i = 0; i < 6; i++)
{
ch395f_write_data(p_mac[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:从 CH395 读取 MAC 地址
* 出口参数p_mac - 6 字节 MAC 地址缓冲区指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_get_mac_addr(uint8_t *p_mac)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_mac == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取 MAC 命令 */
ch395f_write_cmd(CH395F_CMD_GET_MAC_ADDR);
/* 逐字节读取 MAC 地址 */
for (i = 0; i < 6; i++)
{
p_mac[i] = ch395f_read_data();
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:读取 IP 信息IP + 掩码 + DNS共 20 字节)
* 出口参数p_buf - 20 字节缓冲区指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_get_ip_inf(uint8_t *p_buf)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_buf == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取 IP 信息命令 */
ch395f_write_cmd(CH395F_CMD_GET_IP_INF);
/* 逐字节读取 IP 信息(共 20 字节) */
for (i = 0; i < 20; i++)
{
p_buf[i] = ch395f_read_data();
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:获取 PHY 连接状态
* 返回值PHY 状态码CH395F_PHY_DISCONN、CH395F_PHY_10M_FULL 等uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_phy_status(void)
{
uint8_t status;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取 PHY 状态命令 */
ch395f_write_cmd(CH395F_CMD_GET_PHY_STATUS);
/* 读取 PHY 状态 */
status = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:设置 PHY 连接模式
* 入口参数phystat - 连接模式码 uint8_t 0x20 = 自动协商
* 限定条件:芯片已初始化
*/
void ch395f_set_phy(uint8_t phystat)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置 PHY 命令 */
ch395f_write_cmd(CH395F_CMD_SET_PHY);
/* 发送连接模式参数 */
ch395f_write_data(phystat);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:启用/禁用 DHCP
* 入口参数enable - 1 启用0 禁用 uint8_t
* 限定条件:芯片已初始化
*/
void ch395f_set_dhcp(uint8_t enable)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送 DHCP 使能命令 */
ch395f_write_cmd(CH395F_CMD_DHCP_ENABLE);
/* 发送启用/禁用参数 */
ch395f_write_data(enable);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:获取 DHCP 状态
* 返回值0 = 成功,非零 = 错误/超时 uint8_t
* 限定条件:芯片已初始化且 DHCP 已启用
*/
uint8_t ch395f_get_dhcp_status(void)
{
uint8_t status;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取 DHCP 状态命令 */
ch395f_write_cmd(CH395F_CMD_GET_DHCP_STATUS);
/* 读取 DHCP 状态 */
status = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:设置 Socket 协议类型
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* proto - 协议类型 uint8_t CH395F_PROTO_TYPE_xxx
* 限定条件Socket 未打开
*/
void ch395f_set_proto_type(uint8_t sock, uint8_t proto)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置协议类型命令 */
ch395f_write_cmd(CH395F_CMD_SET_PROTO_TYPE_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 发送协议类型 */
ch395f_write_data(proto);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置 Socket 目标 IP 地址
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_ip - 4 字节目标 IP 指针 uint8_t*
* 限定条件:指针非空
*/
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip)
{
uint8_t i;
/* 检查输入参数合法性 */
if (p_ip == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置目标 IP 命令 */
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 逐字节发送目标 IP */
for (i = 0; i < 4; i++)
{
ch395f_write_data(p_ip[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置 Socket 目标端口(小端序)
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* port - 目标端口 uint16_t
* 限定条件:无
*/
void ch395f_set_des_port(uint8_t sock, uint16_t port)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置目标端口命令 */
ch395f_write_cmd(CH395F_CMD_SET_DES_PORT_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 发送端口低字节 */
ch395f_write_data(port & 0xFFU);
/* 发送端口高字节 */
ch395f_write_data((port >> 8) & 0xFFU);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置 Socket 源端口(小端序)
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* port - 源端口 uint16_t
* 限定条件:无
*/
void ch395f_set_sour_port(uint8_t sock, uint16_t port)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送设置源端口命令 */
ch395f_write_cmd(CH395F_CMD_SET_SOUR_PORT_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 发送端口低字节 */
ch395f_write_data(port & 0xFFU);
/* 发送端口高字节 */
ch395f_write_data((port >> 8) & 0xFFU);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:打开 Socket
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件:协议类型、目标 IP、端口已设置
*/
void ch395f_open_socket(uint8_t sock)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送打开 Socket 命令 */
ch395f_write_cmd(CH395F_CMD_OPEN_SOCKET_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:关闭 Socket
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开
*/
void ch395f_close_socket(uint8_t sock)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送关闭 Socket 命令 */
ch395f_write_cmd(CH395F_CMD_CLOSE_SOCKET_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:启动 TCP 监听模式
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开且协议类型为 TCP
*/
void ch395f_tcp_listen(uint8_t sock)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送 TCP 监听命令 */
ch395f_write_cmd(CH395F_CMD_TCP_LISTEN_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:启动 TCP 连接
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件Socket 已打开且协议类型为 TCP
*/
void ch395f_tcp_connect(uint8_t sock)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送 TCP 连接命令 */
ch395f_write_cmd(CH395F_CMD_TCP_CONNECT_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:断开 TCP 连接
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 限定条件TCP 已建立连接
*/
void ch395f_tcp_disconnect(uint8_t sock)
{
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送 TCP 断开命令 */
ch395f_write_cmd(CH395F_CMD_TCP_DISCONNECT_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:向 Socket 发送缓冲区写入数据
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_data - 数据指针 uint8_t*
* len - 数据长度 uint16_t
* 限定条件:指针非空,长度大于 0TCP 已连接或 UDP 已打开
*/
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len)
{
uint16_t i;
/* 检查输入参数合法性 */
if (p_data == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送写入发送缓冲区命令 */
ch395f_write_cmd(CH395F_CMD_WRITE_SEND_BUF_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 发送数据长度低字节 */
ch395f_write_data(len & 0xFFU);
/* 发送数据长度高字节 */
ch395f_write_data((len >> 8) & 0xFFU);
/* 逐字节发送数据 */
for (i = 0; i < len; i++)
{
ch395f_write_data(p_data[i]);
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:从 Socket 接收缓冲区读取数据
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* p_data - 输出缓冲区指针 uint8_t*
* len - 待读取数据长度 uint16_t
* 限定条件:指针非空,长度大于 0接收缓冲区有数据
*/
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len)
{
uint16_t i;
/* 检查输入参数合法性 */
if (p_data == NULL)
{
return;
}
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取接收缓冲区命令 */
ch395f_write_cmd(CH395F_CMD_READ_RECV_BUF_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 发送读取长度低字节 */
ch395f_write_data(len & 0xFFU);
/* 发送读取长度高字节 */
ch395f_write_data((len >> 8) & 0xFFU);
/* 逐字节读取数据 */
for (i = 0; i < len; i++)
{
p_data[i] = ch395f_read_data();
}
/* 结束 SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:获取 Socket 接收缓冲区数据长度
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 返回值:接收数据长度 uint16_t
* 限定条件Socket 已打开
*/
uint16_t ch395f_get_recv_len(uint8_t sock)
{
uint16_t recv_len;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送获取接收长度命令 */
ch395f_write_cmd(CH395F_CMD_GET_RECV_LEN_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 读取长度低字节 */
recv_len = ch395f_read_data();
/* 读取长度高字节并组合 */
recv_len |= (uint16_t)ch395f_read_data() << 8;
/* 结束 SPI 事务 */
ch395f_spi_end();
return recv_len;
}
/*
* 函数功能:获取全局中断状态
* 返回值:中断状态字节 uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_glob_int_status(void)
{
uint8_t status;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取全局中断状态命令 */
ch395f_write_cmd(CH395F_CMD_GET_GLOB_INT_STATUS);
/* 读取中断状态 */
status = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:获取 Socket 中断状态
* 入口参数sock - Socket 索引 uint8_t 0 - 3
* 返回值Socket 中断状态字节 uint8_t
* 限定条件:芯片已初始化
*/
uint8_t ch395f_get_sock_int_status(uint8_t sock)
{
uint8_t status;
/* 开始 SPI 事务 */
ch395f_spi_begin();
/* 发送读取 Socket 中断状态命令 */
ch395f_write_cmd(CH395F_CMD_GET_INT_STATUS_SN);
/* 发送 Socket 索引 */
ch395f_write_data(sock);
/* 读取中断状态 */
status = ch395f_read_data();
/* 结束 SPI 事务 */
ch395f_spi_end();
return status;
}

View File

@@ -47,11 +47,19 @@ void MX_GPIO_Init(void)
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, LED1_Pin|LED2_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LED3_Pin|LED4_Pin|CH395_SCS_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, LED5_Pin|LED6_Pin, GPIO_PIN_SET);
/*Configure GPIO pins : LED1_Pin LED2_Pin */
GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@@ -59,6 +67,27 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : LED3_Pin LED4_Pin */
GPIO_InitStruct.Pin = LED3_Pin|LED4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : LED5_Pin LED6_Pin */
GPIO_InitStruct.Pin = LED5_Pin|LED6_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pin : CH395_SCS_Pin */
GPIO_InitStruct.Pin = CH395_SCS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(CH395_SCS_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */

View File

@@ -18,11 +18,15 @@
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
#include "ch395f.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -65,7 +69,7 @@ int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t str[] = "Hello World\n";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
@@ -86,8 +90,12 @@ int main(void)
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
/* CH395F 初始化 */
ch395f_reset();
ch395f_init();
/* USER CODE END 2 */
/* Infinite loop */
@@ -98,7 +106,12 @@ int main(void)
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin);
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED5_Pin);
HAL_GPIO_TogglePin(LED6_GPIO_Port, LED6_Pin);
HAL_UART_Transmit(&huart1, str, strlen((char*)str), 1000);
HAL_Delay(500);
}
/* USER CODE END 3 */

127
Src/spi.c Normal file
View File

@@ -0,0 +1,127 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.c
* @brief This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SPI_HandleTypeDef hspi2;
/* SPI2 init function */
void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = CH395F_SCK_Pin|CH395F_SDOB15_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = CH395F_SDO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(CH395F_SDO_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspDeInit 0 */
/* USER CODE END SPI2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI2_CLK_DISABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
HAL_GPIO_DeInit(GPIOB, CH395F_SCK_Pin|CH395F_SDO_Pin|CH395F_SDOB15_Pin);
/* USER CODE BEGIN SPI2_MspDeInit 1 */
/* USER CODE END SPI2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

129
Src/usart.c Normal file
View File

@@ -0,0 +1,129 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = ST_TX0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(ST_TX0_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ST_RX0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(ST_RX0_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, ST_TX0_Pin|ST_RX0_Pin);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
#include <stdio.h>
int fputc(int ch, FILE *f)
{
(void)f;
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END 1 */

View File

@@ -0,0 +1,495 @@
## 1. 文档概述
### 1.1 目的
本文档旨在统一嵌入式C语言代码的编写风格提高代码的可读性、可维护性、可移植性和可靠性降低团队协作成本减少代码缺陷。
### 1.2 适用范围
本规范适用于所有基于C语言的嵌入式软件开发项目包括但不限于51单片机、STM32、ARM、DSP等平台。
### 1.3 修订记录
| 版本号 | 修订日期 | 修订内容 | 修订人 |
| ---- | ---------- | ------ | --- |
| V1.0 | 2026-05-11 | 创建初始版本 | 王建锋 |
## 2. 文件结构规范
### 2.1 头文件(.h)结构
```c
#ifndef __MODULE_NAME_H
#define __MODULE_NAME_H
/*
* 模块名称:模块英文名称
* 模块功能:简要描述模块的主要功能
* 适用平台:列出支持的硬件平台
* 作者:作者姓名
* 创建日期YYYY-MM-DD
* 修改记录:
* YYYY-MM-DD 修改人 修改内容说明
*/
#ifdef __cplusplus
extern "C" {
#endif
/* 头文件包含区 - 仅包含本模块必需的头文件 */
#include "stdint.h"
/* 宏定义区 */
#define MODULE_NAME_CONSTANT 100
/* 类型定义区 */
typedef enum {
MODULE_NAME_STATUS_OK = 0,
MODULE_NAME_STATUS_ERROR
} module_name_status_t;
/* 函数声明区 */
void module_name_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __MODULE_NAME_H */
```
### 2.2 源文件(.c)结构
```c
/*
* 模块名称:模块英文名称
* 模块功能:简要描述模块的主要功能
* 适用平台:列出支持的硬件平台
* 作者:作者姓名
* 创建日期YYYY-MM-DD
* 修改记录:
* YYYY-MM-DD 修改人 修改内容说明
*/
/* 头文件包含区 - 先包含系统头文件,再包含自定义头文件 */
#include "module_name.h"
/* 私有宏定义区 */
#define MODULE_NAME_PRIVATE_CONSTANT 200
/* 私有类型定义区 */
typedef struct {
uint8_t data;
} module_name_private_t;
/* 全局变量定义区 - 尽量避免使用全局变量 */
uint8_t g_module_name_global_var = 0;
/* 静态变量定义区 */
static module_name_private_t s_module_name_private_var;
/* 私有函数声明区 */
static void module_name_private_function(void);
/* 函数定义区 - 先写公共函数,再写私有函数 */
void module_name_init(void) {
/* 函数实现 */
}
static void module_name_private_function(void) {
/* 函数实现 */
}
```
### 2.3 头文件包含规则
1. 头文件必须包含头文件保护宏,格式为`__MODULE_NAME_H`
2. 头文件中只包含本模块接口必需的其他头文件
3. 源文件中先包含系统头文件,再包含自定义头文件
4. 禁止在头文件中定义变量和函数体
5. 禁止使用相对路径包含头文件
## 3. 命名规范
### 3.1 通用命名原则
1. 所有名称必须使用英文,禁止使用拼音和中文
2. 名称必须准确反映其实际含义,做到"见名知意"
3. 名称长度适中,避免过长或过短
4. 禁止使用单个字母作为变量名循环变量i、j、k除外
5. 禁止使用关键字和保留字作为名称
### 3.2 变量命名
1. 采用**小写字母+下划线**命名法
2. 全局变量以`g_`前缀开头
3. 静态变量以`s_`前缀开头
4. 指针变量以`p_`前缀开头
5. 数组变量以`a_`前缀开头
6. 布尔变量以`is_``has_``can_`等前缀开头
**示例:**
```c
uint8_t g_system_status; /* 全局系统状态变量 */
static uint16_t s_timer_count; /* 静态定时器计数变量 */
uint8_t *p_data_buffer; /* 数据缓冲区指针 */
uint16_t a_adc_value[10]; /* ADC采样值数组 */
bool is_button_pressed; /* 按钮是否按下标志 */
```
### 3.3 函数命名
1. 采用**小写字母+下划线**命名法
2. 公共函数以**模块名**作为前缀
3. 私有函数以**模块名+private**作为前缀
4. 函数名应为"动词+名词"结构,明确表示函数功能
**示例:**
```c
/* 公共函数 */
void uart_init(uint32_t baud_rate);
uint8_t uart_send_byte(uint8_t data);
/* 私有函数 */
static void uart_private_handle_interrupt(void);
```
### 3.4 宏和常量命名
1. 采用**大写字母+下划线**命名法
2. 以**模块名**作为前缀
3. 常量优先使用`const`定义,而非`#define`
**示例:**
```c
#define UART_BAUD_RATE_9600 9600
#define UART_BUFFER_SIZE 128
const uint8_t UART_DEFAULT_DATA_BITS = 8;
```
### 3.5 类型定义命名
1. 采用**小写字母+下划线**命名法
2.`_t`作为后缀
3. 枚举类型成员以**模块名**作为前缀
**示例:**
```c
typedef enum {
UART_STATUS_OK = 0,
UART_STATUS_ERROR,
UART_STATUS_TIMEOUT
} uart_status_t;
typedef struct {
uint8_t data_bits;
uint8_t stop_bits;
uint32_t baud_rate;
} uart_config_t;
```
## 4. 格式与排版规范
### 4.1 缩进
1. 使用**4个空格**进行缩进禁止使用Tab键
2. 所有包含关系的内容必须缩进
3. 同一级别的代码保持相同的缩进级别
### 4.2 空格使用
1. 所有赋值语句、比较语句、算术运算符前后必须加空格
2. 函数参数列表中,逗号后面必须加空格
3. 关键字后面必须加空格
4. 括号内部两侧不加空格
5. 一元运算符前后不加空格
**正确示例:**
```c
int a = 10;
if (a > 5) {
b = a + 3;
}
for (i = 0; i < 10; i++) {
c[i] = 0;
}
```
**错误示例:**
```c
int a=10;
if(a>5){
b=a+3;
}
for(i=0;i<10;i++){
c[i]=0;
}
```
### 4.3 换行与空行
1. 每行代码长度不超过80个字符
2. 函数之间必须空一行
3. 逻辑上相关的代码块之间可以空一行
4. 函数内变量声明区和代码执行区之间必须空一行
5. 长表达式应在运算符处换行,新行与运算符对齐
**示例:**
```c
int calculate_sum(int a, int b, int c, int d) {
int sum;
sum = a + b
+ c
+ d;
return sum;
}
```
### 4.4 大括号使用
1. **所有包含关系必须加大括号**,即使只有一条语句或为空
2. 左大括号`{`与前面的语句在同一行,前面加一个空格
3. 右大括号`}`单独占一行,与对应的左大括号缩进级别相同
4. 空函数体的大括号也必须单独占一行
**正确示例:**
```c
if (condition) {
do_something();
}
while (1) {
}
```
**错误示例:**
```c
if (condition)
do_something();
while (1) ;
```
## 5. 注释规范
### 5.1 通用注释原则
1. 注释必须清晰、准确、简洁,与代码保持一致
2. 解释性注释使用`/* */`,调试性注释使用`//`
3. 注释应解释"为什么这么做",而不是"做了什么"
4. 代码修改时,必须同步修改相关注释
5. 禁止注释掉的代码提交到版本库
### 5.2 文件头注释
每个文件开头必须包含文件头注释格式见2.1和2.2节。
### 5.3 函数注释
所有函数(包括私有函数)必须包含完整的函数注释,格式如下:
```c
/*
* 函数功能:详细描述函数的功能
* 入口参数param1 - 参数1说明 类型 取值范围
* param2 - 参数2说明 类型 取值范围
* 出口参数param3 - 参数3说明 类型 取值范围
* 返回值:返回值说明 类型 取值范围
* 限定条件:函数使用的前提条件和限制
* 函数说明1. 函数的详细说明
* 2. 注意事项
* 3. 其他需要说明的内容
*/
```
**示例:**
```c
/*
* 函数功能:毫秒级软件延时函数
* 入口参数ms - 需要延时的毫秒数 unsigned int 0 - 65535
* 限定条件0 <= ms <= 65535
* 函数说明1. 采用空指令循环方式实现延时会阻塞CPU运行
* 2. 延时精度依赖系统时钟默认适配12MHz时钟12T模式
* 3. 系统时钟改变时,需重新调整内层循环次数
* 4. 当ms为0时函数立即返回
*/
void delay_ms(unsigned int ms) {
unsigned int i;
unsigned int j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 123; j++) {
}
}
}
```
### 5.4 变量注释
1. 全局变量和静态变量必须添加注释
2. 重要的局部变量应添加注释
3. 注释可以写在变量定义的同一行或上一行
**示例:**
```c
/* 系统运行时间,单位:毫秒 */
uint32_t g_system_time = 0;
static uint8_t s_uart_rx_buffer[UART_BUFFER_SIZE]; /* UART接收缓冲区 */
```
### 5.5 代码行注释
1. **关键逻辑代码每一行都要添加注释**
2. 复杂的算法和逻辑必须添加详细注释
3. 注释应单独占一行,与被注释代码缩进级别相同
**示例:**
```c
/* 计算CRC校验值 */
uint16_t crc_calculate(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
uint16_t i;
uint16_t j;
/* 遍历所有数据字节 */
for (i = 0; i < length; i++) {
/* 将当前字节与CRC寄存器低8位异或 */
crc ^= data[i];
/* 对每个位进行处理 */
for (j = 0; j < 8; j++) {
/* 检查最低位是否为1 */
if (crc & 0x0001) {
/* 最低位为1右移并与多项式异或 */
crc = (crc >> 1) ^ 0xA001;
} else {
/* 最低位为0直接右移 */
crc = crc >> 1;
}
}
}
/* 返回计算得到的CRC值 */
return crc;
}
```
## 6. 编程实践规范
### 6.1 变量声明与初始化
1. 变量应在使用前声明,并尽可能在靠近使用的地方声明
2. 所有变量必须初始化,禁止使用未初始化的变量
3. 尽量使用局部变量,避免使用全局变量
4. 指针变量必须初始化为`NULL`
5. 使用标准数据类型(`uint8_t``int32_t`等),避免使用`char``int`等不确定长度的类型
**示例:**
```c
void function(void) {
uint8_t status = 0;
uint16_t count = 0;
uint8_t *p_data = NULL;
p_data = (uint8_t *)malloc(100);
if (p_data == NULL) {
return;
}
/* 使用p_data */
free(p_data);
p_data = NULL;
}
```
### 6.2 函数设计原则
1. 函数应遵循"单一职责原则",一个函数只做一件事
2. 函数长度不宜过长一般不超过50行
3. 函数参数不宜过多一般不超过5个
4. 函数必须有明确的返回值,用于表示执行状态
5. 避免使用函数参数作为返回值
6. 私有函数必须声明为`static`
### 6.3 控制结构
1. `if`语句中,常量应写在比较运算符的左边
2. `switch`语句必须包含`default`分支
3. 避免使用`goto`语句,除非用于错误处理
4. 循环嵌套不宜超过3层
**示例:**
```c
if (0 == status) {
do_something();
}
switch (command) {
case COMMAND_START:
start_process();
break;
case COMMAND_STOP:
stop_process();
break;
default:
handle_unknown_command();
break;
}
```
### 6.4 错误处理
1. 所有可能失败的函数都必须检查返回值
2. 对输入参数进行合法性检查
3. 对指针进行非空检查
4. 数组访问时检查下标是否越界
5. 使用断言`assert`检查开发阶段的错误
**示例:**
```c
uint8_t uart_send_data(uint8_t *data, uint16_t length) {
/* 检查输入参数合法性 */
if (data == NULL) {
return UART_STATUS_ERROR;
}
if (length == 0 || length > UART_BUFFER_SIZE) {
return UART_STATUS_ERROR;
}
/* 发送数据 */
return UART_STATUS_OK;
}
```
## 7. 可移植性与安全规范
1. 避免使用编译器特有的扩展功能
2. 避免使用硬编码的数值,使用宏定义代替
3. 注意字节序问题,多字节数据传输时进行字节序转换
4. 注意数据类型的长度和符号问题
5. 避免使用不安全的函数,如`strcpy``sprintf`等,使用`strncpy``snprintf`代替
6. 禁止使用可变参数函数
7. 禁止使用递归函数
## 8. 版本控制规范
1. 每次提交必须填写清晰、准确的提交信息
2. 提交信息格式:`[模块名] 修改内容说明`
3. 每次提交只包含一个逻辑修改
4. 提交前必须进行代码编译和测试
5. 禁止提交编译错误的代码
6. 禁止提交调试信息和注释掉的代码
## 9. 附录
### 9.1 完整示例代码
```c
#ifndef __LED_H
#define __LED_H
/*
* 模块名称LED控制模块
* 模块功能提供LED初始化、点亮、熄灭和翻转功能
* 适用平台STM32F103系列单片机
* 作者:张三
* 创建日期2026-05-11
* 修改记录:
* 2026-05-11 张三 创建初始版本
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
/* LED编号定义 */
#define LED_NUM_1 0
#define LED_NUM_2 1
#define LED_NUM_MAX 2
/* LED状态定义 */
#define LED_OFF 0
#define LED_ON 1
/*
* 函数功能LED初始化函数
* 入口参数led_num - LED编号 uint8_t 0 - LED_NUM_MAX-1
* 返回值0 - 成功,其他 - 失败
* 限定条件:无
* 函数说明初始化LED对应的GPIO引脚为推挽输出模式
*/
uint8_t led_init(uint8_t led_num);
/*
* 函数功能点亮LED
* 入口参数led_num - LED编号 uint8_t 0 - LED_NUM_MAX-1
* 返回值0 - 成功,其他 - 失败
* 限定条件led_init()函数已成功调用
* 函数说明将LED对应的GPIO引脚置为低电平
*/
uint8_t led_on(uint8_t led_num);
/*
* 函数功能熄灭LED
* 入口参数led_num - LED编号 uint8_t 0 - LED_NUM_MAX-1
* 返回值0 - 成功,其他 - 失败
* 限定条件led_init()函数已成功调用
* 函数说明将LED对应的GPIO引脚置为高电平
*/
uint8_t led_off(uint8_t led_num);
/*
* 函数功能翻转LED状态
* 入口参数led_num - LED编号 uint8_t 0 - LED_NUM_MAX-1
* 返回值0 - 成功,其他 - 失败
* 限定条件led_init()函数已成功调用
* 函数说明将LED对应的GPIO引脚电平取反
*/
uint8_t led_toggle(uint8_t led_num);
#ifdef __cplusplus
}
#endif
#endif /* __LED_H */
```