打印
[51单片机]

从业十年,教你单片机入门基础。(连载)

[复制链接]
楼主: jianhong_wu
手机看帖
扫描二维码
随时随地手机跟帖
141
乐逍遥6| | 2015-8-1 17:09 | 只看该作者 回帖奖励 |倒序浏览
努力追贴中 顶

使用特权

评论回复
142
吴玉成77| | 2015-8-3 14:11 | 只看该作者
学习了,吸取精华!

使用特权

评论回复
143
xu518dong| | 2015-8-5 10:28 | 只看该作者
顶顶

使用特权

评论回复
144
jianhong_wu|  楼主 | 2015-8-8 11:38 | 只看该作者
本帖最后由 jianhong_wu 于 2015-8-8 11:41 编辑

第三十节:逻辑运算符的“与”运算。
       单片机任何数字的底层运算都是以二进制的形式进行,前面讲的加减乘除也不例外。只不过加减乘除是生活常用的运算,任意给两个十进制的数据让单片机运算,我们都可以凭借既有的生活经验通过口算或者笔算来计算出结果,不需要刻意模拟单片机底层的二进制运算。但是本节讲的“与”运算却不行,它是为二进制而生的,若想使用它,必先把参与运算的数据双双转换成二进制格式的数据,你才能分析“与”运算的含义和规律。“与”运算是以位来进行运算的,位就是代表二进制中的每一位,每一个位只能是0或者1。两个数的“与”运算就是两个数被展开成二进制后的“与”运算。
       “与”运算的运算符号是“&”。运算规律是:两个位进行“与”运算,只有两个位都同时是1运算结果才能等于1,,否则,只要其中有一位是0,运算结果都是0.比如:
0&0等于0。
0&1等于0。
1&0等于0。
1&1等于1。
注意,上述的0和1都是指二进制的0和1。
        现在举一个完整的例子来分析“与”运算的规律。有两个unsigned char类型的十进制数分别是12和9,求12&9的结果是多少?分析步骤如下:
        第一步:先把参与运算的两个数以二进制的格式展开。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制12的二进制格式是:00001100。
十进制9的二进制格式是:00001001。
        第二步:二进制数右对齐,按每一位进行“与”运算。
       00001100
      &00001001
结果是 00001000。
        第三步:把二进制的00001000转换成十六进制是:0x08。转换成十进制是8。所以12&9的结果是8。
        上述举的例子只能分析“与”运算的规律,并没有看出“与”运算的意义所在。“与”运算有啥用途呢?其实用途很多,最常见的用途是可以指定一个变量的某位清零,其它位保持不变。比如一个unsigned char类型的变量b,数据长度一共是8位,从右往左:
想让第0位清零,其它位保持不变,只需跟十六进制的0xfe相“与”:b=b&0xfe。
想让第1位清零,其它位保持不变,只需跟十六进制的0xfd相“与”:b=b&0xfd。
想让第2位清零,其它位保持不变,只需跟十六进制的0xfb相“与”:b=b&0xfb。
想让第3位清零,其它位保持不变,只需跟十六进制的0xf7相“与”:b=b&0xf7。
想让第4位清零,其它位保持不变,只需跟十六进制的0xef相“与”:b=b&0xef。
想让第5位清零,其它位保持不变,只需跟十六进制的0xdf相“与”:b=b&0xdf。
想让第6位清零,其它位保持不变,只需跟十六进制的0xbf相“与”:b=b&0xbf。
想让第7位清零,其它位保持不变,只需跟十六进制的0x7f相“与”:b=b&0x7f。
       根据上述规律,假设b原来等于十进制的85(十六进制是0x55,二进制是01010101),要想把此数据的第0位清零,只需b=b&0xfe。最终b的运算结果是十进制是84(十六进制是0x54,二进制是01010100)。

       现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;
  unsigned char b=85;  //十六进制是0x55,二进制是01010101。

  a=12&9;
  b=b&0xfe;   


  GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  GuiWdData1=b;   //把b这个变量放到窗口变量1里面显示

        
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
   while(1)  
   {
      initial();
      key_service();
      display_service();
   }

}


        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0上坚鸿51学习板观察程序执行的结果如下:
        变量a为8(十六进制是0x08,二进制是00001000)。
        变量b为84(十六进制是0x54,二进制是01010100)。
        下节预告:逻辑运算符的“或”运算。
