lcd154完成

This commit is contained in:
许晟昊 2025-01-21 23:56:10 +08:00
parent 0988d478e0
commit 7bd9f1376a
76 changed files with 40994 additions and 7467 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @file main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
@ -32,7 +32,7 @@ extern "C" {
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lib.h"
#include "bsp.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
@ -60,6 +60,14 @@ void Error_Handler(void);
/* Private defines -----------------------------------------------------------*/
#define LED_USER_Pin GPIO_PIN_13
#define LED_USER_GPIO_Port GPIOC
#define FATFS_Pin GPIO_PIN_10
#define FATFS_GPIO_Port GPIOB
#define LCD_CS_Pin GPIO_PIN_11
#define LCD_CS_GPIO_Port GPIOD
#define LCD_DC_Pin GPIO_PIN_12
#define LCD_DC_GPIO_Port GPIOD
#define LCD_BACKLIGHT_Pin GPIO_PIN_13
#define LCD_BACKLIGHT_GPIO_Port GPIOD
/* USER CODE BEGIN Private defines */

52
Core/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) 2025 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 hspi3;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_SPI3_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
Core/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) 2025 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

@ -59,6 +59,9 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_USER_GPIO_Port, LED_USER_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, LCD_CS_Pin|LCD_DC_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PE2 PE3 PE4 PE5
PE6 PE7 PE8 PE9
PE10 PE11 PE12 PE13
@ -100,23 +103,19 @@ void MX_GPIO_Init(void)
/*Configure GPIO pins : PA0 PA1 PA2 PA3
PA4 PA5 PA6 PA7
PA8 PA9 PA10 PA11
PA12 PA15 */
PA8 PA11 PA12 PA15 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7
|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_15;
|GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB2 PB10
PB11 PB12 PB13 PB14
PB15 PB3 PB4 PB5
/*Configure GPIO pins : PB0 PB1 PB2 PB11
PB12 PB13 PB14 PB15
PB6 PB7 PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
@ -134,18 +133,35 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : PD8 PD9 PD10 PD11
PD12 PD13 PD14 PD15
PD0 PD1 PD3 PD4
PD5 PD6 PD7 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
/*Configure GPIO pin : FATFS_Pin */
GPIO_InitStruct.Pin = FATFS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(FATFS_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PD8 PD9 PD10 PD14
PD15 PD0 PD1 PD3
PD4 PD5 PD6 PD7 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : LCD_CS_Pin LCD_DC_Pin */
GPIO_InitStruct.Pin = LCD_CS_Pin|LCD_DC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : LCD_BACKLIGHT_Pin */
GPIO_InitStruct.Pin = LCD_BACKLIGHT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(LCD_BACKLIGHT_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */

View File

@ -1,7 +1,7 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @file main.c
* @brief : Main program body
******************************************************************************
* @attention
@ -20,12 +20,16 @@
#include "main.h"
#include "cmsis_os.h"
#include "dma.h"
#include "fatfs.h"
#include "rtc.h"
#include "sdio.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp.h"
#include "board.h"
#include "app.h"
/* USER CODE END Includes */
@ -95,6 +99,9 @@ int main(void)
MX_DMA_Init();
MX_RTC_Init();
MX_SDIO_SD_Init();
MX_FATFS_Init();
MX_USART1_UART_Init();
MX_SPI3_Init();
/* USER CODE BEGIN 2 */
board_init();
app_init();

View File

@ -44,20 +44,13 @@ void MX_SDIO_SD_Init(void)
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.BusWide = SDIO_BUS_WIDE_4B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 4;
if (HAL_SD_Init(&hsd) != HAL_OK)
{
Error_Handler();
}
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDIO_Init 2 */
#endif
/* USER CODE END SDIO_Init 2 */
}
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
@ -82,7 +75,8 @@ void HAL_SD_MspInit(SD_HandleTypeDef *sdHandle)
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
@ -164,7 +158,8 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef *sdHandle)
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);

119
Core/Src/spi.c Normal file
View File

@ -0,0 +1,119 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.c
* @brief This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 hspi3;
/* SPI3 init function */
void MX_SPI3_Init(void)
{
/* USER CODE BEGIN SPI3_Init 0 */
/* USER CODE END SPI3_Init 0 */
/* USER CODE BEGIN SPI3_Init 1 */
/* USER CODE END SPI3_Init 1 */
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI3_Init 2 */
/* USER CODE END SPI3_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/* SPI3 clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI3 GPIO Configuration
PB3 ------> SPI3_SCK
PB4 ------> SPI3_MISO
PB5 ------> SPI3_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspDeInit 0 */
/* USER CODE END SPI3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI3_CLK_DISABLE();
/**SPI3 GPIO Configuration
PB3 ------> SPI3_SCK
PB4 ------> SPI3_MISO
PB5 ------> SPI3_MOSI
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
/* USER CODE BEGIN SPI3_MspDeInit 1 */
/* USER CODE END SPI3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

118
Core/Src/usart.c Normal file
View File

@ -0,0 +1,118 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 = GPIO_PIN_9|GPIO_PIN_10;
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(GPIOA, &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, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100); // 发送单字节数据
return (ch);
}
/* USER CODE END 1 */

View File

@ -0,0 +1,729 @@
/**
******************************************************************************
* @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

54
FATFS/App/fatfs.c Normal file
View File

@ -0,0 +1,54 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file fatfs.c
* @brief Code for fatfs applications
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
#include "fatfs.h"
uint8_t retSD; /* Return value for SD */
char SDPath[4]; /* SD logical drive path */
FATFS SDFatFS; /* File system object for SD logical drive */
FIL SDFile; /* File object for SD */
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
void MX_FATFS_Init(void)
{
/*## FatFS: Link the SD driver ###########################*/
retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
/* USER CODE BEGIN Init */
/* additional user code for init */
/* USER CODE END Init */
}
/**
* @brief Gets Time from RTC
* @param None
* @retval Time in DWORD
*/
DWORD get_fattime(void)
{
/* USER CODE BEGIN get_fattime */
return 0;
/* USER CODE END get_fattime */
}
/* USER CODE BEGIN Application */
/* USER CODE END Application */

47
FATFS/App/fatfs.h Normal file
View File

@ -0,0 +1,47 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file fatfs.h
* @brief Header for fatfs applications
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 __fatfs_H
#define __fatfs_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ff.h"
#include "ff_gen_drv.h"
#include "sd_diskio.h" /* defines SD_Driver as external */
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern uint8_t retSD; /* Return value for SD */
extern char SDPath[4]; /* SD logical drive path */
extern FATFS SDFatFS; /* File system object for SD logical drive */
extern FIL SDFile; /* File object for SD */
void MX_FATFS_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__fatfs_H */

View File

@ -0,0 +1,316 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file bsp_driver_sd.c for F4 (based on stm324x9i_eval_sd.c)
* @brief This file includes a generic uSD card driver.
* To be completed by the user according to the board used for the project.
* @note Some functions generated as weak: they can be overridden by
* - code in user files
* - or BSP code from the FW pack files
* if such files are added to the generated project (by the user).
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
#ifdef OLD_API
/* kept to avoid issue when migrating old projects. */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#else
/* USER CODE BEGIN FirstSection */
/* can be used to modify / undefine following code or add new definitions */
/* USER CODE END FirstSection */
/* Includes ------------------------------------------------------------------*/
#include "bsp_driver_sd.h"
/* Extern variables ---------------------------------------------------------*/
extern SD_HandleTypeDef hsd;
/* USER CODE BEGIN BeforeInitSection */
/* can be used to modify / undefine following code or add code */
/* USER CODE END BeforeInitSection */
/**
* @brief Initializes the SD card device.
* @retval SD status
*/
__weak uint8_t BSP_SD_Init(void)
{
uint8_t sd_state = MSD_OK;
/* Check if the SD card is plugged in the slot */
if (BSP_SD_IsDetected() != SD_PRESENT)
{
return MSD_ERROR;
}
/* HAL SD initialization */
sd_state = HAL_SD_Init(&hsd);
/* Configure SD Bus width (4 bits mode selected) */
if (sd_state == MSD_OK)
{
/* Enable wide operation */
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
sd_state = MSD_ERROR;
}
}
return sd_state;
}
/* USER CODE BEGIN AfterInitSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END AfterInitSection */
/* USER CODE BEGIN InterruptMode */
/**
* @brief Configures Interrupt mode for SD detection pin.
* @retval Returns 0
*/
__weak uint8_t BSP_SD_ITConfig(void)
{
/* Code to be updated by the user or replaced by one from the FW pack (in a stmxxxx_sd.c file) */
return (uint8_t)0;
}
/** @brief SD detect IT treatment
*/
__weak void BSP_SD_DetectIT(void)
{
/* Code to be updated by the user or replaced by one from the FW pack (in a stmxxxx_sd.c file) */
}
/* USER CODE END InterruptMode */
/* USER CODE BEGIN BeforeReadBlocksSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeReadBlocksSection */
/**
* @brief Reads block(s) from a specified address in an SD card, in polling mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param ReadAddr: Address from where data is to be read
* @param NumOfBlocks: Number of SD blocks to read
* @param Timeout: Timeout for read operation
* @retval SD status
*/
__weak uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
uint8_t sd_state = MSD_OK;
if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* USER CODE BEGIN BeforeWriteBlocksSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeWriteBlocksSection */
/**
* @brief Writes block(s) to a specified address in an SD card, in polling mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param WriteAddr: Address from where data is to be written
* @param NumOfBlocks: Number of SD blocks to write
* @param Timeout: Timeout for write operation
* @retval SD status
*/
__weak uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
uint8_t sd_state = MSD_OK;
if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* USER CODE BEGIN BeforeReadDMABlocksSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeReadDMABlocksSection */
/**
* @brief Reads block(s) from a specified address in an SD card, in DMA mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param ReadAddr: Address from where data is to be read
* @param NumOfBlocks: Number of SD blocks to read
* @retval SD status
*/
__weak uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
uint8_t sd_state = MSD_OK;
/* Read block(s) in DMA transfer mode */
if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* USER CODE BEGIN BeforeWriteDMABlocksSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeWriteDMABlocksSection */
/**
* @brief Writes block(s) to a specified address in an SD card, in DMA mode.
* @param pData: Pointer to the buffer that will contain the data to transmit
* @param WriteAddr: Address from where data is to be written
* @param NumOfBlocks: Number of SD blocks to write
* @retval SD status
*/
__weak uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
uint8_t sd_state = MSD_OK;
/* Write block(s) in DMA transfer mode */
if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* USER CODE BEGIN BeforeEraseSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeEraseSection */
/**
* @brief Erases the specified memory area of the given SD card.
* @param StartAddr: Start byte address
* @param EndAddr: End byte address
* @retval SD status
*/
__weak uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
{
uint8_t sd_state = MSD_OK;
if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/**
* @brief Gets the current SD card data status.
* @param None
* @retval Data transfer state.
* This value can be one of the following values:
* @arg SD_TRANSFER_OK: No data transfer is acting
* @arg SD_TRANSFER_BUSY: Data transfer is acting
*/
__weak uint8_t BSP_SD_GetCardState(void)
{
return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER ) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);
}
/**
* @brief Get SD information about specific SD card.
* @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure
* @retval None
*/
__weak void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo)
{
/* Get SD card Information */
HAL_SD_GetCardInfo(&hsd, CardInfo);
}
/* USER CODE BEGIN BeforeCallBacksSection */
/* can be used to modify previous code / undefine following code / add code */
/* USER CODE END BeforeCallBacksSection */
/**
* @brief SD Abort callbacks
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_AbortCallback();
}
/**
* @brief Tx Transfer completed callback
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_WriteCpltCallback();
}
/**
* @brief Rx Transfer completed callback
* @param hsd: SD handle
* @retval None
*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
BSP_SD_ReadCpltCallback();
}
/* USER CODE BEGIN CallBacksSection_C */
/**
* @brief BSP SD Abort callback
* @retval None
* @note empty (up to the user to fill it in or to remove it if useless)
*/
__weak void BSP_SD_AbortCallback(void)
{
}
/**
* @brief BSP Tx Transfer completed callback
* @retval None
* @note empty (up to the user to fill it in or to remove it if useless)
*/
__weak void BSP_SD_WriteCpltCallback(void)
{
}
/**
* @brief BSP Rx Transfer completed callback
* @retval None
* @note empty (up to the user to fill it in or to remove it if useless)
*/
__weak void BSP_SD_ReadCpltCallback(void)
{
}
/* USER CODE END CallBacksSection_C */
#endif
/**
* @brief Detects if SD card is correctly plugged in the memory slot or not.
* @param None
* @retval Returns if SD is detected or not
*/
__weak uint8_t BSP_SD_IsDetected(void)
{
__IO uint8_t status = SD_PRESENT;
if (BSP_PlatformIsDetected() == 0x0)
{
status = SD_NOT_PRESENT;
}
return status;
}
/* USER CODE BEGIN AdditionalCode */
/* user code can be inserted here */
/* USER CODE END AdditionalCode */

View File

@ -0,0 +1,91 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file bsp_driver_sd.h for F4 (based on stm324x9i_eval_sd.h)
* @brief This file contains the common defines and functions prototypes for
* the bsp_driver_sd.c driver.
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 __STM32F4_SD_H
#define __STM32F4_SD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "fatfs_platform.h"
/* Exported types --------------------------------------------------------*/
/**
* @brief SD Card information structure
*/
#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef
/* Exported constants --------------------------------------------------------*/
/**
* @brief SD status structure definition
*/
#define MSD_OK ((uint8_t)0x00)
#define MSD_ERROR ((uint8_t)0x01)
/**
* @brief SD transfer state definition
*/
#define SD_TRANSFER_OK ((uint8_t)0x00)
#define SD_TRANSFER_BUSY ((uint8_t)0x01)
#define SD_PRESENT ((uint8_t)0x01)
#define SD_NOT_PRESENT ((uint8_t)0x00)
#define SD_DATATIMEOUT ((uint32_t)100000000)
#ifdef OLD_API
/* kept to avoid issue when migrating old projects. */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#else
/* USER CODE BEGIN BSP_H_CODE */
/* Exported functions --------------------------------------------------------*/
uint8_t BSP_SD_Init(void);
uint8_t BSP_SD_ITConfig(void);
void BSP_SD_DetectIT(void);
void BSP_SD_DetectCallback(void);
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout);
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks);
uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr);
void BSP_SD_IRQHandler(void);
void BSP_SD_DMA_Tx_IRQHandler(void);
void BSP_SD_DMA_Rx_IRQHandler(void);
uint8_t BSP_SD_GetCardState(void);
void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo);
uint8_t BSP_SD_IsDetected(void);
/* These functions can be modified in case the current settings (e.g. DMA stream)
need to be changed for specific application needs */
void BSP_SD_AbortCallback(void);
void BSP_SD_WriteCpltCallback(void);
void BSP_SD_ReadCpltCallback(void);
/* USER CODE END BSP_H_CODE */
#endif
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4_SD_H */

View File

@ -0,0 +1,32 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : fatfs_platform.c
* @brief : fatfs_platform source file
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
#include "fatfs_platform.h"
uint8_t BSP_PlatformIsDetected(void) {
uint8_t status = SD_PRESENT;
/* Check SD card detect pin */
if(HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != GPIO_PIN_RESET)
{
status = SD_NOT_PRESENT;
}
/* USER CODE BEGIN 1 */
/* user code can be inserted here */
/* USER CODE END 1 */
return status;
}

View File

@ -0,0 +1,27 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : fatfs_platform.h
* @brief : fatfs_platform header file
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 "stm32f4xx_hal.h"
/* Defines ------------------------------------------------------------------*/
#define SD_PRESENT ((uint8_t)0x01) /* also in bsp_driver_sd.h */
#define SD_NOT_PRESENT ((uint8_t)0x00) /* also in bsp_driver_sd.h */
#define SD_DETECT_PIN GPIO_PIN_10
#define SD_DETECT_GPIO_PORT GPIOB
/* Prototypes ---------------------------------------------------------------*/
uint8_t BSP_PlatformIsDetected(void);

270
FATFS/Target/ffconf.h Normal file
View File

@ -0,0 +1,270 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* FatFs - Generic FAT file system module R0.12c (C)ChaN, 2017
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
#ifndef _FFCONF
#define _FFCONF 68300 /* Revision ID */
/*-----------------------------------------------------------------------------/
/ Additional user header to be used
/-----------------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "bsp_driver_sd.h"
#include "cmsis_os.h" /* _FS_REENTRANT set to 1 and CMSIS API chosen */
/*-----------------------------------------------------------------------------/
/ Function Configurations
/-----------------------------------------------------------------------------*/
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0 /* 0 to 3 */
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 1
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
#define _USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define _USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
#define _USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*-----------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/-----------------------------------------------------------------------------*/
#define _CODE_PAGE 936
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
*/
#define _USE_LFN 3 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN switches the support of long file name (LFN).
/
/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
/ This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/
/ This option has no effect when _LFN_UNICODE == 0. */
#define _FS_RPATH 0 /* 0 to 2 */
/* This option configures support of relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 2
/* Number of volumes (logical drives) to be used. */
/* USER CODE BEGIN Volumes */
#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
/* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
/* USER CODE END Volumes */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Multiple partition */
/* This option switches support of multi-partition on a physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When multi-partition is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ function will be available. */
#define _MIN_SS 512 /* 512, 1024, 2048 or 4096 */
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
#define _USE_TRIM 0
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0 /* 0,1,2 or 3 */
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards C89 compatibility. */
#define _FS_NORTC 0
#define _NORTC_MON 6
#define _NORTC_MDAY 4
#define _NORTC_YEAR 2015
/* The option _FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
#define _FS_LOCK 2 /* 0:Disable or >=1:Enable */
/* The option _FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define _FS_REENTRANT 1 /* 0:Disable or 1:Enable */
#define _USE_MUTEX 0 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t osSemaphoreId
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* define the ff_malloc ff_free macros as FreeRTOS pvPortMalloc and vPortFree macros */
#if !defined(ff_malloc) && !defined(ff_free)
#define ff_malloc pvPortMalloc
#define ff_free vPortFree
#endif
#endif /* _FFCONF */

683
FATFS/Target/sd_diskio.c Normal file
View File

@ -0,0 +1,683 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file sd_diskio.c
* @brief SD Disk I/O driver
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
/* Note: code generation based on sd_diskio_dma_rtos_template_bspv1.c v2.1.4
as FreeRTOS is enabled. */
/* USER CODE BEGIN firstSection */
/* can be used to modify / undefine following code or add new definitions */
/* USER CODE END firstSection*/
/* Includes ------------------------------------------------------------------*/
#include "ff_gen_drv.h"
#include "sd_diskio.h"
#include <string.h>
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define QUEUE_SIZE (uint32_t) 10
#define READ_CPLT_MSG (uint32_t) 1
#define WRITE_CPLT_MSG (uint32_t) 2
/*
==================================================================
enable the defines below to send custom rtos messages
when an error or an abort occurs.
Notice: depending on the HAL/SD driver the HAL_SD_ErrorCallback()
may not be available.
See BSP_SD_ErrorCallback() and BSP_SD_AbortCallback() below
==================================================================
#define RW_ERROR_MSG (uint32_t) 3
#define RW_ABORT_MSG (uint32_t) 4
*/
/*
* the following Timeout is useful to give the control back to the applications
* in case of errors in either BSP_SD_ReadCpltCallback() or BSP_SD_WriteCpltCallback()
* the value by default is as defined in the BSP platform driver otherwise 30 secs
*/
#define SD_TIMEOUT 30 * 1000
#define SD_DEFAULT_BLOCK_SIZE 512
/*
* Depending on the use case, the SD card initialization could be done at the
* application level: if it is the case define the flag below to disable
* the BSP_SD_Init() call in the SD_Initialize() and add a call to
* BSP_SD_Init() elsewhere in the application.
*/
/* USER CODE BEGIN disableSDInit */
/* #define DISABLE_SD_INIT */
/* USER CODE END disableSDInit */
/*
* when using cacheable memory region, it may be needed to maintain the cache
* validity. Enable the define below to activate a cache maintenance at each
* read and write operation.
* Notice: This is applicable only for cortex M7 based platform.
*/
/* USER CODE BEGIN enableSDDmaCacheMaintenance */
/* #define ENABLE_SD_DMA_CACHE_MAINTENANCE 1 */
/* USER CODE END enableSDDmaCacheMaintenance */
/*
* Some DMA requires 4-Byte aligned address buffer to correctly read/write data,
* in FatFs some accesses aren't thus we need a 4-byte aligned scratch buffer to correctly
* transfer data
*/
/* USER CODE BEGIN enableScratchBuffer */
/* #define ENABLE_SCRATCH_BUFFER */
/* USER CODE END enableScratchBuffer */
/* Private variables ---------------------------------------------------------*/
#if defined(ENABLE_SCRATCH_BUFFER)
#if defined (ENABLE_SD_DMA_CACHE_MAINTENANCE)
ALIGN_32BYTES(static uint8_t scratch[BLOCKSIZE]); // 32-Byte aligned for cache maintenance
#else
__ALIGN_BEGIN static uint8_t scratch[BLOCKSIZE] __ALIGN_END;
#endif
#endif
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;
#if (osCMSIS <= 0x20000U)
static osMessageQId SDQueueID = NULL;
#else
static osMessageQueueId_t SDQueueID = NULL;
#endif
/* Private function prototypes -----------------------------------------------*/
static DSTATUS SD_CheckStatus(BYTE lun);
DSTATUS SD_initialize (BYTE);
DSTATUS SD_status (BYTE);
DRESULT SD_read (BYTE, BYTE*, DWORD, UINT);
#if _USE_WRITE == 1
DRESULT SD_write (BYTE, const BYTE*, DWORD, UINT);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT SD_ioctl (BYTE, BYTE, void*);
#endif /* _USE_IOCTL == 1 */
const Diskio_drvTypeDef SD_Driver =
{
SD_initialize,
SD_status,
SD_read,
#if _USE_WRITE == 1
SD_write,
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
SD_ioctl,
#endif /* _USE_IOCTL == 1 */
};
/* USER CODE BEGIN beforeFunctionSection */
/* can be used to modify / undefine following code or add new code */
/* USER CODE END beforeFunctionSection */
/* Private functions ---------------------------------------------------------*/
static int SD_CheckStatusWithTimeout(uint32_t timeout)
{
uint32_t timer;
/* block until SDIO peripheral is ready again or a timeout occur */
#if (osCMSIS <= 0x20000U)
timer = osKernelSysTick();
while( osKernelSysTick() - timer < timeout)
#else
timer = osKernelGetTickCount();
while( osKernelGetTickCount() - timer < timeout)
#endif
{
if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
{
return 0;
}
}
return -1;
}
static DSTATUS SD_CheckStatus(BYTE lun)
{
Stat = STA_NOINIT;
if(BSP_SD_GetCardState() == SD_TRANSFER_OK)
{
Stat &= ~STA_NOINIT;
}
return Stat;
}
/**
* @brief Initializes a Drive
* @param lun : not used
* @retval DSTATUS: Operation status
*/
DSTATUS SD_initialize(BYTE lun)
{
Stat = STA_NOINIT;
/*
* check that the kernel has been started before continuing
* as the osMessage API will fail otherwise
*/
#if (osCMSIS <= 0x20000U)
if(osKernelRunning())
#else
if(osKernelGetState() == osKernelRunning)
#endif
{
#if !defined(DISABLE_SD_INIT)
if(BSP_SD_Init() == MSD_OK)
{
Stat = SD_CheckStatus(lun);
}
#else
Stat = SD_CheckStatus(lun);
#endif
/*
* if the SD is correctly initialized, create the operation queue
* if not already created
*/
if (Stat != STA_NOINIT)
{
if (SDQueueID == NULL)
{
#if (osCMSIS <= 0x20000U)
osMessageQDef(SD_Queue, QUEUE_SIZE, uint16_t);
SDQueueID = osMessageCreate (osMessageQ(SD_Queue), NULL);
#else
SDQueueID = osMessageQueueNew(QUEUE_SIZE, 2, NULL);
#endif
}
if (SDQueueID == NULL)
{
Stat |= STA_NOINIT;
}
}
}
return Stat;
}
/**
* @brief Gets Disk Status
* @param lun : not used
* @retval DSTATUS: Operation status
*/
DSTATUS SD_status(BYTE lun)
{
return SD_CheckStatus(lun);
}
/* USER CODE BEGIN beforeReadSection */
/* can be used to modify previous code / undefine following code / add new code */
/* USER CODE END beforeReadSection */
/**
* @brief Reads Sector(s)
* @param lun : not used
* @param *buff: Data buffer to store read data
* @param sector: Sector address (LBA)
* @param count: Number of sectors to read (1..128)
* @retval DRESULT: Operation result
*/
DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
uint8_t ret;
DRESULT res = RES_ERROR;
uint32_t timer;
#if (osCMSIS < 0x20000U)
osEvent event;
#else
uint16_t event;
osStatus_t status;
#endif
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
uint32_t alignedAddr;
#endif
/*
* ensure the SDCard is ready for a new operation
*/
if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0)
{
return res;
}
#if defined(ENABLE_SCRATCH_BUFFER)
if (!((uint32_t)buff & 0x3))
{
#endif
/* Fast path cause destination buffer is correctly aligned */
ret = BSP_SD_ReadBlocks_DMA((uint32_t*)buff, (uint32_t)(sector), count);
if (ret == MSD_OK) {
#if (osCMSIS < 0x20000U)
/* wait for a message from the queue or a timeout */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
if (event.value.v == READ_CPLT_MSG)
{
timer = osKernelSysTick();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelSysTick() - timer <SD_TIMEOUT)
#else
status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);
if ((status == osOK) && (event == READ_CPLT_MSG))
{
timer = osKernelGetTickCount();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelGetTickCount() - timer <SD_TIMEOUT)
#endif
{
if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
{
res = RES_OK;
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
/*
the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
adjust the address and the D-Cache size to invalidate accordingly.
*/
alignedAddr = (uint32_t)buff & ~0x1F;
SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
#endif
break;
}
}
#if (osCMSIS < 0x20000U)
}
}
#else
}
#endif
}
#if defined(ENABLE_SCRATCH_BUFFER)
}
else
{
/* Slow path, fetch each sector a part and memcpy to destination buffer */
int i;
for (i = 0; i < count; i++)
{
ret = BSP_SD_ReadBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1);
if (ret == MSD_OK )
{
/* wait until the read is successful or a timeout occurs */
#if (osCMSIS < 0x20000U)
/* wait for a message from the queue or a timeout */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
if (event.value.v == READ_CPLT_MSG)
{
timer = osKernelSysTick();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelSysTick() - timer <SD_TIMEOUT)
#else
status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);
if ((status == osOK) && (event == READ_CPLT_MSG))
{
timer = osKernelGetTickCount();
/* block until SDIO IP is ready or a timeout occur */
ret = MSD_ERROR;
while(osKernelGetTickCount() - timer < SD_TIMEOUT)
#endif
{
ret = BSP_SD_GetCardState();
if (ret == MSD_OK)
{
break;
}
}
if (ret != MSD_OK)
{
break;
}
#if (osCMSIS < 0x20000U)
}
}
#else
}
#endif
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
/*
*
* invalidate the scratch buffer before the next read to get the actual data instead of the cached one
*/
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif
memcpy(buff, scratch, BLOCKSIZE);
buff += BLOCKSIZE;
}
else
{
break;
}
}
if ((i == count) && (ret == MSD_OK ))
res = RES_OK;
}
#endif
return res;
}
/* USER CODE BEGIN beforeWriteSection */
/* can be used to modify previous code / undefine following code / add new code */
/* USER CODE END beforeWriteSection */
/**
* @brief Writes Sector(s)
* @param lun : not used
* @param *buff: Data to be written
* @param sector: Sector address (LBA)
* @param count: Number of sectors to write (1..128)
* @retval DRESULT: Operation result
*/
#if _USE_WRITE == 1
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
DRESULT res = RES_ERROR;
uint32_t timer;
#if (osCMSIS < 0x20000U)
osEvent event;
#else
uint16_t event;
osStatus_t status;
#endif
#if defined(ENABLE_SCRATCH_BUFFER)
int32_t ret;
#endif
/*
* ensure the SDCard is ready for a new operation
*/
if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0)
{
return res;
}
#if defined(ENABLE_SCRATCH_BUFFER)
if (!((uint32_t)buff & 0x3))
{
#endif
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
uint32_t alignedAddr;
/*
the SCB_CleanDCache_by_Addr() requires a 32-Byte aligned address
adjust the address and the D-Cache size to clean accordingly.
*/
alignedAddr = (uint32_t)buff & ~0x1F;
SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
#endif
if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff,
(uint32_t) (sector),
count) == MSD_OK)
{
#if (osCMSIS < 0x20000U)
/* Get the message from the queue */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
if (event.value.v == WRITE_CPLT_MSG)
{
#else
status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);
if ((status == osOK) && (event == WRITE_CPLT_MSG))
{
#endif
#if (osCMSIS < 0x20000U)
timer = osKernelSysTick();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelSysTick() - timer < SD_TIMEOUT)
#else
timer = osKernelGetTickCount();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelGetTickCount() - timer < SD_TIMEOUT)
#endif
{
if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
{
res = RES_OK;
break;
}
}
#if (osCMSIS < 0x20000U)
}
}
#else
}
#endif
}
#if defined(ENABLE_SCRATCH_BUFFER)
else {
/* Slow path, fetch each sector a part and memcpy to destination buffer */
int i;
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
/*
* invalidate the scratch buffer before the next write to get the actual data instead of the cached one
*/
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE);
#endif
for (i = 0; i < count; i++)
{
memcpy((void *)scratch, buff, BLOCKSIZE);
buff += BLOCKSIZE;
ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1);
if (ret == MSD_OK )
{
/* wait until the read is successful or a timeout occurs */
#if (osCMSIS < 0x20000U)
/* wait for a message from the queue or a timeout */
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage)
{
if (event.value.v == READ_CPLT_MSG)
{
timer = osKernelSysTick();
/* block until SDIO IP is ready or a timeout occur */
while(osKernelSysTick() - timer <SD_TIMEOUT)
#else
status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);
if ((status == osOK) && (event == READ_CPLT_MSG))
{
timer = osKernelGetTickCount();
/* block until SDIO IP is ready or a timeout occur */
ret = MSD_ERROR;
while(osKernelGetTickCount() - timer < SD_TIMEOUT)
#endif
{
ret = BSP_SD_GetCardState();
if (ret == MSD_OK)
{
break;
}
}
if (ret != MSD_OK)
{
break;
}
#if (osCMSIS < 0x20000U)
}
}
#else
}
#endif
}
else
{
break;
}
}
if ((i == count) && (ret == MSD_OK ))
res = RES_OK;
}
}
#endif
return res;
}
#endif /* _USE_WRITE == 1 */
/* USER CODE BEGIN beforeIoctlSection */
/* can be used to modify previous code / undefine following code / add new code */
/* USER CODE END beforeIoctlSection */
/**
* @brief I/O control operation
* @param lun : not used
* @param cmd: Control code
* @param *buff: Buffer to send/receive control data
* @retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff)
{
DRESULT res = RES_ERROR;
BSP_SD_CardInfo CardInfo;
if (Stat & STA_NOINIT) return RES_NOTRDY;
switch (cmd)
{
/* Make sure that no pending write process */
case CTRL_SYNC :
res = RES_OK;
break;
/* Get number of sectors on the disk (DWORD) */
case GET_SECTOR_COUNT :
BSP_SD_GetCardInfo(&CardInfo);
*(DWORD*)buff = CardInfo.LogBlockNbr;
res = RES_OK;
break;
/* Get R/W sector size (WORD) */
case GET_SECTOR_SIZE :
BSP_SD_GetCardInfo(&CardInfo);
*(WORD*)buff = CardInfo.LogBlockSize;
res = RES_OK;
break;
/* Get erase block size in unit of sector (DWORD) */
case GET_BLOCK_SIZE :
BSP_SD_GetCardInfo(&CardInfo);
*(DWORD*)buff = CardInfo.LogBlockSize / SD_DEFAULT_BLOCK_SIZE;
res = RES_OK;
break;
default:
res = RES_PARERR;
}
return res;
}
#endif /* _USE_IOCTL == 1 */
/* USER CODE BEGIN afterIoctlSection */
/* can be used to modify previous code / undefine following code / add new code */
/* USER CODE END afterIoctlSection */
/* USER CODE BEGIN callbackSection */
/* can be used to modify / following code or add new code */
/* USER CODE END callbackSection */
/**
* @brief Tx Transfer completed callbacks
* @param hsd: SD handle
* @retval None
*/
void BSP_SD_WriteCpltCallback(void)
{
/*
* No need to add an "osKernelRunning()" check here, as the SD_initialize()
* is always called before any SD_Read()/SD_Write() call
*/
#if (osCMSIS < 0x20000U)
osMessagePut(SDQueueID, WRITE_CPLT_MSG, 0);
#else
const uint16_t msg = WRITE_CPLT_MSG;
osMessageQueuePut(SDQueueID, (const void *)&msg, 0, 0);
#endif
}
/**
* @brief Rx Transfer completed callbacks
* @param hsd: SD handle
* @retval None
*/
void BSP_SD_ReadCpltCallback(void)
{
/*
* No need to add an "osKernelRunning()" check here, as the SD_initialize()
* is always called before any SD_Read()/SD_Write() call
*/
#if (osCMSIS < 0x20000U)
osMessagePut(SDQueueID, READ_CPLT_MSG, 0);
#else
const uint16_t msg = READ_CPLT_MSG;
osMessageQueuePut(SDQueueID, (const void *)&msg, 0, 0);
#endif
}
/* USER CODE BEGIN ErrorAbortCallbacks */
/*
void BSP_SD_AbortCallback(void)
{
#if (osCMSIS < 0x20000U)
osMessagePut(SDQueueID, RW_ABORT_MSG, 0);
#else
const uint16_t msg = RW_ABORT_MSG;
osMessageQueuePut(SDQueueID, (const void *)&msg, 0, 0);
#endif
}
*/
/* USER CODE END ErrorAbortCallbacks */
/* USER CODE BEGIN lastSection */
/* can be used to modify / undefine previous code or add new code */
/* USER CODE END lastSection */

