關(guān)于單片機上for循環(huán)中運用ACC的隱蔽錯誤
先上代碼:第一個(gè)為錯誤代碼,第二個(gè)為正確代碼。這是用來(lái)向ds1302芯片寫(xiě)入命令或數據的函數。實(shí)現把8位的數據dat一位一位地寫(xiě)入ds1302的io口。其中ACC0為ACC的第0位。
本文引用地址:http://dyxdggzs.com/article/201611/319881.htm認真對比這兩個(gè)代碼,可能會(huì )覺(jué)得沒(méi)區別,而且這兩個(gè)代碼都可以通過(guò)編譯(加上reg52.h和一些宏定義)。我也是一直認為for()這里邊沒(méi)有錯誤,結果。。。試著(zhù)修改時(shí)鐘信號,增加延時(shí)之類(lèi)的,調了好久還是錯,嚴重打擊我的自信心。這兩個(gè)代碼的區別就只有for(i=0;i<8;i++)和for(i=8;i>0;i--)了。學(xué)過(guò)c語(yǔ)言的人都知道,這兩個(gè)句子都是實(shí)現一個(gè)8次的循環(huán),功能一模一樣。怎么會(huì )因為這個(gè)句子的區別就導致單片機控制的錯誤呢?神奇!
接著(zhù)我試著(zhù)把錯誤程序中的ACC改為51芯片的寄存器B,燒錄進(jìn)單片機,程序運行成功,跟“for(i=8;i>0;i--),ACC版”一樣,lcd在很?chē)虖埖仫@示著(zhù)正確的時(shí)間( for(i=0;i<8;i++),ACC版lcd的時(shí)間顯示為0)。附:
這樣就知道原因了,使用for(i=0;i<8;i++)的運算中可能有累加器ACC參與了,導致修改了ACC的值,使寫(xiě)入的命令出現錯誤。但為什么for(i=8;i>0;i--)就沒(méi)有ACC的參與呢?一個(gè)大大的問(wèn)號?;谖艺{試了一個(gè)星期的程序,皆因為這一個(gè)神奇的錯誤,我實(shí)在不甘心,決定研究到底。于是,分別查看了這三個(gè)程序代碼用 keil4 編譯后得到的 匯編代碼。(學(xué)過(guò)匯編就是爽啊,哈)
對比后,可以發(fā)現,出錯的原因是for(i=0;i<8;i++)ACC版中,用ACC接收了實(shí)參(存儲的為要寫(xiě)入的指令),然后在 for 循環(huán)前要給變量 “ i " 賦值時(shí),要用到ACC清零,再把ACC中的零賦給 R7 ("i"的值存儲在R7)。這樣的話(huà),原來(lái)存儲在A(yíng)CC中的寫(xiě)入指令就被清零,自然會(huì )導致控制出現錯誤,最終沒(méi)法讀取ds1302芯片的時(shí)間,故顯示為零。
而在for(i=8;i>0;i--)ACC版中,也用ACC接收了實(shí)參的值,但在 for 循環(huán)前,給變量“ i ” 賦值時(shí),賦值為8,不需要用到ACC,所以ACC一直是存儲著(zhù)實(shí)參中的指令,沒(méi)有被清零,所以能夠順利地向ds1302發(fā)送指令,從而能夠讀取到時(shí)間。
總結:
因為用for(i=0;i0;i--)類(lèi)的指令多了 CLR A 和 INC R7 兩條指令,CJNE 指令又比較DJNZ指令多了一個(gè)字節的程序代碼存儲空間,在頻率為12M的51單片機上體現為執行同樣功能的程序,要多用2us,代碼空間花多一字節。所以前者是毫無(wú)優(yōu)勢的,以后應養成用
for(i=n;i>0;i--)的習慣。
請不要反駁我用了這么長(cháng)的時(shí)間去研究,只能使單片機執行快2us,而說(shuō)我鉆牛角尖,只是因為,這個(gè)錯誤導致我整個(gè)程序無(wú)法正常運行,這不是一件小事。
至于為什么要用到累加器ACC來(lái)接收實(shí)參,是因為后面的程序要把一個(gè)8位的實(shí)參一位一位地輸出到一個(gè)io口,自定義一個(gè)變量的話(huà),按位尋址好像比較麻煩,要經(jīng)過(guò)一系列 位運算 ,或者用bit定義8個(gè)位(有好的方法請告訴我,哈),而且我寫(xiě)不出來(lái)。而用ACC的話(huà),可以很輕易地操作ACC的任意一位,如ACC0,ACC7。在網(wǎng)上查了一下,好像還有一種方法是定義 一種叫 位域 的東東,我看的c語(yǔ)言的書(shū)都沒(méi)介紹,所以還不是很了解。
/************************************************************/
剛剛想了一下,不用ACC 的方法,作一個(gè)位運算dat &0x01,修改如下:
想到了這個(gè)方法后,覺(jué)得自己好白癡,以后都不用ACC了。
評論