diff --git a/examples/stm32cube-hal-pwm-breathing/.gitignore b/examples/stm32cube-hal-pwm-breathing/.gitignore new file mode 100644 index 000000000..89cc49cbd --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/examples/stm32cube-hal-pwm-breathing/.vscode/extensions.json b/examples/stm32cube-hal-pwm-breathing/.vscode/extensions.json new file mode 100644 index 000000000..080e70d08 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/examples/stm32cube-hal-pwm-breathing/include/README b/examples/stm32cube-hal-pwm-breathing/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/stm32cube-hal-pwm-breathing/lib/README b/examples/stm32cube-hal-pwm-breathing/lib/README new file mode 100644 index 000000000..2593a33f9 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/stm32cube-hal-pwm-breathing/platformio.ini b/examples/stm32cube-hal-pwm-breathing/platformio.ini new file mode 100644 index 000000000..c181e1cf2 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/platformio.ini @@ -0,0 +1,33 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:nucleo_f030r8] +platform = ststm32 +framework = stm32cube +board = nucleo_f030r8 +build_flags = -DF0 + +[env:nucleo_f070rb] +platform = ststm32 +framework = stm32cube +board = nucleo_f070rb +build_flags = -DF0 + +[env:nucleo_f072rb] +platform = ststm32 +framework = stm32cube +board = nucleo_f072rb +build_flags = -DF0 + +[env:nucleo_f091rc] +platform = ststm32 +framework = stm32cube +board = nucleo_f091rc +build_flags = -DF0 diff --git a/examples/stm32cube-hal-pwm-breathing/src/main.c b/examples/stm32cube-hal-pwm-breathing/src/main.c new file mode 100644 index 000000000..513a5c072 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/src/main.c @@ -0,0 +1,182 @@ +/* + * STM32Cube HAL - PWM Breathing LED Example + * + * This example demonstrates a smooth "breathing" LED effect using PWM. + * It is compatible with STM32F0 series boards. + * + * Supported Boards: + * - Nucleo-F030R8 + * - Nucleo-F070RB + * - Nucleo-F072RB + * - Nucleo-F091RC + * + * Hardware Setup: + * - PA5: Connect the onboard LED pin in analog mode. + * - PA6: PWM output using TIM3 Channel 1. + * - Jumper wire from PA6 to PA5. + * + * Author: Kiran Jojare + */ + +#if F0 +#include "stm32f0xx_hal.h" +#else +#error "Unsupported STM32 Family" +#endif + +#include + +// LED GPIO Pin and Timer Definitions +#define LED_PIN GPIO_PIN_5 +#define LED_GPIO_PORT GPIOA +#define LED_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define PWM_PIN GPIO_PIN_6 +#define PWM_GPIO_PORT GPIOA +#define PWM_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define PWM_GPIO_AF GPIO_AF1_TIM3 +#define PWM_TIMER TIM3 +#define PWM_CHANNEL TIM_CHANNEL_1 + +// Function Prototypes +void SystemClock_Config(void); +void Error_Handler(void); +static void MX_GPIO_Init(void); +static void MX_TIM3_Init(void); + +// Timer Handle +TIM_HandleTypeDef htim3; + +int main(void) +{ + // HAL Initialization + HAL_Init(); + + // Configure System Clock + SystemClock_Config(); + + // Initialize GPIO and Timer + MX_GPIO_Init(); + MX_TIM3_Init(); + + // Start PWM Output + if (HAL_TIM_PWM_Start(&htim3, PWM_CHANNEL) != HAL_OK) + { + Error_Handler(); + } + + // Variables for Breathing Effect + float phase = 0.0f; // Phase of the sine wave + uint32_t duty_cycle; + + while (1) + { + // Calculate Duty Cycle with Sinusoidal Variation + duty_cycle = (uint32_t)((sinf(phase) + 1.0f) * 500); // Scale to 0-1000 range + __HAL_TIM_SET_COMPARE(&htim3, PWM_CHANNEL, duty_cycle); + + // Increment Phase + phase += 0.05f; // Adjust for breathing speed + if (phase >= 2 * M_PI) + { + phase -= 2 * M_PI; + } + + HAL_Delay(10); // Smooth breathing effect + } +} + +// System Clock Configuration +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + // Configure the main internal regulator output voltage + HAL_PWR_EnableBkUpAccess(); + + // Initializes the RCC Oscillators + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; // Use HSI as PLL source + RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1; // Prescaler + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; // PLL Multiplier for 48 MHz + 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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // Use PLL as system clock source + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB Prescaler + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 Prescaler + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) + { + Error_Handler(); + } +} + + +// GPIO Initialization +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + // Enable GPIOA Clock + LED_GPIO_CLK_ENABLE(); + PWM_GPIO_CLK_ENABLE(); + + // Configure LED Pin (PA5) in Analog Mode + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); + + // Configure PWM Pin (PA6) for Alternate Function + GPIO_InitStruct.Pin = PWM_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = PWM_GPIO_AF; + HAL_GPIO_Init(PWM_GPIO_PORT, &GPIO_InitStruct); +} + +// Timer 3 Initialization for PWM +static void MX_TIM3_Init(void) +{ + TIM_OC_InitTypeDef sConfigOC = {0}; + + __HAL_RCC_TIM3_CLK_ENABLE(); + + htim3.Instance = PWM_TIMER; + htim3.Init.Prescaler = 48 - 1; // 1 MHz Timer Clock + htim3.Init.CounterMode = TIM_COUNTERMODE_UP; + htim3.Init.Period = 1000 - 1; // 1 kHz PWM Frequency + htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + + if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) + { + Error_Handler(); + } + + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + + if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, PWM_CHANNEL) != HAL_OK) + { + Error_Handler(); + } +} + +// Error Handler +void Error_Handler(void) +{ + while (1) + { + } +} diff --git a/examples/stm32cube-hal-pwm-breathing/test/README b/examples/stm32cube-hal-pwm-breathing/test/README new file mode 100644 index 000000000..9b1e87bc6 --- /dev/null +++ b/examples/stm32cube-hal-pwm-breathing/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html