ATmega328의 AVR 타이머 속도 향상


9

ATmega328에서 64의 클럭 프리스케일러를 실행할 때, 타이머 중 하나가 특정 시간에 알 수없는 이유로 실행 속도가 빨라집니다.

ATmega328에서 두 개의 타이머를 사용하여 TLC5940에 필요한 클럭킹을 생성하고 있습니다 (아래 이유를 참조하십시오. 이는 중요하지 않습니다). TIMER0Fast PWM을 사용하여 클록 신호를 생성하며 OC0B다음과 같이 설정됩니다.

TCCR0A = 0
    |(0<<COM0A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM0A0)    // 
    |(1<<COM0B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM0B0)
    |(1<<WGM01)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(1<<WGM00)
    ;
TCCR0B = 0
    |(0<<FOC0A)     // Force Output Compare A
    |(0<<FOC0B)     // Force Output Compare B
    |(1<<WGM02)     // Bit 3 – WGM02: Waveform Generation Mode
    |(0<<CS02)      // Bits 2:0 – CS02:0: Clock Select
    |(1<<CS01)
    |(0<<CS00)      // 010 = clock/8
    ;
OCR0A = 8;
OCR0B = 4;
TIMSK0 = 0;

TIMER2256 TIMER0사이클 마다 블랭킹 펄스를 생성하기 위해 데이터 라인을 돌리고 다음과 같이 설정됩니다.

ASSR = 0;
TCCR2A = 0
    |(0<<COM2A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM2A0)    // 
    |(0<<COM2B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM2B0)
    |(0<<WGM21)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(0<<WGM20)
    ;
TCCR2B = 0
    |(0<<FOC2A)     // Force Output Compare A
    |(0<<FOC2B)     // Force Output Compare B
    |(0<<WGM22)     // Bit 3 – WGM02: Waveform Generation Mode
    |(1<<CS22)      // Bits 2:0 – CS02:0: Clock Select
    |(0<<CS21)
    |(0<<CS20)      // 100 = 64
    ;
OCR2A = 255;
OCR2B = 255;
TIMSK2 = 0
    |(1<<TOIE2);    // Timer/Counter0 Overflow Interrupt Enable

TIMER2오버 플로우시 (256주기마다) ISR을 호출합니다. ISR은 수동으로 블랭킹 펄스와 필요한 경우 래칭 펄스를 생성합니다.

volatile uint8_t fLatch;

ISR(TIMER2_OVF_vect) {
    if (fLatch) {
        fLatch = 0;
        TLC5940_XLAT_PORT |=  (1<<TLC5940_XLAT_BIT);        // XLAT -> high
        for (int i=0;i<10;i++)
            nop();
        TLC5940_XLAT_PORT &= ~(1<<TLC5940_XLAT_BIT);        // XLAT -> high
    }
    // Blank
    TLC5940_BLANK_PORT |= (1<<TLC5940_BLANK_BIT);
    for (int i=0;i<10;i++)
        nop();
    TLC5940_BLANK_PORT &= ~(1<<TLC5940_BLANK_BIT);
}

nop()위 코드 의 지연은 로직 분석기 트레이스에서 펄스를보다 명확하게하기위한 것입니다. main()함수 의 루프는 다음과 같습니다. 직렬 데이터를 보내고 ISR이 래칭을 처리 할 때까지 기다린 후 다시 수행합니다.

for (;;) {
    if (!fLatch) {
        sendSerial();
        fLatch = 1;
        _delay_ms(1);
    }
    nop();
}

sendSerial()일부 SPI 전송을 수행합니다 ( 간단히하기 위해 pastebin의 코드 ). 내 문제는 sendSerial()완료 후 fLatch처리 시간을 낮게 설정하기 를 기다리는 동안 클럭 타이머가 빨라진다는 것입니다. 다음은 로직 분석기 트레이스입니다 (동일한 신호가 그래픽을 계속 작게 만드는 영역을 잘라 냈습니다).

여기에 이미지 설명을 입력하십시오

