Added soft PWM
This commit is contained in:
parent
404618cb8e
commit
9d08b7df59
52
fw/Core/Inc/led.h
Normal file
52
fw/Core/Inc/led.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* led.h
|
||||||
|
*
|
||||||
|
* Created on: Jun 6, 2021
|
||||||
|
* Author: user
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_LED_H_
|
||||||
|
#define INC_LED_H_
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stm32l0xx_hal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context struct
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GPIO_TypeDef *red_led_port;
|
||||||
|
int red_led_pin;
|
||||||
|
GPIO_TypeDef *green_led_port;
|
||||||
|
int green_led_pin;
|
||||||
|
GPIO_TypeDef *blue_led_port;
|
||||||
|
int blue_led_pin;
|
||||||
|
|
||||||
|
} led_context_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Externally defined variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int led_pwm_max;
|
||||||
|
extern int led_pwm_counter;
|
||||||
|
extern int led_red_intensity;
|
||||||
|
extern int led_green_intensity;
|
||||||
|
extern int led_blue_intensity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function prototypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
void led_test();
|
||||||
|
void led_set_color(float red, float green, float blue);
|
||||||
|
// led_off(): turn off all LEDs
|
||||||
|
void led_off();
|
||||||
|
// led_pwm_handler(): handles switching LEDs on/off according to desired intensity;
|
||||||
|
// should be regularly called in timer routine, preferably in SysTick_Handler()
|
||||||
|
void led_pwm_handler();
|
||||||
|
void led_init(led_context_t *context, int pwm_freq, int pwm_handler_freq);
|
||||||
|
void led_test(int r, int g, int b);
|
||||||
|
|
||||||
|
#endif /* INC_LED_H_ */
|
@ -32,7 +32,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN Includes */
|
/* USER CODE BEGIN Includes */
|
||||||
|
#include "led.h"
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Exported types ------------------------------------------------------------*/
|
/* Exported types ------------------------------------------------------------*/
|
||||||
|
121
fw/Core/Src/led.c
Normal file
121
fw/Core/Src/led.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* led.c
|
||||||
|
*
|
||||||
|
* Created on: Jun 6, 2021
|
||||||
|
* Author: user
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
int led_pwm_max;
|
||||||
|
int led_pwm_counter;
|
||||||
|
int led_red_intensity;
|
||||||
|
int led_green_intensity;
|
||||||
|
int led_blue_intensity;
|
||||||
|
int led_red_state;
|
||||||
|
int led_green_state;
|
||||||
|
int led_blue_state;
|
||||||
|
led_context_t *led_context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* led_set_color():
|
||||||
|
* Set LED color
|
||||||
|
* Arguments:
|
||||||
|
* float red: red color intensity, possible values 0.0 ... 1.0
|
||||||
|
* float green: green color intensity, possible values 0.0 ... 1.0
|
||||||
|
* float blue: blue color intensity, possible values 0.0 ... 1.0
|
||||||
|
*/
|
||||||
|
void led_set_color(float red, float green, float blue)
|
||||||
|
{
|
||||||
|
led_red_intensity = red * led_pwm_max;
|
||||||
|
led_green_intensity = green * led_pwm_max;
|
||||||
|
led_blue_intensity = blue * led_pwm_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* led_off():
|
||||||
|
* Set LED intensity to 0 for each color
|
||||||
|
*/
|
||||||
|
void led_off()
|
||||||
|
{
|
||||||
|
led_red_intensity = 0;
|
||||||
|
led_green_intensity = 0;
|
||||||
|
led_blue_intensity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* led_pwm_handler():
|
||||||
|
* handles switching LEDs on/off according to desired intensity;
|
||||||
|
* should be regularly called in timer routine, preferably in SysTick_Handler()
|
||||||
|
*/
|
||||||
|
void led_pwm_handler()
|
||||||
|
{
|
||||||
|
int new_red_state, new_green_state, new_blue_state;
|
||||||
|
|
||||||
|
new_red_state = led_pwm_counter >= led_red_intensity ? 1 : 0;
|
||||||
|
new_green_state = led_pwm_counter >= led_green_intensity ? 1 : 0;
|
||||||
|
new_blue_state = led_pwm_counter >= led_blue_intensity ? 1 : 0;
|
||||||
|
// SysTick() is called at 1 kHz frequency, we don't want to call HAL_GPIO_WritePin() every time
|
||||||
|
if (led_red_state != new_red_state) {
|
||||||
|
HAL_GPIO_WritePin(led_context->red_led_port, led_context->red_led_pin, new_red_state);
|
||||||
|
led_red_state = new_red_state;
|
||||||
|
}
|
||||||
|
if (led_green_state != new_green_state) {
|
||||||
|
HAL_GPIO_WritePin(led_context->green_led_port, led_context->green_led_pin, new_green_state);
|
||||||
|
led_green_state = new_green_state;
|
||||||
|
}
|
||||||
|
if (led_blue_state != new_blue_state) {
|
||||||
|
HAL_GPIO_WritePin(led_context->blue_led_port, led_context->blue_led_pin, new_blue_state);
|
||||||
|
led_blue_state = new_blue_state;
|
||||||
|
}
|
||||||
|
if (++led_pwm_counter > led_pwm_max) {
|
||||||
|
led_pwm_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* led_init():
|
||||||
|
* Saves context and calculates max pwm value. Note that is PWM frequency is low (< 25 Hz),
|
||||||
|
* flickering might be visible. If pwm_handler_freq is low (less than several kHz),
|
||||||
|
* resolution of PWM will be limited
|
||||||
|
* Arguments:
|
||||||
|
* led_context_t *context:
|
||||||
|
* Pointer to LED context struct, which contains port and pin for each LED
|
||||||
|
* int pwm_freq:
|
||||||
|
* Desired frequency of PWM in Hz (e.g. 25 Hz)
|
||||||
|
* int pwm_handler_freq:
|
||||||
|
* Frequency of led_pwm_handler() calls. Eequal to timer frequency if timer callback is used,
|
||||||
|
* e.g. if led_pwm_handler() is called within SysTick_Handler(), then frequency is
|
||||||
|
* HAL_TICK_FREQ_1KHZ
|
||||||
|
*/
|
||||||
|
void led_init(led_context_t *context, int pwm_freq, int pwm_handler_freq)
|
||||||
|
{
|
||||||
|
// save context
|
||||||
|
led_context = context;
|
||||||
|
// Initial values
|
||||||
|
led_red_intensity = 0;
|
||||||
|
led_red_state = 1; // state is inverted (LEDs are sinking current into MCU)
|
||||||
|
led_green_intensity = 0;
|
||||||
|
led_green_state = 1;
|
||||||
|
led_blue_intensity = 0;
|
||||||
|
led_blue_state = 1;
|
||||||
|
// calculate PWM counter overflow value (max value)
|
||||||
|
// e.g. for 1 kHz handler freq and 25 Hz PWM freq, we only have
|
||||||
|
// resolution of 40 steps for pwm
|
||||||
|
led_pwm_max = pwm_handler_freq / pwm_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_test(int r, int g, int b)
|
||||||
|
{
|
||||||
|
HAL_GPIO_WritePin(led_context->red_led_port, led_context->red_led_pin, r);
|
||||||
|
HAL_GPIO_WritePin(led_context->green_led_port, led_context->green_led_pin, g);
|
||||||
|
HAL_GPIO_WritePin(led_context->blue_led_port, led_context->blue_led_pin, b);
|
||||||
|
}
|
@ -93,27 +93,38 @@ int main(void)
|
|||||||
MX_I2C1_Init();
|
MX_I2C1_Init();
|
||||||
MX_LPUART1_UART_Init();
|
MX_LPUART1_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
/* Create LED context */
|
||||||
|
led_context_t led_context;
|
||||||
|
led_context.red_led_port = LED_R_GPIO_Port;
|
||||||
|
led_context.red_led_pin = LED_R_Pin;
|
||||||
|
led_context.green_led_port = LED_G_GPIO_Port;
|
||||||
|
led_context.green_led_pin = LED_G_Pin;
|
||||||
|
led_context.blue_led_port = LED_B_GPIO_Port;
|
||||||
|
led_context.blue_led_pin = LED_B_Pin;
|
||||||
|
led_init(&led_context, 25, 1000);
|
||||||
/* Turn off all LEDs */
|
/* Turn off all LEDs */
|
||||||
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, 1);
|
led_off();
|
||||||
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, 1);
|
led_set_color(0.1, 0.0, 0.0);
|
||||||
HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 1);
|
// led_test(0,0,0);
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
/* USER CODE BEGIN WHILE */
|
/* USER CODE BEGIN WHILE */
|
||||||
|
int counter = 0;
|
||||||
|
float R = 0.0, G = 0.0, B = 0.0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
|
led_pwm_handler();
|
||||||
HAL_Delay(500);
|
if (counter % 1000 == 0) {
|
||||||
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
|
R += 0.05;
|
||||||
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
|
G += 0.01;
|
||||||
HAL_Delay(500);
|
B += 0.02;
|
||||||
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
|
if (R > 1.0) R = 0;
|
||||||
HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin);
|
if (G > 1.0) G = 0;
|
||||||
HAL_Delay(500);
|
if (B > 1.0) B = 0;
|
||||||
HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin);
|
led_set_color(R, G, B);
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
/* USER CODE END WHILE */
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
/* USER CODE BEGIN 3 */
|
/* USER CODE BEGIN 3 */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "stm32l0xx_it.h"
|
#include "stm32l0xx_it.h"
|
||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN Includes */
|
/* USER CODE BEGIN Includes */
|
||||||
|
#include "led.h"
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
@ -130,7 +131,7 @@ void SysTick_Handler(void)
|
|||||||
/* USER CODE END SysTick_IRQn 0 */
|
/* USER CODE END SysTick_IRQn 0 */
|
||||||
HAL_IncTick();
|
HAL_IncTick();
|
||||||
/* USER CODE BEGIN SysTick_IRQn 1 */
|
/* USER CODE BEGIN SysTick_IRQn 1 */
|
||||||
|
// led_pwm_handler();
|
||||||
/* USER CODE END SysTick_IRQn 1 */
|
/* USER CODE END SysTick_IRQn 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,5 +68,6 @@
|
|||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="4"/>
|
<listEntry value="4"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
|
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="reserved-for-future-use"/> "/>
|
||||||
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
|
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
Loading…
Reference in New Issue
Block a user