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

[复制链接]
59470|221
ghl137 发表于 2015-6-26 21:50 | 显示全部楼层
先收藏再慢慢读,学习学习
oldzhang 发表于 2015-6-27 12:03 | 显示全部楼层
其实C语言是入门者的一个难关。学C语言首先要清楚:数和变量;运算符;四条语句;函数。深入点再学结构体;指针;。。。
数和变量按位数分为8位,16位,32位。。。;整数,浮点数,无符号数,二进制,8进制,16进制数。。。;数组。。。
运算符:加减乘除,逻辑运算,比较,单目,双目,3目。。。
四条语句:for,if,while,switch-case语句
函数:带()的,分内函数和自己编写的函数
 楼主| jianhong_wu 发表于 2015-6-28 10:35 | 显示全部楼层
第二十四节:乘法运算的5种常见格式。
      请先看以下的乘法语法格式:
       “保存变量”=“被乘数1”*“乘数2”*... *“乘数N”;
        含义是:右边的“被乘数”与各“乘数”相乘,并且把最终的运算结果赋值给左边的“保存变量”。注意,这里的符号“=”不是等于号的意思,而是赋值的意思。左边的“保存变量”必须是变量,不能是常量,否则编译时会报错。右边的“被乘数”和“乘数”既可以是变量,也可以是常量,也可以是“保存变量”本身自己。多说一句,何谓变量和常量?变量是可以在程序中被更改的,是被分配的一个RAM空间。常量往往是数字,或者是被分配在ROM空间的一个具体数值。下面根据右边“被乘数”与“乘数”的不同组合,列出了乘法运算的5种常见格式。
      第1种:“被乘数1”是常量,“乘数2”是常量。比如:
  1. unsigned char a;
  2. a=15*3;

数字“15”和“3”都是常量。执行上述语句后,保存变量a变成了45。

      第2种:“被乘数1”是变量,“乘数2”是常量。比如:
  1. unsigned char b;
  2. unsigned char x=15;
  3. b=x*10;

x是变量,“10”是常量。由于原来x变量里面的数值是15,执行上述语句后,保存变量b变成了150。而变量x则保持不变,x还是15。

      第3种:“被乘数1”是变量,“乘数2”是变量。比如:
  1. unsigned char c;
  2. unsigned char x=15;
  3. unsigned char y=6;
  4. c=x*y;

x是变量,y也是变量。由于原来x变量里面的数值是15,y变量里面的数值是6,执行上述语句后,保存变量c变成了90。而变量x和y则保持不变,x还是15,y还是6。

      第4种:“被乘数1”是保存变量本身,“乘数2”是常量。比如:
  1. unsigned char d=18;
  2. d=d*2;
  3. d=d*7;

d是保存变量,“2”和“7”都是常量。这类语句有一个特点,具备了自乘功能,可以更改自己本身自己的数值。比如原来保存变量d的数值是18,执行“d=d*2;”语句后,d变成了36,接着再执行完“d=d*7;”语句后,d最后变成了252。

      第5种:“被乘数1”是保存变量本身,“乘数2”是变量。比如:
  1. unsigned char e=2;
  2. unsigned char x=15;
  3. unsigned char y=6;
  4. e=e*x;
  5. e=e*y;

e是保存变量,x与y都是变量。这类语句有一个特点,具备了自乘功能,可以更改自己本身自己的数值。比如原来保存变量e的数值是2,执行“e=e*x;”语句后,e变成了30,接着再执行完“e=e*y;”语句后,e最后变成了180。

       现在编写一个程序来练习上述5种格式的乘法语句,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
  1. void main() //主程序
  2. {
  3. /*---C语言学习区域的开始---------------------------------------------------------------------------*/
  4.         
  5.   unsigned char a;       //定义一个变量a,并且分配了1个字节的RAM空间。
  6.   unsigned char b;       //定义一个变量b,并且分配了1个字节的RAM空间。
  7.   unsigned char c;       //定义一个变量c,并且分配了1个字节的RAM空间。
  8.   unsigned char d=18;       //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为18.
  9.   unsigned char e=2;       //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为2.
  10.         
  11.   unsigned char x=15;    //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为15.
  12.   unsigned char y=6;     //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.        

  13.   //第1种:“被乘数1”是常量,“乘数2”是常量。
  14.   a=15*3;
  15.         
  16.         
  17.   //第2种:“被乘数1”是变量,“乘数2”是常量。
  18.   b=x*10;
  19.         
  20.   //第3种:“被乘数1”是变量,“乘数2”是变量。
  21.   c=x*y;
  22.         
  23.         
  24.   //第4种:“被乘数1”是保存变量本身,“乘数2”是常量。
  25.   d=d*2;
  26.   d=d*7;
  27.         
  28.         
  29.   //第5种:“被乘数1”是保存变量本身,“乘数2”是变量。
  30.   e=e*x;
  31.   e=e*y;


  32.   GuiWdData0=a;   //把变量a这个数值放到窗口变量0里面显示
  33.   GuiWdData1=b;   //把变量b这个数值放到窗口变量1里面显示
  34.   GuiWdData2=c;   //把变量c这个数值放到窗口变量2里面显示
  35.   GuiWdData3=d;   //把变量d这个数值放到窗口变量3里面显示
  36.   GuiWdData4=e;   //把变量e这个数值放到窗口变量4里面显示

  37.         
  38. /*---C语言学习区域的结束---------------------------------------------------------------------------*/
  39.    while(1)  
  40.    {
  41.       initial();
  42.       key_service();
  43.       display_service();
  44.    }

  45. }


        如何在坚鸿51学习板上观察a,b,c,d,e这5个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下:
