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

[复制链接]
59507|221
aodi008 发表于 2015-7-21 07:05 | 显示全部楼层
xxlouz谢谢楼主
aodi008 发表于 2015-7-21 07:07 | 显示全部楼层
谢谢。学习了。
msy912 发表于 2015-7-21 08:53 | 显示全部楼层
写的很好,不仅告诉你怎么做,还告诉你为什么要这么做!赞!每天来学校2小时!
李家老三 发表于 2015-7-21 16:21 来自手机 | 显示全部楼层
楼主辛苦
李家老三 发表于 2015-7-21 16:50 来自手机 | 显示全部楼层
楼主无私奉献,兢兢业业。这两天估计太忙,不像去年那样频繁发了。我把这个资料复印出来学习。我喜欢纸质的。楼主不要认为我侵权啊!李家老三再拜读
乐逍遥6 发表于 2015-7-22 11:21 | 显示全部楼层
支持 100%   :)
chenzhing 发表于 2015-7-23 17:33 | 显示全部楼层
乐逍遥6 发表于 2015-7-24 09:51 | 显示全部楼层
没更新     再顶下  
qjp1988113 发表于 2015-7-24 10:35 | 显示全部楼层
楼主真不错,期待你的新书~~
 楼主| jianhong_wu 发表于 2015-7-27 08:44 | 显示全部楼层
第二十八节:整除求余的运算。
    求余跟上一节讲的求商都是属于整除运算,区别是:求余返回余数,求商返回商。整除求余的余数有一个很明显的规律:余数永远小于除数(除数不为0的情况下)。比如,除数是10,那么不管被除数有多大,余数必然是从0到9的数,不可能是10以上的数。上一节提到除法求商的运算符号是“/”,而除法求余的运算符号是“%”,外形跟百分号一致,只是在C语言中用来做除法求余的运算符而已。
整除求余的通用格式:
“保存变量”=“被除数”% “除数1% “除数2...%  “除数N;
跟之前讲的加减运算一样,左边的“保存变量”必须是变量,右边的可以是变量和常量的任意组合。如果右边只有两个参与运算的数据,就是整除求余的常见格式。
整除求余的常见格式:
“保存变量”=“被除数” % “除数” ;       
现在从整除求余常见格式的6个方面来分析它的规律。
(1)当“除数”等于0时。我们都知道,数**算除数是不允许等于0的,如果在单片机中非要让除数为0,余数会出现什么结果?我在keilC51编译环境试过,发现有一个规律:如果“除数”是变量的0,那么余数等于被除数。如果“除数”是常量的0,那么余数等于1。还有一种特殊的情况是编译不通过的,就是“被除数”是变量,而“除数”是常量的0。其实大家都知道“除数”不能为0,为什么我非要做“除数”为0时的实验呢?意义何在?我虽然知道除数为0时会出错,但是我不知道这个错到底严不严重,会不会程序崩溃,当我做了这个实验后,我心中的石头才放下了,万一除数为0,只是运算出错,至少程序不会崩溃,这样我心里就有了一个底,当哪天我某个程序崩溃时,我至少可以排除了这种情况,方便我找bug。这就是本实验的意义所在。
    比如:
  1. a=23%y;  //假设除数变量y里面是0,那么a的结果是23。
  2. b=23%0;  //除数是常量0,那么b的结果是1。
  3. b=g%0;  //这种特殊情况编译不通过:“被除数”是变量,而“除数”是常量的0。

(2)当被除数小于“除数”时。余数等于被除数本身。比如:
  1. c=7%10;  //c的结果是7。

(3)当被除数等于“除数”时。余数等于0。比如:
  1. d=10%10;  //d的结果是0。

(4)当被除数大于“除数”时。余数也必然小于“除数”。
比如:
  1. e=10%4;  //e的结果是2。
  2. f=10% 3;  //f的结果是1。

(5)自除求余运算的简写。跟前面加减法一样,当“被除数”是“保存变量”时,存在自除求余运算的简写。
“保存变量”=“保存变量” % “除数” ;
上述自除运算的简写如下:
“保存变量” % =“除数” ;
比如:
  1. g%=5;  //相当于g=g%5;

