×
嵌入式 > 技术百科 > 详情

单片机C语言实现NOP 循环移位

发布时间:2020-06-06 发布时间:
|
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_只能用于可直接寻址的位;在表达式中使用是不允许的。

 


   首先声明:我学习单片机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   
           2:+INF   (positive   overflow)  
           3:-INF   (Not    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;      8;   i++)  
           
                   temp   <<=   1;                           //左移  
                   temp   |=   (bit)(date    0x80);    
                   date   <<=   1;  
           
            
         b:如果是先接受低位,后接受高位   则先接受一位数据后循环右移一位  
           uchar   i;  
           uchar   temp    0;  
           uchar   date    0x82;  
           for   (i    0;      8;    ++)  
                         
                   temp   |=   (bit)(date    0x01);  
                   date   >>=   1;            
                   temp    _cror_(temp,1);  
                   //循环右移,应用_cror_()需要包含头文件    
           
           如果不用函数  
           则for循环应该这样写  
           for   (i    0;      8;    ++)  
                         
                   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;        
   --  

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
分拣机器人的工作原理是什么