(未完待续)

使用特权

评论回复
145
乐逍遥6| | 2015-8-10 11:17 | 只看该作者
顶下:)

使用特权

评论回复
146
jianhong_wu|  楼主 | 2015-8-15 09:06 | 只看该作者
本帖最后由 jianhong_wu 于 2015-8-15 09:07 编辑

第三十一节:逻辑运算符的“或”运算。
       “或”运算是以位为单位进行运算的。位是指二进制中的某一位,位只能是0或者1。两个数的“或”运算就是转换成二进制后每一位的“或”运算。
       “或”运算的符号是“|”。运算规律是:两个位的“或”运算,如果两个位都是0,那么运算结果才是0,否则只要其中有一位是1,那么运算结果必定是1。比如:
0|0等于0。
0|1等于1。
1|0等于1。
1|1等于1。
       现在举一个完整的例子来分析“|”运算的规律。有两个unsigned char类型的十进制数分别是12和9,求12|9的结果是多少?分析步骤如下:
       第一步:先把参与运算的两个数都转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制12的二进制格式是:00001100。
十进制9的二进制格式是:00001001。
      第二步:二进制数右对齐,按每一位进行“或”运算。
           00001100
          |00001001
结果是 00001101。
      第三步:把二进制的00001101转换成十六进制是:0x0D。转换成十进制是13。所以12&9的结果是13。
      “或”运算最常见的用途是可以指定一个变量的某位置1,其它位保持不变。比如一个unsigned char类型的变量b,数据长度一共是8位,从右往左:
想让第0位置1,其它位保持不变,只需跟十六进制的0x01相“或”:b=b|0x01。
想让第1位置1,其它位保持不变,只需跟十六进制的0x02相“或”:b=b|0x02。
想让第2位置1,其它位保持不变,只需跟十六进制的0x04相“或”:b=b|0x04。
想让第3位置1,其它位保持不变,只需跟十六进制的0x08相“或”:b=b|0x08。
想让第4位置1,其它位保持不变,只需跟十六进制的0x10相“或”:b=b|0x10。
想让第5位置1,其它位保持不变,只需跟十六进制的0x20相“或”:b=b|0x20。
想让第6位置1,其它位保持不变,只需跟十六进制的0x40相“或”:b=b|0x40。
想让第7位置1,其它位保持不变,只需跟十六进制的0x80相“或”:b=b|0x80。
       根据上述规律,假设b原来等于十进制的84(十六进制是0x54,二进制是01010100),要想把此数据的第0位置1,只需b=b|0x01。最终b的运算结果是十进制是85(十六进制是0x55,二进制是01010101)。

       现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;
  unsigned char b=84;  //十六进制是0x54,二进制是01010100。

  a=12|9;
  b=b|0x01;   


  GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  GuiWdData1=b;   //把b这个变量放到窗口变量1里面显示

        
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
   while(1)  
   {
      initial();
      key_service();
      display_service();
   }

}


        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0上坚鸿51学习板观察程序执行的结果如下:
        变量a为13(十六进制是0x0D,二进制是00001101)。
        变量b为85(十六进制是0x55,二进制是01010101)。
        下节预告:逻辑运算符的“异或”运算。
(未完待续)

使用特权

评论回复
147
乐逍遥6| | 2015-8-17 19:59 | 只看该作者
支持

使用特权

评论回复
148
微纳尔科技| | 2015-8-18 16:02 | 只看该作者
LeaderHuang 发表于 2015-2-24 17:31
对于单片机的内部原理,要得学计算机组成原理和FPGA才有深刻理解。
还是linus那句话,你得先学会使用它。 ...

我是微纳尔小梅,IC内存代理,价格低,保证品质。如有需求请随时联系我:13798276573    0755-2360-0583

使用特权

评论回复
149
微纳尔科技| | 2015-8-18 16:02 | 只看该作者

我是微纳尔小梅,IC内存代理,价格低,保证品质。如有需求请随时联系我:13798276573    0755-2360-0583