41
FATFS/Target/sd_diskio.h Normal file
View File

@ -0,0 +1,41 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file sd_diskio.h
* @brief Header for sd_diskio.c module
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
/* Note: code generation based on sd_diskio_dma_rtos_template.h */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SD_DISKIO_H
#define __SD_DISKIO_H
/* USER CODE BEGIN firstSection */
/* can be used to modify / undefine following code or add new definitions */
/* USER CODE END firstSection */
/* Includes ------------------------------------------------------------------*/
#include "bsp_driver_sd.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern const Diskio_drvTypeDef SD_Driver;
/* USER CODE BEGIN lastSection */
/* can be used to modify / undefine previous code or add new definitions */
/* USER CODE END lastSection */
#endif /* __SD_DISKIO_H */

View File

@ -185,6 +185,16 @@
<WinNumber>1</WinNumber>
<ItemText>read_buffer</ItemText>
</Ww>
<Ww>
<count>7</count>
<WinNumber>1</WinNumber>
<ItemText>lcd,0x10</ItemText>
</Ww>
<Ww>
<count>8</count>
<WinNumber>1</WinNumber>
<ItemText>hspi3,0x10</ItemText>
</Ww>
</WatchWindow1>
<MemoryWindow1>
<Mm>
@ -351,6 +361,30 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/spi.c</PathWithFileName>
<FilenameWithoutPath>spi.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/usart.c</PathWithFileName>
<FilenameWithoutPath>usart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/stm32f4xx_it.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_it.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
@ -358,7 +392,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>9</FileNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -370,7 +404,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -390,7 +424,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>11</FileNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -402,7 +436,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>12</FileNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -414,7 +448,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>13</FileNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -426,7 +460,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -438,7 +472,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -450,7 +484,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -462,7 +496,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -474,7 +508,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -486,7 +520,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -498,7 +532,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -510,7 +544,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -522,7 +556,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -534,7 +568,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -546,7 +580,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -558,7 +592,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>25</FileNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -570,7 +604,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>26</FileNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -582,7 +616,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>27</FileNumber>
<FileNumber>29</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -594,7 +628,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>28</FileNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -606,7 +640,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>29</FileNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -618,7 +652,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>30</FileNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -628,6 +662,30 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_hal_spi.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c</PathWithFileName>
<FilenameWithoutPath>stm32f4xx_hal_uart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
@ -638,7 +696,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>31</FileNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -658,7 +716,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>32</FileNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -670,7 +728,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>33</FileNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -682,7 +740,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>34</FileNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -694,7 +752,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -706,7 +764,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>36</FileNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -718,7 +776,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -730,7 +788,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>38</FileNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -742,7 +800,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>39</FileNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -754,7 +812,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>40</FileNumber>
<FileNumber>44</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -766,7 +824,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>41</FileNumber>
<FileNumber>45</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -786,7 +844,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>42</FileNumber>
<FileNumber>46</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -806,7 +864,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>43</FileNumber>
<FileNumber>47</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -818,7 +876,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>44</FileNumber>
<FileNumber>48</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -838,7 +896,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>45</FileNumber>
<FileNumber>49</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -850,7 +908,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>46</FileNumber>
<FileNumber>50</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -862,7 +920,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>47</FileNumber>
<FileNumber>51</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -882,7 +940,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>48</FileNumber>
<FileNumber>52</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -894,7 +952,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>49</FileNumber>
<FileNumber>53</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -906,7 +964,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>50</FileNumber>
<FileNumber>54</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -918,7 +976,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>51</FileNumber>
<FileNumber>55</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -930,7 +988,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>52</FileNumber>
<FileNumber>56</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -942,7 +1000,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>53</FileNumber>
<FileNumber>57</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -954,7 +1012,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>54</FileNumber>
<FileNumber>58</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -966,7 +1024,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>55</FileNumber>
<FileNumber>59</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -978,7 +1036,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>56</FileNumber>
<FileNumber>60</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -990,7 +1048,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>57</FileNumber>
<FileNumber>61</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1002,7 +1060,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>58</FileNumber>
<FileNumber>62</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1014,7 +1072,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>59</FileNumber>
<FileNumber>63</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1026,7 +1084,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>60</FileNumber>
<FileNumber>64</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1038,7 +1096,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>61</FileNumber>
<FileNumber>65</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1058,7 +1116,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>62</FileNumber>
<FileNumber>66</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1070,7 +1128,7 @@
</File>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>63</FileNumber>
<FileNumber>67</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1080,6 +1138,194 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>68</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\bsp\spis.c</PathWithFileName>
<FilenameWithoutPath>spis.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Application/User/FATFS/Target</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>69</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../FATFS/Target/bsp_driver_sd.c</PathWithFileName>
<FilenameWithoutPath>bsp_driver_sd.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>70</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../FATFS/Target/sd_diskio.c</PathWithFileName>
<FilenameWithoutPath>sd_diskio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>71</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../FATFS/Target/fatfs_platform.c</PathWithFileName>
<FilenameWithoutPath>fatfs_platform.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Application/User/FATFS/App</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>12</GroupNumber>
<FileNumber>72</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../FATFS/App/fatfs.c</PathWithFileName>
<FilenameWithoutPath>fatfs.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Middlewares/FatFs</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>73</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Middlewares/Third_Party/FatFs/src/diskio.c</PathWithFileName>
<FilenameWithoutPath>diskio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>74</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Middlewares/Third_Party/FatFs/src/ff.c</PathWithFileName>
<FilenameWithoutPath>ff.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>75</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Middlewares/Third_Party/FatFs/src/ff_gen_drv.c</PathWithFileName>
<FilenameWithoutPath>ff_gen_drv.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>76</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Middlewares/Third_Party/FatFs/src/option/syscall.c</PathWithFileName>
<FilenameWithoutPath>syscall.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>77</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Middlewares/Third_Party/FatFs/src/option/cc936.c</PathWithFileName>
<FilenameWithoutPath>cc936.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>User/system/lib/lcd</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>14</GroupNumber>
<FileNumber>78</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\lib\lcd\lcd_154.c</PathWithFileName>
<FilenameWithoutPath>lcd_154.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>14</GroupNumber>
<FileNumber>79</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\lib\lcd\lcds.c</PathWithFileName>
<FilenameWithoutPath>lcds.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>14</GroupNumber>
<FileNumber>80</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\lib\lcd\lcd_font.c</PathWithFileName>
<FilenameWithoutPath>lcd_font.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x800
Stack_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
@ -40,7 +40,7 @@ __initial_sp
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x400
Heap_Size EQU 0x1000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base

View File

@ -0,0 +1,144 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2017 */
/* */
/* Portions COPYRIGHT 2017 STMicroelectronics */
/* Portions Copyright (C) 2017, ChaN, all right reserved */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various existing */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
#include "diskio.h"
#include "ff_gen_drv.h"
#if defined ( __GNUC__ )
#ifndef __weak
#define __weak __attribute__((weak))
#endif
#endif
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern Disk_drvTypeDef disk;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Gets Disk Status
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
DSTATUS stat;
stat = disk.drv[pdrv]->disk_status(disk.lun[pdrv]);
return stat;
}
/**
* @brief Initializes a Drive
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = RES_OK;
if(disk.is_initialized[pdrv] == 0)
{
stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
if(stat == RES_OK)
{
disk.is_initialized[pdrv] = 1;
}
}
return stat;
}
/**
* @brief Reads Sector(s)
* @param pdrv: Physical drive number (0..)
* @param *buff: Data buffer to store read data
* @param sector: Sector address (LBA)
* @param count: Number of sectors to read (1..128)
* @retval DRESULT: Operation result
*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
return res;
}
/**
* @brief Writes Sector(s)
* @param pdrv: Physical drive number (0..)
* @param *buff: Data to be written
* @param sector: Sector address (LBA)
* @param count: Number of sectors to write (1..128)
* @retval DRESULT: Operation result
*/
#if _USE_WRITE == 1
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
return res;
}
#endif /* _USE_WRITE == 1 */
/**
* @brief I/O control operation
* @param pdrv: Physical drive number (0..)
* @param cmd: Control code
* @param *buff: Buffer to send/receive control data
* @retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
res = disk.drv[pdrv]->disk_ioctl(disk.lun[pdrv], cmd, buff);
return res;
}
#endif /* _USE_IOCTL == 1 */
/**
* @brief Gets Time from RTC
* @param None
* @retval Time in DWORD
*/
__weak DWORD get_fattime (void)
{
return 0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,80 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl function */
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
DWORD get_fattime (void);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

6140
Middlewares/Third_Party/FatFs/src/ff.c vendored Normal file

File diff suppressed because it is too large Load Diff

361
Middlewares/Third_Party/FatFs/src/ff.h vendored Normal file
View File

@ -0,0 +1,361 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12c /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2017, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 68300 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode (UTF-16) string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* File system type (0:N/A) */
BYTE drv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (_FDID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
_FDID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Alternative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

View File

@ -0,0 +1,122 @@
/**
******************************************************************************
* @file ff_gen_drv.c
* @author MCD Application Team
* @brief FatFs generic low level driver.
*****************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
**/
/* Includes ------------------------------------------------------------------*/
#include "ff_gen_drv.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
Disk_drvTypeDef disk = {{0},{0},{0},0};
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Links a compatible diskio driver/lun id and increments the number of active
* linked drivers.
* @note The number of linked drivers (volumes) is up to 10 due to FatFs limits.
* @param drv: pointer to the disk IO Driver structure
* @param path: pointer to the logical drive path
* @param lun : only used for USB Key Disk to add multi-lun management
else the parameter must be equal to 0
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, uint8_t lun)
{
uint8_t ret = 1;
uint8_t DiskNum = 0;
if(disk.nbr < _VOLUMES)
{
disk.is_initialized[disk.nbr] = 0;
disk.drv[disk.nbr] = drv;
disk.lun[disk.nbr] = lun;
DiskNum = disk.nbr++;
path[0] = DiskNum + '0';
path[1] = ':';
path[2] = '/';
path[3] = 0;
ret = 0;
}
return ret;
}
/**
* @brief Links a compatible diskio driver and increments the number of active
* linked drivers.
* @note The number of linked drivers (volumes) is up to 10 due to FatFs limits
* @param drv: pointer to the disk IO Driver structure
* @param path: pointer to the logical drive path
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path)
{
return FATFS_LinkDriverEx(drv, path, 0);
}
/**
* @brief Unlinks a diskio driver and decrements the number of active linked
* drivers.
* @param path: pointer to the logical drive path
* @param lun : not used
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_UnLinkDriverEx(char *path, uint8_t lun)
{
uint8_t DiskNum = 0;
uint8_t ret = 1;
if(disk.nbr >= 1)
{
DiskNum = path[0] - '0';
if(disk.drv[DiskNum] != 0)
{
disk.drv[DiskNum] = 0;
disk.lun[DiskNum] = 0;
disk.nbr--;
ret = 0;
}
}
return ret;
}
/**
* @brief Unlinks a diskio driver and decrements the number of active linked
* drivers.
* @param path: pointer to the logical drive path
* @retval Returns 0 in case of success, otherwise 1.
*/
uint8_t FATFS_UnLinkDriver(char *path)
{
return FATFS_UnLinkDriverEx(path, 0);
}
/**
* @brief Gets number of linked drivers to the FatFs module.
* @param None
* @retval Number of attached drivers.
*/
uint8_t FATFS_GetAttachedDriversNbr(void)
{
return disk.nbr;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,80 @@
/**
******************************************************************************
* @file ff_gen_drv.h
* @author MCD Application Team
* @brief Header for ff_gen_drv.c module.
*****************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
**/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FF_GEN_DRV_H
#define __FF_GEN_DRV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "diskio.h"
#include "ff.h"
#include "stdint.h"
/* Exported types ------------------------------------------------------------*/
/**
* @brief Disk IO Driver structure definition
*/
typedef struct
{
DSTATUS (*disk_initialize) (BYTE); /*!< Initialize Disk Drive */
DSTATUS (*disk_status) (BYTE); /*!< Get Disk Status */
DRESULT (*disk_read) (BYTE, BYTE*, DWORD, UINT); /*!< Read Sector(s) */
#if _USE_WRITE == 1
DRESULT (*disk_write) (BYTE, const BYTE*, DWORD, UINT); /*!< Write Sector(s) when _USE_WRITE = 0 */
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT (*disk_ioctl) (BYTE, BYTE, void*); /*!< I/O control operation when _USE_IOCTL = 1 */
#endif /* _USE_IOCTL == 1 */
}Diskio_drvTypeDef;
/**
* @brief Global Disk IO Drivers structure definition
*/
typedef struct
{
uint8_t is_initialized[_VOLUMES];
const Diskio_drvTypeDef *drv[_VOLUMES];
uint8_t lun[_VOLUMES];
volatile uint8_t nbr;
}Disk_drvTypeDef;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path);
uint8_t FATFS_UnLinkDriver(char *path);
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, BYTE lun);
uint8_t FATFS_UnLinkDriverEx(char *path, BYTE lun);
uint8_t FATFS_GetAttachedDriversNbr(void);
#ifdef __cplusplus
}
#endif
#endif /* __FF_GEN_DRV_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
typedef unsigned long long QWORD;
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/* Portions COPYRIGHT 2017 STMicroelectronics */
/* Portions Copyright (C) 2014, ChaN, all right reserved */
/*------------------------------------------------------------------------*/
/**
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
**/
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
#if _USE_MUTEX
#if (osCMSIS < 0x20000U)
osMutexDef(MTX);
*sobj = osMutexCreate(osMutex(MTX));
#else
*sobj = osMutexNew(NULL);
#endif
#else
#if (osCMSIS < 0x20000U)
osSemaphoreDef(SEM);
*sobj = osSemaphoreCreate(osSemaphore(SEM), 1);
#else
*sobj = osSemaphoreNew(1, 1, NULL);
#endif
#endif
ret = (*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
#if _USE_MUTEX
osMutexDelete (sobj);
#else
osSemaphoreDelete (sobj);
#endif
return 1;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret = 0;
#if (osCMSIS < 0x20000U)
#if _USE_MUTEX
if(osMutexWait(sobj, _FS_TIMEOUT) == osOK)
#else
if(osSemaphoreWait(sobj, _FS_TIMEOUT) == osOK)
#endif
#else
#if _USE_MUTEX
if(osMutexAcquire(sobj, _FS_TIMEOUT) == osOK)
#else
if(osSemaphoreAcquire(sobj, _FS_TIMEOUT) == osOK)
#endif
#endif
{
ret = 1;
}
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
#if _USE_MUTEX
osMutexRelease(sobj);
#else
osSemaphoreRelease(sobj);
#endif
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return ff_malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
ff_free(mblock); /* Discard the memory block with POSIX API */
}
#endif

View File

@ -8,10 +8,7 @@ void business_task(void *pvParameters)
for (;;)
{
rtc_update();
if (sd_test() == TRUE)
{
led_toggle(LED_USER);
}
vTaskDelay(1000);
}
}

View File

@ -1,6 +1,8 @@
#include "board.h"
#include "bsp.h"
#include "main.h"
#include "rtc.h"
#include "spi.h"
board_t board;
@ -41,27 +43,27 @@ void led_toggle(led_e led)
}
/**
* @brief RTC写入后备区域SRAM
* @param bkrx : ,:0~31
* @param data : ,32
* @retval
* @brief RTC写入后备区域SRAM
* @param bkrx : ,:0~31
* @param data : ,32
* @retval
*/
void rtc_write_bkr(uint32_t bkrx, uint32_t data)
{
HAL_PWR_EnableBkUpAccess(); /* 取消备份区写保护 */
HAL_PWR_EnableBkUpAccess(); /* 取消备份区写保护 */
HAL_RTCEx_BKUPWrite(&hrtc, bkrx, data);
}
/**
* @brief RTC读取后备区域SRAM
* @param bkrx : ,:0~31
* @retval
* @brief RTC读取后备区域SRAM
* @param bkrx : ,:0~31
* @retval
*/
static uint32_t rtc_read_bkr(uint32_t bkrx)
{
uint32_t temp = 0;
temp = RTC_BASE + 0x50 + bkrx * 4;
return (*(uint32_t *)temp); /* 返回读取到的值 */
return (*(uint32_t *)temp); /* 返回读取到的值 */
}
BOOL rtc_set_time(rtc_time_t time, uint8_t ampm)
@ -109,10 +111,10 @@ BOOL rtc_init(void)
{
uint16_t bkpflag = 0;
/* 检查是不是第一次配置时钟 */
bkpflag = rtc_read_bkr(RTC_BKP_DR0); /* 读取BKP0的值 */
/* 检查是不是第一次配置时钟 */
bkpflag = rtc_read_bkr(RTC_BKP_DR0); /* 读取BKP0的值 */
if ((bkpflag != 0x5050) && (bkpflag != 0x5051)) /* 之前未初始化过, 重新配置 */
if ((bkpflag != 0x5050) && (bkpflag != 0x5051)) /* 之前未初始化过, 重新配置 */
{
rtc_date_t date;
rtc_time_t time;
@ -124,25 +126,97 @@ BOOL rtc_init(void)
time.minute = 0;
time.second = 0;
rtc_set_time(time, RTC_HOURFORMAT12_AM); /* 设置时间, 根据实际时间修改 */
rtc_set_date(date); /* 设置日期 */
rtc_set_time(time, RTC_HOURFORMAT12_AM); /* 设置时间, 根据实际时间修改 */
rtc_set_date(date); /* 设置日期 */
rtc_write_bkr(RTC_BKP_DR0, 0x5051); /* 写入标记位 */
rtc_write_bkr(RTC_BKP_DR0, 0x5051); /* 写入标记位 */
}
return TRUE;
}
// 清屏测试
void lcd_test_clear(void)
{
uint8_t i = 0; // 计数变量
board.lcd->driver.set_hz_font(board.lcd, &ch_font_24); // 设置汉字字体
board.lcd->driver.set_color(board.lcd, LCD_BLACK); // 设置画笔颜色
for (i = 0; i < 8; i++)
{
switch (i) // 切换背景色
{
case 0:
board.lcd->driver.full_fill(board.lcd, LIGHT_RED);
break;
case 1:
board.lcd->driver.full_fill(board.lcd, LIGHT_GREEN);
break;
case 2:
board.lcd->driver.full_fill(board.lcd, LIGHT_BLUE);
break;
case 3:
board.lcd->driver.full_fill(board.lcd, LIGHT_YELLOW);
break;
case 4:
board.lcd->driver.full_fill(board.lcd, LIGHT_CYAN);
break;
case 5:
board.lcd->driver.full_fill(board.lcd, LIGHT_GREY);
break;
case 6:
board.lcd->driver.full_fill(board.lcd, LIGHT_MAGENTA);
break;
case 7:
board.lcd->driver.full_fill(board.lcd, LCD_WHITE);
break;
default:
break;
}
board.lcd->driver.clear(board.lcd); // 清屏
board.lcd->driver.display_text(board.lcd, 13, 70, "STM32 刷屏测试");
board.lcd->driver.display_text(board.lcd, 13, 106, "屏幕分辨率:240*240");
board.lcd->driver.display_text(board.lcd, 13, 142, "控制器:ST7789");
HAL_Delay(1000); // 延时
}
}
void lcd_init(void)
{
spi_gpio_group_t gpios;
gpios.cs = gpio_create(LCD_CS_GPIO_Port, LCD_CS_Pin);
gpios.dc = gpio_create(LCD_DC_GPIO_Port, LCD_DC_Pin);
// 初始化LCD相关的SPI
lcd_info_t info = {
.type = LCD_154, // 设置LCD类型为ST7525
.spi = spi_create(SPI_TYPE_LCD, gpios, 0), // 创建SPI总线
.dir = Direction_V, // 设置显示方向为横向
.width = COL_DOT_MAX_240, // 设置LCD最大宽度为400列
.height = LIN_DOT_MAX_240, // 设置LCD最大高度为240行
.retransmission_count = 3, // 设置重传次数为3次
.disp = NULL,
};
info.spi->interface.hardware_enable(info.spi, &hspi3);
board.lcd = lcd_create(info);
DBG_ASSERT(board.lcd != NULL __DBG_LINE);
board.lcd->info.spi->gpios.dc->set(*board.lcd->info.spi->gpios.dc); // DC引脚拉高默认处于写数据状态
board.lcd->info.spi->gpios.cs->set(*board.lcd->info.spi->gpios.cs); // 拉高片选,禁止通信
LCD_BACKLIGHT_OFF; // 先关闭背光,初始化完成之后再打开
board.lcd->driver.init(board.lcd);
LCD_BACKLIGHT_ON;
lcd_test_clear();
}
/**
* @brief
* @brief
*
*/
void board_init(void)
{
lcd_init();
rtc_init();
sd_init();
if (sd_test() == FALSE)
{
DBG_ASSERT(FALSE __DBG_LINE);
}
// sd_fatfs_test();
}

