最近一直在想怎么测单片机的总线时钟,于是想出了一个方法,也不知是否正确,权且估算一下吧。
先说明一下时钟周期,机器周期,总线周期的区别吧:
时钟周期: 时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时间周期就是1/12 us),是计算机中最基本的、最小的时间单位。
机器周期: 在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本 *** 作。完成一个基本 *** 作所需要的时间称为机器周期。一般情况下,一个机器周期由若干个S周期(状态周期)组成。 8051系列单片机的一个机器周期同6个 S周期(状态周期)组成。前面已说过一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示),8051单片机的机器周期由6个 状态周期组成,也就是说一个机器周期=6个状态周期=12个时钟周期。(例如外接24M晶振的单片机,他的一个机器周期=12/24M 秒)
指令周期: 执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期也不同。 对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。 通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。
总结:时钟周期是最小单位,机器周期需要1个或多个时钟周期,指令周期需要1个或多个机器周期;机器周期指的是完成一个基本 *** 作的时间,这个基本 *** 作有时可能包含总线读写,因而包含总线周期,但是有时可能与总线读写无关,所以,并无明确的相互包含的关系。指令周期:是CPU的关键指标,指取出并执行一条指令的时间。一般以机器周期为单位,分单指令执行周期、双指令执行周期等。现在的处理器的大部分指令(ARM、DSP)均采用单指令执行周期。机器周期:完成一个基本 *** 作的时间单元,如取指周期、取数周期。时钟周期:CPU的晶振的工作频率的倒数。
一个nop所占的时间为一个机器指令的时间,8051中为1us。
单片机型号为飞思卡尔MC9s12xep100,在main函数里放置时钟初始化函数,同时初始化一个引脚,并设置为输出,然后主函数放置该引脚电平的翻转函数。大致如下;
void main() { MCUInit(); DDRP_DDRP4=1;//PTP4设置为输出 while(1) { PTP_PTP4=~PTP_PTP4; } }然后用示波器测量该引脚翻转电平所用的时间,以下是部分数据:(示波器精度有限)
总线频率—>耗时 ≈ (1/总线频率)*10
16MHZ —>620ns ≈ 625ns
20MHZ —>500ns ≈ 500ns
32MHZ —>312ns ≈ 312ns
40MHZ —>252ns ≈ 250ns
48MHZ —>208ns ≈ 208ns
60MHZ —>168ns ≈ 166ns
通过上面的数据,发现耗时与 (1/总线频率)*10基本相等,至于为何乘10,不知何因。权且当做粗略估算吧。
----------------------------------------------------------------单片机9s08dz60------------------------------------------------------------------------------
顺便记录下对dz60的测试
总线频率—>翻转电平耗时 ≈ (1/总线频率)*10 asm("nop")耗时
16MHZ —>680ns ≈ 625ns 370ns
8MHZ —>1.36us ≈ 1.25us 740ns
4MHZ —>2.76us ≈ 2.50us 1.5us
其中asm("nop")耗时的计算方法如下:
void main() { MCUInit(); DDRP_DDRP4=1;//PTP4设置为输出 while(1) { PTP_PTP4=1; asm("nop"); PTP_PTP4=0; } }下面附dz60时钟初始化函数(晶振8MHZ,总线8MHZ) void MCUInit(void) { SOPT1 = 0x20; //取消看门狗,使能停止模式 SOPT2 = 0X00; //写入一次SOPT2 /* 初始化时钟,使用PEE模式,晶振为8Mhz,总线频率为8mhz(datasheet P151) */ /*----------------------------FEI -> FBE----------------------------------*/ MCGC2 = 0x36; //总线分频为1.P133. while (!MCGSC_OSCINIT); //EREFS位选择的晶体是否完成初始化.P134. MCGC1 = 0xB8; //选择使用外部晶振.P131. while (MCGSC_IREFST); //等待外部参考成为参考时钟的当前源 while(MCGSC_CLKST != 2); //等待外部参考 时钟成为 MCGOUT /*----------------------------FBE -> BLPE---------------------------------*/ MCGC2 = 0x3E; //设置LP位为1(此时已经进入BLPE模式) MCGC1 = 0x98;//0x98->RDIV=8;0x90->RDIV=4; //更改RDIV MCGC3 = 0x44;//0x44->VDIV=16;0x48->VDIV=32 //选择PLL,VDIV为4 while(!MCGSC_PLLST); //PLLS时钟的当前源是否PLL /*----------------------------BLPE -> PBE---------------------------------*/ MCGC2 = 0x36; //设置LP位为0(此时已经进入BLPE模式) while (!MCGSC_LOCK); //等待PLL获得锁定 /*----------------------------PBE -> PEE----------------------------------*/ MCGC1 = 0x18; //选择PLL为系统时钟 while(MCGSC_CLKST != 3); //等待时钟稳定 }MCGOUT=(8MHZ/8)*16/1=16MHZ,总线时钟为8MHZ
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)