天天看点

单片机定时器精准定时_关于51单片机定时器计时不准确问题(不用定时器中断)...

volatile uint8_t plus_nums = 0;//记录下降沿数量

volatile uint8_t nec_code[4] = {0};//保存NEC协议数据

volatile uint8_t received_flag = 0;//接收完成标志

//#define debug

#ifdef DEBUG

sbit LED0 = P1^0;

sbit LED1 = P1^1;

sbit LED2 = P1^2;

sbit LED3 = P1^3;

sbit LED4 = P1^4;

sbit LED5 = P1^5;

sbit LED6 = P1^6;

sbit LED7 = P1^7;

sbit TEST        = P2^0;

#endif

void Init_all_interrupt(void)

{

TMOD = 0x01;//16位计数值

ET0 = 1;

EX0 = 1;

IT0 = 1;

TR0 = 0;

EA = 1;

P1 = 0xff;

}

void NEC_falldown_INT0(void) interrupt 0

{

uint16_t temp_plus_time = 0;

#ifdef DEBUG

TEST = 0;

#endif

plus_nums++;

if(plus_nums == 1)//第一次下降沿

{

TH0 = 0;

TL0 = 0;

TR0 = 1;//开启定时器

}

else if(plus_nums == 2)//进行“前导码判断”第一次下降沿,清零开始计时脉冲

{

temp_plus_time = TH0;

temp_plus_time = temp_plus_time << 8;

temp_plus_time = temp_plus_time | TL0;//保存脉冲数值

TH0 = 0;

TL0 = 0;

if((temp_plus_time >= 0x2BB0) && (temp_plus_time <= 0x3576))//脉冲时间在(13.5ms)±10%

{

#ifdef DEBUG

LED0 = 0;

#endif

}

else        //前导码异常--重新检测整个NEC协议序列

{

//全部复位--重新开始

plus_nums = 0;

TR0 = 0;//关闭定时器0

}

}

else        //3-34

{

temp_plus_time = TH0;

temp_plus_time = temp_plus_time << 8;

temp_plus_time = temp_plus_time | TL0;//保存脉冲数值

TH0 = 0;

TL0 = 0;

//933~1140;不知道理论计数得到的下限值会偏小很多?---!!!只有一种可能,晶振频率有问题!!!

//650~1140---测试可用

if((temp_plus_time >= 933) && (temp_plus_time <= 1140))//判断”逻辑0“.脉冲时间在(1.125ms)±10%

{

#ifdef DEBUG

LED1 = 0;

#endif

}

//1866~2280;不知道理论计数得到的下限值会偏小很多?---!!!只有一种可能,晶振频率有问题!!!

//1566~2280---测试可用

else if((temp_plus_time >= 1866) && (temp_plus_time <= 2280))//判断”逻辑1“.脉冲时间在(2.25ms)±10%

{

temp_plus_time = plus_nums -3;//产生数组下标

//nec_arr_index / 8可以使用位域代替这个运算,提高执行效率

nec_code[temp_plus_time / 8] = nec_code[temp_plus_time / 8] | (0x01 << (temp_plus_time % 8));

#ifdef DEBUG

LED2 = 0;

#endif

}

else

{

//全部复位--重新开始

plus_nums = 0;

TH0 = 0;

TL0 = 0;

TR0 = 0;//关闭定时器0,重新开始

for(temp_plus_time = 0;temp_plus_time < 4;temp_plus_time++)

{

nec_code[temp_plus_time] = 0;

}

#ifdef DEBUG

LED7 = ~LED7;

#endif

}

//接收到了结束标志脉冲

if(plus_nums == 34)

{

plus_nums = 0;//结束了

received_flag = 1;//可以进行解码操作了

TR0 = 0;//关闭定时器0

#ifdef DEBUG

LED3 = ~LED3;

#endif

}

}

#ifdef DEBUG

TEST = 1;

#endif

}

void NEC_Plus_TIMER0(void) interrupt 1

{

uint8_t i;

TR0 = 0;//关闭定时器

TH0 = 0x00;

TL0 = 0x00;

//所有全局变量清零

plus_nums = 0;

for(i = 0;i < 4;i++)

{

nec_code[i] = 0;

}

#ifdef DEBUG

LED4 = 0;

#endif

}