使用特权

评论回复
150
微纳尔科技| | 2015-8-18 16:03 | 只看该作者
ZHB356 发表于 2015-3-6 16:28
我现在准备学单片机,

我是微纳尔小梅,IC内存代理,价格低,保证品质。如有需求请随时联系我:13798276573    0755-2360-0583

使用特权

评论回复
151
微纳尔科技| | 2015-8-18 16:04 | 只看该作者

我是微纳尔小梅,IC内存代理,价格低,保证品质。如有需求请随时联系我:13798276573    0755-2360-0583

使用特权

评论回复
152
jianhong_wu|  楼主 | 2015-8-23 16:42 | 只看该作者
本帖最后由 jianhong_wu 于 2015-8-23 16:43 编辑

第三十二节:逻辑运算符的“异或”运算。
        “异或”运算是以位为单位进行运算的。位是指二进制中的某一位,位只能是0或者1。两个数的“异或”运算就是转换成二进制后每一位的“异或”运算。
“异或”运算的符号是“^”。运算规律是:两个位的“异或”运算,如果两个位都相同,那么运算结果就是0;如果两个位不同(相异),则运算结果是1。比如:
0^0等于0。(两个位相同)
0^1等于1。(两个位相异)
1^0等于1。(两个位相异)
1^1等于0。(两个位相同)
       现在举一个完整的例子来分析“^”运算的规律。有两个unsigned char类型的十进制数分别是12和9,求12^9的结果是多少?分析步骤如下:
       第一步:先把参与运算的两个数都转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制12的二进制格式是:00001100。
十进制9的二进制格式是:00001001。
       第二步:二进制数右对齐,按每一位进行“异或”运算。
            00001100
         ^00001001
结果是 00000101。
       第三步:把二进制的 00000101转换成十六进制是:0x05。转换成十进制是5。所以12^9的结果是5。
       “异或”在哪些项目上经常应用?以我个人的项目经验,平时很少用“异或”,我唯一用过一次“异或”,是在制定串口通讯协议时,通过“异或”算法,增加一个校验字节,此校验字节是一串数据依次相“异或”的总结果,目的是为了增加数据传送时的抗干扰能力。

       现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;


  a=12^9;


  GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示

        
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
   while(1)  
   {
      initial();
      key_service();
      display_service();
   }

}


        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0上坚鸿51学习板观察程序执行的结果如下:
       变量a为5(十六进制是0x05,二进制是00000101)。

       下节预告:逻辑运算符的“按位取反”运算。
(未完待续)

使用特权

评论回复
153
yaosongjin| | 2015-8-25 16:51 | 只看该作者
jianhong_wu 发表于 2015-3-29 21:10
第八节:把.hex机器码下载到单片机的操作流程。烧录程序也叫下载程序。下载程序的本质是什么?把单片机当做 ...

在下载程序不进时,我遇到一种情况:就是把开发板断电后先按住复位键,再打开开发板的电源,然后松开复位键就能成功下载了,最开始试了各种方法都不行,还换了单片机都不行

使用特权

评论回复
154
乐逍遥6| | 2015-8-26 20:22 | 只看该作者
支持

使用特权

评论回复
155
jianhong_wu|  楼主 | 2015-8-30 07:13 | 只看该作者
本帖最后由 jianhong_wu 于 2015-8-30 07:16 编辑

第三十三节:逻辑运算符的“按位取反”和“非”。
       “按位取反”运算的符号是波浪符号“~”。运算规律是:针对某个数的“按位取反”,先将其展开成二进制的格式,然后每个位取反,所谓取反就是1的变成0,0的变成1。
        现在举一个完整的例子来分析“按位取反”运算的规律。有一个unsigned char类型的十进制数分别是5和0,求~5和~0的结果是多少?分析步骤如下:
       第一步:先把参与运算的数转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制5的二进制格式是:00000101。
十进制0的二进制格式是:00000000。
        第二步:
(1)将5的二进制数每一位取反,1的变成0,0的变成1。
        ~00000101
结果是11111010。
把二进制的11111010转换成十六进制是:0xFA。转换成十进制是250。所以~5的结果是250。
(2)将0的二进制数每一位取反,1的变成0,0的变成1。
        ~00000000
