2017-04-15 2 views
0

저는 AVR C 프로그래밍에 익숙하지 않습니다. LED에 조광기 역할을하는 Atmega328p 카운터/타이머에서 16 비트 타이머를 사용하여 간단한 PWM을 테스트하고 있습니다.16 비트 타이머 PWM LED 조광기

내 코드 :

#define F_CPU 16000000UL 

void initTimer(); 

int x = 1; 
int n = 1000; 

int main(void) 
{ 

    initTimer(); 

    DDRB |= (1 << PB1)| (1 << PB2); 

    while(1) 
    { 
     x++; 

     if(x > 65) { 
      x = 1; 
     } 
    } 
} 

void initTimer() { 

    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); 
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 
    // used for TOP, makes for 50 Hz PWM 
    ICR1 = 40000; 
    OCR1A = n * x; 

} 

ISR(TIMER1_OVF_vect) 
{ 
    OCR1A = n * x; 
} 

문제점이 조광 효과를 표시하지 않는다는 것이다에서, LED의 밝기는 그 가정하자 I 처음 OCR1A (PB1) 출력 핀에 설정된 어떤 값으로 일정하게 유지 인터럽트가 발생했을 때 값을 변경하는 것만으로도이 작업을 수행하지 않는 것이 간단한 테스트 일 수 있습니다. 무엇이 잘못 되었습니까?

업데이트

: OCR1A의 원래 값이 지정되었습니다 조언으로

내가 TIMSK1 레지스터와 SEI는(), 그러나 여전히 LED 밝기 같은 문제가 일정하게 유지를 사용하여 인터럽트를 사용 가능으로 무엇에 initTimer().

int main(void) 
{ 
    initTimer(); 
    DDRB |= (1 << PB1)| (1 << PB2); 

    while(1) 
    { 
     x++; 
     if(x > 65) { 
      x = 1; 
     } 
    } 
} 

void initTimer() { 

    ICR1 = 40000; 
    OCR1A = n * x; 
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); 
    TIMSK1 |= (1 << ICIE1); 
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 
    sei(); 
} 

ISR (TIMER1_COMPA_vect) 
{ 
    OCR1A = n * x; 
} 

내가 다른 방법을 시도하지만 그 날 디밍을 제공은 영향 :

int main(void) 
{ 

    initTimer(); 

    DDRB |= (1 << PB1)| (1 << PB2); 

    while(1) 
    { 
     _delay_ms(20); 
     OCR1A = n * 4; 
     _delay_ms(20); 
     OCR1A = n * 8; 
     _delay_ms(20); 
     OCR1A = n * 15; 
     _delay_ms(20); 
     OCR1A = n * 25; 
     _delay_ms(20); 
     OCR1A = n * 1; 

    } 
} 

void initTimer() { 

    ICR1 = 40000; 
    OCR1A = n * x; 
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); 
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 

} 

그래서 문제가 PWM이 작품에 영향을 미칠하지만 단지 인터럽트 핸들러와 함께 작동하지 않는 때문에 인터럽트 것 같다 .

답변

1

나와 함께 뛰어 내리는 첫 번째 일은 x와 n이 휘발성이어야한다는 것입니다. 또한 TIMSK0 레지스터에서 인터럽트를 활성화해야합니다. 또한 sei를 호출하여 인터럽트를 활성화하십시오.

내가 너라면, 좋은 예제 코드를 알고있는 것으로 시작하겠다. 내가 언급 한 페이지에는 4ms마다 인터럽트를 발생시키는 예제가 있습니다. 해당 코드를 가져와 리드 온/오프를 토글합니다.

또 다른 문제는 isr이 호출되었는지 여부에 관계없이 x를 변경하고 있다는 것입니다. 그래서 실제로 isr에서 무작위 x를 얻을 것입니다. 이 코드는 단순하여 충분히 단순한 패턴으로 고정 될 수 있습니다. 대신 x의 설정을 isr로 이동하십시오.

다음은 avr 타이머에 대한 좋은 소개입니다. https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328