A PWM Algorithm For Software And HardwareRealized With Only One Add Instruction
- A PDM Algorithm Based On Addition (1)
现在出的微控制器,几乎没有不带PWM输出的。PWM一般都用特殊的定时器电路实现。
PWM的本质是在脉冲总周期Nt内输出累积时间为Ht的正脉冲。
本人提出过一种算法,用C语句表达如下:
CNT += H ;
if ( CNT >= N )
{ CNT %= N ; Pout = 1 ; }
else Pout = 0 ;
// 每个t计算一次;
// N为任一正整数,H为0 ~ (N-1),CNT为累计数并保存模除余数。
严格讲,本算法应称为“基于累加的PDM(Pulse Density Modulation)算法”。
本算法可以用FPGA/CPLD或PSoC UDB的Datapath硬件实现,资源占用恐怕比常规PWM还要少。而软件实现,在任何单片机上都可以做,只要它有一个最简单的定时器,就可做出任意多个PDM输出。
本文附上一个用PSoC4 Pioneer Kit实现的实例,软硬并用。其中,红色LED用UDB的Datapath调光;简单到只用一条指令:A0 = A0 + D0,进位co_msb通过引脚输出给红灯。而绿色、蓝色二只LED在SysTick中断里用软件进行调光。三灯都用10KHz时钟,即每100uS计算一次。为便于看程序,没有用汇编。
实例:ZhuPDM8(PSoC Creator 2.2 SP1).rar
http://www.eeskill.com/file/id/26301。
用PSoC4 Pioneer Kit做实例,也是表示我对AET“赛普拉斯PSoC4”主题季活动的支持。更主要的是PSoC(从PSoC3起)UDB的Datapath是我将本算法在MCU芯片内用硬件实现的第一种芯片,而且是目前唯一的一种MCU。这也是我推崇PSoC UDB的原因,而且爱“PSoC Datapath”及“PSoC葡萄酒”。
二十多年前,单片机内还没有PWM,这种算法是我自己逼出来的,算是一种“独门绝技”,我只告诉过几个朋友。如果什么人发现有谁谁谁在什么地方使用这种方法,请告诉我,我会把“独门”二字去掉。
应该说,一个表达式和一个实例,已经把算法叙述清楚了。
有人说当N=2、H=1时占空比不是50%,我以实例说明占空比是50%。录下回应如下:
Re: A PWM Algorithm Realized With Only One Add Instruction
H Lposted on 21 Jul 2013 09:48 PM PST
A clever approach. However, with N =2 and 1 =1, the output duty cycle would not be 50% as there is more CPU cycle in one half of the operation. The slower the CPU the higher the error.
Re: A PWM Algorithm Realized With Only One Add Instruction
fyzhuposted on 22 Jul 2013 09:28 PM PST
What's wrong?
MATLAB shows the duty cycle is 50% for N=2 and H=1:
>>
npulse = 8;
N = 2;
H = 1;
CNT = 0;
disp( ' k Pout for init. CNT=0' )
for k = 1:npulse
CNT = CNT + H;
if CNT >= N
CNT=mod(CNT,N) ;
Pout = 1 ;
else
Pout = 0 ;
end
disp( [k Pout] )
end
k Pout for init. CNT=0
1 0
2 1
3 0
4 1
5 0
6 1
7 0
8 1
>> ...
k Pout for init. CNT=1
1 1
2 0
3 1
4 0
5 1
6 0
7 1
8 0
Re: A PWM Algorithm Realized With Only One Add Instruction
H Lposted on 23 Jul 2013 10:36 PM PST
The difference between the two condition is onewith the % instruction, and the other does not.
My answer is runing it froma 'CPU'. The CPU needs to process the % instruction.
You can compile the code and check the difference of instructions.
我继续回应:
Hi H L,
I don't think there is any difference between the mod() and the %-operator.
The debug result (see attached screen copy) of following programm runing in a real CPU with the %-operator shows the same duty cycle of 50%.
void main()
{
uint16 N = 2;
uint16 H = 1;
uint16 CNT = 1;
uint8 Pout[8];
uint16 k=0;
do {
CNT += H;
if (CNT >= N)
{ CNT %= N ; Pout[k] = 1 ; }
else Pout[k] = 0 ;
k++;
}while(k<8);
for(;;) { }
}
May the defferent compiler cause the defferent result of %-operator ?
附图:
FY_ZHU
2013-07-18 BOS-MA