加减法有自加1++g”和自减1g--”的特殊写法,但是除法不存在这种自除1的特殊写法,因为一个数除以1还是等于它本身,所以自除1没有任何意义,因此C语言语法中没有这种写法。
   (6)除法的溢出规律跟加法的溢出规律是一样的,所以不再多举例子。在实际项目中,为了避免一不小心就溢出的问题,我强烈建议,不管加减乘除,凡是参与运算的变量全部都要转化成unsigned long变量,转化的方法也跟加减运算的转换方法一致,不再详细讲解这方面的内容。
现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
  1. void main() //主程序
  2. {
  3. /*---C语言学习区域的开始---------------------------------------------------------------------------*/
  4.         
  5.   unsigned char a;
  6.   unsigned char b;
  7.   unsigned char c;
  8.   unsigned char d;
  9.   unsigned char e;
  10.   unsigned char f;
  11.         unsigned char g=10;  //初始化为10
  12.         unsigned char y=0; //除数变量初始化为0。
  13.         a=23%y;
  14.         b=23%0;
  15.         //b=g%0;  //这种特殊情况编译不通过:“被除数”是变量,而“除数”是常量的0。
  16.         c=7%10;
  17.         d=10%10;
  18.         e=10%4;
  19.         f=10%3;
  20.         g%=5;  //相当于g=g%5;
  21.        
  22.   GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  23.   GuiWdData1=b;   //把b这个变量放到窗口变量1里面显示
  24.   GuiWdData2=c;   //把c这个变量放到窗口变量2里面显示
  25.   GuiWdData3=d;   //把d这个变量放到窗口变量3里面显示
  26.   GuiWdData4=e;   //把e这个变量放到窗口变量4里面显示
  27.   GuiWdData5=f;   //把f这个变量放到窗口变量5里面显示
  28.   GuiWdData6=g;   //把g这个变量放到窗口变量5里面显示
  29.         
  30. /*---C语言学习区域的结束---------------------------------------------------------------------------*/
  31.    while(1)  
  32.    {
  33.                   initial();
  34.       key_service();
  35.       display_service();
  36.    }

  37. }

    查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。上坚鸿51学习板观察程序执行的结果如下:
     变量a为23。
     变量b为1。
     变量c为7。
     变量d为0。
    变量e为2。
    变量f为1。
    变量g为0。
     下节预告:利用“整除求商求余”来提取一个数的个十百千位。
(未完待续)

乐逍遥6 发表于 2015-7-27 11:56 | 显示全部楼层
jwyx 发表于 2015-7-28 22:48 | 显示全部楼层
谢谢那麽好的教程
xuesheng11 发表于 2015-7-29 16:44 | 显示全部楼层
jianhong_wu 发表于 2015-3-3 10:54
第二节:我眼中学习单片机的四个阶段。

        第一阶段:学会C语言的常用语法,熟悉51单片机开发平台软 ...

现在最缺的就是单片机常用的硬件知识,可惜还要等一两年。唉。期待中...
juneqzeng 发表于 2015-7-30 23:51 | 显示全部楼层
收藏了!向鸿哥致敬!
jw159 发表于 2015-7-31 08:31 来自手机 | 显示全部楼层
写的太好了,正适合我这种想学还不知道学什么的新手
xuesheng11 发表于 2015-7-31 15:28 | 显示全部楼层
jianhong_wu 发表于 2015-7-27 08:44
第二十八节:整除求余的运算。    求余跟上一节讲的求商都是属于整除运算,区别是:求余返回余数,求商返回 ...

吴哥,过两个月我就大四了,看了你的帖子有种热血膨胀的感觉。看了您谈单片机学习的四个阶段中的第三阶段--单片机常用硬件知识,能推荐一些硬件这方面的实用的书吗。我的QQ 1255451357@qq.com
Smiller 发表于 2015-7-31 15:59 | 显示全部楼层
学习中
bestmanyun 发表于 2015-7-31 20:09 | 显示全部楼层
建议楼主尽快出书,防止有人拷贝你这个帖子整理后出书。这是我见过的最适合我等菜鸟的教程。灰常感谢楼主!!!
 楼主| jianhong_wu 发表于 2015-8-1 14:31 | 显示全部楼层