View File

@ -2,11 +2,16 @@
#define __BOARD_H__
#include "lib.h"
#include "sd.h"
#include "lcds.h"
#define UART_RXSIZE (240u) // 接收240个字节
#define UART_TXSIZE (240u) // 发送240个字节
#define TASK_TIM TIM6
#define LCD_BACKLIGHT_ON GPIO_SET(LCD_BACKLIGHT_GPIO_Port, LCD_BACKLIGHT_Pin)
#define LCD_BACKLIGHT_OFF GPIO_RESET(LCD_BACKLIGHT_GPIO_Port, LCD_BACKLIGHT_Pin)
typedef enum
{
LED_USER,
@ -27,6 +32,7 @@ typedef struct
uint16_t adc_raw[ADC1_MAX];
RTC_DateTypeDef rtc_date;
RTC_TimeTypeDef rtc_time;
lcd_t *lcd;
} board_t;
extern board_t board;

View File

@ -1,11 +1,105 @@
#include "sd.h"
#include "sdio.h"
#include "fatfs.h"
#include <string.h>
SD_HandleTypeDef _handle;
#define NUM_OF_BLOCKS 1
#define TEST_ADDRESS 0
#define TEST_BLOCK_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) // 定义数据大小,SD块大小为512字节因为是32位的数组所以这里除以4
BOOL sd_fatfs_test(void)
{
uint32_t byteswritten; /* File write counts */
uint32_t bytesread; /* File read counts */
uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
uint8_t rtext[100]; /* File read buffers */
char filename[] = "STM32cube.txt";
char SensorBuff[100];
printf("********* STM32CubeMX FatFs Example *********\r\n\r\n");
if (f_mount(&SDFatFS, SDPath, 1) == FR_OK)
{
printf("f_mount sucess!!! \r\n");
if (f_open(&SDFile, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
{
printf("f_open file sucess!!! \r\n");
if (f_write(&SDFile, wtext, sizeof(wtext), &byteswritten) == FR_OK)
{
printf("f_write file sucess!!! \r\n");
printf("f_write Data : %s\r\n", wtext);
if (f_close(&SDFile) == FR_OK)
printf("f_close sucess!!! \r\n");
else
printf("f_close error : %d\r\n", retSD);
}
else
printf("f_write file error\r\n");
}
else
printf("f_open file error\r\n");
}
else
{
printf("f_mount error : %d \r\n", retSD);
return FALSE;
}
retSD = f_open(&SDFile, filename, FA_READ);
if (retSD)
{
printf("f_open file error : %d\r\n", retSD);
return FALSE;
}
else
printf("f_open file sucess!!! \r\n");
retSD = f_read(&SDFile, rtext, sizeof(rtext), (UINT *)&bytesread);
if (retSD)
{
printf("f_read error!!! %d\r\n", retSD);
return FALSE;
}
else
{
printf("f_read sucess!!! \r\n");
printf("f_read Data : %s\r\n", rtext);
}
retSD = f_close(&SDFile);
if (retSD)
{
printf("f_close error!!! %d\r\n", retSD);
return FALSE;
}
else
printf("f_close sucess!!! \r\n");
if (bytesread == byteswritten)
printf("FatFs is working well!!!\r\n");
if (f_open(&SDFile, (const char *)"Sensor.csv", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
{
printf("Sensor.csv was opened/created!!!\r\n");
sprintf(SensorBuff, "Item,Temp,Humi,Light\r\n");
f_write(&SDFile, SensorBuff, strlen(SensorBuff), &byteswritten);
for (int i = 0; i < 10; i++)
{
sprintf(SensorBuff, "%d,%d,%d,%d\r\n", i + 1, i + 20, i + 30, i + 40);
f_write(&SDFile, SensorBuff, strlen(SensorBuff), &byteswritten);
f_sync(&SDFile);
}
f_close(&SDFile);
}
else
{
return FALSE;
}
return TRUE;
}
BOOL sd_test(void)
{
BOOL res = FALSE;
@ -83,6 +177,7 @@ void sd_init(void)
{
Error_Handler();
}
sd_info();
}
@ -187,39 +282,3 @@ BOOL sd_write_blocks_dma(uint32_t *data, uint32_t write_address, uint32_t blocks
return TRUE;
}
}
/**
* @brief BSP Tx Transfer completed callbacks
* @retval None
*/
__weak void BSP_SD_WriteCpltCallback(void)
{
}
/**
* @brief BSP Rx Transfer completed callbacks
* @retval None
*/
__weak void BSP_SD_ReadCpltCallback(void)
{
}
/**
* @brief Tx Transfer completed callbacks
* @param _handle: SD handle
* @retval None
*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *_handle)
{
BSP_SD_WriteCpltCallback();
}
/**
* @brief Rx Transfer completed callbacks
* @param _handle: SD handle
* @retval None
*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *_handle)
{
BSP_SD_ReadCpltCallback();
}

View File

@ -11,4 +11,5 @@ BOOL sd_read_blocks_dma(uint32_t *data, uint32_t read_address, uint32_t blocks);
BOOL sd_write_blocks_dma(uint32_t *data, uint32_t write_address, uint32_t blocks);
BOOL sd_test(void);
BOOL sd_fatfs_test(void);
#endif // __SD_H

View File

@ -1,416 +0,0 @@
/**
* @file adcs.c
* @author xxx
* @date 2023-09-04 15:59:16
* @brief LL库ADC驱动 STM32F407
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "adcs.h"
#include "dmas.h"
adcs_t adcs[ADCS_MAX];
static uint8_t adc_get_channels_count(uint32_t channnels); // 通过用户配置的通道号获取通道数量
/**
* @brief ADC初始化
* @param {adcs_e} num ADC编号
* @param {ADC_TypeDef} *adc ADC外设
* @param {DMA_TypeDef} *dma DMA外设
* @param {uint32_t} dma_channel DMA通道
* @param {uint8_t} adc_cct ADC采样次数
* @param {uint32_t} channels
* @return {*}
* @note TCONV() = ( + 12.5 )/(/ADC分频系数)
*/
void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_stream, uint32_t dma_channel, uint16_t adc_cct, uint32_t channels)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
DBG_ASSERT(adc != NULL __DBG_LINE);
DBG_ASSERT(dma != NULL __DBG_LINE);
DBG_ASSERT(adc_cct > 0 __DBG_LINE);
adcs_t *p = &adcs[num];
osel_memset((uint8_t *)p, 0, sizeof(adcs_t));
p->adc = adc;
p->dma = dma;
p->dma_stream = dma_stream;
p->dma_channel = dma_channel;
p->channels.data = channels;
p->adc_cct = adc_cct;
p->adc_chans_count = adc_get_channels_count(channels);
p->adc_sum = adc_cct * p->adc_chans_count;
#if defined(SRAM2_BASE) // SRAM2速度更快
p->adc_value = (uint16_t *)osel_mem_alloc2(sizeof(uint16_t) * p->adc_sum);
#else
p->adc_value = (uint16_t *)osel_mem_alloc(sizeof(uint16_t) * p->adc_sum);
#endif
DBG_ASSERT(p->adc_value != NULL __DBG_LINE);
osel_memset((uint8_t *)p->adc_value, 0, sizeof(uint16_t) * p->adc_sum);
LL_DMA_SetChannelSelection(p->dma, p->dma_stream, p->dma_channel);
LL_DMA_ConfigTransfer(p->dma, p->dma_stream,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
LL_DMA_MODE_CIRCULAR |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_HALFWORD |
LL_DMA_MDATAALIGN_HALFWORD |
LL_DMA_PRIORITY_HIGH);
LL_DMA_ConfigAddresses(p->dma, p->dma_stream,
LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA),
(uint32_t)p->adc_value,
LL_DMA_GetDataTransferDirection(p->dma, p->dma_stream));
LL_DMA_SetDataLength(p->dma, p->dma_stream, p->adc_sum);
LL_DMA_EnableStream(p->dma, p->dma_stream);
LL_ADC_REG_SetContinuousMode(p->adc, LL_ADC_REG_CONV_CONTINUOUS);
LL_ADC_REG_SetDMATransfer(p->adc, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
if (BIT_IS_SET(channels, INVREF))
{
// 使能VREFINT
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p->adc), LL_ADC_PATH_INTERNAL_VREFINT);
}
if (BIT_IS_SET(channels, INTEMP))
{
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p->adc), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
}
LL_mDelay(10);
// 启动 ADC 转换
LL_ADC_Enable(p->adc);
LL_ADC_REG_StartConversionSWStart(p->adc);
}
/**
* @brief
*
* ADCS ADC
*
* @param num ADCS
*/
void start_sample(adcs_e num)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
// adcs_t *p = &adcs[num];
}
/**
* @brief
*
* ADCS ADCS
*
* @param num ADCS
*/
void stop_sample(adcs_e num)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
// adcs_t *p = &adcs[num];
}
/**
* @brief ADC重新开始转换
* @param {adcs_e} num ADC编号
* @return {*}
* @note
*/
void adc_restart(adcs_e num)
{
stop_sample(num);
start_sample(num);
}
/**
* @brief ADC反初始化
* @param {adcs_e} num ADC编号
* @return {*}
* @note
*/
void adc_dinit(adcs_e num)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
adcs_t *p = &adcs[num];
LL_ADC_Disable(p->adc);
if (p->adc_value != NULL)
{
#if defined(SRAM2_BASE)
osel_mem_free2((uint16_t *)p->adc_value);
#else
osel_mem_free((uint16_t *)p->adc_value);
#endif
}
}
/**
* @brief ADC转换结果,
* @param {adcs_e} num
* @param {uint8_t} chan
* @return {*}
* @note
*/
uint16_t adc_result_only_one(adcs_e num, uint8_t chan)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
uint16_t(*gram)[p->adc_chans_count] = (uint16_t(*)[p->adc_chans_count])p->adc_value;
return gram[0][chan];
}
/**
* @brief ,ADC转换结果
* @param {adcs_e} num ADC编号
* @param {uint8_t} chan
* @return {*}
* @note 使O(n^2)
*/
uint16_t adc_result_median_average(adcs_e num, uint8_t chan)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
if (p->adc_cct <= 2)
return 0; // 如果adc_cct小于等于2直接返回0
uint16_t adc_temp[p->adc_cct];
uint32_t adc_sum = 0;
uint16_t count = p->adc_cct >> 2; // 使用位移操作计算n的值
// 减少重复计算,计算基础偏移量
uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
for (uint16_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
{
adc_temp[i] = *adc_values;
}
insertion_sort(adc_temp, p->adc_cct);
// 计算中间部分的和
for (uint16_t i = count; i < p->adc_cct - count; ++i)
{
adc_sum += adc_temp[i];
}
// 计算平均值确保不会除以0
uint16_t res = adc_sum / (p->adc_cct - (count << 1));
return res;
}
/**
* @brief ,ADC转换结果
* @param {adcs_e} num ADC编号
* @param {uint8_t} chan
* @return {*}
* @note 使O(n^2)
*/
uint16_t adc_result_median(adcs_e num, uint8_t chan)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
uint16_t res = 0;
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
uint16_t adc_temp[p->adc_cct];
// 减少重复计算,计算基础偏移量
uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
for (uint16_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
{
adc_temp[i] = *adc_values;
}
insertion_sort(adc_temp, p->adc_cct);
res = adc_temp[p->adc_cct >> 1];
return res;
}
/**
* @brief ,ADC转换结果
* @param {adcs_e} num ADC编号
* @param {uint8_t} chan
* @return {*}
* @note
*/
uint16_t adc_result_average(adcs_e num, uint8_t chan)
{
DBG_ASSERT(num < ADCS_MAX __DBG_LINE);
uint16_t res = 0;
uint32_t adc_sum = 0;
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
// 减少重复计算,计算基础偏移量
uint16_t *adc_values = (uint16_t *)p->adc_value + chan;
for (uint16_t i = 0; i < p->adc_cct; ++i, adc_values += p->adc_chans_count)
{
adc_sum += *adc_values;
}
res = adc_sum / p->adc_cct;
return res;
}
/**
* @brief
* @param {uint16_t} adc_value ADC转换结果
* @return {*}
* @note (measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR) * (int32_t)(130 - 30) / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR)) + 30
* adc_value ADC读取的温度传感器数据
TS_CAL1 30°C时校准的温度传感器数据TEMPSENSOR_CAL1_ADDR
TS_CAL2 110°C时校准的温度传感器数据TEMPSENSOR_CAL2_ADDR
TEMPSENSOR_CAL1_TEMP 30°C
TEMPSENSOR_CAL2_TEMP 110°C
*/
float32 adc_result_temperature(uint16_t adc_value)
{
uint16_t ts_cal1 = *TEMPSENSOR_CAL1_ADDR;
uint16_t ts_cal2 = *TEMPSENSOR_CAL2_ADDR;
float32 temperature = ((float32)(adc_value - ts_cal1) / (ts_cal2 - ts_cal1)) * (TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP) + TEMPSENSOR_CAL1_TEMP;
return temperature;
}
/**
* @brief
* @param {uint16_t} adc_value ADC转换结果
* @return {*} V
* @note
*/
float32 adc_result_value_local(uint16_t adc_value)
{
float32 vdd = (VREFINT_CAL_VREF * (*VREFINT_CAL_ADDR)) / 4095;
return ((vdd / adc_value) * 4095) / 1000;
}
/**
* @brief ADC DMA转换回调函数
{
* @param {adcs_e} num ADC编号
* @return {*}
* @note
*/
void adc_dma_callback(adcs_e num)
{
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
if (LL_DMA_IsActiveFlag_TC1(p->dma) != 0)
{
LL_DMA_ClearFlag_TC1(p->dma);
}
// 检查DMA1的传输错误标志是否为1如果是则清除该标志
if (LL_DMA_IsActiveFlag_TE1(p->dma) != 0)
{
LL_DMA_ClearFlag_TE1(p->dma);
}
}
/**
* @brief ADC回调函数
* @param {adcs_e} num ADC编号
* @return {*}
* @note
*/
void adc_env_callback(adcs_e num)
{
adcs_t *p = &adcs[num];
DBG_ASSERT(p != NULL __DBG_LINE);
if (LL_ADC_IsActiveFlag_OVR(p->adc) != 0)
{
p->ovr_count++;
LL_ADC_ClearFlag_OVR(p->adc);
}
}
/**
* @brief
* @param {uint32_t} channnels
* @return {*}
* @note
*/
static uint8_t adc_get_channels_count(uint32_t channnels)
{
uint8_t ch_num = 0;
if (BIT_IS_SET(channnels, IN0))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN1))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN2))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN3))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN4))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN5))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN6))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN7))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN8))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN9))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN10))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN11))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN12))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN13))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN14))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN15))
{
ch_num++;
}
if (BIT_IS_SET(channnels, IN16))
{
ch_num++;
}
if (BIT_IS_SET(channnels, INVREF))
{
ch_num++;
}
if (BIT_IS_SET(channnels, INVBAT))
{
ch_num++;
}
if (BIT_IS_SET(channnels, INTEMP))
{
ch_num++;
}
return ch_num;
}

View File

@ -1,228 +0,0 @@
/**
* @file adcs.h
* @brief Header file for ADC driver using LL library.
*
* This file contains the declarations and documentation for the ADC driver
* using the LL (Low-Level) library.
*
* @date 2023-09-04 15:59:16
* @author xxx
* @version 1.0
*
* @note This code is proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
*
* @note All rights reserved by xxx.
*/
#ifndef __ADCS_H__
#define __ADCS_H__
#include "sys.h"
#define ADC_CHANNEL_MAX 18 ///< Maximum number of ADC channels
typedef enum
{
IN0 = BIT0,
IN1 = BIT1,
IN2 = BIT2,
IN3 = BIT3,
IN4 = BIT4,
IN5 = BIT5,
IN6 = BIT6,
IN7 = BIT7,
IN8 = BIT8,
IN9 = BIT9,
IN10 = BIT10,
IN11 = BIT11,
IN12 = BIT12,
IN13 = BIT13,
IN14 = BIT14,
IN15 = BIT15,
IN16 = BIT16,
INTEMP = BIT17,
INVBAT = BIT18,
INVREF = BIT19,
} adc_num_e; ///< ADC channel number
typedef enum
{
ADCS_1,
ADCS_2,
ADCS_3,
ADCS_MAX,
} adcs_e; ///< ADC number
typedef union
{
uint32_t data;
struct
{
uint32_t in0 : 1;
uint32_t in1 : 1;
uint32_t in2 : 1;
uint32_t in3 : 1;
uint32_t in4 : 1;
uint32_t in5 : 1;
uint32_t in6 : 1;
uint32_t in7 : 1;
uint32_t in8 : 1;
uint32_t in9 : 1;
uint32_t in10 : 1;
uint32_t in11 : 1;
uint32_t in12 : 1;
uint32_t in13 : 1;
uint32_t in14 : 1;
uint32_t in15 : 1;
uint32_t invref : 1;
uint32_t intemp : 1;
};
} adcs_channels_u; ///< ADC channels
typedef struct
{
ADC_TypeDef *adc; ///< ADC peripheral
DMA_TypeDef *dma; ///< DMA peripheral
uint32_t dma_stream; ///< DMA stream
uint32_t dma_channel; ///< DMA channel
adcs_channels_u channels; ///< ADC channels
uint32_t ovr_count; ///< ADC overflow count
uint16_t adc_cct; ///< Channel single acquisition count
uint8_t adc_chans_count; ///< Number of channels
uint16_t adc_sum; ///< Channel acquisition count
__IO uint16_t *adc_value; ///< Address to store ADC conversion results
} adcs_t;
/**
* @brief Initializes the ADC module.
*
* This function initializes the ADC module with the specified parameters.
*
* @param num The ADC number.
* @param adc Pointer to the ADC peripheral.
* @param dma Pointer to the DMA peripheral.
* @param dma_channel The DMA channel number.
* @param adc_cct The ADC continuous conversion mode.
* @param channels The number of ADC channels to be converted.
*/
extern void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_stream, uint32_t dma_channel, uint16_t adc_cct, uint32_t channels);
/**
* @brief Starts the ADC conversion.
*
* This function starts the ADC conversion for the specified ADC number.
*
* @param num The ADC number.
*/
extern void adc_restart(adcs_e num);
/**
* @brief Deinitializes the ADC module.
*
* This function deinitializes the ADC module.
*
* @param num The ADC number.
*/
extern void adc_dinit(adcs_e num);
/**
* @brief Gets the ADC conversion result for a single channel.
*
* This function gets the ADC conversion result for a single channel.
* It returns only the first converted value.
*
* @param num The ADC number.
* @param chan The ADC channel number.
* @return The ADC conversion result.
*/
extern uint16_t adc_result_only_one(adcs_e num, uint8_t chan);
/**
* @brief Gets the ADC conversion result using median average filtering.
*
* This function gets the ADC conversion result for a single channel.
* It applies median average filtering to the converted values.
*
* @param num The ADC number.
* @param chan The ADC channel number.
* @return The ADC conversion result.
*/
extern uint16_t adc_result_median_average(adcs_e num, uint8_t chan);
/**
* @brief Gets the ADC conversion result using median filtering.
*
* This function gets the ADC conversion result for a single channel.
* It applies median filtering to the converted values.
*
* @param num The ADC number.
* @param chan The ADC channel number.
* @return The ADC conversion result.
*/
extern uint16_t adc_result_median(adcs_e num, uint8_t chan);
/**
* @brief Gets the ADC conversion result using average filtering.
*
* This function gets the ADC conversion result for a single channel.
* It applies average filtering to the converted values.
*
* @param num The ADC number.
* @param chan The ADC channel number.
* @return The ADC conversion result.
*/
extern uint16_t adc_result_average(adcs_e num, uint8_t chan);
/**
* @brief Gets the ADC conversion result using N-times average filtering.
*
* This function gets the ADC conversion result for a single channel.
* It applies N-times average filtering to the converted values.
*
* @param num The ADC number.
* @param chan The ADC channel number.
* @return The ADC conversion result.
*/
extern uint16_t adc_result_n_average(adcs_e num, uint8_t chan);
/**
* @brief Calculates the temperature from the ADC conversion result.
*
* This function calculates the temperature in degrees Celsius
* from the ADC conversion result of the internal temperature sensor.
*
* @param adc_value The ADC conversion result.
* @return The temperature in degrees Celsius.
*/
extern float32 adc_result_temperature(uint16_t adc_value);
/**
* @brief Calculates the voltage from the ADC conversion result.
*
* This function calculates the voltage in millivolts
* from the ADC conversion result of the internal voltage reference.
*
* @param adc_value The ADC conversion result.
* @return The voltage in millivolts.
*/
extern float32 adc_result_value_local(uint16_t adc_value);
/**
* @brief ADC environment callback function.
*
* This function is called when an ADC conversion is completed.
*
* @param num The ADC number.
*/
extern void adc_env_callback(adcs_e num);
/**
* @brief DMA callback function for ADC.
*
* This function is called when a DMA transfer for ADC is completed.
*
* @param num The ADC number.
*/
extern void adc_dma_callback(adcs_e num);
#endif ///< __ADCS_H__

View File

