本帖最后由 znmcu 于 2014-10-15 12:33 编辑
振南网站还在继续美化改进,暂时提供一个平台来发布振南的实验和相关资料! http://www.znmcu.cn/znx_51_iap_exps_pca_pwm_test.html STC/IAP15单片机 ZN-X开发板 群 187478076 振南QQ:987582714 振南的SD卡 FAT32 技术群:198521880
振南ZN-X开发板(STC51版)实验 之 PCA的应用(PWM的产生) 实验说明: 振南的ZN-X开发板率先使用STC最新的增强型51单片机芯片(具体型号包括3种:STC15L2K60S2、IAP15L2K61S2/IAP15W4K61S4),它们在功能上几乎相同,只是RAM与ROM容量不同,另外前缀IAP的芯片本身具有仿真器的功能。 此实验主要是对PCA(Programable Counter Array,即可编程计数器阵列)的应用,它是STC特有的东西,功能强大,配置灵活,可以实现多种功能:捕获、定时、PWM输出、高速时钟输出等等。再加上一些应用上的技巧,将可以实现更多功能。 这里使用PCA产生两路PWM输出,控制两个发光二极管的亮度。 所需硬件: 振南ZN-X开发板(STC51版)基板[此实现只需要ZN-X基板,而不需要额外的模块] USB转串口模块(用于供电与程序的下载) STC PCA简介: STC15系列部分单片机集成 了3路可编程计数器阵列(CCP/PCA)模块,可用于软件定时器、外部脉冲的捕捉、高速脉冲输出以及脉宽调制(PWM)输出。 PWM输出可以在3组不同管脚之间切换: PWM通道 | 可分配管脚 | PWM0 | P1.1 | P3.5 | P2.5 | PWM1 | P1.0 | P3.6 | P2.6 | PWM2 | P3.7 | P3.7 | P2.7 |
此实验中我们选用P1.1与P1.0作为PWM输出,在P1.1与P1.0上接了两个发光二极管,PWM将使它们的亮度发生变化。 振南对PWM的解释: PWM是一种极为重要的控制手段,它的根本思想是使用数字信号对模拟信号进行合成。很多人对此很不理解,数字量为是0和1,高低电平,它怎么可能产生模拟信号呢?对此振南有自己的理解和解释。 一辆汽车,如果我们把1看作是踩油门加速,把0看作是踩刹车减速,那么如果我们一直踩油门,车将会一直加速到全速,反之如果我们一直踩刹车,它将会一直减速到静止,即速度为0。那么你有没有想过一种情况,如果我们踩3秒油门,然后踩1秒刹车,如此往复,会怎么样?车会一会加速,一会减速,它会“一顿一顿”地前进。用极限的思想去想它,如果踩油门和刹车的交替速度非常快,那么车“一顿一顿”的动作将会变得“平滑”,甚至让人感觉不出来,这样给人的感觉就是车在以一种介于0与全速之间的速度前进。这种“平滑”,与踩油门和刹车的交替速度有关;而车最终行驶的速度则取决于踩油门和刹车的时间比例。这也许就是对PWM思想的最为通俗的解释。 上图中,一个脉冲信号作用于一个发光二极管,高电平时LED全亮,低电平时LED灭,那么如果这个脉冲的频率较低,那么我们就可以看到LED时亮时灭,亮灭的时间长短与脉冲一个周期内高电平与低电平的时间有关。如果我们将脉冲频率提高,那么LED就会在亮与灭之间频繁切换,最终的效果就是LED呈现出在灭与全亮之间的一个亮度,这个亮度与脉冲周期中高低电平的比例有关。这就被称为“脉冲宽度调制”! 【通过振南上面形象地介绍,大家应该能够真切地领悟到,PWM确实非常巧妙,脉宽影响合成模拟量的幅值,而频率则影响合成模拟量的精细度!】 产生模拟量的常规方法是依靠DAC,但是DAC芯片的成本太高了。也许你会说:“需要模拟量的场合应该不多吧?!”错!很多,而且可能很巨大。最典型的例子就是全彩LED大屏幕。它要控制每一个像素三种基色亮度(其实就是红绿蓝三种发光二极管),从而调合出指定的颜色。如果为每一个发光二极管都配一个DAC,那造价将可能是难以承受的,而且在电路实现上也非常麻烦。但是如果使用PWM方式,则只需要一个简单的IO即可,再加上一些高速的分时和动态扫描的方法,将使硬件成本极大降低。 实际上,我们身边PWM无处不在,它在数字信号与模拟信号之间架起了一条低成本、高精度而又灵活简单的通道! PWM在电路实现上似乎并不复杂。确实!我们只需要一个带有比较功能的计数器和一个IO即可。计数器递增,当比设定的比较值小时,对IO进行置低,反之置高。在很多单片机中,PWM的实现的确实是基于这种思想。所以,PWM功能经常被集成在定时器中。 STC单片机中与实验相关的寄存器(大部分内容摘自STC芯片手册): CMOD中的CPS2 CPS1 CPS0用来选择PCA的时钟源,说白了它决定了计数器的快慢,也就是决定了PWM输出的频率,它会影响PWM对模拟信号合成的精度。原理上来说,PWM的频率应该越高越好,但是频率越高IO开关速度越快所带来的功耗也越大。我们在实验中直接使用SYSclk(实现中ZN-X上的STC芯片工作频率设置为5.5MHz,它就是SYSclk)。 CCON中的CR位用来启动计数器,它被置1后,计数器立即以时钟频率开始自增。 要得到PCA的的PWM功能,必须要将CCAPMn(STC芯片中有3个独立的PCA电路,我们这里使用第0个,所以n=0)中的PWM0置1。同时还要打开PCA的比较器功能,其原因不言而寓。 CL与CH是PCA中的计数器,它们都是8位的。在PWM功能中,只用到其中的CL,所以PCA的PWM功能最多可以实现8位PWM,即256级PWM。 CCAP0L与CCAP0H在PWM功能中,用来设置PWM的比较值,它决定了PWM的脉宽,即占空比,也就是脉冲一个周期内低电平所占的比例:比如此值为0,则周期内全为高电平;如果此值为255(对于8位PWM来说),那么周期内全为低电平。 在PWM功能中,PCA中的比较器会将计数器中的值与CCAP0L进行比较,如果比它小则在PWM输出管脚中输出低电平,反之输高电平。 那CCAP0H有什么用呢?它是为了无干扰地改变PWM脉宽用的。当我们要改变PWM的脉宽时,不应该直接去改CCAP0L的值,因为这样会影响到当前PWM周期的脉宽。正确的方法应该是将新的比较值写入到CCAP0H中,在计数器自增到255,变为0,即溢出时它会自动将CCAP0H更新到CCAP0L,这样就实现了所谓的“无干扰”的PWM控制。让PWM可以“平滑”地过渡到新的脉宽,而不会出现中间的失真周期! PCA_PWM0中的EBS0_1,EBS0_0用于选择PWM的位数,这个位数越高,当然PWM对模拟信号的合成精度越高。但是PWM的频率会低一些(8位PWM的频率为PCA时钟源频率的256分之1,这里我们选用SYSclk为时钟源,所以8位PWM的频率为5.5MHz/256≈21.5KHz)。 但对于EPC0H与EPC0L,振南一直不明白它们的作用,最终才顿悟。它们与PWM的比较值寄存器CCAP0H与CCAP0L拼成了9位。但是PCA的计数器CL只有8位,所以它最多只能实现8位PWM,这第9位有什么用呢? 有些时候我们希望PWM能够立即变为只输出低电平或高电平的状态。当然我们可以向CCAP0H写入0或255,另一种方法是向EPC0H写入1或0。写入1后,比较值永远都比计数值要大,所以PWM输出一直为低;写入0后(同时将CCAP0H清0),比较值永远不大于计数值,所以PWM输出为高电平。 实验代码: #include "STC15Fxxxx.H" void delay(unsigned int time) { while(time--); } void main(void) { PCA_USE_P12P11P10P37(); //选择PWM输出管脚 PCA_CLK_1T(); //PCA时钟源为SYSclk,即5.5MHz PWM0_NORMAL(); //PWM0正常输出 PWM1_NORMAL(); //PWM1正常输出 PCA0_PWM(8);PCA1_PWM(8); //设置PWM为8位模式 CCAP0L=0;CCAP0H=0; //PWM0比较值为0, CCAP1L=0;CCAP1H=0; //PWM1比较值为0,一开始均输出全高电平 CR=1; //启动PCA计数器 while(1) { delay(10000); CCAP0H++; CCAP1H++; //不断更新PWM的比较值,改变脉宽,LED亮度变化 } while(1); }
注:上面程序中的宏来自于STC15头文件,详见头文件源代码 |
实验效果:
代码下载: 群名称是
|