EditUpdate: Here is an example code illustrating this, I just tested itimplementation of a 16-bit analogWrite()
. It
only works on my scopepins 9 and 10, as these are the only pins connected to the
16-bit timer.
/* Configure digital pins 9 and 10 as 16-bit PWM outputs. */
void setupsetupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting mode PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP = ICR1TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* no prescaling */
ICR1 = 0xffff; /* TOP counter value */
}
void/* loop16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
staticswitch uint16_t(pin) i;{
case 9: OCR1A = i;val; break;
case 10: OCR1B = val; break;
}
}
You may notice that the top of the counter sequence is configured explicitly. You can change this to a smaller value to make the PWM faster, at the cost of decreased resolution.
And here is an example sketch illustrating its use:
void setup() {
setupPWM16();
}
/* outputTest: onsend digitalvery 9slow sawtooth waves. */
void loop() {
OCR1B = 0xffff-static uint16_t i; /* outputanalogWrite16(9, oni);
digital analogWrite16(10, */0xffff - i);
i++;
delay(1);
}
Edit: Here is an example code illustrating this, I just tested it on my scope.
void setup() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting mode PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP = ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* no prescaling */
ICR1 = 0xffff; /* TOP counter value */
}
void loop() {
static uint16_t i;
OCR1A = i; /* output on digital 9 */
OCR1B = 0xffff-i; /* output on digital 10 */
i++;
delay(1);
}
Update: Here is an implementation of a 16-bit analogWrite()
. It
only works on pins 9 and 10, as these are the only pins connected to the
16-bit timer.
/* Configure digital pins 9 and 10 as 16-bit PWM outputs. */
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* no prescaling */
ICR1 = 0xffff; /* TOP counter value */
}
/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
You may notice that the top of the counter sequence is configured explicitly. You can change this to a smaller value to make the PWM faster, at the cost of decreased resolution.
And here is an example sketch illustrating its use:
void setup() {
setupPWM16();
}
/* Test: send very slow sawtooth waves. */
void loop() {
static uint16_t i; analogWrite16(9, i);
analogWrite16(10, 0xffff - i);
i++;
delay(1);
}
The Arduino Uno is based on an ATmega382P microcontroller. This chip has two 8-bit timers, driving two PWM channels each, and one 16-bit timer, driving the last two channels.
You cannot increase the resolution of the 8-bit timers. You can,
however, put the 16-bit timer in 16-bit mode, instead of the 8-bit mode
used by the Arduino core library. This will give you two 16-bit PWM
channels, with a reduced frequency of 244 Hz (maximum). You will
probably have to configure the timer yourself, and will not benefit from
the easy to use analogWrite()
function. For details, see the section
on Timer 1 in in the ATmega328P
datasheet.
Edit: Here is an example code illustrating this, I just tested it on my scope.
void setup() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting mode PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP = ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* no prescaling */
ICR1 = 0xffff; /* TOP counter value */
}
void loop() {
static uint16_t i;
OCR1A = i; /* output on digital 9 */
OCR1B = 0xffff-i; /* output on digital 10 */
i++;
delay(1);
}
The Arduino Uno is based on an ATmega382P microcontroller. This chip has two 8-bit timers, driving two PWM channels each, and one 16-bit timer, driving the last two channels.
You cannot increase the resolution of the 8-bit timers. You can,
however, put the 16-bit timer in 16-bit mode, instead of the 8-bit mode
used by the Arduino core library. This will give you two 16-bit PWM
channels, with a reduced frequency of 244 Hz (maximum). You will
probably have to configure the timer yourself, and will not benefit from
the easy to use analogWrite()
function. For details, see the section
on Timer 1 in in the ATmega328P
datasheet.
The Arduino Uno is based on an ATmega382P microcontroller. This chip has two 8-bit timers, driving two PWM channels each, and one 16-bit timer, driving the last two channels.
You cannot increase the resolution of the 8-bit timers. You can,
however, put the 16-bit timer in 16-bit mode, instead of the 8-bit mode
used by the Arduino core library. This will give you two 16-bit PWM
channels, with a reduced frequency of 244 Hz (maximum). You will
probably have to configure the timer yourself, and will not benefit from
the easy to use analogWrite()
function. For details, see the section
on Timer 1 in in the ATmega328P
datasheet.
Edit: Here is an example code illustrating this, I just tested it on my scope.
void setup() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting mode PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP = ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* no prescaling */
ICR1 = 0xffff; /* TOP counter value */
}
void loop() {
static uint16_t i;
OCR1A = i; /* output on digital 9 */
OCR1B = 0xffff-i; /* output on digital 10 */
i++;
delay(1);
}
The Arduino Uno is based on an ATmega382P microcontroller. This chip has two 8-bit timers, driving two PWM channels each, and one 16-bit timer, driving the last two channels.
You cannot increase the resolution of the 8-bit timers. You can,
however, put the 16-bit timer in 16-bit mode, instead of the 8-bit mode
used by the Arduino core library. This will give you two 16-bit PWM
channels, with a reduced frequency of 244 Hz (maximum). You will
probably have to configure the timer yourself, and will not benefit from
the easy to use analogWrite()
function. For details, see the section
on Timer 1 in in the ATmega328P
datasheet.