@ -1,90 +1,2 @@
#include "bsp.h"
#define EXIT_LINE LL_EXTI_LINE_16
pvd_irq_handle_cb pvd_irq_handle_cb_func = NULL;
/**
* @brief PVD
*
* PVD
*
* @param pwr_level
* @param call PVD中断处理回调函数
*/
void pvd_configuration(uint32_t pwr_level, pvd_irq_handle_cb call)
{
// pvd_irq_handle_cb_func = call;
// // 启用电源时钟
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
// // 设置PVD电平阈值例如设置为2.4V LL_PWR_PVDLEVEL_2
// LL_PWR_SetPVDLevel(pwr_level);
// // 启用PVD
// LL_PWR_EnablePVD();
// // 配置PVD中断
// LL_EXTI_EnableIT_0_31(EXIT_LINE); // PVD连接到EXTI Line
// LL_EXTI_EnableRisingTrig_0_31(EXIT_LINE);
// LL_EXTI_EnableFallingTrig_0_31(EXIT_LINE);
// // 启用PVD中断向量
// NVIC_EnableIRQ(PVD_PVM_IRQn);
// NVIC_SetPriority(PVD_PVM_IRQn, 0);
}
/**
* @brief PVD中断
*
* PVD中断触发时
*
* @note
*/
void pvd_irq_handle(void)
{
// if (LL_EXTI_IsActiveFlag_0_31(EXIT_LINE))
// {
// LL_EXTI_ClearFlag_0_31(EXIT_LINE);
// if (pvd_irq_handle_cb_func != NULL)
// {
// pvd_irq_handle_cb_func();
// }
// }
}
/**
* @brief
*
*
* SWD JTAG GPIO
*
* @note disable_debug_interface调用后 SWD ST-LINK SWD MCU,使 STM32 ST-LINK Utility ST-LINK MCU解除读保护
* :Read Out Protection : Level 0 Level 0 Flash Level 2 Level 2 MCU
*/
void disable_debug_interface(void)
{
// // 使能 SYSCFG 时钟
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
// // 关闭调试接口
// LL_DBGMCU_DisableDBGStopMode();
// LL_DBGMCU_DisableDBGStandbyMode();
// LL_DBGMCU_DisableDBGSleepMode();
// // 关闭 SWD 和 JTAG 接口
// LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
// // 配置 SWDIO (PA13) 和 SWCLK (PA14) 引脚为普通 GPIO
// GPIO_InitStruct.Pin = LL_GPIO_PIN_13 | LL_GPIO_PIN_14;
// GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
// GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// // 如果使用的是 JTAG 接口,还需要配置 JTDI (PA15), JTDO (PB3), 和 NJTRST (PB4) 引脚
// GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIO_InitStruct.Pin = LL_GPIO_PIN_3 | LL_GPIO_PIN_4;
// LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

View File

@ -13,21 +13,6 @@
#define __BSP_H__
#include "gpios.h"
// #include "dmas.h"
// #include "adcs.h"
// #include "dacs.h"
// #include "tims.h"
// #include "pwms.h"
// #include "uarts.h"
// #include "eeprom.h"
// #include "spis.h"
// #include "i2cs.h"
///< 定义回调函数类型
typedef void (*pvd_irq_handle_cb)(void);
extern void pvd_configuration(uint32_t pwr_level, pvd_irq_handle_cb call); ///< Configures the Programmable Voltage Detector (PVD) module
extern void pvd_irq_handle(void); ///< Handles the PVD interrupt
extern void disable_debug_interface(void); ///< Disables the debug interface
#include "spis.h"
#endif ///< __BSP_H__

View File

@ -1,52 +0,0 @@
/**
* @file dacs.c
* @brief This file contains the implementation of the DAC module.
* It provides functions to initialize and de-initialize a DAC instance,
* as well as write a 16-bit value to the specified DAC channel.
* @author xxx
* @date 2023-12-27 14:44:03
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#include "dacs.h"
/**
* @brief Writes a 16-bit value to the specified DAC channel
*
* @param dac pointer to the DAC instance
* @param value 16-bit value to write to the DAC
*/
static void _out(dac_t *dac, uint16_t value)
{
DBG_ASSERT(dac != NULL __DBG_LINE);
DAC_OUT(dac->dac, dac->dac_channel, value);
}
/**
* @brief Initializes a DAC instance
*
* @param dac pointer to the DAC instance
* @param dac_channel DAC channel to use
* @return pointer to the initialized DAC instance
*/
dac_t *dac_create(DAC_TypeDef *dac, uint16_t dac_channel)
{
DBG_ASSERT(dac != NULL __DBG_LINE);
dac_t *handle = (dac_t *)osel_mem_alloc(sizeof(dac_t));
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->dac = dac;
handle->dac_channel = dac_channel;
handle->out = _out;
return handle;
}
/**
* @brief De-initializes a DAC instance
*
* @param dac pointer to the DAC instance
*/
void dac_free(dac_t *dac)
{
DBG_ASSERT(dac != NULL __DBG_LINE);
osel_mem_free(dac);
}

View File

@ -1,55 +0,0 @@
/**
* @file dacs.h
* @brief Header file for DACs module.
*
* This file contains the declarations and definitions for the DACs module.
* DACs (Digital-to-Analog Converters) are used to convert digital signals into analog voltages.
*
* @author xxx
* @date 2023-12-27 14:44:03
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __DACS_H__
#define __DACS_H__
#include "dac.h"
#include "lib.h"
#include "main.h"
/**
* @brief Set the output value for a specific DAC channel.
* @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC.
* @param value: the output value to be set.
* @retval None
*/
#define DAC_OUT(DACx, DAC_Channel, Data) \
do \
{ \
LL_DAC_ConvertData12RightAligned(DACx, DAC_Channel, Data); \
LL_DAC_TrigSWConversion(DACx, DAC_Channel); \
} while (__LINE__ == -1)
/**
* @brief Enable the specified DAC channel.
* @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC.
* @retval None
*/
#define DAC_START(DACx, DAC_Channel) LL_DAC_Enable(DACx, DAC_Channel)
/**
* @brief Disable the specified DAC channel.
* @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC.
* @retval None
*/
#define DAC_STOP(DACx, DAC_Channel) LL_DAC_Disable(DACx, DAC_Channel)
/**
* @brief Structure definition for the DAC driver.
*/
typedef struct DACS
{
DAC_TypeDef *dac;
uint16_t dac_channel;
void (*out)(struct DACS *dac, uint16_t value);
} dac_t;
#endif

View File

@ -1,135 +0,0 @@
#ifndef __DMAS_H__
#define __DMAS_H__
/**
* @brief DMA传输完成标志
* @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
* @param {uint32_t} CHx DMA通道号
* @return {*}
* @note: DMA总线的传输完成标志DMA总线的传输完成标志是否已置位
*/
#define DMA_ClEAR_FLAG_TC(DMAX, CHx) \
do \
{ \
if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
{ \
LL_DMA_ClearFlag_TC##CHx(DMAX); \
} \
} while (__LINE__ == -1)
/**
* @brief DMA传输错误标志
* @param {DMA_HandleTypeDef} *DMAX DMA总线句柄
* @param {uint32_t} CHx DMA通道号
* @return {*}
* @note: DMA总线的传输错误标志DMA总线的传输错误标志是否已置位
*/
#define DMA_ClEAR_FLAG_TE(DMAX, CHx) \
do \
{ \
if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
{ \
LL_DMA_ClearFlag_TE##CHx(DMAX); \
} \
} while (__LINE__ == -1)
/**
* @file uarts.c
* @brief This file contains the implementation of DMA_CLEAR_FLAG_TC_CHANNEL macro.
*/
/**
* @brief Clear the Transfer Complete (TC) flag of a specific DMA channel.
*
* @param dma The DMA peripheral.
* @param channel The DMA channel number.
*/
#define DMA_CLEAR_FLAG_TC_CHANNEL(dma, channel) \
switch (channel) \
{ \
case LL_DMA_CHANNEL_1: \
DMA_ClEAR_FLAG_TC(dma, 1); \
break; \
case LL_DMA_CHANNEL_2: \
DMA_ClEAR_FLAG_TC(dma, 2); \
break; \
case LL_DMA_CHANNEL_3: \
DMA_ClEAR_FLAG_TC(dma, 3); \
break; \
case LL_DMA_CHANNEL_4: \
DMA_ClEAR_FLAG_TC(dma, 4); \
break; \
case LL_DMA_CHANNEL_5: \
DMA_ClEAR_FLAG_TC(dma, 5); \
break; \
case LL_DMA_CHANNEL_6: \
DMA_ClEAR_FLAG_TC(dma, 6); \
break; \
case LL_DMA_CHANNEL_7: \
DMA_ClEAR_FLAG_TC(dma, 7); \
break; \
default: \
break; \
}
/**
* @brief Clear the Transfer Error (TE) flag for the specified DMA channel.
*
* @param dma The DMA peripheral.
* @param channel The DMA channel number.
*/
#define DMA_CLEAR_FLAG_TE_CHANNEL(dma, channel) \
switch (channel) \
{ \
case 1: \
DMA_ClEAR_FLAG_TE(dma, 1); \
break; \
case 2: \
DMA_ClEAR_FLAG_TE(dma, 2); \
break; \
case 3: \
DMA_ClEAR_FLAG_TE(dma, 3); \
break; \
case 4: \
DMA_ClEAR_FLAG_TE(dma, 4); \
break; \
case 5: \
DMA_ClEAR_FLAG_TE(dma, 5); \
break; \
case 6: \
DMA_ClEAR_FLAG_TE(dma, 6); \
break; \
case 7: \
DMA_ClEAR_FLAG_TE(dma, 7); \
break; \
default: \
break; \
}
/**
* @brief Clears the flags of a DMA channel
* @param DMAX DMAx register base
* @param CHx DMA channel number
* @param Flag a boolean variable that indicates if the transfer is complete
* @note This function should be called within the interrupt service routine of the DMA channel
*/
#define DMA_ClEAR_FLAG(DMAX, CHx, Flag) \
do \
{ \
if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \
{ \
LL_DMA_ClearFlag_TC##CHx(DMAX); \
LL_DMA_ClearFlag_GI##CHx(DMAX); \
Flag = TRUE; \
} \
if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \
{ \
LL_DMA_ClearFlag_TE##CHx(DMAX); \
} \
if (LL_DMA_IsActiveFlag_GI##CHx(DMAX)) \
{ \
LL_DMA_ClearFlag_GI##CHx(DMAX); \
} \
} while (__LINE__ == -1)
#endif // __DMAS_H__

View File

@ -1,91 +0,0 @@
/**
* @file eeprom.c
* @author xxx
* @date 2023-11-16 10:28:47
* @brief STM32L072xx EEPROM
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "eeprom.h"
#include "main.h"
#ifdef STM32L072xx
#define PEKEY1 0x89ABCDEF // FLASH_PEKEYR
#define PEKEY2 0x02030405 // FLASH_PEKEYR
#define LOCK __enable_irq(); // 系统开全局中断
#define UNLOCK __disable_irq(); // 系统关全局中断
/**
* @brief EEPROM的函数
* @param {uint32_t} read_addr -
* @param {uint8_t} *data -
* @param {uint16_t} length -
* @return {*}
* @note: EEPROM中
*/
void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length)
{
uint8_t *wAddr;
wAddr = (uint8_t *)(read_addr);
while (length--)
{
*data++ = *wAddr++;
}
}
/**
* @brief EEPROM的函数
* @param {uint32_t} write_addr -
* @param {uint8_t} *data -
* @param {uint16_t} length -
* @return {*}
* @note: EEPROM中EEPROMEEPROM
*/
void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length)
{
uint8_t *addr;
addr = (uint8_t *)(write_addr);
UNLOCK
FLASH->PDKEYR = PEKEY1;
FLASH->PDKEYR = PEKEY2;
while (FLASH->PECR & FLASH_PECR_PELOCK)
;
while (length--)
{
*addr++ = *data++;
while (FLASH->SR & FLASH_SR_BSY)
;
}
FLASH->PECR |= FLASH_PECR_PELOCK;
LOCK
}
#endif // STM32L072xx
#ifdef STM32L476xx
/**
* @brief SRAM2的函数
* @param {uint32_t} read_addr -
* @param {uint8_t} *data -
* @param {uint16_t} length -
* @return {*}
* @note: SRAM2中
*/
void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length)
{
}
/**
* @brief SRAM2的函数
* @param {uint32_t} write_addr - 0
* @param {uint8_t} *data -
* @param {uint16_t} length -
* @return {*}
* @note: SRAM2中
*/
void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length)
{
}
#endif // STM32L476xx

View File

@ -1,7 +0,0 @@
#ifndef __EEPROM_H__
#define __EEPROM_H__
#include "lib.h"
extern void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length); ///< 读取数据
extern void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length); ///< 写入数据
#endif ///< __EEPROM_H__

View File

@ -1,550 +0,0 @@
/**
* @file flash.c
* @author xxx
* @date 2024-02-07 11:49:34
* @brief
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
* @attention
*
* ST LL flash
*
* 1. stm32l4xx_ll_system.h FLASH ACR寄存器的处理
*
*
* 2. Main memory
* 1 FLASH_ACR
* 2 FLASH_PDKEYR
* 3 FLASH_KEYR
* 4 FLASH_OPTKEYR
* 5 FLASH_SR
* 6 FLASH_CR
* 7 FLASH_ECCR
* 8 FLASH_OPTR
* 9 FLASH_PCROP1SR
*
* 3. Information block
* - System memory
* - OTP area
* - Option bytes
* 4. HAL
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "flash.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_system.h"
#include "stm32l4xx_ll_pwr.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#define WHILE_MAX 30000U
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
/** @addtogroup FLASH_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @addtogroup FLASH_LL_Private_Constants
* @{
*/
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup FLASH_LL_Private_Macros
* @{
*/
#define IS_LL_FLASH_WRITE_ADDR(__ADDR__) ((__ADDR__) % LL_FLASH_ALIGNMENT_MIN_SIZE == 0)
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup FLASH_LL_Private_Functions FLASH Private functions
* @{
*/
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup FLASH_LL_Exported_Functions
* @{
*/
/**
* @brief Clear All Error in SR
* @param FLASHx FLASH Instance
* @retval None
*/
void LL_FLASH_ClearAllErrorFlag(void)
{
LL_FLASH_ClearFlag_OPTVERR(FLASH);
LL_FLASH_ClearFlag_RDERR(FLASH);
LL_FLASH_ClearFlag_FASTERR(FLASH);
LL_FLASH_ClearFlag_MISERR(FLASH);
LL_FLASH_ClearFlag_PGSERR(FLASH);
LL_FLASH_ClearFlag_SIZERR(FLASH);
LL_FLASH_ClearFlag_PGAERR(FLASH);
LL_FLASH_ClearFlag_WRPERR(FLASH);
LL_FLASH_ClearFlag_PROGERR(FLASH);
LL_FLASH_ClearFlag_OPERR(FLASH);
}
/**
* @brief Flush the instruction and data caches.
* @retval None
*/
void LL_FLASH_FlushCaches(void)
{
/* Flush instruction cache */
if (LL_FLASH_IsEnabledInstructionCache(FLASH))
{
LL_FLASH_DisableInstructionCache(FLASH);
/* Reset instruction cache */
LL_FLASH_InstructionCacheReset(FLASH);
/* Enable instruction cache */
LL_FLASH_EnableInstructionCache(FLASH);
}
/* Flush data cache */
if (LL_FLASH_IsEnabledDataCache(FLASH))
{
LL_FLASH_ZCS_DisableDataCache(FLASH);
/* Reset data cache */
LL_FLASH_DataCacheReset(FLASH);
/* Enable data cache */
LL_FLASH_ZCS_EnableDataCache(FLASH);
}
}
/**
* @brief Erase Page
* @param pageno Page number
* @retval None
*/
ErrorStatus LL_FLASH_ErasePage(uint32_t pageno)
{
uint16_t count = 0;
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
LL_FLASH_ClearAllErrorFlag();
/* Set the PER bit and select the page you wish to erase (PNB) with the associated bank (BKER) in the Flash control register (FLASH_CR). */
LL_FLASH_EnablePageErase(FLASH);
if (pageno >= LL_FLASH_BANK1_PAGE_NUM)
{
pageno -= LL_FLASH_BANK1_PAGE_NUM;
LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK2);
}
else
{
LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK1);
}
LL_FLASH_SetErasePageNo(FLASH, pageno);
/* Set the STRT bit in the FLASH_CR register. */
LL_FLASH_EraseStart(FLASH);
/* Wait for the BSY bit to be cleared in the FLASH_SR register. */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* 完成只有需要清除擦除标志. */
LL_FLASH_DisablePageErase(FLASH);
/* Flush the caches to be sure of the data consistency */
LL_FLASH_FlushCaches();
return SUCCESS;
}
/**
* @brief Erase bank
* @param bank This parameter can be one of the following values:
* @arg @ref LL_FLASH_BANK1
* @arg @ref LL_FLASH_BANK2
* @retval None
*/
ErrorStatus LL_FLASH_EraseBank(uint32_t bank)
{
uint16_t count = 0;
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
LL_FLASH_ClearAllErrorFlag();
/* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR).
Both banks can be selected in the same operation. */
if (bank == LL_FLASH_BANK1)
{
LL_FLASH_EnableBank1Erase(FLASH);
}
else
{
LL_FLASH_EnableBank2Erase(FLASH);
}
/* Set the STRT bit in the FLASH_CR register. */
LL_FLASH_EraseStart(FLASH);
/* Wait for the BSY bit to be cleared in the FLASH_SR register. */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* 完成只有需要清除擦除标志. */
LL_FLASH_DisableBank1Erase(FLASH);
LL_FLASH_DisableBank2Erase(FLASH);
/* Flush the caches to be sure of the data consistency */
LL_FLASH_FlushCaches();
return SUCCESS;
}
/**
* @brief Erase Chip
* @param None
* @retval None
*/
ErrorStatus LL_FLASH_EraseChip(void)
{
uint16_t count = 0;
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
LL_FLASH_ClearAllErrorFlag();
/* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR).
Both banks can be selected in the same operation. */
LL_FLASH_EnableBank1Erase(FLASH);
LL_FLASH_EnableBank2Erase(FLASH);
/* Set the STRT bit in the FLASH_CR register. */
LL_FLASH_EraseStart(FLASH);
/* Wait for the BSY bit to be cleared in the FLASH_SR register. */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* 完成只有需要清除擦除标志. */
LL_FLASH_DisableBank1Erase(FLASH);
LL_FLASH_DisableBank2Erase(FLASH);
/* Flush the caches to be sure of the data consistency */
LL_FLASH_FlushCaches();
return SUCCESS;
}
/**
* @brief Program Double Word
* @param address specifies the address to be programmed.
* @param data specifies the data to be programmed.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Write successfully
* - ERROR: error
*/
ErrorStatus LL_FLASH_ProgramDoubleWord(uint32_t address, uint64_t data)
{
assert_param(!IS_LL_FLASH_WRITE_ADDR(address));
uint16_t count = 0;
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
LL_FLASH_ClearAllErrorFlag();
/* Set the PG bit in the Flash control register (FLASH_CR). */
LL_FLASH_EnableProgram(FLASH);
/* Perform the data write operation at the desired memory address, inside main memory
block or OTP area. Only double word can be programmed. */
/* Program the double word */
*(__IO uint32_t *)address = (uint32_t)data;
*(__IO uint32_t *)(address + 4U) = (uint32_t)(data >> 32);
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check that EOP flag is set in the FLASH_SR register (meaning that the programming
operation has succeed), and clear it by software. */
if (LL_FLASH_IsActiveFlag_EOP(FLASH))
{
LL_FLASH_ClearFlag_EOP(FLASH);
}
/* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */
LL_FLASH_DisableProgram(FLASH);
/* Flush the caches to be sure of the data consistency */
LL_FLASH_FlushCaches();
return SUCCESS;
}
/**
* @brief Program
* @param address specifies the address to be programmed.
* @param data specifies the data to be programmed.
* @param num specifies the data number
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Write successfully
* - ERROR: error
*/
ErrorStatus LL_FLASH_Program(uint32_t address, uint8_t data[], uint32_t num)
{
static uint64_t DataT = 0;
uint32_t T = 0, S = 0;
uint16_t count = 0;
assert_param(!IS_LL_FLASH_WRITE_ADDR(address));
if (num == 0)
{
return SUCCESS;
}
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */
LL_FLASH_ClearAllErrorFlag();
/* Set the PG bit in the Flash control register (FLASH_CR). */
LL_FLASH_EnableProgram(FLASH);
/* Perform the data write operation at the desired memory address, inside main memory
block or OTP area. Only double word can be programmed. */
T = num;
while (num > 0)
{
DataT = 0;
if (num >= 8)
{
for (int i = 0; i < LL_FLASH_ALIGNMENT_MIN_SIZE; i++)
{
DataT = DataT << 8;
DataT |= data[S + 7 - i];
}
S += LL_FLASH_ALIGNMENT_MIN_SIZE;
num -= LL_FLASH_ALIGNMENT_MIN_SIZE;
}
else
{
for (int i = 0; i < num; i++)
{
DataT = DataT << 8;
DataT |= data[T - 1 - i];
}
num = 0;
}
/* Program the double word */
*(__IO uint32_t *)address = (uint32_t)DataT;
*(__IO uint32_t *)(address + 4U) = (uint32_t)(DataT >> 32);
/* Check that no Flash memory operation is ongoing by checking the BSY bit */
while (LL_FLASH_IsActiveFlag_BSY(FLASH))
{
if (count++ > WHILE_MAX)
{
return ERROR;
}
}
count = 0;
/* Check that EOP flag is set in the FLASH_SR register (meaning that the programming
operation has succeed), and clear it by software. */
if (LL_FLASH_IsActiveFlag_EOP(FLASH))
{
LL_FLASH_ClearFlag_EOP(FLASH);
}
address += LL_FLASH_ALIGNMENT_MIN_SIZE;
}
/* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */
LL_FLASH_DisableProgram(FLASH);
/* Flush the caches to be sure of the data consistency */
LL_FLASH_FlushCaches();
return SUCCESS;
}
/**
* @}
*/
/** @addtogroup FLASH_LL_Private_Functions
* @{
*/
/**
* @brief Fast program a row double-word (64-bit) at a specified address.
* @param address: specifies the address to be programmed.
* @param DataAddress: specifies the address where the data are stored.
* @retval None
*/
void LL_FLASH_ProgramFast(uint32_t address, uint32_t DataAddress)
{
uint8_t row_index = (2 * LL_FLASH_ROW_SIZE);
__IO uint32_t *dest_addr = (__IO uint32_t *)address;
__IO uint32_t *src_addr = (__IO uint32_t *)DataAddress;
/* Check the parameters */
assert_param(IS_FLASH_MAIN_MEM_ADDRESS(address));
/* Set FSTPG bit */
LL_FLASH_EnableFastProgram(FLASH);
/* Disable interrupts to avoid any interruption during the loop */
__disable_irq();
/* Program the double word of the row */
do
{
*dest_addr = *src_addr;
dest_addr++;
src_addr++;
row_index--;
} while (row_index != 0U);
/* Re-enable the interrupts */
__enable_irq();
LL_FLASH_DisableFastProgram(FLASH);
}
/**
* @brief Fast program a row double-word (64-bit) at a specified address.
* @param address: specifies the address to be programmed.
* @param data: specifies the data to be programmed.
* @retval None
*/
ErrorStatus LL_FLASH_Read(uint32_t address, uint8_t data[], uint32_t num)
{
if (num == 0)
{
return SUCCESS;
}
for (uint32_t i = 0; i < num; i++)
{
data[i] = *(__IO uint8_t *)(address + i);
}
return SUCCESS;
}
/**
* @brief FLASH
*
* FLASH
*
* @param address FLASH
* @param size
*/
void LL_FLASH_EraseAddress(uint32_t address, uint16_t size)
{
uint16_t start_page = 0, end_page = 0;
start_page = address / LL_FLASH_PAGE_SIZE;
end_page = (address + size) / LL_FLASH_PAGE_SIZE;
// 擦除页
for (uint16_t i = start_page; i < end_page; i++)
{
LL_FLASH_ErasePage(i);
}
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

View File

@ -1,669 +0,0 @@
#include "i2cs.h"
#include "main.h"
static inline void delay(i2c_t *handle); // 延时函数
static inline void _ack(i2c_t *handle); // 应答
static inline void _nack(i2c_t *handle); // 非应答
/**
* @brief I2C总线
* @param {i2c_t} *handle - I2C总线句柄
* @note: I2C总线的操作线
*/
static void _start(i2c_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
// 获取gpios指针
i2c_gpio_group_t *gpios = &handle->gpios;
// 获取scl指针
gpio_t *scl = gpios->scl;
// 获取sda指针
gpio_t *sda = gpios->sda;
// 设置sda
gpios->sda->set(*sda);
// 设置scl
gpios->scl->set(*scl);
// 延时
delay(handle);
// 重置sda
gpios->sda->reset(*sda);
// 延时
delay(handle);
// 重置scl
gpios->scl->reset(*scl);
// 延时
delay(handle);
}
/**
* @brief I2C总线
* @param {i2c_t} *handle - I2C总线句柄
* @note: I2C总线的操作线
*/
static void _stop(i2c_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
i2c_gpio_group_t *gpios = &handle->gpios;
gpio_t *scl = gpios->scl;
gpio_t *sda = gpios->sda;
gpios->scl->reset(*scl);
gpios->sda->reset(*sda);
delay(handle);
gpios->scl->set(*scl);
gpios->sda->set(*sda);
delay(handle);
}
/**
* @brief
* @param {i2c_t} *handle - I2C总线句柄
* @return {BOOL} - TRUEFALSE
* @note: I2C总线上发送的应答信号
*/
static BOOL _wait_ack(i2c_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
uint8_t count = 0;
i2c_gpio_group_t *gpios = &handle->gpios;
gpio_t *scl = gpios->scl;
gpio_t *sda = gpios->sda;
gpios->sda->set(*sda);
gpios->scl->set(*scl);
delay(handle);
while (gpios->sda->read(*sda))
{
count++;
if (count > 250)
{
_stop(handle);
return FALSE;
}
}
gpios->scl->reset(*scl);
delay(handle);
return TRUE;
}
/**
* @brief
* @param {i2c_t} *handle - I2C总线句柄
* @param {BOOL} ack -
* @return {uint8_t} -
* @note: I2C总线上读取一个字节
*/
static uint8_t _read_byte(i2c_t *handle, BOOL ack)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
uint8_t i = 0, receive = 0;
i2c_gpio_group_t *gpios = &handle->gpios;
gpio_t *scl = gpios->scl;
gpio_t *sda = gpios->sda;
for (i = 0; i < 8; i++)
{
gpios->sda->set(*sda);
gpios->scl->set(*scl);
receive <<= 1;
delay(handle);
if (gpios->sda->read(*sda))
receive++;
gpios->scl->reset(*scl);
delay(handle);
}
if (TRUE == ack)
{
_ack(handle);
}
else
{
_nack(handle);
}
return receive;
}
/**
* @brief I2C总线上
* @param {i2c_t} *handle I2C总线的句柄
* @param {uint8_t} data
* @return {*}
* @note: I2C总线上发送一个字节的数据1SDA为1SDA为0SCL为11msSCL为01msSDA为1
*/
static void _write_byte(i2c_t *handle, uint8_t data)
{
// 定义变量i
uint8_t i = 0;
// 断言参数handle不为空
DBG_ASSERT(handle != NULL __DBG_LINE);
// 定义变量gpios
i2c_gpio_group_t *gpios = &handle->gpios;
// 定义变量scl
gpio_t *scl = gpios->scl;
// 定义变量sda
gpio_t *sda = gpios->sda;
// 遍历每一位
for (i = 0; i < 8; i++)
{
// 如果data的最低位为1
if (data & 0x80)
{
// 设置sda的状态为1
gpios->sda->set(*sda);
}
// 否则设置sda的状态为0
else
{
// 设置sda的状态为0
gpios->sda->reset(*sda);
}
// 设置scl的状态为1
gpios->scl->set(*scl);
// 延时1ms
delay(handle);
// 将data右移1位
data <<= 1;
// 设置scl的状态为0
gpios->scl->reset(*scl);
// 延时1ms
delay(handle);
// 如果i等于7
if (i == 7)
{
// 设置sda的状态为1
gpios->sda->set(*sda);
}
}
}
/**
* @brief I2C总线上
* @param {i2c_t} *handle I2C总线的句柄
* @param {uint16_t} data
* @return {*}
* @note: I2C总线上发送一个字节的数据1SDA为1SDA为0SCL为11msSCL为01msSDA为1
*/
static void _write_word(i2c_t *handle, uint16_t data)
{
// 循环写入2个字节
for (uint8_t i = 0; i < 2; i++)
{
// 将data的第i个字节写入i2c接口
_write_byte(handle, (uint8_t)(data >> (8 * i)));
// 等待ACK
_wait_ack(handle);
}
}
/**
* @brief I2C总线设备
* @param {i2c_gpio_group_t} gpios I2C总线的GPIO配置
* @param {uint16_t} delay_ticks I2C总线的延时参数
* @return {i2c_t *} I2C总线设备句柄
* @note: I2C总线设备i2c_t结构体gpios和delay_ticks的内存地址复制到handle结构体中handle结构体定义了startstopwait_ackread_bytewrite_byte和write_word函数handle结构体
*/
i2c_t *i2c_create(i2c_gpio_group_t gpios, uint16_t delay_ticks)
{
// 创建一个i2c_t结构体
i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t));
// 将gpios的内存地址复制到handle结构体中
osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(i2c_gpio_group_t));
// 将delay_ticks的内存地址复制到handle结构体中
handle->delay_ticks = delay_ticks;
// 创建一个start函数
handle->interface.start = _start;
// 创建一个stop函数
handle->interface.stop = _stop;
// 创建一个wait_ack函数
handle->interface.wait_ack = _wait_ack;
// 创建一个read_byte函数
handle->interface.read_byte = _read_byte;
// 创建一个write_byte函数
handle->interface.write_byte = _write_byte;
// 创建一个write_word函数
handle->interface.write_word = _write_word;
handle->dead_count = 0;
// 返回handle结构体
return handle;
}
/**
* @brief I2C器件地址
* @param {i2c_t} *handle
* @param {uint8_t} w_address
* @param {uint8_t} r_address
* @return {*}
* @note
*/
void i2c_dma_set_address(i2c_t *handle, uint8_t w_address, uint8_t r_address)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->w_address = w_address;
handle->r_address = r_address;
}
/**
* @brief I2C总线设备
* @param {i2c_t} *handle I2C总线设备句柄
* @return {*}
* @note: I2C总线设备handle是否为空GPIOhandle的内存
*/
void i2c_free(i2c_t *handle)
{
// 如果handle不为空则释放所有的gpio
if (NULL != handle)
{
gpio_free(handle->gpios.scl);
gpio_free(handle->gpios.sda);
osel_mem_free(handle);
}
}
/**
* @brief I2C DMA TX回调函数
* @param {i2c_t} handle
* @return {*}
* @note
*/
void i2c_dma_callback(i2c_t *handle)
{
// 检查输入参数是否为空
DBG_ASSERT(handle != NULL __DBG_LINE);
// 清除传输完成标志位
if (handle->dma_tx_cb != NULL)
{
handle->dma_tx_cb(handle);
}
if (handle->dma_rx_cb != NULL)
{
handle->dma_rx_cb(handle);
}
}
#if defined(STM32L4xx_LL_I2C_H)
static void i2c_reset(i2c_t *handle);
static BOOL _read_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size);
static BOOL _write_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size);
/**
* @brief I2C总线设备 DMA
* @param {I2C_TypeDef} *i2c
* @param {DMA_TypeDef} *dma
* @param {uint16_t} rxsize
* @param {uint32_t} dma_rx_channel
* @param {uint16_t} txsize
* @param {uint32_t} dma_tx_channel
* @return {*}
* @note
*/
i2c_t *i2c_create_dma(I2C_TypeDef *i2c, DMA_TypeDef *dma, uint16_t rxsize, uint32_t dma_rx_channel,
i2cs_dma_callback *dma_rx_cb, uint16_t txsize, uint32_t dma_tx_channel, i2cs_dma_callback *dma_tx_cb)
{
i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t));
handle->i2c = i2c;
handle->dma = dma;
handle->dma_rx_channel = dma_rx_channel;
handle->dma_tx_channel = dma_tx_channel;
handle->rxbuf = (uint8_t *)osel_mem_alloc(rxsize);
handle->txbuf = (uint8_t *)osel_mem_alloc(txsize);
handle->rxsize = rxsize;
handle->txsize = txsize;
handle->tx_dma_ok = TRUE;
handle->interface.write_mem_dma = _write_mem_dma;
handle->interface.read_mem_dma = _read_mem_dma;
if (dma_rx_cb != NULL)
{
handle->dma_rx_cb = dma_rx_cb;
}
if (dma_tx_cb != NULL)
{
handle->dma_tx_cb = dma_tx_cb;
}
LL_DMA_DisableChannel(dma, dma_tx_channel);
LL_DMA_DisableChannel(dma, dma_rx_channel);
// TX
uint8_t *pTransmitBuffer = handle->txbuf;
LL_DMA_ConfigTransfer(dma, dma_tx_channel, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(dma, dma_tx_channel, (uint32_t)pTransmitBuffer, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(dma, dma_tx_channel));
LL_DMA_SetPeriphRequest(dma, dma_tx_channel, LL_DMA_REQUEST_3);
// RX
uint8_t *pReceiveBuffer = handle->rxbuf;
LL_DMA_ConfigTransfer(dma, dma_rx_channel, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(dma, dma_rx_channel, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)pReceiveBuffer, LL_DMA_GetDataTransferDirection(dma, dma_rx_channel));
LL_DMA_SetPeriphRequest(dma, dma_rx_channel, LL_DMA_REQUEST_3);
LL_DMA_EnableIT_TC(dma, dma_tx_channel);
LL_DMA_EnableIT_TE(dma, dma_tx_channel);
LL_DMA_EnableIT_TC(dma, dma_rx_channel);
LL_DMA_EnableIT_TE(dma, dma_rx_channel);
LL_I2C_EnableDMAReq_TX(i2c);
LL_I2C_EnableDMAReq_RX(i2c);
LL_I2C_Enable(i2c);
return handle;
}
/**
* @brief 使DMA从特定内存地址读取数据
* @param {i2c_t} *handle i2c_t结构体I2C的配置信息
* @param {uint16_t} dev_address 7
* @param {uint16_t} mem_address
* @param {uint16_t} mem_addsize
* @param {uint8_t} *data
* @param {uint16_t} size
* @return {*}
* @note
*/
static BOOL _read_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1)
{
i2c_reset(handle); // xsh:重置I2C,修复一段时间后无法读写的问题
return FALSE;
}
uint16_t count = 2000;
handle->txsize = 0;
handle->tx_dma_ok = FALSE;
handle->rx_dma_ok = FALSE;
for (uint8_t i = mem_addsize; i > 0; i--)
{
handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1)));
}
LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize);
LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
count = 2000;
while (!handle->tx_dma_ok)
{
if (count-- == 0)
{
handle->tx_dma_ok = TRUE;
return FALSE;
}
}
count = 2000;
while (LL_I2C_IsActiveFlag_TC(handle->i2c) != 1)
{
if (count-- == 0)
{
handle->tx_dma_ok = TRUE;
return FALSE;
}
}
handle->tx_dma_ok = FALSE;
handle->rx_dma_ok = FALSE;
handle->rxsize = size;
osel_memset(handle->rxbuf, 0, handle->rxsize);
LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
LL_DMA_SetDataLength(handle->dma, handle->dma_rx_channel, handle->rxsize);
LL_DMA_EnableChannel(handle->dma, handle->dma_rx_channel);
LL_I2C_HandleTransfer(handle->i2c, handle->r_address, LL_I2C_ADDRSLAVE_7BIT, handle->rxsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ);
count = 2000;
while (!LL_I2C_IsActiveFlag_STOP(handle->i2c))
{
if (count-- == 0)
{
handle->tx_dma_ok = TRUE;
return FALSE;
}
}
LL_DMA_DisableChannel(handle->dma, handle->dma_rx_channel);
LL_I2C_ClearFlag_STOP(handle->i2c);
osel_memcpy(data, handle->rxbuf, handle->rxsize);
return TRUE;
}
/**
* @brief 使DMA将数据写入特定内存地址
* @param {i2c_t} *handle i2c_t结构体I2C的配置信息
* @param {uint16_t} dev_address 7
* @param {uint16_t} mem_address
* @param {uint16_t} mem_addsize
* @param {uint8_t} *data
* @param {uint16_t} size
* @return {*}
* @note
*/
static BOOL _write_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
uint16_t count = 2000;
if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1)
{
i2c_reset(handle); // xsh:重置I2C,修复一段时间后无法读写的问题
return FALSE;
}
handle->txsize = 0;
handle->tx_dma_ok = FALSE;
for (uint8_t i = mem_addsize; i > 0; i--)
{
handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1)));
}
osel_memcpy(&handle->txbuf[handle->txsize], data, size);
handle->txsize += size;
LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize);
LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
count = 2000;
while (!handle->tx_dma_ok)
{
if (count-- == 0)
{
handle->tx_dma_ok = TRUE;
return FALSE;
}
}
count = 2000;
while (!LL_I2C_IsActiveFlag_STOP(handle->i2c))
{
if (count-- == 0)
{
handle->tx_dma_ok = TRUE;
return FALSE;
}
}
LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
LL_I2C_ClearFlag_STOP(handle->i2c);
return TRUE;
}
/**
* @brief I2C重置
* @param {I2C_TypeDef} *I2Cx
* @return {*}
* @note I2C总线死锁问题
*/
static void i2c_reset(i2c_t *handle)
{
LL_I2C_Disable(handle->i2c);
LL_I2C_Enable(handle->i2c);
handle->dead_count++;
}
/**
* @brief I2C
* @param {i2c_t} *handle
* @return {*}
* @note
*/
void i2c_ev_callback(i2c_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (LL_I2C_IsActiveFlag_ADDR(handle->i2c))
{
/* Verify the Address Match with the OWN Slave address */
if (LL_I2C_GetAddressMatchCode(handle->i2c) == handle->w_address || LL_I2C_GetAddressMatchCode(handle->i2c) == handle->r_address)
{
/* Verify the transfer direction, a write direction, Slave enters receiver mode */
if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_WRITE)
{
/* Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(handle->i2c);
/* Enable Receive Interrupt */
LL_I2C_EnableIT_RX(handle->i2c);
}
else if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_READ)
{
/* Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(handle->i2c);
/* Enable Transmit Interrupt */
LL_I2C_EnableIT_TX(handle->i2c);
}
}
else
{
/* Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(handle->i2c);
/* Call Error function */
DBG_ASSERT(FALSE __DBG_LINE);
}
}
/* Check NACK flag value in ISR register */
else if (LL_I2C_IsActiveFlag_NACK(handle->i2c))
{
/* End of Transfer */
LL_I2C_ClearFlag_NACK(handle->i2c);
}
/* Check RXNE flag value in ISR register */
else if (LL_I2C_IsActiveFlag_RXNE(handle->i2c))
{
/* Call function Slave Reception Callback */
}
/* Check TXIS flag value in ISR register */
else if (LL_I2C_IsActiveFlag_TXIS(handle->i2c))
{
/* Call function Slave Ready to Transmit Callback */
}
/* Check STOP flag value in ISR register */
else if (LL_I2C_IsActiveFlag_STOP(handle->i2c))
{
/* End of Transfer */
LL_I2C_ClearFlag_STOP(handle->i2c);
/* Check TXE flag value in ISR register */
if (!LL_I2C_IsActiveFlag_TXE(handle->i2c))
{
/* Flush TX buffer */
LL_I2C_ClearFlag_TXE(handle->i2c);
}
/* Call function Slave Complete Callback */
}
/* Check TXE flag value in ISR register */
else if (!LL_I2C_IsActiveFlag_TXE(handle->i2c))
{
/* Do nothing */
/* This Flag will be set by hardware when the TXDR register is empty */
/* If needed, use LL_I2C_ClearFlag_TXE() interface to flush the TXDR register */
}
else
{
/* Call Error function */
DBG_ASSERT(FALSE __DBG_LINE);
}
}
#endif
/*下面是内部实现方法*/
/**
* @brief 使NOPcountNOP指令的数量使
* @param {uint16_t} count NOP指令的数量
* @return {*}
*/
static inline void delay(i2c_t *handle)
{
// 断言参数handle不为空
DBG_ASSERT(handle != NULL __DBG_LINE);
// 定义循环计数变量count
uint16_t count = 0;
// 设置循环计数变量count的值为handle->delay_ticks
count = handle->delay_ticks;
// 循环计数变量count的值直到count的值为0
while (count--)
{
// 每次循环调用__NOP()函数
__NOP();
}
}
/**
* @brief ACK信号
* @param {i2c_t} *handle I2C总线的句柄
* @return {*}
* @note: I2C总线上发送ACK信号handle不为空gpios和sclsda的指针sda1msscl为11msscl
*/
static inline void _ack(i2c_t *handle)
{
// 断言handle不为空
DBG_ASSERT(handle != NULL __DBG_LINE);
// 获取gpios指针
i2c_gpio_group_t *gpios = &handle->gpios;
// 获取scl指针
gpio_t *scl = gpios->scl;
// 获取sda指针
gpio_t *sda = gpios->sda;
// 重置sda
gpios->sda->reset(*sda);
// 延时
delay(handle);
// 设置scl
gpios->scl->set(*scl);
// 延时
delay(handle);
// 重置scl
gpios->scl->reset(*scl);
}
/**
* @brief NACK信号
* @param {i2c_t} *handle I2C总线的句柄
* @return {*}
* @note: I2C总线上发送NACK信号handle不为空gpios和sclsda的指针sda为11msscl为11msscl
*/
static inline void _nack(i2c_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
// 获取gpios指针
i2c_gpio_group_t *gpios = &handle->gpios;
// 获取scl指针
gpio_t *scl = gpios->scl;
// 获取sda指针
gpio_t *sda = gpios->sda;
// 设置sda引脚
gpios->sda->set(*sda);
// 等待延时
delay(handle);
// 设置scl引脚
gpios->scl->set(*scl);
// 等待延时
delay(handle);
// 重置scl引脚
gpios->scl->reset(*scl);
}