本帖最后由 jianhong_wu 于 2015-8-1 15:04 编辑
bestmanyun 发表于 2015-7-31 20:09
建议楼主尽快出书,防止有人拷贝你这个帖子整理后出书。这是我见过的最适合我等菜鸟的教程。灰常感谢楼主! ...

我不担心这个。拷贝得一时拷贝不了一世。
 楼主| jianhong_wu 发表于 2015-8-1 15:29 | 显示全部楼层
第二十九节:利用“整除求商求余”来拆分提取一个数的个十百千位。
上两节讲了整除的求商求余运算符,这两个运算不仅能用在数**算中,还可以用来拆分提取一个数的个十百千位。提取这些位有什么用呢?因为在以后的单片机显示程序中,不管是液晶屏还是数码管,必须用到这种提取算法,先把一个数的个十百千位一个个拆分提取出来,然后再送到显示屏上显示,所以这种算法很常见和实用。上述提到的“个,十,百,千”位只是一个虚数,具体是多少应该根据实际项目而定,也有可能是“个,十,百,千,万,十万,百万...”等位,但是处理的思路和方法都是一致的。
拆分提取的思路。比如8562这个数,千位是8,百位是5,十位是6,个位是2。可以依次看成是:
  1. 8=8562/1000;
  2. 5=562/100;
  3. 6=62/10;
  4. 2=2/1;

上述用到了整除求商,但是562,62,2又是如何通过8562分解得到的呢?需要用到整除求余:
  1. 562=8562%1000;
  2. 62=8562%100;
  3. 2=8562%10;

最后综合在一起,连在一起写:
  1. 8=8562/1000;
  2. 5=8562%1000/100;
  3. 6=8562%100/10;
  4. 2=8562%10/1;

因为我们预先知道了这个数最大位是千位,所以千位直接整除1000求商就可以了。实际项目中,我们只是用某个变量,而这个变量的大小我们并不知道具体是什么,它的最大位可能并不止千位,也有可能是万位,所以需要把上述最高位的千位也做一下整除10000求余数,然后在整除1000求商,最后整理如下:
  1. 8=8562%10000/1000;
  2. 5=8562%1000/100;
  3. 6=8562%100/10;
  4. 2=8562%10/1;

大家仔细观察和品味一下,很容易发现规律和原因,如果求万,十万,百万,也是用一样的方法。多提醒一句,根据我的经验,有一些单片机的C编译器可能不支持long类型数据的求余求商连写在一起,那么就要用一个中间变量分两步走,先求余,再求商,分开来操作。比如:
  1. 8=8562%10000/1000;

分成两步走:
  1. a=8562%10000;
  2. a=a/1000;

上述的变量a就是引入的中间变量。
现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
  1. void main() //主程序
  2. {
  3. /*---C语言学习区域的开始---------------------------------------------------------------------------*/
  4.         
  5.   unsigned char a;
  6.   unsigned char b;
  7.   unsigned char c;
  8.   unsigned char d;
  9.         unsigned int  x=8562;  //初始化为8562,注意必须是int类型以上,不能是char类型,char最大范围是255。

  10.   a=x%10000/1000;  //拆分提取千位
  11.   b=x%1000/100;    //拆分提取百位
  12.   c=x%100/10;      //拆分提取十位
  13.   d=x%10/1;        //拆分提取个位


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

  19.         
  20. /*---C语言学习区域的结束---------------------------------------------------------------------------*/
  21.    while(1)  
  22.    {
  23.       initial();
  24.       key_service();
  25.       display_service();
  26.    }

  27. }

       
    查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。上坚鸿51学习板观察程序执行的结果如下:
     变量a为8。
     变量b为5。
     变量c为6。
     变量d为2。
     下节预告:逻辑运算符的“与”运算。
(未完待续)

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部