C51編譯器bug 三段代碼如下,,不明白為什么第一段代碼會(huì)有問題? void Ext_INT0 (void) interrupt INT0_VECTOR { unsigned char pos=5-(P3&0x07); display_buffer[pos]=P1;//有問題,,偶爾出現(xiàn)數(shù)據(jù)讀取出錯(cuò) } void Ext_INT1 (void) interrupt INT1_VECTOR { unsigned char pos=5-(P3&0x07); display_buffer[pos]=P1&0x0f;//沒問題,,功能正常 } void Ext_IN0T2 (void) interrupt INT2_VECTOR // { unsigned char pos=5-(P3&0x07); unsigned char value=P1; display_buffer[pos]=value;//沒問題,功能正常 } 編譯后的匯編代碼如下 28: void Ext_INT0 (void) interrupt INT0_VECTOR //進(jìn)中斷時(shí)已經(jīng)清除標(biāo)志 29: { C:0x048F C0E0 PUSH ACC(0xE0) C:0x0491 C0D0 PUSH PSW(0xD0) C:0x0493 75D000 MOV PSW(0xD0),#0x00 C:0x0496 C000 PUSH 0x00 C:0x0498 C007 PUSH 0x07 30: unsigned char pos=5-(P3&0x07); C:0x049A E5B0 MOV A,P3(0xB0) C:0x049C 5407 ANL A,#0x07 C:0x049E FF MOV R7,A C:0x049F C3 CLR C C:0x04A0 7405 MOV A,#0x05 C:0x04A2 9F SUBB A,R7 31: display_buffer[pos]=P1; C:0x04A3 2431 ADD A,#display_buffer(0x31) C:0x04A5 F8 MOV R0,A C:0x04A6 A690 MOV @R0,P1(0x90) 32: } C:0x04A8 D007 POP 0x07 C:0x04AA D000 POP 0x00 C:0x04AC D0D0 POP PSW(0xD0) C:0x04AE D0E0 POP ACC(0xE0) C:0x04B0 32 RETI 35: void Ext_INT1 (void) interrupt INT1_VECTOR //進(jìn)中斷時(shí)已經(jīng)清除標(biāo)志 36: { C:0x001D C0E0 PUSH ACC(0xE0) C:0x001F C0D0 PUSH PSW(0xD0) C:0x0021 75D000 MOV PSW(0xD0),#0x00 C:0x0024 C000 PUSH 0x00 C:0x0026 C006 PUSH 0x06 C:0x0028 C007 PUSH 0x07 37: unsigned char pos=5-(P3&0x07); C:0x002A E5B0 MOV A,P3(0xB0) C:0x002C 5407 ANL A,#0x07 C:0x002E FF MOV R7,A C:0x002F C3 CLR C C:0x0030 7405 MOV A,#0x05 C:0x0032 9F SUBB A,R7 C:0x0033 FF MOV R7,A 38: display_buffer[pos]=P1&0x0f; C:0x0034 E590 MOV A,P1(0x90) C:0x0036 540F ANL A,#0x0F C:0x0038 FE MOV R6,A C:0x0039 7431 MOV A,#display_buffer(0x31) C:0x003B 2F ADD A,R7 C:0x003C F8 MOV R0,A C:0x003D A606 MOV @R0,0x06 39: } C:0x003F D007 POP 0x07 C:0x0041 D006 POP 0x06 C:0x0043 D000 POP 0x00 C:0x0045 D0D0 POP PSW(0xD0) C:0x0047 D0E0 POP ACC(0xE0) C:0x0049 32 RETI 42: void Ext_IN0T2 (void) interrupt INT2_VECTOR // 43: { C:0x03F5 C0E0 PUSH ACC(0xE0) C:0x03F7 C0D0 PUSH PSW(0xD0) C:0x03F9 75D000 MOV PSW(0xD0),#0x00 C:0x03FC C000 PUSH 0x00 C:0x03FE C006 PUSH 0x06 C:0x0400 C007 PUSH 0x07 44: unsigned char pos=5-(P3&0x07); C:0x0402 E5B0 MOV A,P3(0xB0) C:0x0404 5407 ANL A,#0x07 C:0x0406 FF MOV R7,A C:0x0407 C3 CLR C C:0x0408 7405 MOV A,#0x05 C:0x040A 9F SUBB A,R7 45: unsigned char value=P1; C:0x040B AE90 MOV R6,P1(0x90) 46: display_buffer[pos]=value; C:0x040D 2431 ADD A,#display_buffer(0x31) C:0x040F F8 MOV R0,A C:0x0410 A606 MOV @R0,0x06 47: } 48: 49: C:0x0412 D007 POP 0x07 C:0x0414 D006 POP 0x06 C:0x0416 D000 POP 0x00 C:0x0418 D0D0 POP PSW(0xD0) C:0x041A D0E0 POP ACC(0xE0) C:0x041C 32 RETI 總結(jié)如下: 1.通過長表達(dá)式進(jìn)行賦值時(shí)有時(shí)會(huì)出錯(cuò),,最后把復(fù)雜表達(dá)式分解為簡單表達(dá)式并把結(jié)果存在中間變量里,,最后把結(jié)果賦值給需要的變量,這個(gè)可能是C51編譯器的問題,,碰到過很多次了,,在標(biāo)準(zhǔn)C編譯器或者pc環(huán)境下沒發(fā)現(xiàn)過這個(gè)問題。2.再一個(gè)就是讀取端口數(shù)據(jù)的問題 MOV @R0,P1(0x90) 直接把端口數(shù)據(jù)進(jìn)行間接尋址可能出錯(cuò),, MOV R6,P1(0x90) MOV @R0,0x06先把端口數(shù)據(jù)讀取到中間寄存器中,,最后再把中間寄存器值賦給間接地址, 最后,,很遺憾,,只是看到匯編代碼層級(jí)的代碼差別,,未能明白出問題的更深層次原理。 單純從匯編代碼上分析也看不出什么問題,??赡芨布C(jī)制有關(guān)系? 總結(jié):最后發(fā)現(xiàn)問題不是編譯器導(dǎo)致的,而是因?yàn)閿?shù)據(jù)和中斷引腳在同一個(gè)端口P3,, 數(shù)據(jù)在P3^0-P3^3,而中斷引腳是在P3^6和P3^7,,到中斷引腳上接受到信號(hào)是, 再一定程度上引腳到了數(shù)據(jù)P3^0-P3^3,,因?yàn)樗麄兌荚谕粋€(gè)端口,,而作為數(shù)據(jù)的P1端口則沒有收到影響。 一開始數(shù)碼管地址數(shù)據(jù)P3^0-P3^3讀取的,,導(dǎo)致前后兩個(gè)位置的數(shù)據(jù)管有時(shí)出現(xiàn)交錯(cuò)顯示,, 最后根據(jù)數(shù)碼管是以連續(xù)地址顯示的情況,改成在同一個(gè)中斷觸發(fā)的情況下由一個(gè)固定地址自減,,而不是在中斷中從P3^0-P3^3讀取,,處理原理類似乒乓機(jī)制,這樣處理,,數(shù)碼管穩(wěn)定顯示,。 最后還要說的是為什么一開始懷疑是C51編譯器bug的問題了,因?yàn)?span style="line-height: 1.5;">在中斷處理程序中通過增加或減少一行代碼,,發(fā)現(xiàn)數(shù)據(jù)管交錯(cuò)顯示混亂的情況有改變,,因此以為是編譯器bug。 真實(shí)原因是在中斷中增加或減少代碼改變執(zhí)行時(shí)間,,在從P3^0-P3^3讀取地址數(shù)據(jù)的時(shí)候,, 受干擾的情況因?yàn)闀r(shí)間變化有所改變。 代碼如下所示: unsigned char hpos; unsigned char lpos; void Ext_IN0T2 (void) interrupt INT2_VECTOR { display_buffer[hpos--]=P1; lpos=5; } void Ext_INT3 (void) interrupt INT3_VECTOR { display_buffer[lpos--]=P1; hpos=11; } |
|