View File

@ -1,127 +0,0 @@
/**
* @file i2cs.h
* @brief Header file for I2C Slave module.
*
* This file contains the declarations and definitions for the I2C Slave module.
* It provides functions to initialize and configure the I2C peripheral as a slave,
* as well as functions to send and receive data over the I2C bus.
*
* @author xxx
* @date 2023-12-27 14:44:03
* @version 1.0
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __I2CS_H__
#define __I2CS_H__
#include "lib.h"
#include "gpios.h"
/**
* @file i2cs.h
* @brief Header file containing the definition of the I2C slave (I2CS) structure and related functions.
*/
typedef struct I2CS i2c_t;
typedef void i2cs_dma_callback(i2c_t *handle);
typedef struct
{
void (*start)(i2c_t *handle); ///< Function pointer to start the I2C communication.
void (*stop)(i2c_t *handle); ///< Function pointer to stop the I2C communication.
BOOL(*wait_ack)
(i2c_t *handle); ///< Function pointer to wait for the acknowledgment from the I2C bus.
void (*write_byte)(i2c_t *handle, uint8_t data); ///< Function pointer to write a byte of data to the I2C bus.
uint8_t (*read_byte)(i2c_t *handle, BOOL ack); ///< Function pointer to read a byte of data from the I2C bus.
void (*write_word)(i2c_t *handle, uint16_t data); ///< Function pointer to write two bytes of data to the I2C bus.
BOOL(*write_mem_dma)
(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); ///< Function pointer to write multiple bytes of data to a memory address using DMA.
BOOL(*read_mem_dma)
(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); ///< Function pointer to read multiple bytes of data from a memory address using DMA.
} i2c_interface_t;
typedef struct
{
struct GPIO *scl; ///< Pointer to the GPIO pin used for the I2C clock (SCL).
struct GPIO *sda; ///< Pointer to the GPIO pin used for the I2C data (SDA).
} i2c_gpio_group_t;
struct I2CS
{
///< Analog part definition
i2c_gpio_group_t gpios; ///< Structure containing the GPIO pins used for the I2C communication.
uint16_t delay_ticks; ///< Number of NOP instructions to delay the I2C communication.
///< Hardware part definition
I2C_TypeDef *i2c; ///< Pointer to the I2C peripheral.
DMA_TypeDef *dma; ///< Pointer to the DMA peripheral.
uint32_t dma_rx_channel; ///< DMA channel used for receiving data.
uint32_t dma_tx_channel; ///< DMA channel used for transmitting data.
uint8_t *rxbuf; ///< Pointer to the receive buffer.
uint16_t rxsize; ///< Size of the receive buffer.
uint8_t *txbuf; ///< Pointer to the transmit buffer.
uint16_t txsize; ///< Size of the transmit buffer.
uint8_t w_address; ///< 7-bit write address.
uint8_t r_address; ///< 7-bit read address.
__IO BOOL rx_dma_ok; ///< Flag indicating the completion of receive DMA.
__IO BOOL tx_dma_ok; ///< Flag indicating the completion of transmit DMA.
i2cs_dma_callback *dma_rx_cb; ///< Callback function called when receive DMA is completed.
i2cs_dma_callback *dma_tx_cb; ///< Callback function called when transmit DMA is completed.
i2c_interface_t interface; ///< Structure containing the function pointers for the I2C interface.
uint16_t dead_count; ///< Counter for the number of deadlocks.
};
/**
* @brief Creates an I2C slave instance with GPIO pins for clock and data.
* @param gpios The GPIO pins used for the I2C communication.
* @param delay_ticks The number of NOP instructions to delay the I2C communication.
* @return A pointer to the created I2C slave instance.
*/
extern i2c_t *i2c_create(i2c_gpio_group_t gpios, uint16_t delay_ticks);
/**
* @brief Creates an I2C slave instance with DMA support.
* @param i2c Pointer to the I2C peripheral.
* @param dma Pointer to the DMA peripheral.
* @param rxsize Size of the receive buffer.
* @param dma_rx_channel DMA channel used for receiving data.
* @param dma_rx_cb Callback function called when receive DMA is completed.
* @param txsize Size of the transmit buffer.
* @param dma_tx_channel DMA channel used for transmitting data.
* @param dma_tx_cb Callback function called when transmit DMA is completed.
* @return A pointer to the created I2C slave instance.
*/
extern i2c_t *i2c_create_dma(I2C_TypeDef *i2c, DMA_TypeDef *dma, uint16_t rxsize, uint32_t dma_rx_channel,
i2cs_dma_callback *dma_rx_cb, uint16_t txsize, uint32_t dma_tx_channel, i2cs_dma_callback *dma_tx_cb);
/**
* @brief Sets the write and read addresses for the I2C slave instance with DMA support.
* @param handle Pointer to the I2C slave instance.
* @param w_address 7-bit write address.
* @param r_address 7-bit read address.
*/
extern void i2c_dma_set_address(i2c_t *handle, uint8_t w_address, uint8_t r_address);
/**
* @brief Frees the resources used by the I2C slave instance.
* @param handle Pointer to the I2C slave instance.
*/
extern void i2c_free(i2c_t *handle);
/**
* @brief Callback function called when an I2C event occurs.
* @param handle Pointer to the I2C slave instance.
*/
extern void i2c_ev_callback(i2c_t *handle);
/**
* @brief Callback function called when an I2C DMA event occurs.
* @param handle Pointer to the I2C slave instance.
*/
extern void i2c_dma_callback(i2c_t *handle);
#endif ///< __I2CS_H__

View File

@ -1,39 +0,0 @@
#include "iwdgs.h"
/**
* @brief CPU复位是否是看门狗复位
* @return {BOOL}
* @note
*/
BOOL check_watchdog_reset(void)
{
if (LL_RCC_IsActiveFlag_IWDGRST() == SET) // cpu is reset due to iwdg
{
LL_RCC_ClearResetFlags(); // clear flag
return TRUE;
}
else
{
return FALSE;
}
}
/**
* @brief
* @return {*}
* @note
*/
void debug_freeze_watchdog(void)
{
LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP);
}
/**
* @brief
* @return {*}
* @note
*/
void debug_unfreeze_watchdog(void)
{
LL_DBGMCU_APB1_GRP1_UnFreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP);
}

View File

@ -1,45 +0,0 @@
/**
* @file iwdgs.h
* @brief This file contains the declaration of the Independent Watchdog (IWDG) module.
*
* The Independent Watchdog (IWDG) is a hardware module in STM32 microcontrollers that provides a mechanism for system reset in case of software failures or malfunctions. This file declares the functions and constants related to the IWDG module.
*
* @author xxx
* @date 2023-12-27 14:44:03
* @version 1.0
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __IWDGS_H__
#define __IWDGS_H__
#include "main.h"
#include "lib.h"
/**
* @brief Reloads the watchdog counter.
*
* This macro is used to reload the watchdog counter, preventing the system from resetting.
*/
#define WATCHDOG_RESET() LL_IWDG_ReloadCounter(IWDG)
/**
* @brief Checks if the system has been reset by the watchdog.
*
* @return BOOL Returns TRUE if the system has been reset by the watchdog, FALSE otherwise.
*/
extern BOOL check_watchdog_reset(void);
/**
* @brief Freezes the watchdog timer for debugging purposes.
*
* This function freezes the watchdog timer, allowing for debugging without triggering a watchdog reset.
*/
extern void debug_freeze_watchdog(void);
/**
* @brief Unfreezes the watchdog timer after debugging.
*
* This function unfreezes the watchdog timer, allowing it to resume normal operation after debugging.
*/
extern void debug_unfreeze_watchdog(void);
#endif

View File

@ -1,90 +0,0 @@
/**
* @file pwms.h
* @brief Header file for PWMs module.
*
* This file contains the declarations and documentation for the PWMs module.
*
* @author xxx
* @date 2023-12-27 14:44:03
* @version 1.0
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __PWMS_H__
#define __PWMS_H__
#include "lib.h"
/**
* @brief Starts the PWM for a specific channel
* @param TIMx: TIM instance
* @param CHx: Channel to be started
* @retval None
*/
#define PWM_START(TIMx, CHx) \
do \
{ \
LL_TIM_EnableCounter(TIMx); \
LL_TIM_CC_EnableChannel(TIMx, CHx); \
} while (__LINE__ == -1)
/**
* @brief Stops the PWM for a specific channel
* @param TIMx: TIM instance
* @param CHx: Channel to be stopped
* @retval None
*/
#define PWM_STOP(TIMx, CHx) \
do \
{ \
LL_TIM_DisableCounter(TIMx); \
LL_TIM_CC_DisableChannel(TIMx, CHx); \
} while (__LINE__ == -1)
/**
* @brief Sets the PWM frequency
* @param TIMx: TIM instance
* @param CHx: Channel to be set
* @param COMPARE: Compare value
* @retval None
*/
static inline void PWM_SET_COMPARE(TIM_TypeDef *TIMx, uint32_t CHx, uint16_t COMPARE)
{
switch (CHx)
{
case LL_TIM_CHANNEL_CH1:
LL_TIM_OC_SetCompareCH1(TIMx, COMPARE);
break;
case LL_TIM_CHANNEL_CH2:
LL_TIM_OC_SetCompareCH2(TIMx, COMPARE);
break;
case LL_TIM_CHANNEL_CH3:
LL_TIM_OC_SetCompareCH3(TIMx, COMPARE);
break;
case LL_TIM_CHANNEL_CH4:
LL_TIM_OC_SetCompareCH4(TIMx, COMPARE);
break;
default:
break;
}
}
/**
* @brief PWM占空比
*
* TIMx的指定通道CHx的PWM占空比
*
* @param TIMx TIM1TIM2等
* @param CHx TIM_CHANNEL_1TIM_CHANNEL_2等
* @param DUTY 0100
*/
static inline void PWM_SET_DUTY(TIM_TypeDef *TIMx, uint32_t CHx, uint16_t DUTY)
{
PWM_SET_COMPARE(TIMx, CHx, DUTY * LL_TIM_GetAutoReload(TIMx) / 100);
}
// 获取当前频率
static inline uint32_t PWM_GET_FREQ(TIM_TypeDef *TIMx)
{
return SystemCoreClock / (LL_TIM_GetPrescaler(TIMx) + 1) / (LL_TIM_GetAutoReload(TIMx) + 1);
}
#endif ///< __PWMS_H__

View File

@ -1 +0,0 @@

View File

