You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Timer1配置Arduino Uno(ATMEGA328P)自定义PWM参数求助

Custom 12Hz 20% PWM on Arduino Uno (ATmega328P)

Hey Dylan, sorry to hear you're stuck getting that custom PWM working—let's break this down and fix it together. 12Hz is a pretty slow frequency for the Uno's timers, so we need to use the 16-bit Timer1 (since Timer0 is tied up with millis() and delay()) to hit that target without losing precision.

First, let's confirm the parameter math to make sure we're on the same page:

  • CPU frequency: 16MHz
  • Target PWM frequency: 12Hz
  • Target duty cycle: 20%

Key Calculations

Using the Fast PWM formula with ICR1 as the TOP value:
Frequency = F_CPU / (prescaler * (TOP + 1))

We'll use the largest prescaler for Timer1 (1024) to get a manageable TOP value:
TOP = (16e6 / (1024 * 12)) - 1 ≈ 1302
This gives us an exact frequency of 16e6 / (1024 * 1303) ≈ 12.00Hz—perfect.

For 20% duty cycle:
OCR1A = 0.2 * (TOP + 1) ≈ 260.6
We'll round to 260 (this gives ~19.95% duty cycle, which is more than close enough for most use cases).

Working Code Example

Here's the full implementation for pin D9 (Timer1's OC1A PWM pin):

void setup() {
  // Set the PWM pin as output
  pinMode(9, OUTPUT);
  
  // Reset Timer1 registers to start fresh
  TCCR1A = 0;
  TCCR1B = 0;
  
  // Configure non-inverting PWM on OC1A: clears on match, sets at TOP
  TCCR1A |= (1 << COM1A1);
  
  // Set Fast PWM mode with ICR1 as TOP (Mode 14)
  TCCR1A |= (1 << WGM11);
  TCCR1B |= (1 << WGM13) | (1 << WGM12);
  
  // Set prescaler to 1024 (CS12 + CS10 bits)
  TCCR1B |= (1 << CS12) | (1 << CS10);
  
  // Set TOP value for 12Hz frequency
  ICR1 = 1302;
  
  // Set compare value for ~20% duty cycle
  OCR1A = 260;
}

void loop() {
  // No code needed here—Timer1 handles PWM automatically
}

Troubleshooting Common Mistakes

If this still doesn't work, check these easy-to-miss issues:

  • Wrong pin: Make sure you're using D9 (OC1A) or D10 (OC1B)—these are the only pins tied to Timer1's PWM output.
  • Incorrect timer mode: Phase Correct PWM uses a different frequency formula, so stick to Fast PWM (Mode 14) for this setup.
  • Forgot ICR1: The TOP value is critical—if you don't set ICR1, the timer defaults to 0xFFFF, making the frequency way lower than 12Hz.
  • Prescaler mismatch: Double-check that you've enabled the 1024 prescaler (both CS12 and CS10 bits set). A smaller prescaler will result in a higher frequency.

Give this code a shot, and let me know if you still hit snags—we can tweak further if needed!

内容的提问来源于stack exchange,提问作者Dylan144GT

火山引擎 最新活动