Dick Cappels' project pages
Oh, is this ugly! It doesn't take much in the way of hardware to test this code.
What it does
The assembly code given here was written to see what it would take to make an AT90S1200 generate 8 channels of proper PWM. In this case, by proper, I mean with the maximum high frequency content consistent with the needed duty cycle and give clock. Take a look at the scope shots below and notice that when the data value is =$02, there pulse frequency is twice that which occurs when the data value is =$01. The significance of this is that the percent of ripple voltage out of the low pass filter stays much more constant as the data values change than they would with a conventional PWM that merely varies the width of a single pulse (see the auto zero code for the RF Field Strength Probe for an example of code that does this). Take a look at the pictures below to see the effect.
When running with a 4 MHz clock, this code provides 8 channels of 8 bit resolution with a 60 Hz minimum frequency (which occur at data values of $01 and $FF. By adjusting the interrupt timer reload value, the minimum frequency can be taken to 100 Hz, but at the cost of time available for other tasks. Of course, changing the clock oscillator frequency is another way to increase the minimum frequency.
The code was originally written for and tested on an AT90S1200A, I also merged it with a monitor program and tested it on an AT90S2313. Thus, it can be adapted to a variety of AVR chips, including those with really limited resources such as the ATTiny12 easily.
Here is the assembly code for the PWM routine. This code is an example program with the routines necessary to make the PWM machine work, but it only drives values that are preprogrammed in as constants at assembly time. Adding an interface so the PWM values can be adjusted in real time is left as an exercize for the student.
Step size is very good. The largest one I found was about 1/2 lsb (See the table near bottom of this page). I measured this with a single pole RC filter and a 3-1/2 digit DVM, so I suspect that the apparent 1/2 lsb step error is actually much smaller and the error is really the result of the resolution of the measurement. PWM dacs can be very, very linear. What was surprising was to find some cross talk from another channel. All these signals were measured in PORTB bit 4, and while changing the values of bits 0,1,2,3,5,and 6 had not apparent affect on bit 4's voltage, changing bit 7 from $00 to $FF caused about a 1.5 lsb error in bit 4's voltage. Maybe this is a case for buffering PWM outputs in critical situations (then again it was critical, maybe a real DAC would be better).
Use of information presented on this page is for personal, nonprofit educational
and noncommercial use only. This material (including object files) is copyrighted
by Richard Cappels and may not be republished or used directly for commercial
purposes without explicit permission For commercial license, click HERE.
Please see the liability disclaimer on the HOME page.
Contents ©2002 Richard Cappels All Rights Reserved. http://www.projects.cappels.org/