왼쪽에서 채널 0과 1은 전송중인 SPI 데이터의 꼬리 끝을 보여줍니다. 또한 왼쪽의 채널 4에서 블랭킹 펄스를 볼 수 있습니다. 채널 2에서 클럭킹 펄스가 예상대로 맞춰집니다. 이미지의 틈이있는 곳 바로 주위가 루틴 내부 fLatch로 설정됩니다 . 그 후 곧 4 배 정도 속도가 빨라집니다. 결국, 블랭킹 펄스와 래칭 펄스가 수행되고 (채널 3과 4, 이미지의 오른쪽 1/3), 이제 클럭킹 펄스가 규칙적인 주파수를 재개하며 직렬 데이터는 다음과 같습니다. 다시 보냈습니다. 에서 줄을 가져 오려고 했지만 동일한 결과가 나타납니다. 무슨 일이야? ATmega는 20Mhz 크리스탈에서 클럭킹 된 후 다음 코드를 사용하여 64 배 느리게 진행됩니다.1main()TIMER0delay_ms(1);main()

CLKPR = 1<<CLKPCE;
CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0);

TLC5940 LED 드라이버 제어를 실험 중입니다 .이 칩에는 클럭주기가 끝나면 외부 클럭과 리셋이 필요합니다.


디버거가있는 경우 타이머가 너무 빠를 때 코드를 중지하고 해당 타이머의 구성 레지스터를 다시 읽으십시오. 잘못된 값을 가진 값을 찾으면이 레지스터 변경에서 중단 점을 트리거하여 코드의 어떤 부분이 잘못 작동하는지 확인하십시오. 문제는 사용할 수있는 외부 라이브러리에 있으며 지연과 같은 내부 물건에 해당 타이머를 사용한다고 생각합니다.
Blup1980

두 가지 문제 : a) JTAG 프로그래머가 없으므로 칩을 디버깅하는 방법이 없습니다. b) 위에 표시된 설정 후에 타이머 레지스터 값을 변경하지 않으므로 타이머 레지스터 값을 기대하지 않습니다. 실제로 변화합니다. 순진한가요?
angelatlarge

1
실제로 사용하는 하나의 라이브러리가 UART 설정을 변경할 수 있습니다. sendSerial () 함수를 사용하고 있습니다. 코드의 일부입니까, 아니면 외부 라이브러리입니까? 설정을 변경하는 것이 아니라 호출 된 라이브러리 내부의 코드 조각입니다. 직렬 포트를 사용하여 구성 매개 변수를 출력하고 변경된 내용을 파악해보십시오. 사용 된 라이브러리의 소스 (있는 경우)를보고 해당 타이머도 사용하지 않는지 확인할 수 있습니다.
Blup1980

1
@ Blup1980이 시도 할 가치가있는 또 다른 것을 제안한 것 외에도 TLC5940을 제거하여 시계 라인에 아무런 문제가 없는지 확인하십시오.
PeterJ

@ Blup1980 UART의 관련성을 잘 모르겠습니다. USPI를 SPI에 사용하지 않고 "일반적인"SPI 기능 만 사용합니다. sendSerial()SPI를 통해 데이터를 보내는 코드입니다. TCCR(타이머 컨트롤) 레지스터를 건드리지 않습니다 .
angelatlarge

답변:


1

빠른 디버그를 위해 Arduino Library for TLC5940을 사용하여 동일한 작업을 수행하고 빠르게 진행되는지 확인하려고합니다. 라이브러리와 함께 작동하는 경우 소스를 확인하고 자신과 비교할 수 있습니다. AVR에 익숙하므로 Arduino 소스를 기본 AVR로 쉽게 변환해야합니다.

컴파일 된 Arduino 스케치를 AVR에 업로드하는 방법을 모르는 경우 : 스케치를 컴파일하면 16 진수 파일이 생성됩니다 (설정에서 상세 모드를 켜서 파일의 정확한 위치를 볼 수 있음). 좋아하는 프로그래머와 함께 16 진수를 AVR에 업로드 할 수 있습니다.

그것이 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.