Posted by (0) Comment
脉冲宽度调制(PWM)波形常用于闭环反馈和控制应用,例如:控制加热单元的开关状态以调节DWDM(波分复用)系统中激光器的温度。在某些应用中可编程计数器阵列(PCA)的内建8位PWM方式不能提供任务所需要的足够的分辨率。本应用笔记介绍如何用PCA的‘高速输出’方式和最小的软件开销来产生一个16位分辨率的PWM波形。
用于闭环控制应用的PWM信号的频率并不重要,只要波形足够快就可以了,象控制系统的阶跃响应时间就应远远小于PWM信号的周期。信号所携带的的信息用波形的占空度来编码,占空度是波形为高电平的时间与PWM信号的周期之比。对于一个PWM实现来说,其输入是一个数值,通常为整数,该数值与所要求的输出波形的占空度成正比。
在一个基于8051的设计中,有很多方法用于产生PWM波形:软件循环,查询或中断驱动的定时器等.本应用笔记中的例子使用可编程计数器阵列PCA.相对于任何查询机制基于软件或定时器而言,使用PCA产生PWM可以大大降低所需要的CPU带宽,并可以消除在中断驱动的基于定时器的设计中因中断延迟不一致而产生的时序抖动。
PCA包含一个16位的计数器/定时器和5个捕捉/比较模块如图2所示计数器/定时器有一个16位的计数器/定时器寄存器PCA0H:PCA0L一个用于选择时间基准的方式寄存器PCA0MD和一个包含计数器/定时器运行控制及各模块捕捉/比较标志的控制寄存器PCA0CN每个捕捉/比较模块有一个用于选择模块工作方式边沿触发捕捉软件定时器高速输出或PWM的配置寄存器PCA0CPMx和一个16位的捕捉/比较寄存器。
PCA0CPHn:PCA0CPLn由于所有的捕捉/比较模块共享一个时间基准因此它们同步工作例如在电机控制应用中可以提供锁相激励波形另外由于每个模块有其自己的控制和捕捉/比较寄存器因此每一个模块工作上又独立于其它模块只要任何一个模块的服务程序都不影响共享的时间基准停止或重新设置计数器/定时器改变计数器/定时器的时钟源本应用笔记中的例子将PCA配置为独立工作每个模块的服务程序只影响该模块的配置寄存器和捕捉/比较寄存器PCA方式寄存器设置一次后不再改变让计数器/定时器寄存器PCA0H: PCA0L自由运行。
PCA包含一个16位的计数器/定时器和5个捕捉/比较模块。计数器/定时器有一个16位的计数器/定时器寄存器PCA0H:PCA0L、一个用于选择时间基准的方式寄存器PCA0MD和一个包含计数器/定时器运行控制及各模块捕捉/比较标志的控制寄存器PCA0CN。每个捕捉/比较模块有一个用于选择模块工作方式(边沿触发、捕捉软件、定时器高速输出或PWM)的配置寄存器PCA0CPMx和一个16位的捕捉/比较寄存器PCA0CPHn:PCA0CPLn。
由于所有的捕捉/比较模块共享一个时间基准,因此它们同步工作,例如在电机控制应用中可以提供锁相激励波形。另外,由于每个模块有其自己的控制和捕捉/比较寄存器,因此每一个模块工作上又独立于其它模块,只要任何一个模块的服务程序都不影响共享的时间基准(停止或重新设置计数器/定时器、改变计数器/定时器的时钟源)。
PCA的时基信号可以是下述四个时钟源之一SYSCLK/12、SYSCLK/4、定时器0溢出、或出现在一个外部引脚ECI上的下降沿。
用PCA产生16位PWM 为了产生一个具有16位精度的PWM波形,我们将PCA模块配置为高速输出方式。在该方式下,每当主定时器/计数器的寄存器PCA0H:PCA0L与模块的捕捉/比较寄存器PCA0CPHn:PCA0CPLn相匹配时CEXn引脚发生电平转换并可以选择产生中断。
void SysClkInit(void)//配置系统时钟 { int n = 0; OSCXCN = 0x67; for (n = 0; n < 255; n++) ; while ( (OSCXCN & 0x80) == 0 ); OSCICN = 0x0C; } void SystemInit(void)//系统配置 { WDTCN = 0xDE; // 关闭 WDT WDTCN = 0xAD; } void PortInit(void)//端口配置 { //交叉开关配置 XBR0 = 0x10; XBR1 = 0x00; XBR2 = 0x40; // P0 口分配状况 // P0.0 = CEX0 // P0.1 = CEX0 } void PCA_Init(void) { EIE1 |= 0x08; PCA0MD = 0X01;//系统时钟的12分频 PCA0L = 0x00; PCA0H = 0x00; PCA0CPM0 = 0xcb; PCA0CPM1 = 0xcb; PCA0CPM0 |= 0x40; //开启CCFn中断 PCA0CPM1 |= 0x40; //开启CCFn中断 //PWM频率计算:系统时钟/12/计数=22118400/12/65536=28.125 } void PCA_CPHL0(unsigned int PWM) { PCA0CN &= ~0x40; PCA0CPL0 = (0xff & PWM); PCA0CPH0 = (0xff & (PWM >> 8)); PCA0CN |= 0x40; } void PCA_CPHL1(unsigned int PWM) { PCA0CN &= ~0x40; PCA0CPL1 = (0xff & PWM); PCA0CPH1 = (0xff &(PWM >> 8)); PCA0CN |= 0x40; } void PCA_ISR(void) interrupt 9 { if (CCF0) { CCF0 = 0; } else if (CCF1) { CCF1 = 0; } else if (CF) { CF = 0; } }