@ -1,306 +1,210 @@
#include "spis.h"
#include "delay.h"
#define SPI_TIMEOUT 2000
/**
* @brief SPI延时函数
* @param {spi_t} *handle SPI总线设备句柄
* @return {*}
* @note: SPI总线的延时handle不为空handle的delay_ticks的值NOP指令
*/
static inline void spi_delay(spi_t *handle)
{
uint16_t count = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
count = handle->delay_ticks;
if (count > 0)
{
while (count--)
{
__NOP();
}
}
}
#define CMD_RDSR 0x05 /*!< Read Status Register instruction */
#define CMD_WRSR 0x01 /*!< Write Status Register instruction */
#define CMD_WREN 0x06 /*!< Write enable instruction */
#define CMD_WRDI 0x04 /*!< Write disable instruction */
#define CMD_READ 0x03 /*!< Read from Memory instruction */
#define CMD_WRITE 0x02 /*!< Write to Memory instruction */
#define DUMMY_BYTE 0xA5 ///< 虚拟字节
static inline void spi_delay(spi_t *handle); // 延时函数
static inline void spi_rdy_high(spi_t *handle); // RDY高电平
static inline void spi_rdy_low(spi_t *handle); // RDY低电平
static inline void spi_cs_high(spi_t *handle); // CS高电平
static inline void spi_cs_low(spi_t *handle); // CS低电平
static inline void spi_mosi_high(spi_t *handle); // MOSI高电平
static inline void spi_mosi_low(spi_t *handle); // MOSI低电平
static inline void spi_sck_high(spi_t *handle); // SCK高电平
static inline void spi_sck_low(spi_t *handle); // SCK低电平
static inline uint8_t spi_miso_read(spi_t *handle); // 读取MISO电平
static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data); // 读写一个字节
static void spi_reset(spi_t *handle); // 复位
static BOOL spi_write(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); // 写数据
static BOOL spi_read(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); // 读数据
static void spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写寄存器
static uint8_t spi_read_reg(spi_t *handle, uint8_t reg); // 读寄存器
static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi); // 硬件SPI
static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // DMA SPI
static void _spi_dma_callback(spi_t *handle); // DMA发送完成回调
static BOOL _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length); // DMA发送数据
static uint8_t _read_drdy(spi_t *handle); // 读取DRDY电平
static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 写多个寄存器
static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 读多个寄存器
static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写单个寄存器
static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg); // 读单个寄存器
static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd); // 写命令
static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len); // 写数据
// static void spi_reset(spi_t *handle)
// {
// DBG_ASSERT(handle != NULL __DBG_LINE);
// handle->gpios.cs->reset(*handle->gpios.cs);
// delay_tick(10);
// handle->gpios.cs->set(*handle->gpios.cs);
// delay_tick(10);
// }
/**
* @brief SPI总线设备
* @param {spi_type_e} spi_type SPI总线的类型
* @param {spi_gpio_group_t} gpios SPI总线的GPIO配置
* @param {uint16_t} delay_ticks SPI总线的延时参数
* @return {*} SPI总线设备句柄
* @note: SPI总线设备spi_type在有效的范围内spi_t结构体gpios和delay_ticks的内存地址复制到handle结构体中spi_type的值handle结构体
* @brief SPIRST
* @param {spi_id_e} id
* @return {*}
*/
spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks)
static inline void spi_rdy_high(spi_t *handle)
{
DBG_ASSERT(spi_type < SPI_TYPE_MAX __DBG_LINE);
spi_t *handle = (spi_t *)osel_mem_alloc(sizeof(spi_t));
osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(spi_gpio_group_t));
handle->delay_ticks = delay_ticks;
handle->spi_type = spi_type;
handle->simualte_gpio = TRUE;
handle->interface.hardware_enable = _hardware_enable;
handle->interface.dma_enable = _dma_enable;
handle->interface.spi_dma_send = _spi_dma_send;
handle->interface.spi_dma_callback = _spi_dma_callback;
if (spi_type == SPI_TYPE_NORMAL)
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.rdy != NULL)
{
handle->interface.u.normal.write_reg = _spi_write_reg;
handle->interface.u.normal.read_reg = _spi_read_reg;
handle->interface.u.normal.write_regs = _write_regs;
handle->interface.u.normal.read_regs = _read_regs;
handle->interface.u.normal.read_drdy = _read_drdy;
handle->interface.u.normal.spi_send = spi_read_write_byte;
handle->interface.u.normal.spi_reset = spi_reset;
handle->interface.u.normal.spi_read = spi_read;
handle->interface.u.normal.spi_write = spi_write;
handle->interface.u.normal.spi_write_reg = spi_write_reg;
handle->interface.u.normal.spi_read_reg = spi_read_reg;
handle->cfg.cmd_rdsr = CMD_RDSR;
handle->cfg.cmd_wrsr = CMD_WRSR;
handle->cfg.cmd_wren = CMD_WREN;
handle->cfg.cmd_wrdi = CMD_WRDI;
handle->cfg.cmd_read = CMD_READ;
handle->cfg.cmd_write = CMD_WRITE;
handle->cfg.dummy_byte = DUMMY_BYTE;
handle->cfg.continuous_write = FALSE;
handle->gpios.rdy->set(*handle->gpios.rdy);
}
else if (spi_type == SPI_TYPE_LCD)
}
/**
* @brief SPIRST
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_rdy_low(spi_t *handle)
{
handle->interface.u.lcd.write_cmd = _spi_write_cmd;
handle->interface.u.lcd.write_data = _spi_write_data;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.rdy != NULL)
{
handle->gpios.rdy->reset(*handle->gpios.rdy);
}
}
/**
* @brief SPICS
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.cs != NULL)
{
handle->gpios.cs->set(*handle->gpios.cs);
spi_delay(handle);
}
}
/**
* @brief SPICS
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.cs != NULL)
{
handle->gpios.cs->reset(*handle->gpios.cs);
spi_delay(handle);
}
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.mosi != NULL)
{
handle->gpios.mosi->set(*handle->gpios.mosi);
}
}
/**
* @brief SPIMOSI
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.mosi != NULL)
{
handle->gpios.mosi->reset(*handle->gpios.mosi);
}
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.sck != NULL)
{
handle->gpios.sck->set(*handle->gpios.sck);
}
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->gpios.sck != NULL)
{
handle->gpios.sck->reset(*handle->gpios.sck);
}
}
/**
* @brief SPIMISO
* @param {spi_id_e} id
* @return {*}
*/
static inline uint8_t spi_miso_read(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
return handle->gpios.miso->read(*handle->gpios.miso);
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} tx_data
* @return {*}
* @note: SPI总线的读写一个字节handle不为空handle的simulate_gpio的值SPI或硬件SPI
*/
static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data)
{
uint8_t bit_ctr;
uint8_t rdata = 0xff;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->simualte_gpio == TRUE)
{
// 模拟SPI
for (bit_ctr = 0; bit_ctr < 8; bit_ctr++)
{
spi_sck_low(handle);
spi_delay(handle);
if (tx_data & 0x80)
spi_mosi_high(handle);
else
spi_mosi_low(handle);
spi_delay(handle);
spi_sck_high(handle);
spi_delay(handle);
tx_data = (tx_data << 1);
rdata = rdata << 1;
if (NULL != handle->gpios.miso->port)
{
if (spi_miso_read(handle) == 1)
rdata += 0x01;
}
}
return (rdata);
}
else
{
DBG_ASSERT(FALSE __DBG_LINE);
}
return handle;
}
uint8_t rx_data = 0;
void spi_free(spi_t *handle)
if (HAL_SPI_TransmitReceive(handle->spi, &tx_data, &rx_data, 1, SPI_TIMEOUT) != HAL_OK)
{
if (handle != NULL)
{
gpio_free(handle->gpios.cs);
gpio_free(handle->gpios.rdy);
gpio_free(handle->gpios.rst);
gpio_free(handle->gpios.mosi);
gpio_free(handle->gpios.miso);
gpio_free(handle->gpios.sck);
osel_mem_free(handle);
// 处理错误
return 0xff;
}
return rx_data;
}
/**
* @brief SPI模式
* @param {spi_t} *handle SPI总线设备句柄
* @param {SPI_TypeDef} *spi SPI总线的寄存器结构体指针
* @return {*}
* @note: SPI总线的硬件模式handle不为空spix不为空handle的simulate_gpio设置为FALSEspix的地址赋值给handle->spixSPI_ENABLE函数启用SPI总线
*/
static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(spi != NULL __DBG_LINE);
handle->simualte_gpio = FALSE;
handle->spi = spi;
SPI_ENABLE(spi);
}
static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(dma != NULL __DBG_LINE);
DBG_ASSERT(handle->spi != NULL __DBG_LINE);
handle->dma = dma;
handle->dma_rx_channel = dma_rx_channel;
handle->dma_tx_channel = dma_tx_channel;
handle->rx_dma_ok = TRUE;
handle->tx_dma_ok = TRUE;
if (dma_rx_cb != NULL)
{
handle->dma_rx_cb = dma_rx_cb;
}
if (dma_tx_cb != NULL)
{
handle->dma_tx_cb = dma_tx_cb;
}
LL_DMA_SetPeriphAddress(dma, dma_tx_channel, LL_SPI_DMA_GetRegAddr(handle->spi));
LL_DMA_ClearFlag_GI1(dma);
LL_DMA_ClearFlag_TC1(dma);
LL_DMA_EnableIT_TC(dma, dma_tx_channel);
LL_SPI_EnableDMAReq_TX(handle->spi);
LL_SPI_Enable(handle->spi);
}
static void _spi_dma_callback(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->dma_tx_cb != NULL)
{
handle->dma_tx_cb(handle);
}
if (handle->dma_rx_cb != NULL)
{
handle->dma_rx_cb(handle);
}
}
static BOOL _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length)
{
handle->tx_dma_ok = FALSE;
LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel);
LL_DMA_SetMemoryAddress(handle->dma, handle->dma_tx_channel, (uint32_t)data);
LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, length);
LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel);
uint16_t i = 0;
while (handle->tx_dma_ok == FALSE)
{
i++;
if (i > 50000)
{
__NOP();
break;
}
}
return handle->tx_dma_ok == TRUE ? TRUE : FALSE;
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @return {uint8_t}
* @note: SPI总线的数据准备好信号handle不为空handle的gpios.rdy的读取结果
*/
static uint8_t _read_drdy(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
return handle->gpios.rdy->read(*handle->gpios.rdy);
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg
* @param {uint8_t} data
* @return {*}
* @note: SPI总线的单个寄存器handle不为空data不为空SPI总线的CS引脚设置为低电平SPI总线的CS引脚设置为高电平
*/
static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(len != 0 __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg); // 发送寄存器号
while (len--)
{
spi_read_write_byte(handle, *data); // 写入寄存器的值
data++;
}
spi_cs_high(handle);
return status;
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg
* @param {uint8_t} *data
* @param {uint8_t} len
* @return {uint8_t}
* @note: SPI总线的多个寄存器handle不为空data不为空len大于0SPI总线的CS引脚设置为低电平SPI总线的CS引脚设置为高电平
*/
static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(len != 0 __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg);
for (uint8_t i = 0; i < len; i++)
{
data[i] = spi_read_write_byte(handle, 0xff); // 读出数据
}
spi_cs_high(handle);
return status;
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg
* @param {uint8_t} data
* @return {*}
* @note: SPI总线的单个寄存器handle不为空SPI总线的CS引脚设置为低电平SPI总线的CS引脚设置为高电平
*/
static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data)
{
uint8_t status = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_cs_low(handle);
status = spi_read_write_byte(handle, reg); // 发送寄存器号
spi_read_write_byte(handle, data); // 写入寄存器的值
spi_cs_high(handle);
return status;
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} reg
* @return {*}
* @note: SPI总线的单个寄存器handle不为空SPI总线的CS引脚设置为低电平SPI总线的CS引脚设置为高电平
*/
static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg)
{
uint8_t reg_val = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
spi_cs_low(handle);
spi_read_write_byte(handle, reg); // 发送寄存器号
reg_val = spi_read_write_byte(handle, 0);
spi_cs_high(handle);
return reg_val;
}
/**
@ -346,466 +250,41 @@ static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len)
}
/**
* @brief SPI延时函数
* @brief SPI模式
* @param {spi_t} *handle SPI总线设备句柄
* @param {SPI_HandleTypeDef} *spi SPI总线的寄存器结构体指针
* @return {*}
* @note: SPI总线的延时handle不为空handle的delay_ticks的值NOP指令
* @note: SPI总线的硬件模式handle不为空spix不为空handle的simulate_gpio设置为FALSEspix的地址赋值给handle->spixSPI_ENABLE函数启用SPI总线
*/
static inline void spi_delay(spi_t *handle)
static void _hardware_enable(spi_t *handle, SPI_HandleTypeDef *spi)
{
uint16_t count = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
count = handle->delay_ticks;
if (count > 0)
{
while (count--)
{
__NOP();
}
}
DBG_ASSERT(spi != NULL __DBG_LINE);
handle->simualte_gpio = FALSE;
handle->spi = spi;
__HAL_SPI_ENABLE(handle->spi);
}
static BOOL spi_wait_flag(spi_t *handle, uint32_t flag, uint32_t timeout)
spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks)
{
uint32_t i = 0;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (flag == LL_SPI_SR_TXE)
DBG_ASSERT(spi_type < SPI_TYPE_MAX __DBG_LINE);
spi_t *handle = (spi_t *)osel_mem_alloc(sizeof(spi_t));
osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(spi_gpio_group_t));
handle->delay_ticks = delay_ticks;
handle->spi_type = spi_type;
handle->interface.hardware_enable = _hardware_enable;
if (spi_type == SPI_TYPE_NORMAL)
{
while (LL_SPI_IsActiveFlag_TXE(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
else if (spi_type == SPI_TYPE_LCD)
{
__NOP();
}
}
}
else if (flag == LL_SPI_SR_RXNE)
{
while (LL_SPI_IsActiveFlag_RXNE(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
{
__NOP();
}
}
}
else if (flag == LL_SPI_SR_BSY)
{
while (LL_SPI_IsActiveFlag_BSY(handle->spi) == 0)
{
if (i++ > timeout)
{
return FALSE; // 超时
}
else
{
__NOP();
}
}
handle->interface.u.lcd.write_cmd = _spi_write_cmd;
handle->interface.u.lcd.write_data = _spi_write_data;
}
else
{
DBG_ASSERT(FALSE __DBG_LINE);
}
return TRUE; // 成功
}
/**
* @brief
* @param {spi_t} *handle SPI总线设备句柄
* @param {uint8_t} tx_data
* @return {*}
* @note: SPI总线的读写一个字节handle不为空handle的simulate_gpio的值SPI或硬件SPI
*/
static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data)
{
uint8_t bit_ctr;
uint8_t rdata = 0xff;
DBG_ASSERT(handle != NULL __DBG_LINE);
if (handle->simualte_gpio == TRUE)
{
// 模拟SPI
for (bit_ctr = 0; bit_ctr < 8; bit_ctr++)
{
spi_sck_low(handle);
spi_delay(handle);
if (tx_data & 0x80)
spi_mosi_high(handle);
else
spi_mosi_low(handle);
spi_delay(handle);
spi_sck_high(handle);
spi_delay(handle);
tx_data = (tx_data << 1);
rdata = rdata << 1;
if (NULL != handle->gpios.miso->port)
{
if (spi_miso_read(handle) == 1)
rdata += 0x01;
}
}
return (rdata);
}
else
{
LL_SPI_TransmitData8(handle->spi, tx_data);
if (spi_wait_flag(handle, LL_SPI_SR_RXNE, SPI_TIMEOUT) == FALSE)
{
return 0xff;
}
rdata = LL_SPI_ReceiveData8(handle->spi);
return rdata;
}
}
static void _write_enable(spi_t *handle)
{
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_wren);
handle->gpios.cs->set(*handle->gpios.cs);
}
static void _write_disable(spi_t *handle)
{
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_wrdi);
handle->gpios.cs->set(*handle->gpios.cs);
}
static uint8_t _read_status(spi_t *handle)
{
uint8_t data;
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_rdsr);
data = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte);
handle->gpios.cs->set(*handle->gpios.cs);
return data;
}
static void _ready(spi_t *handle)
{
uint16_t count = 0;
while (_read_status(handle) & 0x01)
{
if (count++ > 20000)
{
break;
}
else
{
__NOP();
}
}
}
static BOOL spi_write(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length)
{
BOOL ret = TRUE;
uint8_t cnt = 0; // 返回值检查
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(length > 0 __DBG_LINE);
DBG_ASSERT(handle->cfg.page_size > 0 __DBG_LINE);
uint32_t page_size = handle->cfg.page_size;
_write_enable(handle); // 写入使能命令
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_write); // 发送写入命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr);
if (cnt == 0)
{
return FALSE;
}
}
while (length--)
{
cnt = handle->interface.u.normal.spi_send(handle, *data); // 发送一个字节数据
if (cnt == 0)
{
return FALSE;
}
data++;
if (handle->cfg.continuous_write == FALSE)
{
write_addr++;
if (((write_addr % page_size) == 0) && (length > 0))
{
// 一页写完
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
_ready(handle);
_write_enable(handle); // 写入使能命令
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_write); // 发送写入命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, write_addr);
if (cnt == 0)
{
return FALSE;
}
}
}
}
}
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
_ready(handle);
_write_disable(handle);
return ret;
}
static void spi_write_reg(spi_t *handle, uint8_t reg, uint8_t value)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
_write_enable(handle); // 写入使能命令
handle->interface.u.normal.write_reg(handle, reg, value);
_ready(handle);
_write_disable(handle); // 写入禁止命令
}
static uint8_t spi_read_reg(spi_t *handle, uint8_t reg)
{
uint8_t data;
handle->gpios.cs->reset(*handle->gpios.cs);
handle->interface.u.normal.spi_send(handle, reg);
data = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte);
handle->gpios.cs->set(*handle->gpios.cs);
return data;
}
static BOOL spi_read(spi_t *handle, uint32_t read_addr, uint8_t *data, uint16_t length)
{
BOOL ret = TRUE;
uint8_t cnt = 0; // 返回值检查
DBG_ASSERT(handle != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(length > 0 __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs); // 设置CS引脚为低电平准备开始SPI通信
cnt = handle->interface.u.normal.spi_send(handle, handle->cfg.cmd_read); // 发送读取命令
if (cnt == 0)
{
return FALSE;
}
if (handle->cfg.address_bytes == 2)
{
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 8); // 发送高位地址
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr); // 发送低位地址
if (cnt == 0)
{
return FALSE;
}
}
else
{
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 16);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr >> 8);
if (cnt == 0)
{
return FALSE;
}
cnt = handle->interface.u.normal.spi_send(handle, read_addr);
if (cnt == 0)
{
return FALSE;
}
}
for (uint16_t i = 0; i < length; i++) // 循环读取数据
{
data[i] = handle->interface.u.normal.spi_send(handle, handle->cfg.dummy_byte); // 发送空字节,读取实际数据
}
handle->gpios.cs->set(*handle->gpios.cs); // 设置CS引脚为高电平完成SPI通信
return ret;
}
static void spi_reset(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs);
delay_tick(10);
handle->gpios.cs->set(*handle->gpios.cs);
delay_tick(10);
}
/**
* @brief SPIRST
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_rdy_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.rdy->set(*handle->gpios.rdy);
}
/**
* @brief SPIRST
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_rdy_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.rdy->reset(*handle->gpios.rdy);
}
/**
* @brief SPICS
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->set(*handle->gpios.cs);
spi_delay(handle);
}
/**
* @brief SPICS
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_cs_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.cs->reset(*handle->gpios.cs);
spi_delay(handle);
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.mosi->set(*handle->gpios.mosi);
}
/**
* @brief SPIMOSI
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_mosi_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.mosi->reset(*handle->gpios.mosi);
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_high(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.sck->set(*handle->gpios.sck);
}
/**
* @brief SPISCK
* @param {spi_id_e} id
* @return {*}
*/
static inline void spi_sck_low(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
handle->gpios.sck->reset(*handle->gpios.sck);
}
/**
* @brief SPIMISO
* @param {spi_id_e} id
* @return {*}
*/
static inline uint8_t spi_miso_read(spi_t *handle)
{
DBG_ASSERT(handle != NULL __DBG_LINE);
return handle->gpios.miso->read(*handle->gpios.miso);
return handle;
}

View File

@ -1,30 +1,10 @@
/**
* @file spis.h
* @brief SPI驱动, SPI设备的读写操作
*
* This file contains the SPI driver used for reading and writing operations on SPI devices.
*
* @date 2023-08-01
* @version 1.0
*
* @note This file is part of the STM32 controller-v2 project.
*
*/
#ifndef __SPIS_H__
#define __SPIS_H__
#include "lib.h"
#include "gpios.h"
#define SPI_ENABLE(SPIX) LL_SPI_Enable(SPIX)
typedef struct SPIS spi_t;
typedef void spis_dma_callback(spi_t *handle);
/**
* @brief SPI type enumeration
*/
typedef enum
{
SPI_TYPE_NORMAL = 0, ///< SPI1:NORMAL
@ -43,31 +23,9 @@ typedef struct
gpio_t *cs; ///< CS
gpio_t *rst; ///< RST
gpio_t *rdy; ///< DRDY
gpio_t *dc; ///< DC
} spi_gpio_group_t;
/**
* @brief SPI normal interface structure
*/
typedef struct
{
uint8_t (*write_reg)(spi_t *handle, uint8_t reg, uint8_t data); ///< Write a single register via SPI
uint8_t (*read_reg)(spi_t *handle, uint8_t reg); ///< Read the value of a single register via SPI
uint8_t (*read_drdy)(spi_t *handle); ///< Get the value of the SPI DRDY pin
uint8_t (*write_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); ///< Write multiple registers via SPI
uint8_t (*read_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); ///< Read multiple registers via SPI
uint8_t (*spi_send)(spi_t *handle, uint8_t data); ///< Send data via SPI
void (*spi_reset)(spi_t *handle); ///< Reset SPI
BOOL(*spi_write)
(spi_t *handle, uint32_t write_addr, uint8_t *data, uint16_t length); ///< Write data via SPI
BOOL(*spi_read)
(spi_t *handle, uint32_t read_addr, uint8_t *data, uint16_t length); ///< Read data via SPI
void (*spi_write_reg)(spi_t *handle, uint8_t reg, uint8_t data); ///< Write a single register via SPI
uint8_t (*spi_read_reg)(spi_t *handle, uint8_t reg); ///< Read a single register via SPI
} spi_normal_interface_t;
/**
* @brief SPI LCD interface structure
*/
@ -77,72 +35,30 @@ typedef struct
uint8_t (*write_data)(spi_t *handle, uint8_t *data, uint16_t len); ///< Write data via SPI
} spi_lcd_interface_t;
/**
* @brief SPI interface structure
*/
typedef struct
{
union
{
spi_normal_interface_t normal;
// spi_normal_interface_t normal;
spi_lcd_interface_t lcd;
} u;
void (*hardware_enable)(spi_t *handle, SPI_TypeDef *spi); ///< Enable hardware SPI
void (*dma_enable)(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); ///< Enable DMA SPI
void (*spi_dma_callback)(spi_t *spi); ///< DMA send completion callback
BOOL(*spi_dma_send)
(spi_t *handle, uint8_t *data, uint16_t length); ///< DMA send
void (*hardware_enable)(spi_t *handle, SPI_HandleTypeDef *spi); ///< Enable hardware SPI
// void (*dma_enable)(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb,
// uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); ///< Enable DMA SPI
// void (*spi_dma_callback)(spi_t *spi); ///< DMA send completion callback
// BOOL(*spi_dma_send)
// (spi_t *handle, uint8_t *data, uint16_t length); ///< DMA send
} spi_interface_t;
/**
* @brief SPI structure
*/
typedef struct SPIS spi_t;
/**
* @brief SPI DMA callback function
*/
typedef void spis_dma_callback(spi_t *handle);
typedef struct
{
// CMD
uint8_t cmd_rdsr; ///< Read Status Register instruction
uint8_t cmd_wrsr; ///< Write Status Register instruction
uint8_t cmd_wren; ///< Write enable instruction
uint8_t cmd_wrdi; ///< Write disable instruction
uint8_t cmd_read; ///< Read from Memory instruction
uint8_t cmd_write; ///< Write to Memory instruction
uint8_t dummy_byte; ///< Dummy byte
uint8_t address_bytes;
uint32_t page_size;
uint32_t total_size;
uint8_t ticks; ///< Delay in NOP ticks
BOOL continuous_write; ///< Continuous write
} spi_normal_config_t;
struct SPIS
{
spi_type_e spi_type; ///< SPI type
uint16_t delay_ticks; ///< Delay in NOP ticks
spi_gpio_group_t gpios; ///< SPI GPIOs
spi_interface_t interface; ///< SPI interface
SPI_TypeDef *spi; ///< SPI peripheral
BOOL simualte_gpio; ///< Simulate GPIO
spi_normal_config_t cfg; ///< Normal SPI configuration
///< DMA
DMA_TypeDef *dma; ///< External setting
uint32_t dma_rx_channel; ///< External setting
uint32_t dma_tx_channel; ///< External setting
__IO BOOL rx_dma_ok;
__IO BOOL tx_dma_ok;
spis_dma_callback *dma_rx_cb; ///< DMA receive callback function
spis_dma_callback *dma_tx_cb; ///< DMA send callback function
SPI_HandleTypeDef *spi; ///< SPI handle
void *params; ///< 扩展参数
spi_interface_t interface; ///< SPI interface
spi_type_e spi_type; ///< SPI type
BOOL simualte_gpio; ///< Simulate GPIO
};
/**
@ -155,11 +71,4 @@ struct SPIS
*/
extern spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks);
/**
* @brief Free the SPI instance
*
* @param spi The SPI instance to free
*/
extern void spi_free(spi_t *spi);
#endif ///< __SPIS_H__

View File

@ -1 +0,0 @@
#include "tims.h"

View File

@ -1,128 +0,0 @@
/**
* @file tims.h
* @brief Header file for TIMS module.
*
* This file contains the declarations and definitions for the TIMS module.
* TIMS stands for Timer System and provides functionality related to timers.
*
* @author xxx
* @date 2024-01-16 22:23:43
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
#ifndef __TIMS_H__
#define __TIMS_H__
#include "lib.h"
/**
Timer overflow time calculation formula
Tout = ((ARR + 1)*(PSC + 1)) / Tclk
Given Tclk as 84MHz, we need Tout to be 200ms or 200000us. Let's assume PSC is 839, substituting it into the formula gives ARR = 19999.
With these calculated values, both ARR and PSC are within the range of 0 to 65535, so we can use this parameter set.
*/
#define ENABLE_TIM_COUNT(TIMx) \
do \
{ \
LL_TIM_EnableCounter(TIMx); \
} while (__LINE__ == -1);
#define RESET_TIM_COUNT(TIMx) \
do \
{ \
LL_TIM_DisableCounter(TIMx); \
LL_TIM_SetCounter(TIMx, 0); \
LL_TIM_EnableCounter(TIMx); \
} while (__LINE__ == -1);
/**
* @brief Enables the specified TIMx.
* @param TIMx TIM instance.
*/
#define ENABLE_TIM(TIMx) \
do \
{ \
LL_TIM_EnableCounter(TIMx); \
LL_TIM_EnableIT_UPDATE(TIMx); \
} while (__LINE__ == -1);
/**
* @brief Checks if the specified TIMx is enabled.
* @param TIMx TIM instance.
* @retval The new state of TIMx (1 or 0).
*/
#define IS_ENABLE_TIM(TIMx) LL_TIM_IsEnabledIT_UPDATE(TIMx)
/**
* @brief Disables the specified TIMx.
* @param TIMx TIM instance.
*/
#define DISABLE_TIM(TIMx) \
do \
{ \
LL_TIM_DisableCounter(TIMx); \
LL_TIM_DisableIT_UPDATE(TIMx); \
} while (__LINE__ == -1);
#define ENABLE_TIM_ARR_RELOAD(TIMx) LL_TIM_EnableARRPreload(TIMx)
#define DISABLE_TIM_ARR_RELOAD(TIMx) LL_TIM_DisableARRPreload(TIMx)
/**
* @brief Checks if the specified TIMx interrupt flag is set.
* @param TIMx TIM instance.
* @retval The new state of the specified TIMx interrupt flag (1 or 0).
*/
#define IS_TIM_IT_FLAG(TIMx) (LL_TIM_IsActiveFlag_UPDATE(TIMx) == 1)
/**
* @brief TIM interrupt handler.
* @param TIMx TIM instance.
*/
#define TIM_IRQ_HANDLER(TIMx) \
do \
{ \
if (LL_TIM_IsActiveFlag_CC1(TIMx) == SET) \
{ \
if (LL_TIM_IsEnabledIT_CC1(TIMx) == SET) \
{ \
LL_TIM_ClearFlag_CC1(TIMx); \
} \
} \
if (LL_TIM_IsActiveFlag_CC2(TIMx) == SET) \
{ \
if (LL_TIM_IsEnabledIT_CC2(TIMx) == SET) \
{ \
LL_TIM_ClearFlag_CC2(TIMx); \
} \
} \
if (LL_TIM_IsActiveFlag_CC3(TIMx) == SET) \
{ \
if (LL_TIM_IsEnabledIT_CC3(TIMx) == SET) \
{ \
LL_TIM_ClearFlag_CC3(TIMx); \
} \
} \
if (LL_TIM_IsActiveFlag_CC4(TIMx) == SET) \
{ \
if (LL_TIM_IsEnabledIT_CC4(TIMx) == SET) \
{ \
LL_TIM_ClearFlag_CC4(TIMx); \
} \
} \
if (LL_TIM_IsActiveFlag_UPDATE(TIMx) == SET) \
{ \
if (LL_TIM_IsEnabledIT_UPDATE(TIMx) == SET) \
{ \
LL_TIM_ClearFlag_UPDATE(TIMx); \
} \
} \
} while (__LINE__ == -1)
/**
* @brief
*
* TIMx的周期时间
*
* @param TIMx
*
* @return
*/
#define TIM_CYCLE(TIMx) ((LL_TIM_GetAutoReload(TIMx) + 1) * 0.1)
#endif ///< __TIMS_H__

View File

