HCS08单片机PWM功能非正常使用方法的研究
0赞昨天一客户提出要让PWM周期结束前强制改变占空比,比如当20%占空比的波形进行到50%时,突然想将该引脚置高电平或低电平,并维持0占空比或满占空比。使用中发现状态不可控,达不到他想要的目的。我做实验进行了分析,请看下面代码:
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#define PWM_ON { TPM2C0SC=0x28,TPM2SC=0x16;} //方波启动 TPM2SC=0x16 is 4uS/conter
#define PWM_OFF { TPM2SC=0x00,TPM2CNT=0x0,TPM2C0SC=0x00;} //方波停止
#define PWM_SET(Tpulse,clyle) {TPM2C0V=Tpulse,TPM2MOD=clyle; }
unsigned int PWMDUTY;
//=================================================================================================
//函数名:Init_tpm1_counter
//作用:初始化TPM1,内部时钟工作于自时钟模式,总线频率4M;自由计数;溢出时间间隔=8000/4000近似2ms
//=================================================================================================
void Init_tpm1_counter(void)
{
TPM1SC=0x48;//TPM1时钟源为总线时钟;分频系数为1;溢出中断允许
TPM1MOD = 8000 - 1;
TPM1CNTH=0;//任意时刻对TPM1CNTH或TPM1CNTL的写操作将计数寄存器的计数值复位(清零)
}
void TPM2_init(void) //PWM OUTPUT ,TPM2-TH0为硬件比较输出 PTF4 顺序,需要先启动后设置,否则设置无效
{
PWM_OFF; //PWM-STEP1
PWM_ON; //PWM-STEP2
PWMDUTY=0x0000; // PTF4 LOW-LEVEL TIME
}
void main(void) {
EnableInterrupts; /* enable interrupts */
/* include your code here */
Init_tpm1_counter();
PTFDD_PTFDD0 = 1;
PTFDD_PTFDD4 = 1;
TPM2_init();
for(;;) {
__RESET_WATCHDOG(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
上面的定时器1专门用来产生翻转状态的时刻,定时器2用来产生PWM波形。采用4种状态轮流切换的方式,即“50%占空比->低电平->->高电平->50%占空比”以便观察。下面用3种方法的现象来对比其可行性,绿线(PTFD0)翻转表示状态切换,黄线(PTFD4,PWM波)是PWM波形引脚。
一、简单切换占空比,中断程序如下:
//==================计数器1溢出中断服务程序==========================
interrupt VectorNumber_Vtpm1ovf void TPM1_OVF_ISR(void)
{
static int cnt=0;
if((TPM1SC & 0x80)==0x80)
{
TPM1SC_TOF=0;
switch(cnt)
{
case 0:
case 14:
PWM_SET(50,100);
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 7:
PWM_SET(0,100);
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 21:
PWM_SET(100,100);
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 28:
cnt = -1;
break;
}
cnt++;
}
}
上面的波形显示,各状态切换都有很大延时。这是因为新状态的生效要等前一次PWM周期结束,在最坏的情况下要延时近一个周期。
二、设置占空比时停止定时器,之后再开启。
//==================计数器1溢出中断服务程序==========================
interrupt VectorNumber_Vtpm1ovf void TPM1_OVF_ISR(void)
{
static int cnt=0;
if((TPM1SC & 0x80)==0x80)
{
TPM1SC_TOF=0;
switch(cnt)
{
case 0:
case 14:
PWM_OFF;
PWM_SET(50,100);
PWM_ON;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 7:
PWM_OFF;
PWM_SET(0,100);
PWM_ON;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 21:
PWM_OFF;
PWM_SET(100,100);
PWM_ON;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 28:
cnt = -1;
break;
}
cnt++;
}
}
上面的波形仍存在2个问题:
1、从正常波形到0占空比(完全低电平)有个延时。
2、满占空比(完全高电平)时有毛刺。
三、改用IO口方式实现满占空比
//==================计数器1溢出中断服务程序==========================
interrupt VectorNumber_Vtpm1ovf void TPM1_OVF_ISR(void)
{
static int cnt=0;
if((TPM1SC & 0x80)==0x80)
{
TPM1SC_TOF=0;
switch(cnt)
{
case 0:
case 14:
PWM_OFF;
PWM_SET(50,100);
PWM_ON;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 7:
PWM_OFF;
PTFD_PTFD4 = 0;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 21:
PWM_OFF;
PTFD_PTFD4 = 1;
PTFD_PTFD0=~PTFD_PTFD0;
break;
case 28:
cnt = -1;
break;
}
cnt++;
}
}
上面的波形很正常了。



