>> On_IRQ >> =A0increment counter ; with rollover to zero >> =A0if counter =3D 0 then set all PWM output bits high. >> =A0for all channels >> =A0 =A0 if counter >=3D channel_value set relevant PWM bit low. > I've seen lots of people implement soft PWM with this type of scheme, and > it's always seemed... I was going to say "stupid" but perhaps "silly" is = a > better choice, though political correctness may force me to temper that t= o > "less than optimum". > With this scheme you have a _ton_ of interrupts. 8 bit resolution gets yo= u > 256 interrupts per PWM cycle - which obviously limits the upper frequency > and burdens the processor for other tasks. I've always preferred a variab= le > timer reload approach: Definitely true for many values of "'stupid". But not all. I think :-) [NB - I have NO problem with "seems stupid" in that context (or almost any other :-)) Sufficient to the morrow be the evil thereof ... . If we can kill stupid before the morrow it never happened, so : I assume that all the following is obvious and trivial but it may promote some relevant discussion: If you have a fastish timer tick and spare processing capacity (and you seem to easily be able to handle both in your scenario) then you can handle all sorts of useful things this way. Not only as many timers as you want but in-program delays anywhere and almost everywhere you want (set register to N, test on subsequent loops and ignore until zero, reload when / if required ) and more. A super simple transparentish Mickey Mouse* non pre-emptive , better be cooperative or else RTOS [tm] that takes literally a few lines of code to get going. Presumably many people do almost exactly this. .. I thought about adding complexity or comment in the pseudo code and decided not to. "Delays" can be handled by DSNZ, INC in the IRQ routine (or DNZ if you have it)(or code equivalent). A background client simply loads a value and the IRQ routine progressively zeros it. IRQ overhead is one DSNZ and one INC (or one DNZ) per delay. PWM is almost the same. At say 4 bit resolution and 400 Hz the slowest IRQ period is 1/(2^4 x 400) =3D 156 uS For 6 bit resolution it's ~=3D 40 uS and for 8 bit it's ~ 10 uS. Once upon a time a 10 uS (9.765625 ...) timer IRQ would have been unthinkable and even now it's not a zero load, but system overhead for an empty IRQ routine can be a few percent of total time. This may be very bearable. Using only 6 bit resolution drops you down to around 1% +/- depending on how fast a clock you are using and on a system where you the processor is twiddling its thumbs (ARM not implied) it can be a really useful powerful tool. More stupid :-) : Blinky LED. Sure. Turn off power after xxx to peripheral Y? sure - load a register and if it ever goes to zero kneecap the power. Somewhere else in the system if a client routine wants the power kept on it will reload the register. etc. Emergency power down (non sequenced) - kill the timer and it triggers the routine next time through the loop without the code ever talking directly. (Complexity and implications and timer boundary condition handling and who-has-the-"token" issues left as an exercise for the student). The background routine can shuffle cooperatively through their tasks at a rate that is completely independent of the IRQ rate. You can easily add relative prioritization of background tasks by group etc. eg Delay 1 is set to 50 counts. Delay 2 is set to 500 counts ( > 8 bit timer in this example and often in reality.) Say IRQ is 20 uS. Call all P0 tasks in order. These execute round-robin with the expectation that they will never sum to > (here) 1 mS in total processor demand. If Delay 2 expired call P2 tasks and reset Delay 2. Note that you may want to check P0 tasks before you call P2's. Note that if you want isochronousish P0 behaviour (eg UART sampling) the the two timers may need to be interlocked etc etc . If Delay 3 expired call all P3 tasks and reset Delay 3. (Same caveats but w= orse) Obviously, if total possible period taken by P2 tasks exceeds maximum allowed latency of P1 tasks then some interleaving or other mechanism is required. eg bit flags or whatever. Computed COMEFROM ? :-) Part of my brain was about to launch into comments on task partitioning and interleaving and handoff mechanisms to not exceed desired worst case latency in a non-preemptive better-be-cooperative adhoc multitasking mess. But, what say I stop at saying that once you have a general purpose timer tick with IRQ driven timers, you get easily implemented with a few bytes per decision point task control and it can work rather well. The above rather assumes but is not limited to assembler. If working in a HLL you'd want the IRQ routines manually checked if not assembler coded. Lots of room for doing non-ideal things there. Again, presumably many people do variations of the above, but as it is an outgrowth of the 'stupid' approach, I mention it. .. Russell * I understand that in some cultures "Mickey Mouse" means "pretty good". That's not so here :-). --=20 http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .