vuoi
o PayPal
tutte le volte che vuoi
Initially, we set up the flowchart:
The differences are in the configuration of the components and the fact that the toggle takes
place automatically.
NOTE: we chose these pins because they are connected to the alternate function of channel 1
(PINA6) and channel 2 (PINA7) of Timer 3.
Secondly, we proceeded with the setup. Since the configuration is very similar to the previous
one, only the changes made are reported:
• Output Compare mode: “Toggle on match” for both channels:
• Pin configuration:
PINA6: alternate function associated with channel 1 of Timer 3;
PINA7: alternate function associated with channel 2 of timer 3.
The HAL functions used are the same.
As for the code, the only difference is the omission of the lines inherent to the pin toggle, as it
happens automatically.
The results obtained on the oscilloscope are the same as for the previous exercise.
3.3 Square wave generation, Output Compare and Interrupts
The goal of this exercise is to use interrupts to generate three square waves with different
periods using timer 3:
• Channel 1: 1 ms period;
• Channel 2: 2 ms period;
• Channel 3: 4 ms period.
We began by developing the flowchart:
In the default conditions, the timer and its channels are enabled, the interrupt for timer 3 is
activated, and the values for PSC and CCR are set. Then, the system waits for an interrupt event
from one of the channels, which indicates when the CCR value has been reached. At that point,
the pin is toggled, and the CCR value is updated.
NOTE: With the HAL, the interrupt flag is automatically cleared.
Moving on to the configuration:
• Setting the timer frequency to 84MHz and configuring the three output channels, no
output appears, as in exercise 1;
• Enable Timer Interrupt 3;
• Calculating the values to be written to the Output Compare registers according to the
desired frequency: 84
= = = 1
1 ( ( ( )
+ 1) ∙ ( ) + 1) ∙
1 1
84
= = = 500
2 ( ( ) ( ( )
+ 1) ∙ + 1) ∙
2 2
84
= = = 250
3 ( ( ) ( ( )
+ 1) ∙ + 1) ∙
2 3
We decide to set the making sure to get an OCR value lower than the value of
= 83,
and that we obtain integer results in the calculations, allowing us to write the
(65535)
values to OCR. The toggle function is also used here to generate the signal. Therefore, to
calculate the OCR value, the signal frequency is doubled.
From the calculations: 84
= = 1000
1 (83 (1)
+ 1) ∙ 2 ∙
84
= = 2000
2 (83 (500)
+ 1) ∙ 2 ∙
84
= = 4000
2 (83 (250)
+ 1) ∙ 2 ∙
Below is the setup in the graphical interface:
• Pin Configuration
PA6 in output mode;
PA7 in output mode;
PB0 in output mode.
Afterward, we proceeded with reading the manual, from which we identified the following
functions:
• HAL_GPIO_TogglePin(): toggle the state of a GPIO pin;
1. HAL_TIM_OC_Start_IT (): starts the Timer in Output Compare mode with Interrupt
enabled;
1. __HAL_TIM_SET_COMPARE(): updates the compare value for a specific channel of a
timer;
1. __HAL_TIM_GET_COMPARE(): returns the current compare value for a specific channel
of a timer;
1. HAL_TIM_OC_DelayElapsedCallback(): is a callback function automatically called by
the HAL when an "Output Compare" Interrupt occurs on a Timer.
At this point, we started writing the code:
#include "main.h"
int main(void)
{
// Start the three channels in Output Compare mode with Interrupt
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2);
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_3);
while (1)
{
}
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) {
// Check if interrupt is coming from TIM3
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { // Check TIM3 channel 1
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_6); // Toggle PA6 pin state
// Update comparison value for next event on TIM3 Channel 1
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1) +
1000);
}
else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { // Check TIM3 channel 2
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_7); // Change state of pin PA7
// Update the comparison value for the next event on TIM3 Channel 2
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_2, __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_2) +
2000);
}
else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) { // Check TIM3 channel 3
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // Change state of pin PB0
// Update comparison value for next event on TIM3 Channel 3
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_3, __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_3) +
4000);
}
}
Finally, we ran the code and displayed the results on the oscilloscope:
The results showed a perfect match between ideal and real behavior, which underlines the
efficiency of .
3.4 Square wave generation, and GPIO interrupts
In this exercise, a GPIO Interrupt functionality is added to change the state of the LED (PINA5)
when the pushbutton (PC13) is pressed. To implement this functionality via Interrupt, the
pushbutton must be associated with an EXTI (External Interrupt) line, meaning that PINC13 is
configured to generate a Hardware Interrupt Event whenever it detects a specific condition, in
this case, the pressing of the pushbutton.
First, we created the flow chart:
What is added compared to the previous exercise is the setup of the LED and the pushbutton,
along with the toggling of the LED in case of an EXTI interrupt.
We then proceeded with the configuration of the peripherals:
• Timer 3 has been configured exactly like the last exercise, as well as pins PA6 PA7 and
PINB0;
• PINA5 in output mode;
• PINC13 in EXTI sensitive to the falling edge;
• Activation the EXTI Interrupt:
Regarding the HAL functions, compared to the previous exercise, the function
HAL_GPIO_EXTI_Callback() was added, which is the callback function for the Interrupt
generated by the EXTI.
Moving on to the code, we report only the part added to Exercise 3’s code:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{ if (GPIO_Pin == GPIO_PIN_13) // PC13 è il pin associato al pulsante
{ HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle del LED su PA5
}
}
After running the program, we checked that the program was working correctly.
3.5 LED dimmer
This exercise focuses on controlling the brightness of a LED using PWM (Pulse Width
Modulation). PWM is a technique where a timer is configured to generate a periodic signal with
an adjustable duty cycle. The timer counts from 0 to a maximum value (ARR). When the count
reaches a predefined value in the CCR, the signal toggles. The duty cycle is adjusted by
changing the CCR, while the frequency is determined by the ARR and the prescaler (PSC).
To control the LED brightness without visible flickering, a PWM frequency of 100 Hz is used.
Timer2 generates the fixed-frequency PWM signal, while Timer 3 periodically adjusts Timer2's
duty cycle to control the LED's brightness. Timer2 is configured to produce a square wave with
an initial duty cycle, and its output is connected to pin PINA5 (LED). Meanwhile, Timer3
operates as a periodic timer: each time it triggers an update event, it modifies the CCR value of
Timer2, thereby altering the on/off time ratio of the LED relative to the full period. This creates a
dimming effect that increases or decreases the brightness gradually, without changing the
frequency of the PWM signal.
The first step was creating the flowchart:
Next, we proceeded with the configuration:
Set the timer frequency to 84 MHz from the Clock Configuration;
• Enable Timer 2 and configure channel 1 in PWM mode;
•
• Enable Timer3 in OC and its Interrupt:
• Calculate the values for the ARR, CCR and PSC registers for the timers:
The goal is to gradually increase and decrease the brightness of the LED in a continuous cycle
of 2 seconds, where the duty cycle changes from 0% to 100% (in 1 second) and back again (in
1 second), using:
- Timer2 to generate the PWM signal with a frequency of 100 Hz;
- Timer3 to periodically update the value of the duty cycle of Timer2.
The frequency of 100 Hz for the PWM on Timer2 requires the following calculation:
= ( + +1) ∙
For a frequency of 100 Hz it was decided to use a PSC = 839 and an ARR = 1000.
Since the duty cycle must vary from 0% to 100% in 1 second, then 20 increments or decrements
in 1 second, the Timer3 interrupt must be set for a period of 50 ms:
1
= =
50 ( + +1) ∙
We set PSC = 8399 and CCR = 100 to get the desired frequency.
• Configuration of PINA5 (LED) in alternate function linked to Timer2:
Regarding the HAL functions used:
• HAL_TIM_PWM_Star(): starts generating the PWM signal on a specific channel;
1. HAL_TIM_Base_Start_IT(): starts the timer with Interrupt enabled;
1. __HAL_TIM_SET_COMPARE(): updates the compare value for a specific channel of a
timer;
1. void HAL_TIM_PeriodElapsedCallback(): callback function called whenever the timer
has completed a period.
The next step was writing the code:
#include "main.h"
uint32_t duty_cycle = 0; // Current duty cycle
int8_t direction = 1; // Direction of change: +1 (increase) or -1 (decrease)
int main(void)
{ // Start PWM on TIM2
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
// Start TIM3 in interrupt mode
HAL_TIM_Base_Start_IT(&htim3);
while (1)
{
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{ if (htim->Instance == TIM3) // Controlla che l'interrupt provenga da TIM3
{ // Cambia il duty cycle gradualmente
duty_cycle += direction;
// Gestione del ciclo di aumento/diminuzione
if (duty_cycle >= 100)
{ duty_cycle = 100;
direction = -1; // Inizia a diminuire
}
else if (duty_cycle <= 0)
{ duty_cycle = 0;
direction = 1; // Inizia ad aumentare
}
// Aggiorna il registro di confronto per cambiare il duty cycle
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 10 * duty_cycle);
}
}
Finally, verified the correct functioning of the program, below the images representing the
different intensities of the LED. Figure 2 High britness of the green LED
Figur