當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]一、如何從匯編轉(zhuǎn)向PICC首先要求你要有C 語言的基礎(chǔ)。C代碼的頭文件一定要有#include,它是很多頭文件的集合,C 編譯器在pic.h 中根據(jù)你的芯片自動(dòng)載入相應(yīng)的其它頭文件。這點(diǎn)比匯編好用。載入的頭文件中其實(shí)是聲明

一、如何從匯編轉(zhuǎn)向PICC

首先要求你要有C 語言的基礎(chǔ)。C代碼的頭文件一定要有#include,它是很多頭文件的集合,C 編譯器在pic.h 中根據(jù)你的芯片自動(dòng)載入相應(yīng)的其它頭文件。這點(diǎn)比匯編好用。載入的頭文件中其實(shí)是聲明芯片的寄存器和一些函數(shù)。順便摘抄一個(gè)片段:
static volatile unsigned char TMR0 @ 0x01;
static volatile unsigned char PCL @ 0x02;
static volatile unsigned char STATUS @ 0x03;
可以看出和匯編的頭文件中定義寄存器是差不多的。如下:
TMR0 EQU 0X01;
PCL EQU 0X02;
STATUS EQU 0X03;
都是把無聊的地址定義為大家公認(rèn)的名字。
1、如何賦值?
如對(duì)TMR0 附值,匯編中:
MOVLW 200;
MOVWF TMR0;
當(dāng)然得保證當(dāng)前頁面在0,不然會(huì)出錯(cuò)。
C 語言:
TMR0=200;//無論在任何頁面都不會(huì)出錯(cuò)。
可以看出來C 是很直接了當(dāng)?shù)?。并且最大好處是操作一個(gè)寄存器時(shí)候,不用考慮頁面的問題。一切由
C 自動(dòng)完成。
2、如何位操作?
匯編中的位操作是很容易的。在C 中更簡單。C 的頭文件中已經(jīng)對(duì)所有可能需要位操作的寄存器的每
一位都有定義名稱:
如:PORTA 的每一個(gè)I/O 口定義為:RA0、RA1、RA2。。。RA7。OPTION 的每一位定義為:PS0、
PS1、PS2 、PSA 、T0SE、T0CS、INTEDG 、RBPU。可以對(duì)其直接進(jìn)行運(yùn)算和附值。
如:
RA0=0;
RA2=1;
在匯編中是:
BCF PORTA,0;
BSF PORTA,2;
可以看出2 者是大同小異的,只是C 中不需要考慮頁面的問題。
3、內(nèi)存分配問題
在匯編中定義一個(gè)內(nèi)存是一件很小心的問題,要考慮太多的問題,稍微不注意就會(huì)出錯(cuò)。比如16 位的
運(yùn)算等。用C 就不需要考慮太多。下面給個(gè)例子:
16 位的除法(C 代碼):
INT X=5000;
INT Y=1000;
INT Z=X/Y;
而在匯編中則需要花太多精力。
給一個(gè)小的C 代碼,用RA0 控制一個(gè)LED 閃爍:
#include
void main()
{
int x;
CMCON=0B111; //掉A 口比較器,要是有比較器功能的話。
ADCON1=0B110; //掉A/D 功能,要是有A/D 功能的話。
TRISA=0; //RA 口全為輸出。
loop:RA0=!RA0;
for(x=60000;--x;){;} //延時(shí)
goto loop;
}
說說RA0=!RA0 的意思:PIC 對(duì)PORT 寄存器操作都是先讀取----修改----寫入。上句的含義是程序先
讀RA0,然后取反,最后把運(yùn)算后的值重新寫入RA0,這就實(shí)現(xiàn)了閃爍的功能。


二、淺談PICC 的位操作
由于PIC 處理器對(duì)位操作是最高效的,所以把一些BOOL 變量放在一個(gè)內(nèi)存的位中,既可以達(dá)到運(yùn)算
速度快,又可以達(dá)到最大限度節(jié)省空間的目的。在C 中的位操作有多種選擇。
*********************************************
如:char x;x=x|0B00001000;
char x;x=x & 0B11011111;
把上面的變成公式則是:
#define bitset(var,bitno)(var |=1<#define bitclr(var,bitno)(var &=~(1<則上面的操作就是:

