-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimerPWMsoftware.c
More file actions
149 lines (133 loc) · 4.24 KB
/
timerPWMsoftware.c
File metadata and controls
149 lines (133 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* @file timerPWMsoftware.c
* @author Alessandro Ferrante (github@alessandroferrante.net)
* @brief This file implements a software PWM using timer interrupt, to vary the brightness of a LED.
*
* The code configures GPIO pins and external interrupts to control the duty cycle of a PWM signal.
* The PWM signal is generated on pin PB0 with timer (TIM2), and its duty cycle can be adjusted
* using buttons connected to pins PB4 (button Y) and PB10 (button X).
*
* The software PWM is implemented using timer interrupts to generate
* the desired PWM frequency and duty cycle. The module allows for multiple
* PWM channels to be controlled independently.
*
* The main difference between hardware PWM and software PWM is how the PWM signals
* are generated and handled. Here is a summary of the differences:
*
* ? Hardware PWM:
* - Generated by dedicated hardware peripherals within the microcontroller.
* - Produces precise, high-frequency PWM signals with minimal CPU intervention.
* - Ideal for applications that require stable, high-frequency PWM signals.
*
* ? Software PWM:
* - Generated by the CPU using software routines and timers.
* - May be less precise and consume more CPU resources than hardware PWM.
* - Offers more flexibility and can be used on microcontrollers without dedicated PWM hardware.
*
* The basic operation of PWM, i.e. pulse width modulation to control the average power delivered to a load,
* remains the same in both cases. The main difference is in the method of generating the PWM signal.
*
* @version 0.1
* @date 2024-10-18
*
* @copyright Copyright (c) 2024
*
*/
#include "stm32_unict_lib.h"
int T_on, T_off;
#define PERIOD 2000
void setup(void)
{
ClockConfig();
// configure the clock @ 84 MHz
DISPLAY_init();
GPIO_init(GPIOB); // initialize port B
GPIO_init(GPIOC); // initialize port C
GPIO_config_output(GPIOB, 0); // configure pin PB0 as output
GPIO_config_output(GPIOC, 2); // configure pin PC2 as output
GPIO_config_input(GPIOB, 10); // configure pin PB10 as input
GPIO_config_input(GPIOB, 4); // configure pin PB4 as input
GPIO_config_input(GPIOB, 5); // configure pin PB5 as input
GPIO_config_input(GPIOB, 6); // configure pin PB6 as input
GPIO_config_EXTI(GPIOB, EXTI10); // attach PB10 to EXTI10
GPIO_config_EXTI(GPIOB, EXTI4); // attach PB4 to EXTI4
GPIO_config_EXTI(GPIOB, EXTI5); // attach PB5 to EXTI5
GPIO_config_EXTI(GPIOB, EXTI6); // attach PB6 to EXTI6
EXTI_enable(EXTI10, FALLING_EDGE);
EXTI_enable(EXTI4, FALLING_EDGE);
EXTI_enable(EXTI5, FALLING_EDGE);
EXTI_enable(EXTI6, FALLING_EDGE);
T_on = PERIOD / 2;
T_off = PERIOD / 2;
TIM_init(TIM2);
TIM_config_timebase(TIM2, 420, T_off);
TIM_enable_irq(TIM2, IRQ_UPDATE);
TIM_on(TIM2);
}
/**
* @brief
* create a PWM signal on pin GPIOB 0
* with a period that alternates between T_ON and T_OFF
* used to control the brightness of the LED
*/
void TIM2_IRQHandler(void)
{
if (TIM_update_check(TIM2)) {
GPIO_toggle(GPIOB,0);
if (GPIO_read(GPIOB,0) == 1) {
// stato on
TIM2->ARR = T_on;
}
else {
// stato off
TIM2->ARR = T_off;
}
TIM_update_clear(TIM2);
}
}
/**
* @brief Manages the interrupt (of the X button),
* If T_on is greater than 20, decrement
* of 10 units the value of T_on, and update T_off.
*/
void EXTI15_10_IRQHandler(void) {
if (EXTI_isset(EXTI10)) {
// X button, decrement T_on
if (T_on > 20) {
T_on -= 10;
T_off = PERIOD - T_on;
}
EXTI_clear(EXTI10);
}
}
/**
* @brief Manages the interrupt (of the Y button),
* If T_on is less than PERIOD - 20, increment
* of 10 units the value of T_on, and update T_off.
*/
void EXTI4_IRQHandler(void) {
if (EXTI_isset(EXTI4)) {
// Y button, increment T_on
if (T_on < PERIOD - 20) {
T_on += 10;
T_off = PERIOD - T_on;
}
EXTI_clear(EXTI4);
}
}
void EXTI9_5_IRQHandler(void) {
if (EXTI_isset(EXTI5)) {
EXTI_clear(EXTI5);
}
if (EXTI_isset(EXTI6)) {
EXTI_clear(EXTI6);
}
}
void loop(void) {
}
int main() {
setup();
for (;;) {
loop();
}
}