51单片机晶振如果是12Mhz,,那么时钟周期是1/12M,为什么机器周期是12/12M?
for(i=0,i<1000;i++),,这个循环i每加一次是一个机器周期还是一个时钟周期?如果是机器周期1000次循环是不是相当于过了1ms?
首先需要了解51单片机的时钟分频器和定时器,以及它们之间的关系。
对于12MHz的晶振频率,51单片机的机器周期为12/12M=1us,即每个机器周期1us。但是,由于51单片机时钟分频器的作用,实际上单片机的运行时钟频率会比晶振频率低一些,分频倍数根据不同的晶振频率和时钟模式而定。
在使用定时器实现一秒定时的过程中,可以通过计算定时器的初值和工作模式来实现。假设要实现的精度为1ms,在12MHz晶振频率下,使用12分频,即每秒钟时钟溢出次数为12*1000=12000次。因此,定时器的初值应设置为65536-12000=53536(因为定时器初值为2^16-计数值),同时选择定时器的工作模式为自动重载方式,即当计时器计满时自动重新装载计时初值,这样可以实现定时器的循环启动。每次定时器溢出后,可以在ISR中设置一个标志量,表示一秒时间已经过去,从而在主程序中实现相应的操作。
关于for循环中i的增加是一个机器周期还是一个时钟周期,可以根据具体情况来决定。在单片机中,一般采用机器周期计数方式。因此,在循环中,i的增加是一个机器周期。如果需要更精确的计时,可以使用定时器来实现。每次定时器溢出后,在ISR中进行计数并清零计数器,从而实现更准确的计时。
下面是一段参考代码实现一秒定时器:
#include <reg51.h>
#define TIMER0_RELOAD_VALUE 53536
volatile unsigned char timerFlag = 0;
void initTimer0(void)
{
TMOD |= 0x01; // 设置定时器0为模式1
TH0 = TIMER0_RELOAD_VALUE >> 8;
TL0 = TIMER0_RELOAD_VALUE & 0xFF;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
}
void timer0Isr(void) interrupt 1
{
TH0 = TIMER0_RELOAD_VALUE >> 8;
TL0 = TIMER0_RELOAD_VALUE & 0xFF;
timerFlag = 1;
}
void main(void)
{
initTimer0();
while (1)
{
if (timerFlag)
{
// 代码段1
// ...
timerFlag = 0;
}
// 代码段2
// ...
}
}
其中,initTimer0()
函数用于初始化定时器0,timer0Isr()
函数是定时器0的中断服务程序,用于定时器溢出后的操作。在main()
函数中,可以根据定义的timerFlag
标志量来判断一秒时间是否已经过去,从而在代码段1中执行相应的操作。在代码段2中,可以放其他需要处理的代码段。
1,51的一个标准机器周期是12个时钟周期,所以这样。
2,这个不好精确计算,现在的51都带流水线,一个指令的执行最快可以只要1个时钟周期。而且一次for循环,并不只有一个指令,你这个i超过了256,所以是整形,处理一次整形的自加都要几个机器周期,还要加上判断,就更多了
3,你问的东西文不对题,你标题的问题解决方案是,多个定时器周期累加。因为12M的51单片机,定时器做不到1秒一次。