diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cbbef4..a033ddd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,12 +11,13 @@ cmake_minimum_required(VERSION 3.22) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) +option(DRIVER_CPP "cpp driver" OFF) # Define the build type -if(NOT CMAKE_BUILD_TYPE) +if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug") -endif() +endif () # Set the project name set(CMAKE_PROJECT_NAME CLion_STM32) @@ -35,26 +36,26 @@ enable_language(C ASM) add_executable(${CMAKE_PROJECT_NAME}) # Add STM32CubeMX generated sources add_subdirectory(cmake/stm32cubemx) -add_subdirectory(Core/driver/led) +add_subdirectory(Core/driver) # Link directories setup target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE - # Add user defined library search paths + # Add user defined library search paths ) # Add sources to executable target_sources(${CMAKE_PROJECT_NAME} PRIVATE - # Add user sources here + # Add user sources here ) # Add include paths target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE - # Add user defined include paths + # Add user defined include paths ) # Add project symbols (macros) target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE - # Add user defined symbols + # Add user defined symbols ) # Remove wrong libob.a library dependency when using cpp files @@ -62,11 +63,7 @@ list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_LIBRARIES ob) # Add linked libraries target_link_libraries(${CMAKE_PROJECT_NAME} - stm32cubemx - # Add user defined libraries + stm32cubemx + # Add user defined libraries + driver ) -if (FEATURE_LED) - target_link_libraries(${CMAKE_PROJECT_NAME} - led_lib - ) -endif () diff --git a/Core/Src/main.c b/Core/Src/main.c index 8f29202..e44ff49 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -19,12 +19,10 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "gpio.h" -#ifdef FEATURE_LED -#include "led.h" -#endif + /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "interface.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -50,6 +48,7 @@ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); + /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ @@ -63,9 +62,7 @@ void SystemClock_Config(void); * @brief The application entry point. * @retval int */ -int main(void) -{ - +int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ @@ -89,74 +86,64 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ - + interface(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ - while (1) - { + while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ -#ifdef FEATURE_LED - led_off(); - HAL_Delay(200); - led_on(); - HAL_Delay(200); -#endif } #if 0 /* USER CODE END 3 */ } -/** - * @brief System Clock Configuration - * @retval None - */ -void SystemClock_Config(void) -{ - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + /** + * @brief System Clock Configuration + * @retval None + */ + void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - /** Configure the main internal regulator output voltage - */ - __HAL_RCC_PWR_CLK_ENABLE(); - __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - /** Initializes the RCC Oscillators according to the specified parameters - * in the RCC_OscInitTypeDef structure. - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_ON; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 4; - RCC_OscInitStruct.PLL.PLLN = 168; - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = 4; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { - Error_Handler(); + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 4; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { + Error_Handler(); + } } - /** Initializes the CPU, AHB and APB buses clocks - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) - { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ + /* USER CODE BEGIN 4 */ #endif } @@ -164,8 +151,7 @@ void SystemClock_Config(void) * @brief System Clock Configuration * @retval None */ -void SystemClock_Config(void) -{ +void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; @@ -176,8 +162,7 @@ void SystemClock_Config(void) RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) - { + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } /** Initializes the RCC Oscillators according to the specified parameters @@ -191,38 +176,35 @@ void SystemClock_Config(void) RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) - { + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } + /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ -void Error_Handler(void) -{ +void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); - while (1) - { + while (1) { } /* USER CODE END Error_Handler_Debug */ } @@ -234,8 +216,7 @@ void Error_Handler(void) * @param line: assert_param error line source number * @retval None */ -void assert_failed(uint8_t *file, uint32_t line) -{ +void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ diff --git a/Core/driver/CMakeLists.txt b/Core/driver/CMakeLists.txt new file mode 100644 index 0000000..d867330 --- /dev/null +++ b/Core/driver/CMakeLists.txt @@ -0,0 +1,12 @@ +add_subdirectory(led) + +add_library(driver INTERFACE) +target_link_libraries(driver INTERFACE led_lib) +target_sources(driver INTERFACE ./base/interface.cpp) +target_include_directories(driver INTERFACE ./base) + +if (DRIVER_CPP) + add_subdirectory(base/gpio) + target_compile_definitions(driver INTERFACE DRIVER_CPP) +endif () + diff --git a/Core/driver/base/gpio/CMakeLists.txt b/Core/driver/base/gpio/CMakeLists.txt new file mode 100644 index 0000000..f4de8b1 --- /dev/null +++ b/Core/driver/base/gpio/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(gpio INTERFACE) +target_sources(gpio PUBLIC include/gpio_base.hpp) +target_include_directories(gpio INTERFACE ./include) diff --git a/Core/driver/base/gpio/include/gpio_base.hpp b/Core/driver/base/gpio/include/gpio_base.hpp new file mode 100644 index 0000000..00e23e5 --- /dev/null +++ b/Core/driver/base/gpio/include/gpio_base.hpp @@ -0,0 +1,79 @@ +// +// Created by Wind on 2025/11/9. +// + +#ifndef CLION_STM32_GPIO_H +#define CLION_STM32_GPIO_H +#include "main.h" + +class Gpio { +public: + enum class Mode { + Input, + Output, + Alternate, + Analog + }; + + enum class PULL { + None, + PullUp, + PullDown, + }; + + Gpio(GPIO_TypeDef *port, const uint16_t pin) : port_(port), pin_(pin) { + enableClock(); + } + + void setMode(const Mode mode, const PULL pull) const { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_; + switch (mode) { + case Mode::Input: GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + break; + case Mode::Output: GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + break; + case Mode::Alternate: GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + break; + case Mode::Analog: GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + break; + } + + switch (pull) { + case PULL::None: GPIO_InitStruct.Pull = GPIO_NOPULL; + break; + case PULL::PullUp: GPIO_InitStruct.Pull = GPIO_PULLUP; + break; + case PULL::PullDown: GPIO_InitStruct.Pull = GPIO_PULLDOWN; + break; + } + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(port_, &GPIO_InitStruct); + } + + void write(const bool v) const { HAL_GPIO_WritePin(port_, pin_, v ? GPIO_PIN_SET : GPIO_PIN_RESET); } + + void toggle() const { HAL_GPIO_TogglePin(port_, pin_); } + + bool read() const { return HAL_GPIO_ReadPin(port_, pin_); } + +private: + GPIO_TypeDef *port_{}; + uint16_t pin_{}; + + void enableClock() const { + if (port_ == GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (port_ == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (port_ == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else if (port_ == GPIOD) + __HAL_RCC_GPIOD_CLK_ENABLE(); + else if (port_ == GPIOE) + __HAL_RCC_GPIOE_CLK_ENABLE(); + } +}; + + +#endif //CLION_STM32_GPIO_H diff --git a/Core/driver/base/interface.cpp b/Core/driver/base/interface.cpp new file mode 100644 index 0000000..57593f4 --- /dev/null +++ b/Core/driver/base/interface.cpp @@ -0,0 +1,33 @@ +// +// Created by Wind on 2025/11/9. +// + +#include "interface.h" +#include "led.h" + +#ifdef DRIVER_CPP +#include "led_cpp.h" + +void cpp_interface() { + const auto led = LED(LED_GPIO_Port, LED_Pin); + while (true) { + led.toggle(); + HAL_Delay(50); + } +} +#endif + +void interface() { +#ifdef DRIVER_CPP + cpp_interface(); +#else + const led_t led = { + LED_GPIO_Port, LED_Pin + }; + led_init(&led); + while (true) { + led_toggle(&led); + HAL_Delay(1000); + } +#endif +} diff --git a/Core/driver/base/interface.h b/Core/driver/base/interface.h new file mode 100644 index 0000000..1bee6db --- /dev/null +++ b/Core/driver/base/interface.h @@ -0,0 +1,17 @@ +// +// Created by Wind on 2025/11/9. +// + +#ifndef CLION_STM32_CPP_INTERFACE_H +#define CLION_STM32_CPP_INTERFACE_H +#ifdef __cplusplus +extern "C" { +#endif + +void interface(); + +#ifdef __cplusplus +} +#endif + +#endif //CLION_STM32_CPP_INTERFACE_H diff --git a/Core/driver/led/CMakeLists.txt b/Core/driver/led/CMakeLists.txt index d9b49b2..f931c52 100644 --- a/Core/driver/led/CMakeLists.txt +++ b/Core/driver/led/CMakeLists.txt @@ -1,11 +1,12 @@ option(FEATURE_LED "Build LED Module" ON) -if (FEATURE_LED) - add_library(led_lib INTERFACE) +add_library(led_lib INTERFACE) - target_sources(led_lib PUBLIC led.c) +if (FEATURE_LED) + if (DRIVER_CPP) + target_link_libraries(led_lib INTERFACE gpio) + target_sources(led_lib INTERFACE led_cpp.cpp) + endif () target_include_directories(led_lib INTERFACE ./include) + target_sources(led_lib INTERFACE led.c) target_compile_definitions(led_lib INTERFACE FEATURE_LED) endif () - - - diff --git a/Core/driver/led/include/led.h b/Core/driver/led/include/led.h index fb6ce92..c08a567 100644 --- a/Core/driver/led/include/led.h +++ b/Core/driver/led/include/led.h @@ -5,10 +5,28 @@ #ifndef CLION_STM32_LED_H #define CLION_STM32_LED_H -void led_on(void); + +#include "main.h" +#ifdef __cplusplus +extern "C" { -void led_off(void); +#endif +typedef struct { + GPIO_TypeDef *port; + uint16_t pin; +} led_t; + +void led_init(const led_t *led); + +void led_on(const led_t *led); + +void led_off(const led_t *led); + +void led_toggle(const led_t *led); +#ifdef __cplusplus +} +#endif #endif //CLION_STM32_LED_H diff --git a/Core/driver/led/include/led_cpp.h b/Core/driver/led/include/led_cpp.h new file mode 100644 index 0000000..c3bfb77 --- /dev/null +++ b/Core/driver/led/include/led_cpp.h @@ -0,0 +1,29 @@ +// +// Created by Wind on 2025/11/9. +// + +#ifndef CLION_STM32_LED_CPP_H +#define CLION_STM32_LED_CPP_H + + +#ifdef __cplusplus + +#include "gpio_base.hpp" + +class LED : public Gpio { +public: + LED(GPIO_TypeDef *port, uint16_t pin); + + ~LED(); + + void ledOn() const; + + void ledOff() const; + + void ledToggle() const; +}; + + +#endif + +#endif //CLION_STM32_LED_CPP_H diff --git a/Core/driver/led/led.c b/Core/driver/led/led.c index 13a5451..c64f4ed 100644 --- a/Core/driver/led/led.c +++ b/Core/driver/led/led.c @@ -4,13 +4,35 @@ #include "led.h" -#include "main.h" - -void led_on(void) { - HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET); +void led_init(const led_t *led) { + const GPIO_TypeDef *port_ = led->port; + if (port_ == GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (port_ == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (port_ == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else if (port_ == GPIOD) + __HAL_RCC_GPIOD_CLK_ENABLE(); + else if (port_ == GPIOE) + __HAL_RCC_GPIOE_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = led->pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(led->port, &GPIO_InitStruct); } -void led_off(void) { - HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET); -} \ No newline at end of file +void led_on(const led_t *led) { + HAL_GPIO_WritePin(led->port, led->pin, GPIO_PIN_SET); +} + +void led_off(const led_t *led) { + HAL_GPIO_WritePin(led->port, led->pin, GPIO_PIN_RESET); +} + +void led_toggle(const led_t *led) { + HAL_GPIO_TogglePin(led->port, led->pin); +} diff --git a/Core/driver/led/led_cpp.cpp b/Core/driver/led/led_cpp.cpp new file mode 100644 index 0000000..66066ed --- /dev/null +++ b/Core/driver/led/led_cpp.cpp @@ -0,0 +1,22 @@ +// +// Created by Wind on 2025/11/9. +// + +#include "include/led_cpp.h" + +LED::LED(GPIO_TypeDef *port, const uint16_t pin) : Gpio(port, pin) { +} + +LED::~LED() = default; + +void LED::ledOn() const { + this->write(true); +} + +void LED::ledOff() const { + this->write(false); +} + +void LED::ledToggle() const { + this->toggle(); +}