MCF52233_GPT
0赞今天给介绍下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");
}