char x;bitset(x,4);
char x;bitclr (x,5);
*************************************************
但上述的方法有缺點(diǎn),就是對(duì)每一位的含義不直觀,最好是能在代碼中能直觀看出每一位代表的意思,
這樣就能提高編程效率,避免出錯(cuò)。如果我們想用X 的0-2 位分別表示溫度、電壓、電流的BOOL 值可以如下:
unsigned char x @ 0x20;
bit temperature@ (unsigned)&x*8+0;
bit voltage@ (unsigned)&x*8+1;
bit current@ (unsigned)&x*8+2;
這樣定義后X的位就有一個(gè)形象化的名字,不再是枯燥的1、2、3、4 等數(shù)字了??梢詫?duì)X 全局修改,也可以對(duì)每一位進(jìn)行操作:
char=255;
temperature=0;
if(voltage)......
*****************************************************************
還有一個(gè)方法是用C 的struct 結(jié)構(gòu)來定義,如:
struct cypok{
temperature:1;
voltage:1;
current:1;
none:4;
}x @ 0x20;
這樣就可以用
x.temperature=0;
if(x.current)....
等操作了。
**********************************************************
上面的方法在一些簡單的設(shè)計(jì)中很有效,但對(duì)于復(fù)雜的設(shè)計(jì)中就比較吃力。如象在多路工業(yè)控制上。
前端需要分別收集多路的多路信號(hào),然后再設(shè)定控制多路的多路輸出。如:有2 路控制,每一路的前端信
號(hào)有溫度、電壓、電流。后端控制有電機(jī)、喇叭、繼電器、LED。如果用匯編來實(shí)現(xiàn)的話,是很頭疼的事
情,用C 來實(shí)現(xiàn)是很輕松的事情,這里也涉及到一點(diǎn)C 的內(nèi)存管理(其實(shí)C 的最大優(yōu)點(diǎn)就是內(nèi)存管理)。
采用如下結(jié)構(gòu):
union cypok{
struct out{
motor:1;
relay:1;
speaker:1;
led1:1;
led2:1;
}out;
struct in{
none:5;
temperature:1;
voltage:1;
current:1;
}in;
char x;
};
union cypok an1;
union cypok an2;
上面的結(jié)構(gòu)有什么好處呢?
細(xì)分了信號(hào)的路an1 和an2;
細(xì)分了每一路的信號(hào)的類型(是前端信號(hào)in 還是后端信號(hào)out):
an1.in ;
an1.out;
an2.in;
an2.out;
然后又細(xì)分了每一路信號(hào)的具體含義,如:
an1.in.temperature;
an1.out.motor;
an2.in.voltage;
an2.out.led2;等
這樣的結(jié)構(gòu)很直觀的在2 個(gè)內(nèi)存中就表示了2 路信號(hào)。并且可以極其方便的擴(kuò)充。
如添加更多路的信號(hào),只需要添加:
union cypok an3;
union cypok an4;
從上面就可以看出用C 的巨大好處。


