PWM8 with OutputCapture on mega328p

Discussion specific to the DIP and TQFP packaged ZX devices like the ZX-40, ZX-44, ZX-32 and ZX-328 series. The differences between these devices is primarily the packaging and pinout so most issues will apply to all devices.
Post Reply
jay
Posts: 37
Joined: 08 July 2006, 13:58 PM
Location: Vermont, USA

PWM8 with OutputCapture on mega328p

Post by jay »

Reworking a old project (another IR vacation TV timer) that uses a ZX40 for scheduling and PWM to generate the IR command data stream. A PIC12F683 generated the carrier freq as gated by the PWM stream and controls the LEDs. I thought I'd move to a zx-328n, use the PWM as before, then use a PWM8 to generate the carrier. It doesn't appear that I can use the PWM8 to generate carrier frequencies (~37kHz for some devices and ~58kHz for others).

OutputCapture uses Timer 1 PWM8 uses Timer 2 so there would be no conflict, but as I read it, PWM8 can only generate a set of base frequencies.

I would like to remove the PIC, but don't understand how.

Any suggestions?

Thanks
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: PWM8 with OutputCapture on mega328p

Post by dkinzer »

jay wrote:[A]s I read it, PWM8 can only generate a set of base frequencies.
That is true but you needn't use the timer in PWM mode to generate a simple square wave. The code below sets up Timer2 in CTC (Clear on Timer Compare) mode. In this mode the timer counts from zero up to N and then resets to zero. The second part of the configuration is to set the COM2xN bits to toggle the output compare pin on every compare match - the frequency of the compare match must, therefore, be twice the desired frequency.

For the two frequencies mentioned, I concluded that the timer's prescaler must be set to divide-by-1. The expression giving the OCR2A value should be easily understood if you realize that the OCR2A register gives the value of N, the +1 in the middle combined with the subsequent division by 2 implements rounding, and the final -1 accounts for the fact that a counter has N states when counting from 0 to N-1. The resulting frequencies are 37.04KHz and 58.14KHz when operating at 14.74 MHz.

Code: Select all

Const frequency as UnsignedLong = 58000
Const prescaler as UnsignedLong = 1

#if Option.TargetDevice = "ZX24n"
    Const pin as Byte = D.7
#elseif Option.TargetDevice = "ZX328n"
    Const pin as Byte = B.3
#else
	#error need OC2A pin for target device
#endif

Sub Main()
    ' set up Timer2 to generate a square wave on OC2A
    Register.OCR2A = CByte(((Register.CPUFrequency \ prescaler \ frequency) + 1) \ 2 - 1)
    Register.TCCR2A = &H42  ' set OC2A to toggle on compare     
    Register.TCCR2B = &H01  ' set prescaler to divide-by-1, CTC mode
    Call PutPin(pin, 0)
End Sub
Note that if the OC2A pin isn't convenient to use, you could configure the timer to toggle the OC2B pin. How to accomplish this is left as an exercise for the interested reader.

For more information on how AVR timers work and how to configure them in various modes, see Dean Camera's AVR Timer Tutorial.
Last edited by dkinzer on 10 January 2013, 18:30 PM, edited 2 times in total.
- Don Kinzer
jay
Posts: 37
Joined: 08 July 2006, 13:58 PM
Location: Vermont, USA

Post by jay »

Don thanks so much. I was starting to think about putting a pic back in..

Also, thanks for the pointer to Dean's articles. Some good late night reading.

Best regards,

..jay
Post Reply