garfield

MCF52233_GPT

0
阅读(28502)

今天给介绍下Coldfire的GPT这个模块。在调这块的时候碰到了一个问题。验证脉宽检测的时候用的是另一个实验箱输出的PWM波,测出来的结果老是相差10倍,在一大堆数据中会有那么一个是正常的结果。晕、迷茫,手册看了一遍又一遍始终找不出来哪地方的问题。弄了快一天,忽然想到把两个电路的地连起来,呵呵,马上就看到了期盼了一天的数据。其实这个小细节以前老师跟我们讲过的,只是当是没在意,慢慢就忘了,现在看来真是太重要了,经验乎教训乎……

  呵呵,Coldfire的定时器可真是多啊!两路的PIT;四路的GPT实际上是由2计数器组成的,并不像第一印象4个那样;8路的PWM用的8个定时器我感觉用计数器来定义更合适些。从更接近硬件的本质的角度来看好多都是计数器,但表现出来的却都是定时器的功能。哈哈,我们就把他们统统当成定时器吧,总共14个!(以表对Coldfire的崇拜,GPT我把它当作有4个)嘿嘿,个人认为还是很N的。

  在这些定时器中,最复杂的要数GPT了,因为它的功能真是太多了(呵呵,用“全”来形容更合适)。4路的输出比较/输入捕获、1路的外部事件计数、1路的脉宽检测,这其中有些是共用一个引脚的,所以并不是这6路可以同时使用的。另外它的中断也肯定会让你笑的,共有7个。

  首先说下输出比较/输入捕获(output compare/input capture):虽然Coldfire已经有了很方便的8路PWM功能,但它GPT的output compare同样可以用来产生PWM,不同的是GPT可以产生更精确的PWM波形,频率控制也更自由灵活。美中不足的是要产生高频的PWM波的话就要使用channel 3来限制计数上限,这样就限制了channel 3功能的发挥。要是能再增加寄存器来存放计数上限就好了,不过这样的话GPT可能就真的要4个计数器而不是现在的2个了,这个就不讨论了。

  对于input capture,就是个边沿触发器,当有效边沿来时记下当前时刻,跟据自己的爱好产生中断。这个用来对外部事件计数,或者当作外部中断,再或者用来测脉宽那都是没问题的。

  然后是计数功能,它直接就给出了有效边沿发生的次数,用来计数的话,程序那是相当的简便啊!

  最后是脉宽检测(Pulse Accumulator),这个只是在input capture上作了点手脚。它是一个有效边沿发生时启动PA计数器,结束边沿到达时停止PA计数器,并产生中断。我们直接就可以得到被测脉宽了。

  还有一点要引起大家注意的是GPTOC3D与GPTOC3M这两个寄存器。在输出比较功能中,当channel 3输出比较发生,并且GPTOC3M是某一位被置1时,会把对应的GPTOC3D里的那位输出到对应的引脚上。

  无论初始化还是7个中断都要跟据不同的功能来写,看代码吧:

