中级会员
- 积分
- 417
- 威望
- 319
- 贡献
- 62
- 兑换币
- 12
- 注册时间
- 2010-1-23
- 在线时间
- 18 小时
|
3贡献
//下面的小程序是我测试 PIT 写的,目的是利用级联的24位计数器产生1ms的延时函数,然后调用该函数,使最小系统版上的LED亮一秒,灭一秒
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative information */
static dword PIT_Timing_00,PIT_Timing_00_Temp=0; //用于8位位计数器0和16位计数器0级联的计数器产生延时用的变量
static byte Flag_Delay=0; //定时完成标志
void InitialPLL(void) //外部时钟为16MHz,PLLCLK=96MHz,BUSCLK=48MHz
{ CLKSEL=0X00; //disengage PLL to system
POSTDIV=0x00; //后除数无效,则PLLCLK=fVCO
SYNR=0xcb; //PLLCLK =2*OSCCLK*(SYNR + 1)/(REFDV + 1)=120MHz
REFDV=0x43; //SYNR,REFDV最高两位的确定依据数据手册提供的资料
PLLCTL=0xc0; //打开时钟监视,并且打开PLL
CLKSEL=0X80; //选通PLL时钟提供给总线
__asm {
NOP;
NOP;
NOP;
}
while((CRGFLG&0X08)==0)
{ } //时钟校正同步,等待单片机内部时钟稳定
CLKSEL=0X80; //再次使能PLLCLK,确保不出错
}
void InitialPIT(void){ //定时计数器初始化,BUSCLK=48MHz
//8位微计数器0和16计数器0级联产生一个 1ms 的基准定时,用于其他程序
//其它几个计数器作用待定,暂时不用,所以是对位进行的操作
PITTF=0xff; //使用定时器前先将所有中断标志位清除,以免不必要错误,注意此寄存器需要写入"1"才能清除
PITINTE=0x00; //所有通道中断禁用
PITCE=0x00; //所有定时器通道关闭
PITCFLMT_PITE=0; //所有定时通道禁用
PITMTLD0=0x2f; //8位定时器0初值设定,48分频。溢出周期=(PITMTLD + 1) * (PITLD + 1) /BUSCLK。
PITLD0=0x03e7; //16位定时器初值设定,在8位微计数器基础上在1000分频,即是级联的24位计数器为BUSCLK的
//48*1000分频,所以计数周期为1ms,频率 1KHz
PITMUX_PMUX0=0; //选定16位计数器0所用的基准8位微计数器0
//因为8位微计数器0和16位计数器0是其它程序调用,用于延时的,所以初始化时并不使能
//PITINTE_PINTE0=1; //定时器中断通道0中断使能
//PITCE_PCE0=1; //打开16位计数器0的
//PITCFLMT_PITE=1; //所有定时器通道使能
}
void InitialPort(void){
DDRB=0xff; //B口作为输出,利用LED组合显示系统状态
PORTB=0x00; //复位时最小系统板上接B口的8位LED亮
}
void Delay(dword del_ms){
PIT_Timing_00 = del_ms;
PITTF_PTF0=1;
PITINTE_PINTE0=1; //定时器中断通道0中断使能
PITCE_PCE0=1; //打开16位计数器0的
PITCFLMT_PITE=1; //所有定时器通道使能
while(PIT_Timing_00 > PIT_Timing_00_Temp);
Flag_Delay=1;
PIT_Timing_00_Temp=0;
}
void main(void)
{
InitialPLL();
InitialPIT();
InitialPort();
EnableInterrupts;
for(;;) {Delay(1000);}
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 66 PIT0(void) {
PIT_Timing_00_Temp++;
if(Flag_Delay){ //Flag_Delay为定时完成的标志位
Flag_Delay=0x00; //达到想要的定时时间,清除标志位
PORTB=~PORTB;
}
PITCE_PCE0=0;
__asm {
NOP;
NOP;
NOP;
}
PITINTE_PINTE0=0;
__asm {
NOP;
NOP;
NOP;
}
PITTF_PTF0|=0x00; __asm {
NOP;
NOP;
NOP;
}
PITINTE_PINTE=1;
__asm {
NOP;
NOP;
NOP;
}
PITCE_PCE0=1;}
我的测试结果是,只有这样LED才是亮1秒,熄1秒。问题来了,如果按照datashit所说的清除标志位需要在该计数器没启用或者PITE无效时,向该位写1,LED就一直亮着,只是1秒后亮度小了点(我的猜测是由于标志位没有清除,会一直执行中断函数,导致PB口输出的高低电平周期严重减小)……
在这执行“ PITCE_PCE0=0;”后标志位确实被清除了,但一运行到绿色那句时,PITTF_PTF0 标志位那上就变成 1 了!!!!!!实在是让我很无语有很无奈。。。。。
我在飞思卡尔板块也发了同样的求助帖,希望论坛里车友们解救小弟 ,谢谢!!!!! 由于我的贡献币不多,各位多多包涵~ |
|