基于Timer1配置Arduino Uno(ATMEGA328P)自定义PWM参数求助
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