变量a为45。
变量b为150。
变量c为90。
变量d为252。
变量e为180。

     下节预告:乘法连写的简写。
(未完待续)

czdo 发表于 2015-6-30 09:22 | 显示全部楼层
我也来预订一本书
dianzijiangren 发表于 2015-6-30 17:57 | 显示全部楼层
搞了十年,还做单片机,哥们你也是让我醉了
神奇号 发表于 2015-7-1 20:24 | 显示全部楼层
学习了,
NoTCsmile 发表于 2015-7-2 14:00 | 显示全部楼层
原来 只是卖开发板的。。。。再说 就是十年也算不得高手吧。。。
弥勒开怀笑 发表于 2015-7-2 15:12 | 显示全部楼层
fmzhangpei241 发表于 2015-7-4 09:29 | 显示全部楼层
 楼主| jianhong_wu 发表于 2015-7-6 10:16 | 显示全部楼层
第二十五节:连乘以及自乘运算的简写。
       上一节我列举的乘法例子中,右边的参与运算的数据都是两个。实际上,C语言规则没有限制数据个数,它的通用格式如下:
       “保存变量”=“被乘数1”*“乘数2”...*“乘数N”;
       当右边的乘数个数超过两个的时候,就是我所说的“连乘”,每个乘数的属性没有限定,可以是常量,也可以是变量。比如:
  1. a=2*5*3;  //被乘数和乘数全部是常量。a的结果为30。
  2.   b=k*x*y;  //被乘数和乘数全部是变量。b的结果为36。
  3.   c=x*5*y;  //被乘数和乘数,有的是常量,有的是变量。c的结果为90。

        连乘的运行顺序是,赋值符号“=”右边的乘数挨个相乘,把每一次的运算结果放在一个临时的隐蔽变量里,这个隐蔽的变量我们看不到,是单片机系统内部参与运算时的专用寄存器,等右边所有的乘数连乘的计算结果出来后,再把这个隐蔽变量所保存的计算结果赋值给左边的“保存变量”。
        讲完了连乘的格式,接着讲自乘的简写。何谓自乘?当右边的被乘数是“保存变量”本身时,这种情况就是我所说的“自乘”。比如:
“保存变量”=“保存变量”*“乘数1”;
“保存变量”=“保存变量”*“乘数1”*“乘数2”...*“乘数N”;
        上述自加计算式可以简写成如下格式:
“保存变量”*=“乘数1”;       
“保存变量”*=“乘数1”*“乘数2”...*“乘数N”;
        这种格式就是我所说的自乘简写。现在举几个例子如下:
  
  1. d*=6;     //相当于d=d*6;最后d的结果为30。
  2.   e*=x;     //相当于e=e*x;最后e的结果为15。
  3.   f*=2*y*k; //相当于f=f*(2*y*k);最后f的结果为120。

     我之前在讲加法的自加和减法的自减运算时,还给大家介绍了它们另外一种特殊的简写方式。比如减法运算,当右边只有2减数,当一个减数是“保存变量”,另一个是常数1时,格式如下:
“保存变量”=“保存变量”-1;       
        这时候,可以把上述格式简写成如下两种格式:
“保存变量”--;
--“保存变量”;
        这两种格式也是俗称的“自减1”操作。比如:
  1. g--;  //相当于g=g-1或者g-=1;
  2. --h;  //相当于h=h-1或者h-=1;

         那么,本节所讲的自乘运算,有没有这种特殊写法“g**”或者“**h”?答案很明显,没有。因为任何一个数“自乘1”还是等于它本身,所以研究这种特殊写法就没有任何意义。
         现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:


  1. void main() //主程序
  2. {
  3. /*---C语言学习区域的开始---------------------------------------------------------------------------*/
  4.         
  5.   unsigned char a;       //定义一个变量a,并且分配了1个字节的RAM空间。
  6.   unsigned char b;       //定义一个变量b,并且分配了1个字节的RAM空间。
  7.   unsigned char c;       //定义一个变量c,并且分配了1个字节的RAM空间。
  8.   unsigned char d=5;       //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为5.
  9.   unsigned char e=5;       //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为5.
  10.   unsigned char f=5;       //定义一个变量f,并且分配了1个字节的RAM空间。初始化默认为5.
  11.    
  12.   unsigned char x=3;    //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为3.
  13.   unsigned char y=6;     //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.        
  14.   unsigned char k=2;     //定义一个变量k,并且分配了1个字节的RAM空间。初始化默认为2.
  15.         
  16.         
  17.             //第1个知识点:连乘。
  18.   a=2*5*3;  //被乘数和乘数全部是常量。a的结果为30。
  19.   b=k*x*y;  //被乘数和乘数全部是变量。b的结果为36。
  20.   c=x*5*y;  //被乘数和乘数,有的是常量,有的是变量。c的结果为90。

  21.             //第2个知识点:自乘的简写。
  22.   d*=6;     //相当于d=d*6;最后d的结果为30。
  23.   e*=x;     //相当于e=e*x;最后e的结果为15。
  24.   f*=2*y*k; //相当于f=f*(2*y*k);最后f的结果为120。
  25.          
  26.          


  27.    GuiWdData0=a;   //把变量a这个数值放到窗口变量0里面显示
  28.    GuiWdData1=b;   //把变量b这个数值放到窗口变量1里面显示
  29.    GuiWdData2=c;   //把变量c这个数值放到窗口变量2里面显示
  30.    GuiWdData3=d;   //把变量d这个数值放到窗口变量3里面显示
  31.    GuiWdData4=e;   //把变量e这个数值放到窗口变量4里面显示
  32.    GuiWdData5=f;   //把变量f这个数值放到窗口变量5里面显示


  33.         
  34. /*---C语言学习区域的结束---------------------------------------------------------------------------*/
  35.    while(1)  
  36.    {
  37.       initial();
  38.       key_service();
  39.       display_service();
  40.    }

  41. }

        如何在坚鸿51学习板上观察a,b,c,d,e,f这6个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下:
变量a为30。
变量b为36。
变量c为90。
变量d为30。
变量e为15。
变量f为120。
     下节预告:乘法运算的溢出。
(未完待续)
cccsssc 发表于 2015-7-6 10:59 | 显示全部楼层
要是真能仔细看完其实收获还是非常可观的!
shenxfs 发表于 2015-7-7 07:55 | 显示全部楼层
初看教程感觉还可以,但仔细阅读还是有些不对,误人子弟之嫌。
首先main函数书写就有问题:void main(),函数的形参为空,返回值也是空。LZ搞了单片机十年,嵌入式c语言编码规范是否知道,规范要求main函数必须明确返回值和形参的类型,写成int main(void)或int main(int argc.char **argv)。void main()在keil不会告警,可在其它编译器会出错。
风继续吹AQA 发表于 2015-7-8 10:51 | 显示全部楼层
太赞了!
Aidon_Zhang 发表于 2015-7-8 16:27 | 显示全部楼层
 楼主| jianhong_wu 发表于 2015-7-12 07:26 | 显示全部楼层
第二十六节:乘法运算的溢出。
     乘法的溢出规律跟加法的溢出规律是一样的。举一个例子如下:
  1.    unsigned char k=30;
  2.    unsigned char n=10;
  3.    unsigned char a;
  4.    a=k*n;  