@ -1,486 +0,0 @@
/*
* @Author:
* @Date: 2023-07-31 11:47:35
* @LastEditors: xxx
* @LastEditTime: 2023-08-25 15:30:33
* @Description: LL库的串口驱动
* email:
* Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "uarts.h"
#include "dma.h"
// 清理接收中断错误标志
static void uart_clear_error(uart_t *uart)
{
if (uart == NULL)
{
return;
}
uart->rx_error_count = 0;
if (uart->rx_err_en == TRUE && uart->rx_error != NULL)
{
osel_memset((uint8_t *)uart->rx_error, 0, sizeof(uarts_interupt_error_t) * uart->rxsize);
}
}
/**
* @brief UART设备
* @param {USART_TypeDef} *huart USART总线设备句柄
* @param {BOOL} rx_dma_en DMA使能标志
* @param {uint16_t} rxsize
* @param {rx_interrupt_cb_t} rx_cb
* @param {BOOL} tx_dma_en DMA使能标志
* @param {uint16_t} txsize
* @param {tx_complete_cb_t} tx_complete_cb
* @return {*} UART设备指针
* @note: UART设备huart不为空UART设备指针
*/
uart_t *uart_create(USART_TypeDef *huart, BOOL rx_dma_en, uint16_t rxsize, rx_interupt_cb_t rx_cb,
BOOL tx_dma_en, uint16_t txsize, tx_complete_cb_t tx_complete_cb)
{
DBG_ASSERT(huart != NULL __DBG_LINE);
// 分配内存
uart_t *uart = (uart_t *)osel_mem_alloc(sizeof(uart_t));
DBG_ASSERT(uart != NULL __DBG_LINE);
uart->rx_interupt_timeout = TRUE; // 接收超时标志
uart->rx_interupt_cnt = 0; // 接收中断计数
// 设置接收回调函数
uart->rx_interupt_cb = rx_cb;
// 设置接收数据大小
uart->rxsize = rxsize;
// 设置发送完成回调函数
uart->tx_complete_cb = tx_complete_cb;
// 设置发送数据大小
uart->txsize = txsize;
// 如果接收大小大于0则分配内存
if (rxsize > 0)
{
uart->rxbuf = (uint8_t *)osel_mem_alloc(rxsize);
DBG_ASSERT(uart->rxbuf != NULL __DBG_LINE);
}
// 如果发送大小大于0则分配内存
if (txsize > 0)
{
uart->txbuf = (uint8_t *)osel_mem_alloc(txsize);
DBG_ASSERT(uart->txbuf != NULL __DBG_LINE);
}
// 设置接收DMA禁用
uart->rx_dma_en = rx_dma_en;
// 设置发送DMA禁用
uart->tx_dma_en = tx_dma_en;
// 设置huart
uart->huart = huart;
// 返回uart
return uart;
}
/**
* @brief 使UART接收
* @param {uart_t} *uart UART设备句柄
* @param {BOOL} rx_err_en 使,使
* @return {*}
* @note: 使UART设备的接收功能UART设备的接收DMA使能标志RX DMA并启用RX DMA通道UART设备的发送DMA使能标志TX DMA并启用TX DMA通道
*/
void uart_recv_en(uart_t *uart, BOOL rx_err_en)
{
if (FALSE == uart->rx_dma_en)
{
uart->rx_err_en = rx_err_en;
LL_USART_EnableIT_RXNE(uart->huart); // 使用接收中断处理
}
else
{
uart->rx_err_en = FALSE;
LL_USART_ClearFlag_IDLE(uart->huart);
// 配置RX DMA
LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
// 配置RX DMA
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_rx_channel, LL_USART_DMA_GetRegAddr(uart->huart));
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_rx_channel, (uint32_t)uart->rxbuf);
LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize);
LL_DMA_EnableIT_TC(uart->dma, uart->dma_rx_channel);
LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel);
LL_USART_EnableDMAReq_RX(uart->huart);
LL_USART_EnableIT_IDLE(uart->huart);
// 配置TX DMA
LL_DMA_SetPeriphAddress(uart->dma, uart->dma_tx_channel, LL_USART_DMA_GetRegAddr(uart->huart));
// 配置内存地址
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf);
LL_DMA_EnableIT_TC(uart->dma, uart->dma_tx_channel);
LL_USART_EnableDMAReq_TX(uart->huart);
uart->tx_dma_ok = TRUE;
}
if (uart->rx_err_en == TRUE)
{
if (uart->rx_error == NULL)
{
uart->rx_error = (uarts_interupt_error_t *)osel_mem_alloc(sizeof(uarts_interupt_error_t) * uart->rxsize);
DBG_ASSERT(uart->rx_error != NULL __DBG_LINE);
}
LL_USART_EnableIT_PE(uart->huart); // 使能奇偶校验错误中断
// 使能帧错误中断
// 使能帧错误中断
// 使能溢出错误中断
// LL_USART_EnableIT_ERROR 可以使能上面3个中断
/**
* When set, Error Interrupt Enable Bit is enabling interrupt generation in case of a framing
* error, overrun error or noise flag (FE=1 or ORE=1 or NF=1 in the USARTx_ISR register).
*/
LL_USART_EnableIT_ERROR(uart->huart);
}
}
/**
* @brief UART设备资源
* @param {uart_t} *uart UART设备句柄
* @return {*}
* @note: UART设备的接收缓冲区UART设备本身
*/
void uart_free(uart_t *uart)
{
if (uart != NULL)
{
if (uart->rxbuf != NULL)
{
osel_mem_free(uart->rxbuf);
}
if (uart->rx_error != NULL)
{
osel_mem_free(uart->rx_error);
}
if (uart->txbuf != NULL)
{
osel_mem_free(uart->txbuf);
}
osel_mem_free(uart);
}
}
/**
* @brief
* @param {uart_t} *uart
* @param {uint32_t} baudrate
* @return {*}
* @note
*/
void uart_set_baudrate(USART_TypeDef *uart, uint32_t baudrate)
{
LL_USART_SetBaudRate(uart, SystemCoreClock, LL_USART_OVERSAMPLING_16);
}
/**
* @brief
* @param {uart_t} *uart UART设备句柄
* @param {uint8_t} *data
* @param {uint16_t} len
* @return {*}
* @note: UART设备的发送DMA使能标志TX DMA并启用TX DMA通道
*/
void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len)
{
DBG_ASSERT(uart != NULL __DBG_LINE);
DBG_ASSERT(data != NULL __DBG_LINE);
DBG_ASSERT(len > 0 __DBG_LINE);
uint16_t count = 0;
if (TRUE == uart->tx_dma_en)
{
uart->tx_dma_ok = FALSE;
osel_memcpy(uart->txbuf, data, len); // 拷贝数据到发送缓冲区
LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
// 配置 DMA 源地址
LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf);
// 配置数据长度
LL_DMA_SetDataLength(uart->dma, uart->dma_tx_channel, len);
// 使能DMA STREAM 也就是发送数据
LL_DMA_EnableChannel(uart->dma, uart->dma_tx_channel);
// 等待DMA发送完成
while (uart->tx_dma_ok == FALSE)
{
if (count++ >= 2000)
{
return;
}
}
}
else
{
count = 0;
for (uint16_t i = 0; i < len; i++)
{
count = 0;
LL_USART_TransmitData8(uart->huart, data[i]);
while (!LL_USART_IsActiveFlag_TXE(uart->huart))
{
if (count++ >= 0xFE)
{
count = 0;
continue;
}
}
}
while (!LL_USART_IsActiveFlag_TC(uart->huart))
{
if (count++ >= 0xFE)
{
count = 0;
continue;
}
}
if (uart->tx_complete_cb != NULL)
{
uart->tx_complete_cb();
}
LL_USART_ClearFlag_TC(uart->huart);
}
}
/**
* @brief UART接收超时定时器
*
* UART接收超时定时器触发时UART接收超时事件
*
* @param uart UART对象指针
*/
void uart_rx_timeout_timer(uart_t *uart)
{
// DBG_ASSERT(uart != NULL __DBG_LINE);
if (uart == NULL)
{
return;
}
if (uart->rx_dma_en == FALSE && uart->rx_interupt_timeout == FALSE) // 中断方式
{
if (uart->rx_interupt_cnt++ == RX_TIMEOUT_MSEC)
{
uart->rx_interupt_timeout = TRUE;
if (uart->rx_interupt_cb != NULL && uart->rx_index > 0)
{
uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index);
}
uart_data_storage_reset(uart);
}
}
}
/**
* @brief UART接收完成回调函数
*
* UART接收完成时调用此函数
*
* @param uart UART设备指针
*/
void uart_rx_cd_callback(uart_t *uart)
{
if (uart == NULL)
{
return;
}
if (uart->rx_cd_en == FALSE)
{
return;
}
if (uart->rx_dma_en == FALSE) // 中断方式
{
if (uart->rx_interupt_cb != NULL && uart->rx_index > 0)
{
uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index);
}
uart_data_storage_reset(uart);
}
}
/**
* @brief UART通信错误计数
*
* UART设备的接收错误计数
*
* @param uart UART设备指针
*
* @return uint16_t uart为NULL0
*/
uint16_t uart_get_error_count(uart_t *uart)
{
if (uart == NULL)
{
return 0;
}
return uart->rx_error_count;
}
/**
* @brief UART通信中的错误信息
*
* UART设备中获取接收错误信息和错误计数
*
* @param uart UART设备指针
* @param count
*
* @return NULL
*/
uarts_interupt_error_t *uart_get_error(uart_t *uart)
{
if (uart == NULL)
{
return NULL;
}
if (uart->rx_error_count > 0)
{
return uart->rx_error;
}
else
{
return NULL;
}
}
/**
* @brief UART数据存储
*
* UART接收到的数据缓冲区重置
*
* @param uart UART结构体指针
*/
void uart_data_storage_reset(uart_t *uart)
{
if (uart == NULL)
{
return;
}
uart->rx_index = 0;
uart_clear_error(uart);
}
/**
* @brief
* @param {uart_t} *uart UART设备句柄
* @return {*}
* @note: DMA使能标志RX DMA并启用RX DMA通道RX DMA通道并重置接收索引
*/
void uart_reception_callback(uart_t *uart)
{
// DBG_ASSERT(uart != NULL __DBG_LINE);
if (uart == NULL)
{
return;
}
if (LL_USART_IsEnabledIT_RXNE(uart->huart) && LL_USART_IsActiveFlag_RXNE(uart->huart))
{
if (uart->rx_index >= uart->rxsize)
{
uart_data_storage_reset(uart);
}
uart->rxbuf[uart->rx_index++] = LL_USART_ReceiveData8(uart->huart);
uart->rx_interupt_cnt = 0;
uart->rx_interupt_timeout = FALSE;
// 数据交给超时中断处理 uart_rx_timeout_timer
}
else if (LL_USART_IsEnabledIT_IDLE(uart->huart) && LL_USART_IsActiveFlag_IDLE(uart->huart))
{
if (uart->rx_dma_en == TRUE)
{
uart->rx_index = uart->rxsize - LL_DMA_GetDataLength(uart->dma, uart->dma_rx_channel);
if (uart->rx_cd_en == FALSE)
{
LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel);
if (uart->rx_interupt_cb != NULL && (uart->rx_index > 0 && uart->rx_index <= uart->rxsize))
{
uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index);
osel_memset(uart->rxbuf, 0, uart->rxsize);
}
LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize); // 这个不能少 先关闭DMA才能重新设置长度
LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel);
}
}
uart->rx_index = 0;
LL_USART_ClearFlag_IDLE(uart->huart);
}
if (LL_USART_IsEnabledIT_TC(uart->huart) && LL_USART_IsActiveFlag_TC(uart->huart))
{
if (uart->tx_complete_cb != NULL)
{
uart->tx_complete_cb();
}
LL_USART_ClearFlag_TC(uart->huart);
}
if (uart->rx_err_en == TRUE)
{
uarts_interupt_error_e err = UART_NO_ERROR;
if (LL_USART_IsEnabledIT_PE(uart->huart) && LL_USART_IsActiveFlag_PE(uart->huart))
{
err = UART_PARITY_ERROR;
LL_USART_ClearFlag_PE(uart->huart); // 清除奇偶校验错误标志
}
if (LL_USART_IsActiveFlag_FE(uart->huart) && LL_USART_IsActiveFlag_FE(uart->huart))
{
err = UART_FRAME_ERROR;
LL_USART_ClearFlag_FE(uart->huart); // 清除帧错误标志
}
if (LL_USART_IsActiveFlag_NE(uart->huart) && LL_USART_IsActiveFlag_NE(uart->huart))
{
// err = UART_NOISE_ERROR;
LL_USART_ClearFlag_NE(uart->huart); // 清除噪声错误标志
}
if (LL_USART_IsActiveFlag_ORE(uart->huart) && LL_USART_IsActiveFlag_ORE(uart->huart))
{
err = UART_OVERRUN_ERROR;
LL_USART_ClearFlag_ORE(uart->huart); // 清除溢出错误标志
}
if (err != UART_NO_ERROR && uart->rx_error != NULL)
{
uint16_t index = uart->rx_index - 1;
uart->rx_error[uart->rx_error_count].index = index;
uart->rx_error[uart->rx_error_count].err = err;
uart->rx_error_count++;
}
}
}
/**
* @brief DMA接收中断的回调函数
* @param {uart_t} *uart -
* @return {*}
* @note:
*/
void uart_dma_reception_callback(uart_t *uart)
{
// 检查输入参数是否为空
DBG_ASSERT(uart != NULL __DBG_LINE);
uart->tx_dma_ok = TRUE;
// 禁用串口DMA的发送通道
LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel);
// 清除发送中断标志位
DMA_CLEAR_FLAG_TC_CHANNEL(uart->dma, uart->dma_tx_channel);
// 使能发送中断,用于关闭发送使能引脚
LL_USART_EnableIT_TC(uart->huart); // 使能发送中断,用于关闭发送使能引脚
// 清除传输错误标志
DMA_CLEAR_FLAG_TE_CHANNEL(uart->dma, uart->dma_tx_channel);
}

View File

@ -1,218 +0,0 @@
/**
* @file uarts.h
* @brief Header file for UARTs module.
*
* This file contains the definitions and function prototypes for UARTs module.
* The UARTs module provides functions for creating and managing UART instances,
* enabling reception, sending data, and handling interrupts.
*/
#ifndef __UARTS_H__
#define __UARTS_H__
#include "lib.h"
#include "main.h"
// 串口中断用于接收超时的参数
#define RX_TIMEOUT_TICK (1U) /* 10ms的tick */
#define RX_TIMEOUT_MSEC (20U / RX_TIMEOUT_TICK) /* 20毫秒需要的tick可以根据需求添加其他时间更短的宏 */
/**
* @brief Enumeration for UART status.
*/
typedef enum
{
UART_OK = 0x00u, /**< The action was successful. */
UART_ERROR = 0xFFu /**< Generic error. */
} uart_status_e;
typedef enum
{
// 无错误
UART_NO_ERROR = BIT0,
// 奇偶校验错误中断
UART_PARITY_ERROR = BIT1,
// 帧错误中断
UART_FRAME_ERROR = BIT2,
// 噪声错误中断
UART_NOISE_ERROR = BIT3,
// 溢出错误中断
UART_OVERRUN_ERROR = BIT4,
} uarts_interupt_error_e; ///< UART中断错误枚举
typedef struct
{
uarts_interupt_error_e err; ///< 错误标志
uint16_t index; ///< 接收到的第几个字节
} uarts_interupt_error_t;
/**
* @brief Callback function type for UART receive interrupt.
*
* This function type is used to define the callback function for UART receive interrupt.
* The callback function is called when data is received on the UART.
*
* @param uart_index The index of the UART.
* @param uart_error The error code.
* @param data The received data.
* @param len The length of the received data.
*/
typedef void (*rx_interupt_cb_t)(uint8_t uart_index, uint8_t *data, uint16_t len);
/**
* @brief Callback function type for UART transmit complete.
*
* This function type is used to define the callback function for UART transmit complete.
* The callback function is called when the UART transmission is complete.
*/
typedef void (*tx_complete_cb_t)(void);
/**
* @brief Structure representing a UART instance.
*/
typedef struct
{
uint8_t uart_index; /**< The index of the UART. */
USART_TypeDef *huart; /**< The UART peripheral. */
DMA_TypeDef *dma; /**< The DMA peripheral. */
uint32_t dma_rx_channel; /**< The DMA receive channel. */
uint32_t dma_tx_channel; /**< The DMA transmit channel. */
//*******************RX*************************/
BOOL rx_cd_en; /**< Flag indicating if carrier detect is enabled. */
BOOL rx_dma_en; /**< Flag indicating if DMA reception is enabled. */
BOOL rx_err_en; /**< Flag indicating if error interrupt is enabled. */
__IO BOOL rx_interupt_timeout; /**< Flag indicating if receive interrupt timeout. */
__IO uint8_t rx_interupt_cnt; /**< The receive interrupt count. */
uint8_t *rxbuf; /**< The receive buffer. */
uint16_t rxsize; /**< The size of the receive buffer. */
uarts_interupt_error_t *rx_error; /**< The receive error. */
uint16_t rx_error_count; /**< The receive error count. */
__IO uint16_t rx_index; /**< The receive data index. */
//*******************TX*************************/
BOOL tx_dma_en; /**< Flag indicating if DMA transmission is enabled. */
uint8_t *txbuf; /**< The transmit buffer. */
uint16_t txsize; /**< The size of the transmit buffer. */
uint16_t tx_index; /**< The transmit data index. */
__IO BOOL tx_dma_ok; /**< Flag indicating if DMA transmission is complete. */
rx_interupt_cb_t rx_interupt_cb; /**< The receive interrupt callback function. */
tx_complete_cb_t tx_complete_cb; /**< The transmit complete callback function. */
} uart_t;
/**
* @brief Creates a UART instance.
*
* This function creates a UART instance with the specified parameters.
*
* @param huart The UART peripheral.
* @param rx_dma_en Flag indicating if DMA reception is enabled.
* @param rxsize The size of the receive buffer.
* @param rx_cb The receive interrupt callback function.
* @param tx_dma_en Flag indicating if DMA transmission is enabled.
* @param txsize The size of the transmit buffer.
* @param tx_complete_cb The transmit complete callback function.
* @return The created UART instance.
*/
extern uart_t *uart_create(USART_TypeDef *huart, BOOL rx_dma_en, uint16_t rxsize, rx_interupt_cb_t rx_cb,
BOOL tx_dma_en, uint16_t txsize, tx_complete_cb_t tx_complete_cb);
/**
* @brief Frees the resources of a UART instance.
*
* This function frees the resources allocated for a UART instance.
*
* @param uart The UART instance to free.
*/
extern void uart_free(uart_t *uart);
/**
* @brief Initializes a UART instance.
*
* This function initializes the specified UART instance with the specified parameters.
*
* @param uart The UART instance.
* @param baudrate The baudrate.
*/
extern void uart_set_baudrate(USART_TypeDef *uart, uint32_t baudrate);
/**
* @brief Enables UART reception.
*
* This function enables reception on the specified UART instance.
*
* @param uart The UART instance.
*/
extern void uart_recv_en(uart_t *uart, BOOL rx_err_en);
/**
* @brief Sends data over UART.
*
* This function sends the specified data over the specified UART instance.
*
* @param uart The UART instance.
* @param data The data to send.
* @param len The length of the data.
*/
extern void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len);
/**
* @brief UART receive carrier detect callback.
*
* This function is the callback for UART receive carrier detect.
*
* @param uart The UART instance.
*/
extern void uart_rx_cd_callback(uart_t *uart);
/**
* @brief UART receive timeout timer.
*
* This function is the timer callback for UART receive timeout.
*
* @param uart The UART instance.
*/
extern void uart_rx_timeout_timer(uart_t *uart);
/**
* @brief UART receive interrupt callback.
*
* This function is the interrupt callback for UART receive interrupt.
*
* @param uart The UART instance.
*/
extern void uart_reception_callback(uart_t *uart);
/**
* @brief Get the UART error count.
*
* This function returns the number of errors that have occurred on the specified UART instance.
*
* @param uart The UART instance.
* @return The number of errors.
*/
extern uint16_t uart_get_error_count(uart_t *uart);
/**
* @brief Get UART interrupt error.
*
* This function gets the UART interrupt error.
*
* @param uart The UART instance.
* @param count The error count.
* @return The error.
*/
extern uarts_interupt_error_t *uart_get_error(uart_t *uart);
extern void uart_data_storage_reset(uart_t *uart);
/**
* @brief DMA receive interrupt callback.
*
* This function is the interrupt callback for DMA receive interrupt.
*
* @param uart The UART instance.
*/
extern void uart_dma_reception_callback(uart_t *uart);
#endif ///< __UARTS_H__

View File

@ -12,7 +12,7 @@
#define __DELAY_H
#include "sys.h"
#include "tims.h"
#define USE_OS 0

View File

