新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機C語言實現NOP 循環移位

        單片機C語言實現NOP 循環移位

        作者: 時間:2016-11-24 來源:網絡 收藏
        INTRINS.H:內部函數

        函數名: _crol_,_irol_,_lrol_
        原 型: unsigned char _crol_(unsigned char val,unsigned char n);
        unsigned int _irol_(unsigned int val,unsigned char n);
        unsigned int _lrol_(unsigned int val,unsigned char n);
        功 能:_crol_,_irol_,_lrol_以位形式將val 左移n 位,該函數與8051“RLA”指令
        相關,上面幾個函數不同于參數類型。
        例:
        #include
        main()
        {
        unsigned int y;
        C-5 1 程序設計 37
        y=0x00ff;
        y=_irol_(y,4);
        }
        函數名: _cror_,_iror_,_lror_
        原 型: unsigned char _cror_(unsigned char val,unsigned char n);
        unsigned int _iror_(unsigned int val,unsigned char n);
        unsigned int _lror_(unsigned int val,unsigned char n);
        功 能:_cror_,_iror_,_lror_以位形式將val 右移n 位,該函數與8051“RRA”指令
        相關,上面幾個函數不同于參數類型。
        例:
        #include
        main()
        {
        unsigned int y;
        y=0x0ff00;
        y=_iror_(y,4);
        }
        函數名: _nop_
        原 型: void _nop_(void);
        功 能:_nop_產生一個NOP 指令,該函數可用作C 程序的時間比較。C51 編譯器在_nop_

        數工作期間不產生函數調用,即在程序中直接執行了NOP 指令。
        例:
        P()=1;
        _nop_();
        P()=0;
        函數名: _testbit_
        原 型:bit _testbit_(bit x);
        功 能:_testbit_產生一個JBC 指令,該函數測試一個位,當置位時返回1,否則返回0。
        如果該位置為1,則將該位復位為0。8051 的JBC 指令即用作此目的。
        _testbit_只能用于可直接尋址的位;在表達式中使用是不允許的。

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


        首先聲明:我學習單片機C語言還不到半年,所以我還是菜鳥,我貼出的東西或許你們都知道,但我只想把我學習的經歷給記錄下來,希望你能找到你所想要的.
        我記得做學單片機做的第一個實驗就是做循環彩燈的實驗,如果用匯編RL和RR很容易實現循環移位,但是C語言編程的移位指指令不能循環,移了后以0填充。
        如果用C實現循環移位呢?
        我的思路是:
        比如將a=0x45循環左移二位。
        a循環左移n位,即將原來右面(8-n)位左移n位,而將原來左端的n位移到最右面n位。
        1、將a的左端n位先放到b中的高n位中
        b=>>(8-n);
        2、將a左移n位,其右面高n位被補0
        c=<
        3、將b,c進行或運算
        a=c|b;
        程序如下:
        main()
        {
        unsigned char a=0x45,b,c;
        unsigned int n=2;
        b=a>>(8-n)
        c=a<
        a=c|b;
        }

        記得我才學單片機的時候做的第一個實驗就是循環彩燈(那時候用的匯編)
        學單片機C語言的時候,第一個實驗當然也就是循環彩燈了,C沒有直接循環移位的指令沒關系,用上面的語句即可實現。:)
        如果用keil C的話,它的內部函數_cror_, _crol_實現了這個,包含即可,由于是intrins函數,步步生成函數調用代碼,效率很高

        用C51自己編一個多字節的循環移位是一件比較麻煩的事,自己可以嵌入匯編的方
        法,但是這給編程者容易隱含錯誤,特別是對于匯編語言不熟的人用匯編是一件
        難事。其實在KEIL C51中有這樣一個庫,其頭文件為intrins.h在C51INC目錄下
        ,有以下幾個操作,它不是函數,但象函數,它們有入口出口,但是,沒有返回R
        ET語句,如果有這些操作,用disassembly窗口可以看到是將代碼直接嵌入到你的
        代碼中,其效率很高,比如一個空操作,_nop_() 嵌入的代碼就是一個NOP指令。
        在這個庫中,有如下操作:
        unsigned char _chkfloat_(float val) 檢查浮點數狀態
        返回值:0: standard floating-point numbers
        1: Floating-point value 0
        2:+INF (positive overflow)
        3:-INF (Not a number) error status
        unsigned char _crol_( //字節的多次循環左移
        unsigned char c, //C左移的字符
        unsigned char b);//b左移的位數
        unsigned char _cror_( //字節的多次循環右移
        unsigned char c, //C右移的字符
        unsigned char b);//b右左移的位數
        unsigned int _irol_ ( //字的循環左移
        unsigned int c, //c左移的字
        unsigned char b);//b左移的次數
        unsigned int _iror_ ( //字的循環右移
        unsigned int c, //c右移的字
        unsigned char b);//b右移的次數
        unsigned long _lrol_ ( //4字節(雙字)的循環左移
        unsigned long c,//c左移的雙字
        unsigned char b);//b左移的次數
        unsigned long _lror_ ( //4字節(雙字)的循環右移
        unsigned long c,//c右移的雙字
        unsigned char b);//b右移的次數
        void _nop_ (void); //NOP 8051中的空操作
        bit _testbit_ (bit b);//8051中的JBC指令,測試b,然后清0,返回b的值。


        下面是我自己以前寫的東西

        匯編的移位操作很容易 RR RRC RL RLC
        C51中,移出很容易,<< >> ;移入操作中的左移入也容易,困難在右移入
        一:IC讀寫應用
        1:送數
        送兩個單獨字節的數據的程序,左送 &0x80 右送 &0x01
        bit out;
        out = low & 0x01;
        low >>= 1;
        low |= (high & 0x01)<<7;
        high >>= 1;

        2:取數(不管怎么移入,第一次操作之后獲取的那一位數據必須在接受數據的最高位或
        者最低位上,從而選擇是先取數還是先移位)
        a:如果是先接受高位后接受低位 則先左移一位后接受一位數據(i2c總線
        uchar i;
        uchar temp = 0;
        uchar date = 0x82;
        for (i = 0; i < 8; i++)
        {
        temp <<= 1; //左移
        temp |= (bit)(date & 0x80);
        date <<= 1;
        }

        b:如果是先接受低位,后接受高位 則先接受一位數據后循環右移一位
        uchar i;
        uchar temp = 0;
        uchar date = 0x82;
        for (i = 0; i < 8; i ++)
        {
        temp |= (bit)(date & 0x01);
        date >>= 1;
        temp = _cror_(temp,1);
        //循環右移,應用_cror_()需要包含頭文件
        }
        如果不用函數
        則for循環應該這樣寫
        for (i = 0; i < 8; i ++)
        {
        temp >>= 1;
        temp |= (date & 0x01) << 7;
        date >>= 1;

        }
        三:任意一位的置位或者取反運算
        置位運算
        low |= 0x01; (置最低位為1)
        取反運算
        low |= ~low & 0x01;
        四:合并和拆分數據
        1:合并兩個單字節數據為一個雙字節數據
        int len;
        uchar low;
        uchar high;
        Len |= high;
        Len <<= 8;
        Len |= low;
        2: 拆分一個雙字節數據為兩個單字節數據
        int len;
        uchar low;
        uchar high;
        low |= len;
        high |= len >> 8;
        --



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 益阳市| 唐海县| 台东县| 兴义市| 海阳市| 阳曲县| 大方县| 肃南| 河曲县| 沅陵县| 名山县| 镇安县| 大石桥市| 大冶市| 遵义县| 临高县| 徐闻县| 简阳市| 阳山县| 文登市| 秦皇岛市| 措美县| 曲阜市| 云安县| 左贡县| 昌平区| 武安市| 昭通市| 顺昌县| 桓台县| 平谷区| 应城市| 格尔木市| 岑巩县| 清苑县| 高青县| 富源县| 察哈| 永年县| 巴彦淖尔市| 济宁市|