结果是11111111。
把二进制的11111111转换成十六进制是:0xFF。转换成十进制是255。所以~0的结果是255。
       讲完“按位取反”,现在接着讲“非”。 “非”跟“按位取反”有点相似,但是区别也明显。“按位取反”针对的是一个数的某一位,侧重在局部。而“非”是针对一个数的整体,侧重在全局。“非”只有两种状态“假”和“真”。0代表假,大于0的数值代表真,也可以说“非”假即真,“非”真即假。不是假的就是真的,不是真的就是假的。强调的是两种状态的切换。在数值表示上,用0代表假的状态,用1代表真的状态。
“非”运算的符号是感叹号“!”。运算规律是:针对某个数的“非”,不管此数有多大,只要它大于0,那么被“非”后就一定是0。也不管此数是什么变量类型,只要它数值等于0,那么被“非”后就一定是1。
        现在举一个完整的例子来分析“非”运算的规律。有一个unsigned char类型的十进制数分别是5和0,求!5和!0的结果是多少?分析步骤如下:
        第一步:5大于0,是一个整体,被“非”后为0.
        第二步:0就是0,是一个整体,被“非”后为1.

        现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        

  unsigned char a=5;
  unsigned char b=5;
  unsigned char c=0;
  unsigned char d=0;

  a=~a;
  b=!b;


  c=~c;
  d=!d;

  GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  GuiWdData1=b;   //把a这个变量放到窗口变量1里面显示
  GuiWdData2=c;   //把a这个变量放到窗口变量2里面显示
  GuiWdData3=d;   //把a这个变量放到窗口变量3里面显示   


/*---C语言学习区域的结束---------------------------------------------------------------------------*/
   while(1)  
   {
                  initial();
      key_service();
      display_service();
   }

}


       查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0。上坚鸿51学习板观察程序执行的结果如下:
       变量a为250(十六进制是0xFA,二进制是11111010)。
       变量b为0 (十六进制是0x00,二进制是00000000)。
       变量c为255(十六进制是0xFF,二进制是11111111)。
       变量d为1 (十六进制是0x01,二进制是00000001)。
       下节预告:移位运算的左移。
(未完待续)

使用特权

评论回复
156
edu118nn| | 2015-8-30 14:53 | 只看该作者
嵌入式系统实训课程学习,
让没有ARM编程基础和实际工作经验的大专以上学历的学员在2到3个月的时间内迅速获得1-3年的ARM开发经验,
具备实际ARM开发的能力,月薪5-10K。想学习嵌入式、单片机等私聊。Q2532176025  13397813997黄!

使用特权

评论回复
157
乐逍遥6| | 2015-8-31 08:46 | 只看该作者
此处有掌声

使用特权

评论回复
158
peijianzhang| | 2015-9-3 09:13 | 只看该作者
学习学习

使用特权

评论回复
159
jianhong_wu|  楼主 | 2015-9-5 13:18 | 只看该作者
本帖最后由 jianhong_wu 于 2015-9-6 07:24 编辑

第三十四节:移位运算的左移。
       前面讲的“与,或,异或”运算,漏讲了它们的简写格式的内容,在本节开始之前先把这部分内容补上。在“与,或,异或”这些运算中,当赋值语句左边的“保存变量”是参与运算的变量本身时,也存在简写的语法格式,比如:
       a&=0x01;  //相当于a=a&0x01;
       a|=0x01;  //相当于a=a|0x01;
       a^=0x01;  //相当于a=a^0x01;

       现在正式开始本节内容“移位运算的左移”。左移的运算符号是“<<”,语法格式如下:
       保存变量=被移数<<n;
       其中n代表“被移数”需要左移的位数。
       整句语法的含义是:“被移数”的二进制格式数据被整体往左边移动了n位,原来高n位数据被直接覆盖,新空出的低n位数据填入0。最后把移位结果存入“保存变量”。
       现在举一个完整的例子来分析“左移”运算的规律。有2个unsigned char类型的变量a和b,a的初始值是十进制数5,a=a<<1的结果是多少?b的初始值也是十进制数5,b=b<<2的结果是多少?
