PWM(Pulse Width Modulation)
출력의 주파수는 Auto Reload 값(ARR)에 결정되며 duty ratio는 Capture Compare(CCR)값에 의해 결정된다.
PWM 출력 발생 모드는 Mode 1, Mode 2에 따라 구분된다.
Mode 1
Up Counting일 때 Count 값이 CCR보다 작으면 1을 Count값이 CCR보다 같거나 크면 0을 출력한다.
Mode 2
Up Counting일 때 Count 값이 CCR보다 작으면 0을 Count값이 CCR보다 같거나 크면 1을 출력한다.
ARR(Auto-Reload Register)
ARR은 주기적인 PWM 신호의 주기를 설정하는 레지스터다. 주로 타이머의 설정 중 하나다.
주기 = Timer Clock 속도 / (ARR 값 + 1)이 된다.
CCR(Channel Compare Register)
CCR은 PWM 신호의 듀티 사이클(일정 시간 동안 신호가 활성화되어 있는 시간)을 설정하는 레지스터다.
타이머가 ARR 값에 도달할 때마다 CCR 값과 비교하여 PWM 신호의 ON 상태를 제어한다.
ON 시간 = CCR 값 / (ARR 값 + 1) * 주기
위 그림은 위의 설명을 그림으로 나타낸 것이다. ARR을 기준으로 CCR 값에 달 펄스 폭의 변조되는 위치가 바뀌는 것을 확인 할 수 있다.
PWM는 TIM을 통해 설정할 수 있다.
TIM과 PWM을 사용할 채널을 설정해준다.
이전 TIM 글에서 각 TIM는 APB1 or APB2 중 하나를 사용하는 것을 알 수 있다. 현재 TIM가 사용하는 APB를 잘 확인하고 PWM을 위한 주기를 계산해 주어야 한다.
우선 TIM의 주기를 Prescaler와 ARR를 통해 조절 할 수 있다.
TIM3의 경우 84MHz를 클럭을 사용하고 있기 때문에 Prescaler 8400, ARR 10000을 사용하게 되면 1초에 한번의 주기가 생성된다.
위 설정에서 CCR의 값을 5000으로 설정하게 되면 ARR의 절반 값이기 때문에 Up Counting / Mode 1일 경우 1초의 주기동안 0.5초동안 1을 나머지 0.5초 동안 0의 신호를 전달하게 된다.
위 오실로스코프의 측정 결과는 주기가 동일한 2개의 신호에서
1. 초록색 : CCR의 값이 ARR의 값의 1/10
2. 노란색 : CCR의 값이 ARR의 값의 1/5
일 때 신호를 측정한 결과다.
PWM_Start 함수를 통해 PWM을 사용하는 TIM Port와 PWM Channel를 선언해준다.
PWM Channel을 설정해주게 되면 위와 같이 TIM_Init() 함수에 CCR에 해당하는 코드가 생성된 것을 확인할 수 있다.
PWM를 이용한 모터 제어
공식 홈페이지에서 확인할 결과 s90을 동작시키기 위해 3개의 선이 존재하고 PWM 의 펄스 주기는 50Hz (20ms)가 되어야 한다.
또한 펄스 폭의 최소는 0.2ms / 최대는 3ms다.
현재 TIM3을 사용하고 있고, TIM3의 경우 Clock Configuration을 보게되면 84MHz를 사용하고 있기 때문에 해당 클럭을 50Hz로 줄여줘야 한다.
84MHz를 50Hz로 나누게 되면 16,800,000Hz가 된다. 해당 16,800,000Hz를 Perscaler와 ARR을 통해 클럭을 조절할 수 있다.
Prescaler가 168일 경우 클럭 주기는 500,000Hz가 되고 ARR을 10,000으로 설정할 경우 1/500,000초마다 1칸씩 Count되고, 10,000이 Count되기 위해서는 10,000/500,000초 = 0.02ms가 걸리게 된다. 또한 펄스 주기는 시간의 역수이기 때문에 50Hz가 된다.
ARR을 통해 펄스 주기를 조절하게 되고, CCR을 통해 duty cycle을 조절할 수 있다.
ARR을 10000으로 설정했을 경우 최소 펄스 폭은 0.2ms이기 때문에 20ms 주기를 0.2ms로 만들기 위해선 CCR의 최소값은 100으로 설정해줘야 하고, 최대 3ms를 만들기 위해서는 CCR 최소값의 15배를 만들어주면 된다.
TIM의 PWM을 사용하기 위해 PWM을 시작시켜준다.
* GUI에서 설정하는 값들은 결국 편의성을 위한 것이다. code generation 이 후 해당 레지스터에 직접 접근하게 되면 Presclaer, ARR, CCR 값 전부 초기 설정과 다르게 변경할 수 있다.
위 코드와 같이 CCR 레지스터에 직접 접근하여 값을 변경시킬 수 있다.
위 코드는 GUI에서 설정한 값이 초기 상태가 되지만 value 변수를 통해서 CCR 값을 전달받고, ARR 보다 작을 때 까지 계속 커지는(모터의 각도가 최소에서 최대가 되게 만드는 코드) 코드에 해당한다.
PWM을 이용하여 부저 멜로디 만들기
부저도 모터와 마찬가지로 PWM을 이용하여 소리를 만들 수 있고, 주파수를 조절하여 음을 조절할 수 있다.
아래는 부저에 소리를 내기위한 조건이고,
구동전원 : 3.3V ~ 5V
펄스주기 : 음계주파수
펄스폭 : 항상 50%
아래는 소리를 내기위한 주파수를 나타낸 표에 해당한다.
도~시까지 각 계이름에 맞게 소리를 내기 위한 값을 enum 타입으로 생성한다.
enum 배열을 통해 원하는 악보의 멜로디를 생성한다. (위 멜로디는 학교종이 땡땡땡에 해당한다.)
부저의 경우 펄스 폭은 50%로 일정하고 펄스 주기를 통해 음계를 변경한다.
TIM3번의 ARR 레지스터에 접근하여 enum을 통해 생성한 계이름 주파수 값을 전달하여 ARR의 값을 for문을 통해 반복하며 출력한다.
부저의 계이름은 각 주파수가 존재하기 때문에 ARR 레지스터에 값을 전달할 때 전달 받는 초기 Clock 값과 Prescaler 값과 ARR 값을 조절하여 타이머의 주파수를 조절해야 한다.
타이머 주파수 => 공급 Clock / (PSC * ARR)
'Embedded > 1. STM32, Arduino' 카테고리의 다른 글
STM32 - OC (Output Capture) (0) | 2024.06.24 |
---|---|
STM32 - RTC (Real Time Clock), Alarm을 통한 시간 및 알람 출력 (0) | 2024.06.20 |
HAL 함수 모음 (GPIO, EXTI, UART, ADC, DAC, TIM...) (0) | 2024.06.16 |
Clock Configuration, UART 글자 깨짐 현상 해결 방법 (0) | 2024.06.12 |
STM32 - Clock, Timer 구현 (SysTick, Timer 사용) (0) | 2024.06.11 |