void GPT_init(void)
{
 
 uart0_putstr("GPT_init\n");
  MCF_GPIO_PTAPAR=MCF_GPIO_PTAPAR_GPT0_GPT0
                |MCF_GPIO_PTAPAR_GPT1_GPT1
                |MCF_GPIO_PTAPAR_GPT2_GPT2
                |MCF_GPIO_PTAPAR_GPT3_GPT3;
 //set pin as input capture or output compare 0:input 
                  //          1:output
  MCF_GPTA_GPTIOS=MCF_GPTA_GPTIOS_IOS0
                 |MCF_GPTA_GPTIOS_IOS1;
                 //|MCF_GPTA_GPTIOS_IOS2;
                //|MCF_GPTA_GPTIOS_IOS3;
 //force a compare
  MCF_GPTA_GPTCFORC=0;
 //config corresponding pin as output
  MCF_GPTA_GPTOC3M=MCF_GPTA_GPTOC3M_OC3M0
                |MCF_GPTA_GPTOC3M_OC3M1;
                //|MCF_GPTA_GPTOC3M_OC3M2;
                //|MCF_GPTA_GPTOC3M_OC3M3;
 
  MCF_GPTA_GPTOC3D=MCF_GPTA_GPTOC3D_OC3D0
                |MCF_GPTA_GPTOC3D_OC3D1
                |MCF_GPTA_GPTOC3D_OC3D2
                |MCF_GPTA_GPTOC3D_OC3D3;
 //toggles the output compare pin on overflow for each channel
  MCF_GPTA_GPTTOV=MCF_GPTA_GPTTOV_TOV0
                 |MCF_GPTA_GPTTOV_TOV1
                 |MCF_GPTA_GPTTOV_TOV2
                 |MCF_GPTA_GPTTOV_TOV3;
 //disconnect(NOGHING)/toggle/set/clesr when compare occured
  MCF_GPTA_GPTCTL1=MCF_GPTA_GPTCTL1_OUTPUT0_CLEAR
                |MCF_GPTA_GPTCTL1_OUTPUT1_CLEAR
                |MCF_GPTA_GPTCTL1_OUTPUT2_NOTHING
                |MCF_GPTA_GPTCTL1_OUTPUT3_NOTHING;
 //input capture disable/on rising/on falling/on any edge
  MCF_GPTA_GPTCTL2=MCF_GPTA_GPTCTL2_INPUT0_DISABLED
                 |MCF_GPTA_GPTCTL2_INPUT1_DISABLED
                 |MCF_GPTA_GPTCTL2_INPUT2_RISING
                 |MCF_GPTA_GPTCTL2_INPUT3_DISABLED;
// channel interrupt enable
  MCF_GPTA_GPTIE=//MCF_GPTA_GPTIE_CI0
               //|MCF_GPTA_GPTIE_CI1
               MCF_GPTA_GPTIE_CI2;
               //MCF_GPTA_GPTIE_CI3;
 //TOI time over interrupt
 //pull-up resistor when the pin configured as input
 //prescaler bits
  MCF_GPTA_GPTSCR2=//MCF_GPTA_GPTSCR2_TOI
                MCF_GPTA_GPTSCR2_PUPT
                //|MCF_GPTA_GPTSCR2_TCRE
                |MCF_GPTA_GPTSCR2_PR_128;
 //a channel flag is set when an input capture or output compare event occurs
  MCF_GPTA_GPTFLG1=0x0F;
  MCF_GPTA_GPTFLG2=0x80;// timer overflow flag
 //
  MCF_GPTA_GPTC0=51;
  MCF_GPTA_GPTC1=110;
  MCF_GPTA_GPTC2=0;
  MCF_GPTA_GPTC3=240;
 //
  MCF_GPTA_GPTPACTL=MCF_GPTA_GPTPACTL_PAI
                 //|MCF_GPTA_GPTPACTL_PAOVI
                  |MCF_GPTA_GPTPACTL_CLK_GPTPR
                 //|MCF_GPTA_GPTPACTL_PEDGE
                  |MCF_GPTA_GPTPACTL_PAMOD;
 //
  MCF_GPTA_GPTPAFLG=MCF_GPTA_GPTPAFLG_PAIF
                 |MCF_GPTA_GPTPAFLG_PAOVF;
  MCF_GPTA_GPTPACNT=0;
 //
  MCF_GPTA_GPTPORT=MCF_GPTA_GPTPORT_PORTT0
                |MCF_GPTA_GPTPORT_PORTT1
                |MCF_GPTA_GPTPORT_PORTT2
                |MCF_GPTA_GPTPORT_PORTT3;
  MCF_GPTA_GPTDDR=MCF_GPTA_GPTDDR_DDRT0 
                 |MCF_GPTA_GPTDDR_DDRT1; 
                 //|MCF_GPTA_GPTDDR_DDRT2;
                 //|MCF_GPTA_GPTDDR_DDRT3;
 //
 
 //configure interrupts
  MCF_INTC0_IMRL&=~MCF_INTC_IMRL_MASKALL;
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK41;//TOF
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK42;//PAIF
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK43;//PAOVF
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK44;//C0F
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK45;//C1F
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK46;//C2F
  MCF_INTC0_IMRH&=~MCF_INTC_IMRH_INT_MASK47;//C3F
  MCF_INTC0_ICR41=MCF_INTC_ICR_IP(6)+MCF_INTC_ICR_IL(2);//TOF
  MCF_INTC0_ICR42=MCF_INTC_ICR_IP(5)+MCF_INTC_ICR_IL(2);//PAIF
  MCF_INTC0_ICR43=MCF_INTC_ICR_IP(4)+MCF_INTC_ICR_IL(2);//PAOVF
  MCF_INTC0_ICR44=MCF_INTC_ICR_IP(3)+MCF_INTC_ICR_IL(2);//C0F
  MCF_INTC0_ICR45=MCF_INTC_ICR_IP(2)+MCF_INTC_ICR_IL(2);//C1F
  MCF_INTC0_ICR46=MCF_INTC_ICR_IP(1)+MCF_INTC_ICR_IL(2);//C2F
  MCF_INTC0_ICR47=MCF_INTC_ICR_IP(0)+MCF_INTC_ICR_IL(2);//C3F

 
 
 //start GPT
  MCF_GPTA_GPTSCR1=MCF_GPTA_GPTSCR1_GPTEN;
 //start Pulse Accumulator
  MCF_GPTA_GPTPACTL|=MCF_GPTA_GPTPACTL_PAE; 
}