@ -0,0 +1,451 @@
#include "lcd_154.h"
#define FILL_ZERO 0 // 填充0
#define FILL_SPACE 1 // 填充空格
// 因为这类SPI的屏幕每次更新显示时需要先配置坐标区域、再写显存
// 在显示字符时,如果是一个个点去写坐标写显存,会非常慢,
// 因此开辟一片缓冲区,先将需要显示的数据写进缓冲区,最后再批量写入显存。
// 用户可以根据实际情况去修改此处缓冲区的大小,
// 例如用户需要显示32*32的汉字时需要的大小为 32*32*2 = 2048 字节每个像素点占2字节
static uint16_t pri[1024]; // 显示缓存区
// 等待通讯完成
static void _wait_finish(spi_t *lcd_spi)
{
while ((lcd_spi->spi->Instance->SR & 0x0080) != RESET)
; // 等待通信完成
}
// 等待发送缓冲区清空
static void _wait_send_empty(spi_t *lcd_spi)
{
while ((lcd_spi->spi->Instance->SR & 0x0002) == 0)
; // 等待发送缓冲区清空
}
static void _write_command(spi_t *lcd_spi, uint8_t command)
{
_wait_finish(lcd_spi); // 等待通讯完成
lcd_spi->gpios.dc->reset(*lcd_spi->gpios.dc); // DC置低表示发送命令
(lcd_spi->spi)->Instance->DR = command; // 发送数据
_wait_send_empty(lcd_spi); // 等待发送缓冲区清空
_wait_finish(lcd_spi); // 等待通讯完成 等待通信完成
lcd_spi->gpios.dc->set(*lcd_spi->gpios.dc); // DC置高表示发送数据
}
static void _write_data_8bit(spi_t *lcd_spi, uint8_t data)
{
lcd_spi->spi->Instance->DR = data; // 发送数据
_wait_send_empty(lcd_spi); // 等待发送缓冲区清空
}
static void _write_data_16bit(spi_t *lcd_spi, uint16_t data)
{
lcd_spi->spi->Instance->DR = data >> 8; // 发送数据高8位
_wait_send_empty(lcd_spi); // 等待发送缓冲区清空
lcd_spi->spi->Instance->DR = data; // 发送数据低8位
_wait_send_empty(lcd_spi); // 等待发送缓冲区清空
}
static void _write_buff(lcd_t *lcd, uint16_t *data, uint16_t size)
{
uint32_t i;
lcd->info.spi->spi->Instance->CR1 &= 0xFFBF; // 关闭SPI
lcd->info.spi->spi->Instance->CR1 |= 0x0800; // 切换成16位数据格式
lcd->info.spi->spi->Instance->CR1 |= 0x0040; // 使能SPI
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
for (i = 0; i < size; i++)
{
lcd->info.spi->spi->Instance->DR = data[i];
_wait_send_empty(lcd->info.spi); // 等待发送缓冲区清空
}
_wait_finish(lcd->info.spi); // 等待通讯完成
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
lcd->info.spi->spi->Instance->CR1 &= 0xFFBF; // 关闭SPI
lcd->info.spi->spi->Instance->CR1 &= 0xF7FF; // 切换成8位数据格式
lcd->info.spi->spi->Instance->CR1 |= 0x0040; // 使能SPI
}
// 设置方向
static void _set_dir(lcd_t *lcd, uint8_t scan_dir)
{
lcd->info.dir = scan_dir;
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
if (scan_dir == Direction_H) // 横屏显示
{
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0x70); // 横屏显示
lcd->info.x_offset = 0; // 设置控制器坐标偏移量
lcd->info.y_offset = 0;
}
else if (scan_dir == Direction_V)
{
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0x00); // 垂直显示
lcd->info.x_offset = 0; // 设置控制器坐标偏移量
lcd->info.y_offset = 0;
}
else if (scan_dir == Direction_H_Flip)
{
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0xA0); // 横屏显示并上下翻转RGB像素格式
lcd->info.x_offset = 80; // 设置控制器坐标偏移量
lcd->info.y_offset = 0;
}
else if (scan_dir == Direction_V_Flip)
{
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0xC0); // 垂直显示 并上下翻转RGB像素格式
lcd->info.x_offset = 0; // 设置控制器坐标偏移量
lcd->info.y_offset = 80;
}
_wait_finish(lcd->info.spi); // 等待通讯完成
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
}
// 设置画笔颜色
static void _set_color(lcd_t *lcd, uint32_t color)
{
uint16_t red_value = 0, green_value = 0, blue_value = 0; // 各个颜色通道的值
red_value = (uint16_t)((color & 0x00F80000) >> 8); // 转换成 16位 的RGB565颜色
green_value = (uint16_t)((color & 0x0000FC00) >> 5);
blue_value = (uint16_t)((color & 0x000000F8) >> 3);
lcd->info.color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD参数
}
static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
_write_command(lcd->info.spi, 0x2a); // 列地址设置即X坐标
_write_data_16bit(lcd->info.spi, x1 + lcd->info.x_offset);
_write_data_16bit(lcd->info.spi, x2 + lcd->info.x_offset);
_write_command(lcd->info.spi, 0x2b); // 行地址设置即Y坐标
_write_data_16bit(lcd->info.spi, y1 + lcd->info.y_offset);
_write_data_16bit(lcd->info.spi, y2 + lcd->info.y_offset);
_write_command(lcd->info.spi, 0x2c); // 开始写入显存,即要显示的颜色数据
_wait_finish(lcd->info.spi); // 等待通讯完成
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
}
static void _set_asscii_font(lcd_t *lcd, lcd_font *font)
{
lcd->info.ascii_font = font;
}
static void _set_hz_font(lcd_t *lcd, lcd_font *font)
{
lcd->info.hz_font = font;
switch (font->width)
{
case 12:
lcd->driver.set_asscii_font(lcd, &ascii_font_12);
break; // 设置ASCII字符的字体为 1206
case 16:
lcd->driver.set_asscii_font(lcd, &ascii_font_16);
break; // 设置ASCII字符的字体为 1608
case 20:
lcd->driver.set_asscii_font(lcd, &ascii_font_20);
break; // 设置ASCII字符的字体为 2010
case 24:
lcd->driver.set_asscii_font(lcd, &ascii_font_24);
break; // 设置ASCII字符的字体为 2412
case 32:
lcd->driver.set_asscii_font(lcd, &ascii_font_32);
break; // 设置ASCII字符的字体为 3216
default:
break;
}
}
/****************************************************************************************************************************************
* : LCD_DisplayChar
*
* : x -
* y -
* c - ASCII字符
*
* :
*
* : 1. 使 LCD_SetAsciiFont(&ASCII_Font24) 2412ASCII字体
* 2. 使 LCD_SetColor(0xff0000FF)
* 3. 使 LCD_SetBackColor(0x000000)
* 4. 使 LCD_DisplayChar( 10, 10, 'a') (10,10) 'a'
*
*****************************************************************************************************************************************/
void _display_char(lcd_t *lcd, uint16_t x, uint16_t y, uint8_t c)
{
uint16_t index = 0, counter = 0, i = 0, w = 0; // 计数变量
uint8_t disChar; // 存储字符的地址
c = c - 32; // 计算ASCII字符的偏移
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
for (index = 0; index < lcd->info.ascii_font->sizes; index++)
{
disChar = lcd->info.ascii_font->table[c * lcd->info.ascii_font->sizes + index]; // 获取字符的模值
for (counter = 0; counter < 8; counter++)
{
if (disChar & 0x01)
{
pri[i] = lcd->info.color; // 当前模值不为0时使用画笔色绘点
}
else
{
pri[i] = lcd->info.back_color; // 否则使用背景色绘制点
}
disChar >>= 1;
i++;
w++;
if (w == lcd->info.ascii_font->width) // 如果写入的数据达到了字符宽度,则退出当前循环
{ // 进入下一字符的写入的绘制
w = 0;
break;
}
}
}
lcd->driver.set_address(lcd, x, y, x + lcd->info.ascii_font->width - 1, y + lcd->info.ascii_font->height - 1); // 设置坐标
_write_buff(lcd, pri, lcd->info.ascii_font->width * lcd->info.ascii_font->height); // 写入显存
}
void _display_chinese(lcd_t *lcd, uint16_t x, uint16_t y, char *text)
{
uint16_t i = 0, index = 0, counter = 0; // 计数变量
uint16_t addr; // 字模地址
uint8_t disChar; // 字模的值
uint16_t Xaddress = 0; // 水平坐标
while (1)
{
// 对比数组中的汉字编码,用以定位该汉字字模的地址
if (*(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 0) == *text && *(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 1) == *(text + 1))
{
addr = i; // 字模地址偏移
break;
}
i += 2; // 每个中文字符编码占两字节
if (i >= lcd->info.hz_font->table_rows)
break; // 字模列表中无相应的汉字
}
i = 0;
for (index = 0; index < lcd->info.hz_font->sizes; index++)
{
disChar = *(lcd->info.hz_font->table + (addr)*lcd->info.hz_font->sizes + index); // 获取相应的字模地址
for (counter = 0; counter < 8; counter++)
{
if (disChar & 0x01)
{
pri[i] = lcd->info.color; // 当前模值不为0时使用画笔色绘点
}
else
{
pri[i] = lcd->info.back_color; // 否则使用背景色绘制点
}
i++;
disChar >>= 1;
Xaddress++; // 水平坐标自加
if (Xaddress == lcd->info.hz_font->width) // 如果水平坐标达到了字符宽度,则退出当前循环
{ // 进入下一行的绘制
Xaddress = 0;
break;
}
}
}
lcd->driver.set_address(lcd, x, y, x + lcd->info.hz_font->width - 1, y + lcd->info.hz_font->height - 1); // 设置坐标
_write_buff(lcd, pri, lcd->info.hz_font->width * lcd->info.hz_font->height); // 写入显存
}
static void _display_text(lcd_t *lcd, uint16_t x, uint16_t y, char *text)
{
while (*text != 0) // 判断是否为空字符
{
if (*text <= 0x7F) // 判断是否为ASCII码
{
_display_char(lcd, x, y, *text); // 显示ASCII
x += lcd->info.ascii_font->width; // 水平坐标调到下一个字符处
text++; // 字符串地址+1
}
else // 若字符为汉字
{
_display_chinese(lcd, x, y, text); // 显示汉字
x += lcd->info.hz_font->width; // 水平坐标调到下一个字符处
text += 2; // 字符串地址+2汉字的编码要2字节
}
}
}
// 设置背景色
static void _full_fill(lcd_t *lcd, uint32_t color)
{
uint16_t red_value = 0, green_value = 0, blue_value = 0; // 各个颜色通道的值
red_value = (uint16_t)((color & 0x00F80000) >> 8); // 转换成 16位 的RGB565颜色
green_value = (uint16_t)((color & 0x0000FC00) >> 5);
blue_value = (uint16_t)((color & 0x000000F8) >> 3);
lcd->info.back_color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD参数
}
static void _clear(lcd_t *lcd)
{
uint32_t i;
lcd->driver.set_address(lcd, 0, 0, lcd->info.width - 1, lcd->info.height - 1);
lcd->info.spi->spi->Instance->CR1 &= 0xFFBF; // 关闭SPI
lcd->info.spi->spi->Instance->CR1 |= 0x0800; // 切换成16位数据格式
lcd->info.spi->spi->Instance->CR1 |= 0x0040; // 使能SPI
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
for (i = 0; i < lcd->info.width * lcd->info.height; i++)
{
lcd->info.spi->spi->Instance->DR = lcd->info.back_color;
_wait_send_empty(lcd->info.spi); // 等待发送缓冲区清空
}
_wait_finish(lcd->info.spi); // 等待通讯完成
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
lcd->info.spi->spi->Instance->CR1 &= 0xFFBF; // 关闭SPI
lcd->info.spi->spi->Instance->CR1 &= 0xF7FF; // 切换成8位数据格式
lcd->info.spi->spi->Instance->CR1 |= 0x0040; // 使能SPI
}
static int32_t _init(lcd_t *lcd)
{
HAL_Delay(10);
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0x00); // 配置成 从上到下、从左到右RGB像素格式
_write_command(lcd->info.spi, 0x3A); // 接口像素格式 指令,用于设置使用 12位、16位还是18位色
_write_data_8bit(lcd->info.spi, 0x05); // 此处配置成 16位 像素格式
// 接下来很多都是电压设置指令,直接使用厂家给设定值
_write_command(lcd->info.spi, 0xB2);
_write_data_8bit(lcd->info.spi, 0x0C);
_write_data_8bit(lcd->info.spi, 0x0C);
_write_data_8bit(lcd->info.spi, 0x00);
_write_data_8bit(lcd->info.spi, 0x33);
_write_data_8bit(lcd->info.spi, 0x33);
_write_command(lcd->info.spi, 0xB7); // 栅极电压设置指令
_write_data_8bit(lcd->info.spi, 0x35); // VGH = 13.26VVGL = -10.43V
_write_command(lcd->info.spi, 0xBB); // 公共电压设置指令
_write_data_8bit(lcd->info.spi, 0x19); // VCOM = 1.35V
_write_command(lcd->info.spi, 0xC0);
_write_data_8bit(lcd->info.spi, 0x2C);
_write_command(lcd->info.spi, 0xC2); // VDV 和 VRH 来源设置
_write_data_8bit(lcd->info.spi, 0x01); // VDV 和 VRH 由用户自由配置
_write_command(lcd->info.spi, 0xC3); // VRH电压 设置指令
_write_data_8bit(lcd->info.spi, 0x12); // VRH电压 = 4.6+( vcom+vcom offset+vdv)
_write_command(lcd->info.spi, 0xC4); // VDV电压 设置指令
_write_data_8bit(lcd->info.spi, 0x20); // VDV电压 = 0v
_write_command(lcd->info.spi, 0xC6); // 正常模式的帧率控制指令
_write_data_8bit(lcd->info.spi, 0x0F); // 设置屏幕控制器的刷新帧率为60帧
_write_command(lcd->info.spi, 0xD0); // 电源控制指令
_write_data_8bit(lcd->info.spi, 0xA4); // 无效数据固定写入0xA4
_write_data_8bit(lcd->info.spi, 0xA1); // AVDD = 6.8V AVDD = -4.8V VDS = 2.3V
_write_command(lcd->info.spi, 0xE0); // 正极电压伽马值设定
_write_data_8bit(lcd->info.spi, 0xD0);
_write_data_8bit(lcd->info.spi, 0x04);
_write_data_8bit(lcd->info.spi, 0x0D);
_write_data_8bit(lcd->info.spi, 0x11);
_write_data_8bit(lcd->info.spi, 0x13);
_write_data_8bit(lcd->info.spi, 0x2B);
_write_data_8bit(lcd->info.spi, 0x3F);
_write_data_8bit(lcd->info.spi, 0x54);
_write_data_8bit(lcd->info.spi, 0x4C);
_write_data_8bit(lcd->info.spi, 0x18);
_write_data_8bit(lcd->info.spi, 0x0D);
_write_data_8bit(lcd->info.spi, 0x0B);
_write_data_8bit(lcd->info.spi, 0x1F);
_write_data_8bit(lcd->info.spi, 0x23);
_write_command(lcd->info.spi, 0xE1); // 负极电压伽马值设定
_write_data_8bit(lcd->info.spi, 0xD0);
_write_data_8bit(lcd->info.spi, 0x04);
_write_data_8bit(lcd->info.spi, 0x0C);
_write_data_8bit(lcd->info.spi, 0x11);
_write_data_8bit(lcd->info.spi, 0x13);
_write_data_8bit(lcd->info.spi, 0x2C);
_write_data_8bit(lcd->info.spi, 0x3F);
_write_data_8bit(lcd->info.spi, 0x44);
_write_data_8bit(lcd->info.spi, 0x51);
_write_data_8bit(lcd->info.spi, 0x2F);
_write_data_8bit(lcd->info.spi, 0x1F);
_write_data_8bit(lcd->info.spi, 0x1F);
_write_data_8bit(lcd->info.spi, 0x20);
_write_data_8bit(lcd->info.spi, 0x23);
_write_command(lcd->info.spi, 0x21); // 打开反显,因为面板是常黑型,操作需要反过来
// 退出休眠指令LCD控制器在刚上电、复位时会自动进入休眠模式 ,因此操作屏幕之前,需要退出休眠
_write_command(lcd->info.spi, 0x11); // 退出休眠 指令
HAL_Delay(120); // 需要等待120ms让电源电压和时钟电路稳定下来
// 打开显示指令LCD控制器在刚上电、复位时会自动关闭显示
_write_command(lcd->info.spi, 0x29); // 打开显示
_wait_finish(lcd->info.spi); // 等待通讯完成
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
// 以下进行一些驱动的默认设置
lcd->driver.set_dir(lcd, Direction_V); // 默认竖屏显示
lcd->driver.full_fill(lcd, LCD_BLACK); // 默认背景色为黑色
lcd->driver.set_color(lcd, LCD_WHITE); // 默认画笔颜色为白色
lcd->driver.clear(lcd); // 清除屏幕
lcd->driver.set_asscii_font(lcd, &ascii_font_24); // 默认ASCII字体
lcd->info.show_num_mode = FILL_ZERO; // 设置变量显示模式多余位填充空格还是填充0
return 0;
}
void lcd_154_init(lcd_driver_t *driver)
{
DBG_ASSERT(driver != NULL __DBG_LINE);
driver->init = _init; // 已实现
// driver->set_point = _set_point; // 已实现
// driver->get_point = _get_point; // 已实现
// driver->color_fill = _color_fill; // 已实现
// driver->onoff = _onoff; // 已实现
driver->set_dir = _set_dir; // 已实现
driver->set_color = _set_color; // 已实现
driver->set_address = _set_address; // 已实现
driver->set_asscii_font = _set_asscii_font; // 已实现
driver->set_hz_font = _set_hz_font; // 已实现
driver->display_text = _display_text; // 已实现
// driver->get_dir = _get_dir; // 已实现
// driver->flush = _flush; // 已实现
// driver->flush_clear = _flush_clear; // 已实现
driver->clear = _clear; // 已实现
// driver->set_clear_flag = _set_clear_flag; // 已实现
// driver->get_clear_flag = _get_clear_flag; // 已实现
driver->full_fill = _full_fill; // 已实现
// driver->copy_template = _copy_template; // 已实现
// driver->clear_ram = _clear_ram; // 已实现
}

View File

@ -0,0 +1,8 @@
#ifndef __LCD_154_H
#define __LCD_154_H
// 彩色液晶屏驱动-基于1.54寸240x240分辨率
#include "lcds.h"
extern void lcd_154_init(lcd_driver_t *driver);
#endif // __LCD_154_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
#ifndef _FONT_H
#define _FONT_H
#include <stdint.h>
// 字体相关结构定义
typedef struct _lcd_font
{
const uint8_t *table; // 字模数组地址
uint16_t width; // 单个字符的字模宽度
uint16_t height; // 单个字符的字模长度
uint16_t sizes; // 单个字符的字模数据个数
uint16_t table_rows; // 该参数只有汉字字模用到,表示二维数组的行大小
} lcd_font;
/*------------------------------------ 中文字体 ---------------------------------------------*/
extern lcd_font ch_font_12; // 1212字体
extern lcd_font ch_font_16; // 1616字体
extern lcd_font ch_font_20; // 2020字体
extern lcd_font ch_font_24; // 2424字体
extern lcd_font ch_font_32; // 3232字体
/*------------------------------------ ASCII字体 ---------------------------------------------*/
extern lcd_font ascii_font_32; // 3216 字体
extern lcd_font ascii_font_24; // 2412 字体
extern lcd_font ascii_font_20; // 2010 字体
extern lcd_font ascii_font_16; // 1608 字体
extern lcd_font ascii_font_12; // 1206 字体
#endif // _FONT_H

View File

@ -74,7 +74,7 @@ static BOOL sharp_transmit_byte(lcd_t *lcd, uint8_t data)
* @return {*}
* @note
*/
static int32_t _clear(lcd_t *lcd)
static void _clear(lcd_t *lcd)
{
DBG_ASSERT(lcd != NULL __DBG_LINE);
DBG_ASSERT(lcd->info.spi != NULL __DBG_LINE);
@ -86,7 +86,6 @@ static int32_t _clear(lcd_t *lcd)
lcd->info.clear_flag = FALSE;
osel_memset((uint8_t *)change_line, 1, lcd->info.height);
return 0;
}
/**

View File

@ -9,6 +9,7 @@
#include "lcds.h"
#include "lcd_st7525.h"
#include "lcd_sharp.h"
#include "lcd_154.h"
#include <string.h>
#define BACK_COLOR WHITE
@ -33,7 +34,10 @@ lcd_t *lcd_create(lcd_info_t info)
// lcd_st7525_init(&handle->driver);
break;
case LCD_SHARP:
lcd_sharp_init(&handle->driver);
// lcd_sharp_init(&handle->driver);
break;
case LCD_154:
lcd_154_init(&handle->driver);
break;
default:
lcd_free(handle);

View File

@ -37,38 +37,24 @@
#include "lib.h"
#include "spis.h"
#include "lcd_font.h"
#define USE_UCGUI (1) // 0不使用1:使用uc-gui
// 列点阵数
#define COL_DOT_MAX_128 128
#define COL_DOT_MAX_192 192
#define COL_DOT_MAX_240 240
#define COL_DOT_MAX_400 400
// 行点阵数
#define LIN_DOT_MAX_64 64
#define LIN_DOT_MAX_240 240
#if 0
#define H_LCD 0 // 竖屏
#define W_LCD 1 // 横屏
// 扫描方向定义
// BIT 0 标识LR1 R-L0 L-R
// BIT 1 标识UD1 D-U0 U-D
// BIT 2 标识LR/UD1 DU-LR0 LR-DU
// #define LR_BIT_MASK 0X01
// #define UD_BIT_MASK 0X02
// #define LRUD_BIT_MASK 0X04
// #define L2R_U2D (0) // 从左到右,从上到下
// #define L2R_D2U (0 + UD_BIT_MASK) // 从左到右,从下到上
// #define R2L_U2D (0 + LR_BIT_MASK) // 从右到左,从上到下
// #define R2L_D2U (0 + UD_BIT_MASK + LR_BIT_MASK) // 从右到左,从下到上
// #define U2D_L2R (LRUD_BIT_MASK) // 从上到下,从左到右
// #define U2D_R2L (LRUD_BIT_MASK + LR_BIT_MASK) // 从上到下,从右到左
// #define D2U_L2R (LRUD_BIT_MASK + UD_BIT_MASK) // 从下到上,从左到右
// #define D2U_R2L (LRUD_BIT_MASK + UD_BIT_MASK + LR_BIT_MASK) // 从下到上,从右到左
// 画笔颜色
/*
@ -99,6 +85,46 @@
#define LGRAY 0XC618 // 浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 // 浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 // 浅棕蓝色(选择条目的反色)
#endif
// 显示方向参数
#define Direction_H 0 // LCD横屏显示
#define Direction_H_Flip 1 // LCD横屏显示,上下翻转
#define Direction_V 2 // LCD竖屏显示
#define Direction_V_Flip 3 // LCD竖屏显示,上下翻转
/*---------------------------------------- 常用颜色 ------------------------------------------------------
1. 便使24 RGB888颜色 16 RGB565
2. 24 RGB 3
3. 24RGB颜色LCD_SetColor()LCD_SetBackColor()
*/
#define LCD_WHITE 0xFFFFFF // 纯白色
#define LCD_BLACK 0x000000 // 纯黑色
#define LCD_BLUE 0x0000FF // 纯蓝色
#define LCD_GREEN 0x00FF00 // 纯绿色
#define LCD_RED 0xFF0000 // 纯红色
#define LCD_CYAN 0x00FFFF // 蓝绿色
#define LCD_MAGENTA 0xFF00FF // 紫红色
#define LCD_YELLOW 0xFFFF00 // 黄色
#define LCD_GREY 0x2C2C2C // 灰色
#define LIGHT_BLUE 0x8080FF // 亮蓝色
#define LIGHT_GREEN 0x80FF80 // 亮绿色
#define LIGHT_RED 0xFF8080 // 亮红色
#define LIGHT_CYAN 0x80FFFF // 亮蓝绿色
#define LIGHT_MAGENTA 0xFF80FF // 亮紫红色
#define LIGHT_YELLOW 0xFFFF80 // 亮黄色
#define LIGHT_GREY 0xA3A3A3 // 亮灰色
#define DARK_BLUE 0x000080 // 暗蓝色
#define DARK_GREEN 0x008000 // 暗绿色
#define DARK_RED 0x800000 // 暗红色
#define DARK_CYAN 0x008080 // 暗蓝绿色
#define DARK_MAGENTA 0x800080 // 暗紫红色
#define DARK_YELLOW 0x808000 // 暗黄色
#define DARK_GREY 0x404040 // 暗灰色
#if !USE_UCGUI
// 对齐方式
@ -120,6 +146,7 @@ typedef enum
{
LCD_ST7525,
LCD_SHARP,
LCD_154,
} lcd_type_e;
typedef enum
@ -130,6 +157,7 @@ typedef enum
} template_copy_type_e; // 0,拷贝pri_template到pri1拷贝pri到pri_template; 其余清空
typedef struct LCDS lcd_t;
typedef struct
{
lcd_type_e type;
@ -141,6 +169,15 @@ typedef struct
uint16_t width; // LCDS 宽度
uint16_t height; // LCDS 高度
uint16_t x_offset; // 控制器坐标偏移量
uint16_t y_offset; // 控制器坐标偏移量
uint16_t back_color; // 背景颜色
uint16_t color; // 画笔颜色
uint8_t show_num_mode; // 数字显示模式:设置变量显示时多余位补0还是补空格可输入参数 Fill_Space 填充空格Fill_Zero 填充零
lcd_font *ascii_font; // ASCII字体
lcd_font *hz_font; // 汉字字体
// private:
uint8_t on; // 开关 0关1开
uint8_t scandir; // 扫描方向0, 0度扫描1 180度扫描
@ -168,13 +205,20 @@ typedef struct
int32_t (*onoff)(lcd_t *lcd, uint8_t sta); // 开关
void (*set_dir)(lcd_t *lcd, uint8_t scan_dir); // 设置扫描方向
void (*set_color)(lcd_t *lcd, uint32_t color); // 设置画笔颜色
void (*backlight)(lcd_t *lcd, uint8_t sta); // 背光控制
void (*full_fill)(lcd_t *lcd, uint16_t color);
int32_t (*clear)(lcd_t *lcd); // 清屏
void (*display_text)(lcd_t *lcd, uint16_t x, uint16_t y, char *text); // 显示字符串
void (*full_fill)(lcd_t *lcd, uint32_t color);
void (*set_address)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); // 设置显示区域
void (*clear)(lcd_t *lcd); // 清屏
void (*set_clear_flag)(lcd_t *lcd); // 设置清屏标志
void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // 拷贝模板 0,拷贝pri_template到pri1拷贝pri到pri_template; 其余清空
void (*clear_ram)(lcd_t *lcd, uint16_t min_row, uint16_t max_row); // 清除显存
// 扩展接口
void (*set_asscii_font)(lcd_t *lcd, lcd_font *font); // 设置ASCII字体
void (*set_hz_font)(lcd_t *lcd, lcd_font *font); // 设置汉字字体
// 获取接口
uint8_t (*get_dir)(lcd_t *lcd); // 获取扫描方向
BOOL(*get_clear_flag)

View File

@ -257,18 +257,3 @@ void system_clock_read(void)
original_clock_config.sysclk = SystemCoreClock;
#endif
}
/**
* @brief Write a character to a file stream, used for FLASHDB printf
*
* Writes the specified character to the given file stream and returns the written character.
*
* @param ch The character to be written
* @param stream Pointer to the file stream
*
* @return The written character
*/
int fputc(int ch, FILE *stream)
{
return ch;
}

View File

@ -31,6 +31,21 @@ Dma.SDIO_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_WORD
Dma.SDIO_TX.1.PeriphInc=DMA_PINC_DISABLE
Dma.SDIO_TX.1.Priority=DMA_PRIORITY_LOW
Dma.SDIO_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
FATFS.BSP.number=1
FATFS.IPParameters=_CODE_PAGE,_USE_LFN,_VOLUMES
FATFS._CODE_PAGE=936
FATFS._USE_LFN=3
FATFS._VOLUMES=2
FATFS0.BSP.STBoard=false
FATFS0.BSP.api=Unknown
FATFS0.BSP.component=
FATFS0.BSP.condition=
FATFS0.BSP.instance=PB10
FATFS0.BSP.ip=GPIO
FATFS0.BSP.mode=Input
FATFS0.BSP.name=Detect_SDIO
FATFS0.BSP.semaphore=
FATFS0.BSP.solution=PB10
FREERTOS.IPParameters=Tasks01
FREERTOS.Tasks01=defaultTask,0,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
File.Version=6
@ -39,33 +54,46 @@ KeepUserPlacement=false
Mcu.CPN=STM32F407ZGT6
Mcu.Family=STM32F4
Mcu.IP0=DMA
Mcu.IP1=FREERTOS
Mcu.IP2=NVIC
Mcu.IP3=RCC
Mcu.IP4=RTC
Mcu.IP5=SDIO
Mcu.IP6=SYS
Mcu.IPNb=7
Mcu.IP1=FATFS
Mcu.IP2=FREERTOS
Mcu.IP3=NVIC
Mcu.IP4=RCC
Mcu.IP5=RTC
Mcu.IP6=SDIO
Mcu.IP7=SPI3
Mcu.IP8=SYS
Mcu.IP9=USART1
Mcu.IPNb=10
Mcu.Name=STM32F407Z(E-G)Tx
Mcu.Package=LQFP144
Mcu.Pin0=PC13-ANTI_TAMP
Mcu.Pin1=PC14-OSC32_IN
Mcu.Pin10=PC11
Mcu.Pin11=PC12
Mcu.Pin12=PD2
Mcu.Pin13=VP_FREERTOS_VS_CMSIS_V1
Mcu.Pin14=VP_RTC_VS_RTC_Activate
Mcu.Pin15=VP_RTC_VS_RTC_Calendar
Mcu.Pin16=VP_SYS_VS_tim6
Mcu.Pin10=PC9
Mcu.Pin11=PA9
Mcu.Pin12=PA10
Mcu.Pin13=PA13
Mcu.Pin14=PA14
Mcu.Pin15=PC10
Mcu.Pin16=PC11
Mcu.Pin17=PC12
Mcu.Pin18=PD2
Mcu.Pin19=PB3
Mcu.Pin2=PC15-OSC32_OUT
Mcu.Pin20=PB4
Mcu.Pin21=PB5
Mcu.Pin22=VP_FATFS_VS_SDIO
Mcu.Pin23=VP_FREERTOS_VS_CMSIS_V1
Mcu.Pin24=VP_RTC_VS_RTC_Activate
Mcu.Pin25=VP_RTC_VS_RTC_Calendar
Mcu.Pin26=VP_SYS_VS_tim6
Mcu.Pin3=PH0-OSC_IN
Mcu.Pin4=PH1-OSC_OUT
Mcu.Pin5=PC8
Mcu.Pin6=PC9
Mcu.Pin7=PA13
Mcu.Pin8=PA14
Mcu.Pin9=PC10
Mcu.PinsNb=17
Mcu.Pin5=PB10
Mcu.Pin6=PD11
Mcu.Pin7=PD12
Mcu.Pin8=PD13
Mcu.Pin9=PC8
Mcu.PinsNb=27
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F407ZGTx
@ -90,10 +118,23 @@ NVIC.TIM6_DAC_IRQn=true\:4\:0\:true\:false\:true\:false\:false\:true\:true
NVIC.TimeBase=TIM6_DAC_IRQn
NVIC.TimeBaseIP=TIM6
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
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.Mode=Asynchronous
PA9.Signal=USART1_TX
PB10.GPIOParameters=GPIO_Label
PB10.GPIO_Label=FATFS
PB10.Signal=GPIO_Input
PB3.Mode=Full_Duplex_Master
PB3.Signal=SPI3_SCK
PB4.Mode=Full_Duplex_Master
PB4.Signal=SPI3_MISO
PB5.Mode=Full_Duplex_Master
PB5.Signal=SPI3_MOSI
PC10.GPIOParameters=GPIO_PuPd,GPIO_Speed_High_Default
PC10.GPIO_PuPd=GPIO_PULLUP
PC10.GPIO_Speed_High_Default=GPIO_SPEED_FREQ_HIGH
@ -126,6 +167,15 @@ PC9.GPIO_PuPd=GPIO_PULLUP
PC9.GPIO_Speed_High_Default=GPIO_SPEED_FREQ_HIGH
PC9.Mode=SD_4_bits_Wide_bus
PC9.Signal=SDIO_D1
PD11.GPIOParameters=GPIO_Label
PD11.GPIO_Label=LCD_CS
PD11.Signal=GPIO_Output
PD12.GPIOParameters=GPIO_Label
PD12.GPIO_Label=LCD_DC
PD12.Signal=GPIO_Output
PD13.GPIOParameters=GPIO_Label
PD13.GPIO_Label=LCD_BACKLIGHT
PD13.Signal=GPXTI13
PD2.GPIOParameters=GPIO_PuPd,GPIO_Speed_High_Default
PD2.GPIO_PuPd=GPIO_PULLUP
PD2.GPIO_Speed_High_Default=GPIO_SPEED_FREQ_HIGH
@ -148,7 +198,7 @@ ProjectManager.DeviceId=STM32F407ZGTx
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.28.1
ProjectManager.FreePins=true
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x400
ProjectManager.HeapSize=0x1000
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=1
@ -160,13 +210,13 @@ ProjectManager.ProjectFileName=freertos_f407.ioc
ProjectManager.ProjectName=freertos_f407
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x800
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=MDK-ARM V5.32
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,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_SDIO_SD_Init-SDIO-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_SDIO_SD_Init-SDIO-false-HAL-true,6-MX_FATFS_Init-FATFS-false-HAL-false,7-MX_USART1_UART_Init-USART1-false-HAL-true,8-MX_SPI3_Init-SPI3-false-HAL-true
RCC.48MHZClocksFreq_Value=48000000
RCC.AHBFreq_Value=168000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4
@ -204,6 +254,18 @@ RCC.VCOOutputFreq_Value=336000000
RCC.VcooutputI2S=192000000
SDIO.ClockDiv=4
SDIO.IPParameters=ClockDiv
SH.GPXTI13.0=GPIO_EXTI13
SH.GPXTI13.ConfNb=1
SPI3.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2
SPI3.CalculateBaudRate=21.0 MBits/s
SPI3.Direction=SPI_DIRECTION_2LINES
SPI3.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler
SPI3.Mode=SPI_MODE_MASTER
SPI3.VirtualType=VM_MASTER
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_FATFS_VS_SDIO.Mode=SDIO
VP_FATFS_VS_SDIO.Signal=FATFS_VS_SDIO
VP_FREERTOS_VS_CMSIS_V1.Mode=CMSIS_V1
VP_FREERTOS_VS_CMSIS_V1.Signal=FREERTOS_VS_CMSIS_V1
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled