Hey, guys!
Does anybody know which registers to use for PWM through direct port manipulation? Are any tricks to doing it this way?
Yes, the TCCR0A/B, TCCR1A/B, and TCCR2A/B registers. It's a bit lengthy but the descriptions in Section 15.9 of the ATmega328P datasheet explains it all. This is for Timer 1; similar descriptions exist for Timers 0 and 2.
As for tricks? There are no tricks, just careful coding Maybe study how the built-in tone() and analogWrite() functions work to get a sense for how to work with these registers.
--
The Gadget Shield: accelerometer, RGB LED, IR transmit/receive, light sensor, potentiometers, pushbuttons
PWM is generated by using a timer and an Output Compare Register. Specifically, for the ATmega328P there are three timers: Timer0, Timer1, and Timer2. Each timer has two Output Compare Registers and each OCR can be connected to an output pin that is toggled at times depending on the timer frequency (controlled by a prescaler register for that timer) and by the timer mode and by the value entered into the OCR.
Here's a summary of the timers and pins that can be used with the ATmega328p:
ATmega328p OC ATmega328p avr-gcc Arduino
Timer Register 28-DIP Pin Port Pin Digital Pin
-------------------------------------------------------------------
Timer 0 OC0A 12 PD6 6
Timer 0 OC0B 11 PD5 5
Timer 1 OC1A 15 PB1 9
Timer 1 OC1B 16 PB2 10
Timer 2 OC2A 17 PB3 11
Timer 2 OC2B 5 PD3 3
Note that a particular OCR is connected to its pin by setting a bit in one of the timer control registers. When that bit is not set, that pin is available for "normal" I/O.
Also note, particularly, that Timer0 is used for millis() and delay() functions, so using Timer0 for PWM may require some care (or else...)
Regards,
Dave
I'm rather new to microcontrollers in earnest. I'm kind of pressed for time on a project and I'm wondering, can this be effectively done within the Arduino IDE, should I take up ASM, or should I just do bona fide GCC? What are the options with Linux (Ubuntu) (which I am also fairly new to)?
This can be done from the IDE, as you are mainly writing GCC-type code. The IDE simply makes it easy to pull in the Arduino infrastructure code (stuff that lets you call analogWrite() and such). You don't have to use that code. You can reprogram the timer registers but then take care not to try to use the Arduino infrastructure code that expects to have the timers configured in a certain way.
You can also write basic GCC code using only AVR-LIBC interfaces and forget about the Arduino infrastructure code. All of these tools are available for Ubuntu (check out avr-gcc in the package manager). You can download your program to your board using AVRDUDE (also should be in the package manager).
I don't think there's any need to write in assembly language unless your project demands it (and the vast majority don't).
--
The Quick Shield: breakout all 28 pins to quick-connect terminals
Also note, particularly, that Timer0 is used for millis() and delay() functions, so using Timer0 for PWM may require some care (or else...)
Yeah, I had read that PWM might not shut off completely under certain conditions associated with delay instructions. I need to control some H-bridges that carry several amps, so that kind of made me anxious. I won't need to delay or time anything, though. If I don't use any delay() or millis(), will that get rid of the complications?
will that get rid of the complications?
I haven't tried to do away with all of the mechanism that is used with millis() and delay() functions. So much stuff out there (various libraries that people use) depends on them that I would be reluctant to plan on trying to defeat them, knowing that all kinds of other stuff depends on Timer0.
I mean, anything is possible, but that doesn't mean that it is easy. (Of course it might be easy, but...)
Regards,
Dave