1. 程式人生 > >關於51微控制器中斷標誌的一個小問題

關於51微控制器中斷標誌的一個小問題

第一張圖片:

第二張圖片:


程式碼:

#include

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

unsigned char code LedChar[]={
	0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
	0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
	};
unsigned char LedBuff[6]={
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
	};


unsigned int cnt = 0;

void main()
{
	
	unsigned long sec = 0;
	

	ENLED = 0;
	ADDR3 = 1;
	TMOD = 0x01;
	TH0 = 0xFC;
	TL0 = 0x67;
	TR0 = 1;
	EA = 1;
	ET0 = 1;

	while(1)
	{
	   	if(cnt >= 1000)
		{
			cnt = 0;
			sec++;
			LedBuff[0] = LedChar[sec%10];
			LedBuff[1] = LedChar[sec/10%10];
			LedBuff[2] = LedChar[sec/100%10];
			LedBuff[3] = LedChar[sec/1000%10];
			LedBuff[4] = LedChar[sec/10000%10];
			LedBuff[5] = LedChar[sec/100000%10];
		}		    
	}
}

 unsigned char i = 0; 
void InterruptTimer0()  interrupt 1		 
{
	TH0 = 0xFC;
	TL0 = 0x67;
	cnt++;
	P0 = 0xFF;
	switch(i)
	{
		case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0];break;
		case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1];break;
		case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2];break;
		case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3];break;
		case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4];break;
		case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5];break;
		default:break;
	}
}
此為數碼管顯示計數的程式,但筆者發現,當代碼為第一張圖片時候,當計數到30s時候,實際秒錶是24s,而第二張圖片加一個標誌位時候確與實際一致。以下為筆者分析,有不足之處望前輩指點~ 分析如下: 第一張圖片程式實際上是有問題的,因為cnt是int型,也就是2個位元組,51微控制器是8位的,一次只能讀寫1個位元組,所以當你判斷cnt>=1000的時候是要執行好幾條指令的,而如果剛判斷了低位元組還沒來得及判斷高位元組,這時中斷中cnt的值就變了,那就有可能導致判斷錯誤。 也就是說假設當進行if (cnt>=1000)判斷的時候,1ms到了進入中斷cnt++可能cnt變成了1001或者更多,這樣中斷結束返回判斷的時候cnt的值就不再是1000了,時間就變長了。 而第二張圖片加了一個flag判斷標誌位,假設在滿足了flag為1,if(flag==1)判斷時,進入中斷,可是cnt在中斷時已經清0了,又是從1開始加(flag在這裡始終為1),所以對中斷完回去判斷if,沒有影響。 當然這裡只是筆者的愚見,還請前輩多多指點~吐舌頭