⏰ 실습 목표
PWM (펄스 폭 변조) 신호를 LED1이 연결된 포트에 전달하여 LED를 작동시키고 DutyCycle을 변경시켜 LED의 밝기를
아래 2가지 방법으로 변경한다.
1.1 시간 경과에 따라서 LED 밝기를 변경시킨다.
1.2 버튼 눌름 여부에 따라서 LED 밝기를 변경시킨다.
⏰ Tim3 세팅
동작을 알아보기 위해서 TIM2, TIM3(General Purpose Timer)의 세팅을 각각 아래와 같이 하였습니다.
위 그림에서 LD1과 연결된 Pin은 PB0임을 알 수 있으며 PB0에 TIM3_CH3를 연결하였습니다.
Counter Settings
Prescaler와 Counter Period 설정을 통해 타이머 동작 설정
1. TIM2
Prescaler : 8399, Counter Period : 9999, Update Cycle : 1초 -> (1초마다 동작을 확인하기 위한 타이머)
2. TIM3
Prescaler : 83, CounterPeriod : 9999, PWM Pulse : 0, Update Cycle : 100초 -> (LED 밝기 변화를 확인하기 위한 타이머)
Slave Mode
해당 타이머가 독자적으로 동작하는 것이 아닌 다른 타이머 또는 외부 장치의 신호에 따라 on/off 등의 제어가 필요할 때
사용하며 아래 4가지 세부 모드가 있다. 추가로 어떠한 신호(Trigger Source)를 사용할 것인지 아래에서 설정해야 한다.
1. External Clock Mode
다른 외부 장치의 UEV(Update 이벤트)를 가져와 Clock을 제어한다.
2. Reset Mode
다른 외부 장치의 UEV(Update 이벤트)를 받았을 때 해당 타이머의 카운트는 Reset 된다.
3. Gated Mode
Slave 타이머의 시작, 중지를 외부 트리거 신호를 통해 제어할 수 있게 하는 모드
4. Trigger Mode
Slave 타이머의 시작만을 트리거 신호를 통해 제어할 수 있게 하는 모드(※ 중지는 불가)
Trigger Source
Slave Mode(External Clock Mode)로 선택 되었을 경우 사용할 Trigger를 선택한다.
크게 ITR(Internal Trigger)와 ETR(External Trigger)로 나뉘며
ITR의 경우에는 아래와 같이 내부에 있는 다른 타이머로 부터의 트리거를 사용할 수 있게 된다.
Clock Source
Clock Source를 내부 Internal Clock을 사용할 것인지 외부(ETR 핀에 연결된 장치)로 부터 가져올 것인지 선택한다.
Channel
Timer의 펄스를 In 또는 Out에 대한 설정을 각 채널(Pin)별로 할 수 있으며 IN의 경우 크게 OC 모드와 PWM 모드가 있으며
Out의 경우 채널(Pin)로 아웃, No Out이 있다.
-PWM 모드 1: TIMx_CNT < TIMx_CCRx 출력이 LOW인 경우 그렇지 않으면 HIGH
-PWM 모드 2: TIMx_CNT < TIMx_CCRx 출력이 HIGH인 경우 그렇지 않으면 LOW
-OC 모드 1: TIMx_CNT == TIMx_CCRx 일치 시 HIGH
-OC 모드 2: TIMx_CNT == TIMx_CCRx 일치 시 LOW
1. Output Compare No Output
카운터의 값(CNT)과 설정한 값(CCRx)이 일치할 때 출력 핀에 출력을 생성하진 않는 경우
(※ 단순히 타이머의 주기를 측정하거나 특정 값을 측정 해당 값을 전자 장치등에 전달하진 않는 경우에 사용한다.)
2. Output Compare Channel
카운터의 값(CNT)과 설정한 값(CCRx)이 일치할 때 출력 핀에 출력을 생성하는 경우
3. Pwm Generation No Output
PWM 신호를 생성하면서 생성한 클럭 정보를 실제 출력 핀에 출력을 생성하진 않는 경우
4. Pwm Generation Channel
PWM 신호를 생성하면서 생성한 클럭 정보를 실제 출력 핀에 출력을 생성하는 경우
⏰ 주요 함수
HAL_TIM_Base_Start
//Base 카운터의 시작 함수
HAL_TIM_PWM_Start
//해당 타이머의 pwm 출력 시작
HAL_TIM_SET_COMPARE
//해당 함수를 통해 원하는 타이머의 Duty 비를 변경할 수 있으며 Duty 비를 통해 LD1의 밝기를 컨트롤 할 수 있다.
⏰ 실습 결과
https://github.com/Tobbyvv/stm32-project/tree/main/timer
시간 경과에 따라서 LED 밝기를 변경시킨다.
버튼 눌름 여부에 따라서 LED 밝기를 변경시킨다.
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include "main.h"
#include "app.h"
extern TIM_HandleTypeDef htim2; // 타이머 핸들러 가져옴
extern TIM_HandleTypeDef htim3;
extern UART_HandleTypeDef huart3; // uart 핸들러 가져옴
#define D_DUTY_MAX 1000 // 최대 duty 값
bool exti_flag = false; // 외부 인터럽트 플래그 선언
static void app_init(void);
void app(void)
{
int16_t duty = 0; //pwm duty 변수 선언
volatile bool dir_flag = true; //duty 증가 감소 방향 flag 선언
volatile uint32_t prev, curr; //현재 시간, 이전 시간 변수 선언
printf("System started.....\r\n");
app_init();
prev = curr = HAL_GetTick();
while (1)
{
#if 1 // 시간 방식 duty가 Max 1000을 기준으로 50씩 감소 또는 증가
curr = HAL_GetTick();
if (curr - prev > 25) {
if (dir_flag == true) {
duty += 50;
if (duty > D_DUTY_MAX) {
dir_flag = false;
duty = D_DUTY_MAX;
}
} else if(dir_flag == false) {
duty -= 50;
if (duty < 0) {
dir_flag = true;
duty = 0;
}}
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, (uint16_t)duty);
//TIM3 PWM 채널 3의 duty 주기를 계속해서 적용시킴
prev = curr;
}
#else // 버튼 방식 버튼을 눌렀을 때 99씩 duty 증가 MAx 1000이 되면 duty를 0으로
if (exti_flag == true) {
exti_flag = false;
duty += 99;
if (duty > 1000) duty = 0;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, duty);
}
#endif
}}
// 애플리케이션 초기화 함수 정의
static void app_init(void)
{
printf("Timer2,3 Base start\r\n");
// TIM2&TIM3 Base 타이머 시작
HAL_TIM_Base_Start(&htim2);
HAL_TIM_Base_Start(&htim3);
// TIM3 채널3 PWM 시작
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
}
// 외부 입출력 Callback 함수
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint32_t prev;
volatile uint32_t curr = HAL_GetTick();
if (curr - prev > 150 ) { //인터럽트 발생 최소 간격 0.15초
if (GPIO_Pin == GPIO_PIN_13) exti_flag = true;
prev = curr;
}}
// UART 출력 함수
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
[참조]
'embedded' 카테고리의 다른 글
[stm32] UART 실습 (0) | 2023.08.30 |
---|---|
[stm32] UART 이론 정리 (0) | 2023.08.16 |
[stm32] Timer 이론 정리 (0) | 2023.08.16 |
[stm32] GPIO 실습 (0) | 2023.08.13 |
[stm32] GPIO 이론 정리 (0) | 2023.08.12 |