分析步骤如下:
       第一步:先把参与运算的数转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制5的二进制格式是:00000101。
       第二步:
(1) 将5的二进制数整体往左边移动1位:
                                  原来是:00000101
        整体往左移动1位后变成:00001010
        把二进制的00001010转换成十六进制是:0x0A。转换成十进制是10。所以a初始值是5,左移1位后的结果是10.
(2) 将5的二进制数整体往左边移动2位:
                                  原来是:00000101
        整体往左移动2位后变成:00010100
        把二进制的00010100转换成十六进制是:0x14。转换成十进制是20。所以b初始值是5,左移2位后的结果是20.
        仔细观察上述两个例子,发现了一个重要的规律:某数左移1位相当于此数乘以2,左移多少位相当于乘以多少个2.比如上述例子中5左移1位相当于5乘以2,结果等于10。而5左移2位相当于5乘以2再乘以2,5*2*2的结果等于20。既然左移1位相当于某个数乘以2,那么为什么不直接用乘法来替代左移呢?原因是一条左移语句的运算速度比一条乘法语句的运算速度要快很多倍。
        左移是在单片机项目中很常用的语法,也经常应用在一些数据类型之间的合并中。比如有两个unsigned char单字节的类型数据H和L,H的初始值是十六进制的0x12,L的初始值是十六进制的0x34,要将两个单字节的H和L合并成一个unsigned int双字节的数据c,其中H是高8位字节,L是低八位字节,合并成c后,c的值应该是十六进制的0x1234,此程序如何写?就需要用到左移。程序分析如下:
unsigned char H=0x12;  //单字节
unsigned char L=0x34;  //单字节
unsigned int c; //双字节
c=H;//c的低8位被H覆盖,也就是c的低8位得到了H的各位值。
c=c<<8; //及时把c的低8位移动到高8位,同时c原来的低8位被填入0
c=c+L;//此时c再加L,c的低8位就L的值。
       程序运行结果:c就等于十六进制的0x1234,十进制是4660。
       再多讲一下知识点,左移也存在简写格式,比如:
d<<=1; //就相当于d=d<<1;
e<<=2; //就相当于e=e<<2;
       现在编写一个程序来练习刚才讲到的主要内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:





void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/


unsigned char a=5;
unsigned char b=5;

unsigned char H=0x12; //单字节
unsigned char L=0x34; //单字节
unsigned int c; //双字节

a=a<<1; //a左移1位,从原来的5变成了10.
b=b<<2; //b左移2位,从原来的5变成了20.


c=H; //c的低8位被H覆盖,也就是此时c的低8位得到了H的各位值。
c=c<<8; //及时把c的低8位移动到高8位,同时c原来的低8位被填入0
c=c+L; //此时c再加L,c的低8位就L的值。此时c得到了H和L合并而来的值。


GuiWdData0=a; //把a这个变量放到窗口变量0里面显示
GuiWdData1=b; //把b这个变量放到窗口变量1里面显示
GuiWdData2=c; //把c这个变量放到窗口变量2里面显示



/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}

}


        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0。上坚鸿51学习板观察程序执行的结果如下:
        变量a为10 (十六进制是0x0A,二进制是00001010)。
        变量b为20(十六进制是0x14,二进制是00010100)。
        变量c为4660(十六进制是0x1234,二进制是0001 0010 0011 0100)。
        下节预告:移位运算的右移。
(未完待续)



使用特权

评论回复
160
jianhong_wu|  楼主 | 2015-9-6 07:26 | 只看该作者
本帖最后由 jianhong_wu 于 2015-9-6 07:29 编辑

第三十五节:移位运算的右移。
        右移的运算符号是“>>”,语法格式如下:
        保存变量=被移数>>n;
        其中n代表“被移数”需要右移的位数。
        整句语法的含义是:“被移数”的二进制格式数据被整体往右边移动了n位,原来低n位数据被直接覆盖,新空出的高n位数据填入0。最后把移位结果存入“保存变量”。
        现在举一个完整的例子来分析“右移”运算的规律。有2个unsigned char类型的变量a和b,a的初始值是十进制数5,a=a>>1的结果是多少?b的初始值也是十进制数5,b=b>>2的结果是多少?
