新聞中心

        EEPW首頁(yè) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)C環(huán)境下位操作的實(shí)現(xiàn)方法

        單片機(jī)C環(huán)境下位操作的實(shí)現(xiàn)方法

        ——
        作者:黑龍江工程學(xué)院 劉海成 時(shí)間:2007-01-26 來(lái)源:《單片機(jī)與嵌入式系統(tǒng)應(yīng)用》 收藏

        c語(yǔ)言既有高級(jí)語(yǔ)言的各種特點(diǎn),又可對(duì)硬件進(jìn)行操作,并對(duì)進(jìn)行結(jié)構(gòu)化程序設(shè)計(jì),用c語(yǔ)言編寫(xiě)的程序較容易移植,它們可生成簡(jiǎn)潔可靠的目標(biāo)代碼,在代碼效率和代碼執(zhí)行速度上完全可以和匯編媲美。采用c語(yǔ)言進(jìn)行單片機(jī)編程是嵌入式程序設(shè)計(jì)的發(fā)展趨勢(shì)。但是,在嵌入式控制等領(lǐng)域,經(jīng)常需要控制某一個(gè)二進(jìn)制位,然而除了keil c51等c環(huán)境外,很多單片機(jī)c環(huán)境都沒(méi)有擴(kuò)充對(duì)位變量定義的關(guān)鍵字,甚至單片機(jī)本身的硬件上也沒(méi)有對(duì)單個(gè)位操作的匯編指令,這使得已習(xí)慣mcs-51內(nèi)核單片機(jī)keil c51編程的用戶(hù)都為其c環(huán)境不能對(duì)位變量進(jìn)行位操作而煩惱。

        1 用“讀-修改-寫(xiě)”方法實(shí)現(xiàn)對(duì)單個(gè)位的位操作

        本文引用地址:http://www.104case.com/article/21218.htm

        ansic中,一般采用“讀-修改-寫(xiě)”的方法實(shí)現(xiàn)單個(gè)位的位操作,通過(guò)與0“與”操作,將某一位清0。如使i變量的b0位為0,實(shí)現(xiàn)方法為i=i&0xfe。通過(guò)與1“或”操作,將某一位置1。如使i變量的b0位為1,實(shí)現(xiàn)方法為i=i|0x01。通過(guò)與1“異或”操作,將某一位取反。如使i變量的b0位取反,實(shí)現(xiàn)方法為i=i^0x01。

        注意:錯(cuò)誤“讀-修改-寫(xiě)”方法時(shí)不要影響其他位,即某位清零時(shí),其他位與1“與”;某位置1時(shí),其他位與0“或”;取反時(shí),其他位與0“異或”。

        為了方便程序設(shè)計(jì)和增加程序可讀性,很多程序員喜歡采用下面的移位方式實(shí)現(xiàn)單個(gè)位的位操作,語(yǔ)句簡(jiǎn)練,可讀性強(qiáng),比如在某單片機(jī)的b口連接1個(gè)發(fā)光二極管,其點(diǎn)亮操作方法如下:

        #define bit(x) (1<<(x))

        #define led 2

        使用方法如下:

        portb|=bit(led);//將portb第3位置1,點(diǎn)

                   //亮連接在i/o口的led

        該方式下,程序運(yùn)行時(shí)會(huì)增加移位操作,生成的代碼較大,而且執(zhí)行時(shí)間長(zhǎng),實(shí)時(shí)性差,一些c環(huán)境按如下方式直接定義位,則生成的代碼就不會(huì)有移位操作:

        2 通過(guò)位域的方法實(shí)現(xiàn)位操作

        標(biāo)準(zhǔn)c提供了一種基于結(jié)構(gòu)體的數(shù)據(jù)結(jié)構(gòu)--位域(bitfield),位域就是把一個(gè)存儲(chǔ)單元中的二進(jìn)制劃分為幾個(gè)不同的區(qū)域。并說(shuō)明每個(gè)區(qū)域的位數(shù)。每一個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作,位域的定義格式如下:

        struct 位域結(jié)構(gòu)名{

        位域列表 };

        位域列表格式為:類(lèi)型說(shuō)明符 位域名:位域長(zhǎng)度如:

        struct k{

        unsigned int a:1

        unsigned int :2

        unsigned int b:3

        unsigned int :0     //空域

        }k1;

        說(shuō)明:

        1)各位依次從低位到高位排列,排滿(mǎn)一個(gè)存儲(chǔ)單元,按地址接著排下一單元;

        2)位域可以無(wú)域名,但不能被引用,如第二域,這時(shí)其只用來(lái)填充或調(diào)整位置;

        3)第四行稱(chēng)空域,目的是將目前存儲(chǔ)單元的剩余部分分為一個(gè)域,且填充0。

        位域的引用很簡(jiǎn)單,如:

        k1.a=1; //置k1的b0位為1

        k1.b=7; //將k1的b3-5位置111

        通過(guò)位域定義位變量,是實(shí)現(xiàn)單個(gè)位位操作的重要途徑和方法,采用位域定義位變量,產(chǎn)生的代碼緊湊、高效。定義的方法如下:

        通過(guò)位域定義位,再通過(guò)宏進(jìn)行定義,可以方便地將keil c51等程序移植到其他c編譯器,從而不再為沒(méi)有位操作而苦惱。

        對(duì)一個(gè)單片機(jī)的所有i/o口,通過(guò)將位域結(jié)構(gòu)指定到i/o端口地址,i/o口便都可以采用位域進(jìn)行宏定義,這樣,操作i/o口就可以像keil c51編程一樣方便。

        3 基于位域?qū)崿F(xiàn)位操作應(yīng)用舉例

        很多單片機(jī)沒(méi)有硬件的spi,而很多板級(jí)外圍器件為spi接口,而且某些外圍器件不是標(biāo)準(zhǔn)的spi,即通信的總二進(jìn)制位數(shù)不是8的整數(shù)倍,這里編制一個(gè)例程,為同時(shí)收和發(fā)0-16位,全雙工方式,具體使用見(jiàn)例程注解。注意:很多單片機(jī)使用前要對(duì)使用的i/o口進(jìn)行初始化,clk和din為輸出口,dout為輸入口,同時(shí)這里使用了前面通過(guò)讀-修改-寫(xiě)宏定義的一個(gè)函數(shù)get_bit(x,y)。

        該spi模塊已經(jīng)成功應(yīng)用到單片機(jī)與max7219和ch451等spi通信上。

        對(duì)于沒(méi)有擴(kuò)展位變量的c語(yǔ)言環(huán)境,在匯編下沒(méi)有對(duì)單個(gè)位進(jìn)行位操作執(zhí)行的mcu,通過(guò)位域的方法操作i/o口是最佳的方法,匯編下有單個(gè)位的位操作指令mcu。可以嵌入?yún)R編,但是程序的可移植性等性能會(huì)下降,建議使用位域的方法。



        關(guān)鍵詞:

        評(píng)論


        相關(guān)推薦

        技術(shù)專(zhuān)區(qū)

        關(guān)閉
        主站蜘蛛池模板: 临潭县| 武穴市| 台中市| 汉寿县| 庆元县| 宁化县| 长武县| 当阳市| 大姚县| 聂拉木县| 灵丘县| 漳平市| 湘潭县| 济阳县| 农安县| 鞍山市| 利辛县| 广德县| 邢台市| 工布江达县| 壤塘县| 新田县| 固镇县| 黄大仙区| 仪征市| 元阳县| 明水县| 中宁县| 获嘉县| 宁蒗| 新乡市| 扶余县| 井研县| 岢岚县| 涡阳县| 信宜市| 兴义市| 萨迦县| 晋州市| 江华| 忻州市|