天天看點

單片機定時器精準定時_關于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

}