分析步骤如下:
        第一步:先把参与运算的数转换成二进制的格式。十进制转二进制的方法请参考前面第13,14,15节的内容。
十进制5的二进制格式是:00000101。
        第二步:
(1) 将5的二进制数整体往右边移动1位:
                                   原来是:00000101
        整体往右移动1位后变成:00000010
        把二进制的00000010转换成十六进制是:0x02。转换成十进制是2。所以a初始值是5, 右移1位后的结果是2.
(2) 将5的二进制数整体往右边移动2位:
                                   原来是:00000101
        整体往右移动2位后变成:00000001
        把二进制的00000001转换成十六进制是:0x01。转换成十进制是1。所以b初始值是5, 右移2位后的结果是1。
        上一节讲的“左移”1位有乘以2的规律,相反,这节讲的“右移”也存在整除的规律:某数右移1位相当于此数整除2,右移多少位相当于整除多少个2.比如上述例子中5右移1位相当于5整除2,结果等于2。而5右移2位相当于5整除2再整除2,5/2/2的结果等于1。既然右移1位相当于某个数整除2,那么为什么不直接用整除来替代右移呢?原因是一条右移语句的运算速度比一条整除语句的运算速度要快很多倍。
        右移是在单片机项目中很常用的语法,也经常应用在一些数据类型之间的拆分中。比如有一个双字节unsigned int类型的变量c,它的初始值是0x1234,要把它拆分成两个unsigned char单字节的类型数据H和L,其中H是高8位字节,L是低八位字节,拆分后H应该等于0x12,L应该等于0x34,此程序如何写?就需要用到右移。程序分析如下:
unsigned char H;  //单字节
unsigned char L;  //单字节
unsigned int c=0x1234; //双字节
L=c;  //c的低8位直接赋值给单字节的L
H=c>>8;  //c先把高8位右移到低8位,然后再把这8位数据赋值给H
        程序运行结果:H就等于十六进制的0x12,十进制是18。L就等于十六进制的0x34,十进制是52.提一个问题,请问执行完上述最后一条语句H=c>>8后,此时c的值是多少?答案是0x1234,因为只要它没有赋值给它自己,执行完语句后就不会改变它自己本身。
        再多讲一下知识点,右移也存在简写格式,比如:
e>>=1; //就相当于e=e>>1;
f>>=2; //就相当于f=f>>2;
        现在编写一个程序来练习刚才讲到的主要内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:


void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/

unsigned char a=5;
unsigned char b=5;


unsigned char H; //单字节
unsigned char L; //单字节
unsigned int c=0x1234; //双字节

unsigned int d;

a=a>>1;
b=b>>2;

L=c; //c的低8位直接赋值给单字节的L
H=c>>8; //c先把高8位右移到低8位,然后再把这8位数据赋值给H

//执行上述语句后,此时的c变量的数值是多少呢?
//答案是0x1234,因为只要没有赋值给它自己,就不会改变它自己.

d=c; //此时d就等于c,是十六进制的0x1234.十进制是4660

GuiWdData0=a; //把a这个变量放到窗口变量0里面显示
GuiWdData1=b; //把b这个变量放到窗口变量1里面显示
GuiWdData2=H; //把H这个变量放到窗口变量2里面显示
GuiWdData3=L; //把L这个变量放到窗口变量3里面显示
GuiWdData4=d; //把d这个变量放到窗口变量4里面显示

/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}

}

        查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。16个LED灯显示的就是当前变量的二进制数,亮代表1,灭代表0。上坚鸿51学习板观察程序执行的结果如下:
        变量a为2 (十六进制是0x02,二进制是00000010)。
        变量b为1(十六进制是0x01,二进制是00000001)。
        变量H为18(十六进制是0x12,二进制是00010010)。
        变量L为52(十六进制是0x34,二进制是00110100)。
        变量d为4660(十六进制是0x1234,二进制是0001 0010 0011 0100)。

        下节预告:括号改变优先级。
(未完待续)



使用特权

评论回复
发新帖 本帖赏金 10.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则