32U4 내가에 대한 테스트를 한 된 328P 동일 타이머를 가지고 당신의 문제. 최고의 해상도를 제공하는 타이머 1을 사용했습니다. 이 타이머는 CTC 모드에서 실행될 수 있으며 채널 A는 토글 - 온 - 컴 페어 - 매치에서 고정 출력 핀에 바인딩 될 수있다. 따라서 설정이 매우 간단 해지고 인터럽트 로직이 필요하지 않습니다. OCR1A
에 쓰기 만하면 주파수를 간단히 제어 할 수 있습니다 (이 레지스터는 더블 버퍼링되어 주파수 변경시 글리치가 없어야합니다)
*. n은 프리 스케일 값이 오버 플로우 레지스터 비교 여기서 x
f n x = f_cpu/(2 * n * (1 + x))
: CTC 모드에서 타이머 1
는의 출력 주파수를 갖는다. 16MHz 일 클럭에 가능한 주파수 범위를 탐색하여 제공한다 :
| N | f-min | f-max | r-min | r-max | x-100 | x-25k |
+-----+--------+-----------+-----------+-----------+-------+-------+
| 1 | 122.1 | 8,000,000 | 4,000,000 | 0.0019 | n/a | 319 |
| 8 | 15.3 | 1,000,000 | 500,000 | 0.00023 | 9,999 | 39 |
| 64 | 1.91 | 125,000 | 62,500 | 0.000029 | 1,249 | 4 |
| 256 | 0.49 | 31,250 | 15,625 | 0.0000073 | 311 | n/a |
|1024 | 0.12 | 7,812 | 3,906 | 0.0000018 | 77 | n/a |
N은 프리 스케일 설정 F 분 & F-최대 최소 달성 가능한 최대 주파수가 R-분 & R-최대 최소이고 및 최대 주파수 분해능, 마지막으로 x-100 & x-25k는 각각 100Hz 및 25kHz 출력에 대해 OCR1A에 필요한 값입니다. 전체 내용
여기서 일례를 작동 주파수 1Hz로, 2, 5, 10 ... 2 개 초 단위에서 500kHz까지 충분한 통해 사이클 범위의 동작을 관찰하기위한 프로그램이다
#include <avr/io.h>
#include <util/delay.h>
struct CTC1
{
static void setup()
{
// CTC mode with TOP-OCR1A
TCCR1A = 0;
TCCR1B = _BV(WGM12);
// toggle channel A on compare match
TCCR1A = (TCCR1A & ~(_BV(COM1A1) | _BV(COM1A0))) | _BV(COM1A0);
// set channel A bound pin to output mode
DDRB |= _BV(1); // PB1 on 328p, use _BV(5) for PB5 on 32U4
}
static void set_freq(float f)
{
static const float f1 = min_freq(1), f8 = min_freq(8), f64 = min_freq(64), f256 = min_freq(256);
uint16_t n;
if (f >= f1) n = 1;
else if (f >= f8) n = 8;
else if (f >= f64) n = 64;
else if (f >= f256) n = 256;
else n = 1024;
prescale(n);
OCR1A = static_cast<uint16_t>(round(F_CPU/(2 * n * f) - 1));
}
static void prescale(uint16_t n)
{
uint8_t bits = 0;
switch (n)
{
case 1: bits = _BV(CS10); break;
case 8: bits = _BV(CS11); break;
case 64: bits = _BV(CS11) | _BV(CS10); break;
case 256: bits = _BV(CS12); break;
case 1024: bits = _BV(CS12) | _BV(CS10); break;
default: bits = 0;
}
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11) | _BV(CS10))) | bits;
}
static inline float min_freq(uint16_t n)
{
return ceil(F_CPU/(2 * n * 65536));
}
};
void setup()
{
CTC1::setup();
}
void loop()
{
for (uint8_t x = 0; x < 6; ++x)
for (uint8_t y = 0; y < 3; ++y)
{
float k = y > 0 ? (y > 1 ? 5 : 2) : 1;
CTC1::set_freq(k * pow(10, x));
_delay_ms(2000);
}
}
int main()
{
setup();
for (;;)
loop();
}
은 신호는 PB1 (Arduino Uno의 디지털 핀 9)에서 관찰 할 수 있습니다. 32U4 채널 A는 PB5에 바인딩됩니다.
Aleksander Z.가 친절하게 언급했듯이 OCR1A 레지스터는 CTC 모드에서 더블 버퍼링되지 않습니다. 주파수를 전환하면 심각한 글리치가 발생할 수 있습니다.:
이 쉽게 고정 될 수있는 애플리케이션에 따라 바쁜 루핑 (이것은 매우 높은 주파수에서 잘 작동하지 않거나 매우 낮은 주파수 하에서 용납 지연이 발생할 수 있지만)
while (TCNT1 > x)
;
OCR1A = x;
을
을 일으키기 :
당신은 더 구체적인 뭔가를 물어 시도해야합니다. 그 질문은 "다른 튜토리얼"을 답으로 요구할 것입니다. 읽은 자습서의 문제점은 무엇입니까? 어쩌면 당신이 이해하지 못하는 튜토리얼의 섹션/계산을 인용 할 수 있습니다. –