==================================Outline====================================
PWM를 사용한 LED 불 밝기 조절
----------------------------------------------------------------------------
PWM를 사용한 LED 불 밝기 조절
PA0번 핀의 기능을 확인해보자.
![](https://t1.daumcdn.net/cfile/tistory/211B564B5636D2912F)
[PA0]
PA0를 PWM의 출력으로 사용 설정을 해준다.
1. PA/AFIO/TIM2 clock 공급: RCC->APB2ENR, APB1ENR
2. PA 설정: PA0 출력 설정. AFIO를 사용한다. 내부적인 특수 기능을 사용하기 때문에 AFIO를 사용해야 한다.
출력 설정 시 open drain과 push pull을 사용할 수 있다. push/pull은 입출력시 high/low값이 확실하게 구분된다. open drain값은 high출력이 없고 low만 존재한다. open drain은 그라운드 연결을 스위치로 제어하면서 제어하는 방식을 뜻한다.
3. TIM2 설정: TIM2_ARR은 카운팅 시 꼭지점이다. TIM2_CCR은 카운터의 비교 값이 들어있는 레지스터이다. 카운터의 값이 CCR과 일치할 경우 인터럽트가 발생한다.
특정 키를 입력 받았을 때 불 밝기가 조절 되도록 코딩을 해보자.
![](https://t1.daumcdn.net/cfile/tistory/231D7D4B5636D2932B)
/*** 소스 ***/
#include <stm32f10x.h> volatile unsigned int Timer2_Counter=0; void init_port(void) { GPIO_InitTypeDef PORTA; GPIO_InitTypeDef PORTC; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); PORTA.GPIO_Pin = GPIO_Pin_0; PORTA.GPIO_Mode = GPIO_Mode_AF_PP; PORTA.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA, &PORTA); PORTC.GPIO_Pin = GPIO_Pin_12; PORTC.GPIO_Mode = GPIO_Mode_Out_PP; PORTC.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOC, &PORTC); } void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // Clear the interrupt flag Timer2_Counter++; GPIOC->BRR = GPIO_Pin_12; // PB0 OFF } if(TIM_GetITStatus(TIM2,TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM2,TIM_IT_CC1); GPIOC->BSRR = GPIO_Pin_12; // PB0 ON } } void init_Timer2() { NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef OutputChannel; /* TIM2 Clock Enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* Enable TIM2 Global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* TIM2 Initialize */ TIM_TimeBaseStructure.TIM_Period=100-1; // 100kHz TIM_TimeBaseStructure.TIM_Prescaler=24-1; TIM_TimeBaseStructure.TIM_ClockDivision=0; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); /* TIM2 PWM Initialize */ OutputChannel.TIM_OCMode = TIM_OCMode_PWM1; OutputChannel.TIM_OutputState=TIM_OutputState_Enable; OutputChannel.TIM_OutputNState=TIM_OutputNState_Enable; OutputChannel.TIM_Pulse=50-1; // 50% duty ratio OutputChannel.TIM_OCPolarity=TIM_OCPolarity_Low; OutputChannel.TIM_OCNPolarity=TIM_OCNPolarity_High; OutputChannel.TIM_OCIdleState=TIM_OCIdleState_Set; OutputChannel.TIM_OCNIdleState=TIM_OCIdleState_Reset; TIM_OC1Init(TIM2,&OutputChannel); /* TIM2 Enale */ TIM_Cmd(TIM2,ENABLE); TIM_ITConfig(TIM2,TIM_IT_Update | TIM_IT_CC1 ,ENABLE); // interrupt enable } void make_pwm(u16 val) { TIM_OCInitTypeDef OutputChannel; OutputChannel.TIM_OCMode = TIM_OCMode_PWM1; OutputChannel.TIM_OutputState=TIM_OutputState_Enable; OutputChannel.TIM_OutputNState=TIM_OutputNState_Enable; OutputChannel.TIM_Pulse=val; OutputChannel.TIM_OCPolarity=TIM_OCPolarity_Low; OutputChannel.TIM_OCNPolarity=TIM_OCNPolarity_High; OutputChannel.TIM_OCIdleState=TIM_OCIdleState_Set; OutputChannel.TIM_OCNIdleState=TIM_OCIdleState_Reset; TIM_OC1Init(TIM2,&OutputChannel); } void delay(unsigned int del) { Timer2_Counter=0; while(Timer2_Counter < del); } int main() { u16 i; SystemInit(); init_port(); init_Timer2(); while(1) { for(i=0; i<100; i++) { TIM2->CCR1 = i; delay(100); } for(i=98; i>0; i--) { TIM2->CCR1 = i; delay(100); } } } |