三、PICC 之延時(shí)函數(shù)和循環(huán)體優(yōu)化。
很多朋友說C 中不能精確控制延時(shí)時(shí)間,不能象匯編那樣直觀。其實(shí)不然,對(duì)延時(shí)函數(shù)深入了解一下
就能設(shè)計(jì)出一個(gè)理想的框架出來。一般的我們都用for(x=100;--x;){;}此句等同與x=100;while(--x){;};
或for(x=0;x<100;x++){;}。
來寫一個(gè)延時(shí)函數(shù)。
在這里要特別注意:X=100,并不表示只運(yùn)行100 個(gè)指令時(shí)間就跳出循環(huán)。
可以看看編譯后的匯編:
x=100;while(--x){;}
匯編后:
movlw 100
bcf 3,5
bcf 3,6
movwf _delay
l2 decfsz _delay
goto l2
return
從代碼可以看出總的指令是是303 個(gè),其公式是8+3*(X-1)。注意其中循環(huán)周期是X-1 是99 個(gè)。這
里總結(jié)的是x 為char 類型的循環(huán)體,當(dāng)x 為int 時(shí)候,其中受X 值的影響較大。建議設(shè)計(jì)一個(gè)char 類型的
循環(huán)體,然后再用一個(gè)循環(huán)體來調(diào)用它,可以實(shí)現(xiàn)精確的長時(shí)間的延時(shí)。下面給出一個(gè)能精確控制延時(shí)的
函數(shù),此函數(shù)的匯編代碼是最簡潔、最能精確控制指令時(shí)間的:
void delay(char x,char y){
char z;
do{
z=y;
do{;}while(--z);
}while(--x);
}
其指令時(shí)間為:7+(3*(Y-1)+7)*(X-1)如果再加上函數(shù)調(diào)用的call 指令、頁面設(shè)定、傳遞參數(shù)
花掉的7 個(gè)指令。則是:14+(3*(Y-1)+7)*(X-1)。如果要求不是特別嚴(yán)格的延時(shí),可以用這個(gè)函數(shù):
void delay(){
unsigned int d=1000;
while(--d){;}
}
此函數(shù)在4M 晶體下產(chǎn)生10003us 的延時(shí),也就是10mS。如果把D 改成2000,則是20003uS,以此類推。有朋友不明白,為什么不用while(x--)后減量,來控制設(shè)定X 值是多少就循環(huán)多少周期呢?現(xiàn)在看看編譯它的匯編代碼:
bcf 3,5
bcf 3,6
movlw 10
movwf _delay
l2
decf _delay
incfsz _delay,w
goto l2
return
可以看出循環(huán)體中多了一條指令,不簡潔。所以在PICC 中最好用前減量來控制循環(huán)體。
再談?wù)勥@樣的語句:
for(x=100;--x;){;}和for(x=0;x<100;x++){;}
從字面上看2 者意思一樣,但可以通過匯編查看代碼。后者代碼雍長,而前者就很好的匯編出了簡潔的代
碼。所以在PICC 中最好用前者的形式來寫循環(huán)體,好的C 編譯器會(huì)自動(dòng)把增量循環(huán)化為減量循環(huán)。因?yàn)?br/>這是由處理器硬件特性決定的。PICC 并不是一個(gè)很智能的C 編譯器,所以還是人腦才是第一的,掌握一些
經(jīng)驗(yàn)對(duì)寫出高效,簡潔的代碼是有好處的。


四、深入探討PICC之位操作
1、用位操作來做一些標(biāo)志位,也就是BOOL變量.可以簡單如下定義:
bit a,b,c;
PICC會(huì)自動(dòng)安排一個(gè)內(nèi)存,并在此內(nèi)存中自動(dòng)安排一位來對(duì)應(yīng)a,b,c.由于我們只是用它們來簡單的
表示一些0,1信息,所以我們不需要詳細(xì)的知道它們的地址\位究竟是多少,只管拿來就用好了。
2、要是需要用一個(gè)地址固定的變量來位操作,可以參照PIC.H里面定義寄存器。
如:用25H內(nèi)存來定義8?jìng)€(gè)位變量.
static volatile unsigned char myvar @ 0x25;
static volatile bit b7 @ (unsigned)&myvar*8+7;
static volatile bit b6 @ (unsigned)&myvar*8+6;
static volatile bit b5 @ (unsigned)&myvar*8+5;
static volatile bit b4 @ (unsigned)&myvar*8+4;
static volatile bit b3 @ (unsigned)&myvar*8+3;
static volatile bit b2 @ (unsigned)&myvar*8+2;
static volatile bit b1 @ (unsigned)&myvar*8+1;
static volatile bit b0 @ (unsigned)&myvar*8+0;
這樣即可以對(duì)myvar操作,也可以對(duì)B0--B7直接位操作.
但不好的是,此招在低檔片子,如C5X系列上可能會(huì)出問題.
還有就是表達(dá)起來復(fù)雜,你不覺得輸入代碼累么?呵呵
3、這也是一些常用手法
#definetestbit(var, bit)((var) & (1 <<(bit)))
//測(cè)試某一位,可以做BOOL運(yùn)算
#definesetbit(var, bit)((var) |= (1 << (bit)))//把某一位置1
#defineclrbit(var, bit)((var) &= ~(1 << (bit)))//把某一位清0
附上一段代碼,可以用MPLAB調(diào)試觀察
#i nclude "pic.h"
#definetestbit(var, bit)((var) & (1 <<(bit)))
#definesetbit(var, bit)((var) |= (1 << (bit)))
#defineclrbit(var, bit)((var) &= ~(1 << (bit)))
char a,b;
void main()

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