分析:
kn相乘,相当于30乘以10,运算结果是300(十六进制是0x012c保存在一个隐藏中间变量,根据前面加法运算的规律,我猜测这个隐藏中间变量可能是unsigned int类型,然后再把这个中间变量赋值给单字节变量a,a只能接收十六进制的低8位字节0x2c,所以运算后a的数值由于溢出变成了十六进制的0x2c(十进制是44)。
由于乘法的溢出规律跟加法的溢出规律是一样的,所以不再多举例子。在实际项目中,为了避免一不小心就溢出的问题,我强烈建议,不管加减乘除,凡是参与运算的变量全部都要转化成unsigned long变量,转化的方法也跟加减运算的转换方法一致,不再详细解决这方面的内容。
现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
  1. void main() //主程序
  2. {
  3. /*---C语言学习区域的开始-----------------------------------------------------------------

  4. ----------*/
  5.       
  6.    unsigned char k=30;
  7.    unsigned char n=10;
  8.    unsigned char a;

  9.    a=k*n;  

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



  11.         
  12. /*---C语言学习区域的结束-----------------------------------------------------------------

  13. ----------*/
  14.    while(1)  
  15.    {
  16.       initial();
  17.       key_service();
  18.       display_service();
  19.    }

  20. }

    查看运算结果的方法。如何在坚鸿51学习板上观察变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。上坚鸿51学习板观察程序执行的结果如下:
       变量a为0x2c(十进制是44)。
     下节预告:除法运算的常见格式。
(未完待续)

zjglizhen 发表于 2015-7-13 16:21 | 显示全部楼层
赞,太棒了
multisensor 发表于 2015-7-13 20:21 | 显示全部楼层
万丈高原平地起...
tianjian002 发表于 2015-7-14 22:31 | 显示全部楼层
:P关注航太电子单片机开发板
风去 发表于 2015-7-14 22:33 | 显示全部楼层
 楼主| jianhong_wu 发表于 2015-7-18 07:13 | 显示全部楼层
第二十七节:整除求商的运算。
C语言中,乘法符号不是“×”而是“*”,除法求商的符号不是“÷”而是“/”。乘除法符号跟我们日常用的数学符号有点不一样,我个人猜测C语言这样规定的原因是因为“×”容易跟大写字母“X”搞混,而“÷”这个符号在电脑键盘上不方便直接输入,故分别用“*”和“/”替代。
何谓“整除”?请看以下两个对比例子:
10除以4,商等于2.5------(带小数点)
10除以4,商等于2,余数是2------(这就叫做整除)
什么时候带小数点,什么时候是整除?取决于参与运算的变量类型。标准的C语言中,其实远远不止我前面所说的unsigned char ,unsigned int ,unsigned long这三种类型,还有一种叫浮点数的float类型,当参与运算的变量涉及float类型时,就可能存在小数点。这是题外话,大家大概知道有这么一回事即可,暂时不用深入研究float等其它类型的数据,因为在单片机项目中,只要用我所述的三种常用类型就绝对够用了,单片机不用涉及float类型,如果项目涉及小数点的显示和处理,我们完全可以用那三种类型去处理它,这些处理方法我后续会讲到,暂时不用管。而unsigned char ,unsigned int ,unsigned long这三种类型的除法都是整除,我后续所讲的所有章节内容也都是整除。
整除的通用格式:
“保存变量”=“被除数” /  “除数1/  “除数2... /  “除数N;
跟之前讲的加减运算一样,左边的“保存变量”必须是变量,右边的可以是变量和常量的任意组合。如果右边只有两个参与运算的数据,就是整除的常见格式。
整除的常见格式:
“保存变量”=“被除数” /  “除数” ;       
现在从整除常见格式的6个方面来分析它的规律。
(1)当“除数”等于0时。我们都知道,数**算除数是不允许等于0的,如果在单片机中非要让除数为0,商会出现什么结果?我试过,发现有一个规律:如果“除数”是变量的0,那么商等于十进制的255(十六进制是0xff)。如果“除数”是常量的0,那么商等于十进制的1。比如:
  1. a=23 /y;  //假设除数变量y里面是0,那么a的结果是255(十六进制的0xff)。
  2. b=23 /0;  //除数是常量0,那么b的结果是1。

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

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

(4)当被除数大于“除数”时。商大于0
比如:
  1. e=10/ 4;  //e的结果是2。
  2. f=10/ 3;  //f的结果是3。

(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.         c=7/10;
  16.         d=10/10;
  17.         e=10/4;
  18.         f=10/3;
  19.         g/=5;  //相当于g=g/5;
  20.        
  21.   GuiWdData0=a;   //把a这个变量放到窗口变量0里面显示
  22.   GuiWdData1=b;   //把b这个变量放到窗口变量1里面显示
  23.   GuiWdData2=c;   //把c这个变量放到窗口变量2里面显示
  24.   GuiWdData3=d;   //把d这个变量放到窗口变量3里面显示
  25.   GuiWdData4=e;   //把e这个变量放到窗口变量4里面显示
  26.   GuiWdData5=f;   //把f这个变量放到窗口变量5里面显示
  27.   GuiWdData6=g;   //把g这个变量放到窗口变量5里面显示
  28.         
  29. /*---C语言学习区域的结束---------------------------------------------------------------------------*/
  30.    while(1)  
  31.    {
  32.                   initial();
  33.       key_service();
  34.       display_service();
  35.    }

  36. }

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

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

本版积分规则

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