void convert_to_ASSIC(char str[],int32 data)
{
 str[0]=(char)(data/10000+48);
 str[1]=(char)((data%10000)/1000+48);
 str[2]=(char)((data%1000)/100+48);
 str[3]=(char)((data%100)/10+48);
 str[4]=(char)(data%10+48); 
}

void GPT_stop(void)
{
 MCF_GPTA_GPTSCR1&=~MCF_GPTA_GPTSCR1_GPTEN; 
}

__declspec(interrupt:0) void GPT_TimerOverflow(void)//41
{
 MCF_GPTA_GPTFLG2=0x80;
 uart0_putstr("GPT timer overflow\n");
}

__declspec(interrupt:0) void GPT_PulseAccumulator(void)//42
{
 int32 temp;
 MCF_GPTA_GPTPAFLG|=MCF_GPTA_GPTPAFLG_PAIF;
 MCF_GPTA_GPTPACTL&=~MCF_GPTA_GPTPACTL_PAE;
 temp=MCF_GPTA_GPTPACNT;
 uart0_putstr("GPT_pulse accumulator interrupt\n");
 convert_to_ASSIC(result,temp);
 uart0_putstr(result);
 MCF_GPTA_GPTPACNT=0;
 MCF_GPTA_GPTPACTL|=MCF_GPTA_GPTPACTL_PAE;
 
}

__declspec(interrupt:0) void GPT_PulseAccumulatorOverflow(void)//43
{
 MCF_GPTA_GPTPAFLG|=MCF_GPTA_GPTPAFLG_PAOVF;
 uart0_putstr("GPT pulse accumultor overflow\n");
}

__declspec(interrupt:0) void GPT_Compare0(void)//44
{
 MCF_GPTA_GPTFLG1|=MCF_GPTA_GPTFLG1_CF0;
 uart0_putstr("GPT_compare0\n");
}

__declspec(interrupt:0) void GPT_Compare1(void)//45
{
 MCF_GPTA_GPTFLG1|=MCF_GPTA_GPTFLG1_CF1;
 uart0_putstr("GPT_compare1\n"); 
}

__declspec(interrupt:0) void GPT_Compare2(void)//46
{
 static int32 temp1,temp0=0;
 int32 temp;
 temp1=MCF_GPTA_GPTC2;
 temp=temp1-temp0;
 temp0=temp1;
 MCF_GPTA_GPTFLG1|=MCF_GPTA_GPTFLG1_CF2;
// uart0_putstr("GPT_compare2\n");
// uart0_putstr("GPT_capture2\n");
 convert_to_ASSIC(result,temp);
 uart0_putstr(result);
 
}

__declspec(interrupt:0) void GPT_Compare3(void)//47
{
 MCF_GPTA_GPTFLG1|=MCF_GPTA_GPTFLG1_CF3;
 uart0_putstr("GPT_compare3\n"); 
}