打印
[51单片机]

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

[复制链接]
楼主: jianhong_wu
手机看帖
扫描二维码
随时随地手机跟帖
41
LeaderHuang 发表于 2015-2-24 17:31
对于单片机的内部原理,要得学计算机组成原理和FPGA才有深刻理解。
还是linus那句话,你得先学会使用它。 ...

linus是神马,linux?

使用特权

评论回复
42
风雪残月| | 2015-4-5 00:21 | 只看该作者
楼主流弊啊 看过你上个连载的帖子 准备回去重新看下

使用特权

评论回复
43
LeaderHuang| | 2015-4-5 08:15 | 只看该作者
代码小卒 发表于 2015-4-4 15:18
linus是神马,linux?

linux的创始人linus,中文名李纳斯

使用特权

评论回复
44
pguangchun| | 2015-4-6 09:14 | 只看该作者
鸿哥,原来的帖子呢?

使用特权

评论回复
45
jianhong_wu|  楼主 | 2015-4-7 09:53 | 只看该作者
本帖最后由 jianhong_wu 于 2015-6-3 17:03 编辑

第十一节:变量的定义与赋值语句。
      写程序到底是写什么?我用七个字概括是:对象之间的行为。假设以下a,b,c,d,e.这些都是对象,那么程序往往是对象之间的以下这些行为:
    (1)把某个数值赋值给对象a
    (2)把对象b赋值给对象a
    (3)把对象b与对象c运算的结果赋值给对象a
    (4)如果对象d等于某个数值,则把某个数值赋值给对象a
    (5)如果对象d等于某个数值,则把对象b赋值给对象a
    (6)如果对象d等于某个数值,则把对象b与对象c运算的结果赋值给对象a
    (7)如果对象d等于对象e,则把某个数值赋值给对象a
    (8)如果对象d等于对象e,则把对象b赋值给对象a
    (9)如果对象d等于对象e,则把对象b与对象c运算的结果赋值给对象a
    (10)...等等,不一一列举。
      从上述可以看出,程序的两个要素是:对象和行为。如果把对象看作是单片机的RAM数据存储器,那么行为就是单片机的ROM程序存储器。如果把对象看作是变量,那么行为就是指令语句。本节标题“变量的定义与赋值语句”,其中“变量的定义”就是对象,“赋值语句”就是行为。
      变量的定义。一个程序最大允许有多少个对象,是由数据存储器RAM的字节数决定的(字节是一种单位,后面章节会讲到)stc89c52rc这个单片机有几百个字节的RAM,但是并不意味着程序就一定要全部占用这些RAM。程序需要占用多少RAM,完全是根据程序的实际情况来决定,需要多少就申请多少。这里的“对象”就是变量。这里的“申请”就是变量的定义。
       定义变量的关键字。常用有3种容量的变量,每种变量的取值范围不一样。第一种是”unsigned char”变量,取值范围从0255,占用RAM一个字节,比喻成一房一厅。第二种是”unsigned int”变量,取值范围从065535,占用RAM两个字节,比喻成两房一厅。第三种是“unsigned long”变量,取值范围从04294967295,占用RAM三个字节,比喻成三房一厅。unsigned char,unsigned intunsigned long都是定义变量的关键字。
       定义变量的语法格式。定义变量的语法格式由3部分组成:关键字,变量名,分号。比如:
       unsigned char a;
      其中unsigned char就是关键字,a就是变量名,分号”;”就是一条语句的结束符号。
      变量名的命名规则。变量名的第一个字符不能是数字,必须是字母或者下划线,字母或者下划线后面可以带数字,一个变量名之间的字符不能带空格。变量名不能跟编译器的关键字重名,不能跟函数名重名。比如:
      unsigned char 3a; //不合法,第一个字符不能是数字。
      unsigned char char; //不合法,char是编译器的关键字。
      unsigned char a b; //不合法,ab是一个变量名,ab的中间不能有空格。
      unsigned char a; //合法。
      unsigned char abc; //合法。
      unsigned char _ab; //合法。
      unsigned char _3ab; //合法。
      unsigned char a123; //合法。
      unsigned char a12ced; //合法。
      定义变量与RAM的内在关系。当我们定义一个变量时,相当于向单片机申请了一个RAM空间。C编译器会自动为这个变量名分配一个RAM空间,每个字节的RAM空间都有一个固定的地址。把每个字节的RAM空间比喻成 房间,这个地址就是房号。地址是纯数字编号,不利于我们**,C语言编译器为了降低我们的工作难度,不用我们记每个变量的地址,只需要记住这个变量的名称就可以了。操作某个变量名,就相当于操作到对应地址的RAM空间。变量名与对应地址RAM空间的映射关系是C编译器暗中帮我们做好了。比如:
      unsigned char a;  //a占用一个字节的RAM空间,这个空间的地址由C编译自动分配。
      unsigned char b;  //b占用一个字节的RAM空间,这个空间的地址由C编译自动分配。
      unsigned char c;  //c占用一个字节的RAM空间,这个空间的地址由C编译自动分配。  
      上述a,b,c三个变量名占用一个字节的RAM空间,同时被C编译器分配了3个不同的RAM空间地址。
      赋值语句的含义。赋值语句是行为。把右边对象的内容复制一份给左边对象。 赋值语句有一个很重要的特性,就是覆盖性,左边对象原来的内容会被右边对象复制过来的新内容所覆盖。比如,左边对象是变量a,原来a里面存的数据是3,右边对象是立即数6,执行赋值语句后,把6赋值给了对象a,那么a原来的数据3就被覆盖丢失了,变成了6.
赋值语句的格式。赋值语句的语法格式由4部分组成:左边对象,关键字,右边对象,分号。比如:
      a=b;
      其中a就是左边对象。
      其中“=”就是关键字。写法跟我们平时用的等于号是一样,但是在C语言里不是等于的意思,而是代表赋值的意思。跟等于号是两码事。
      其中b就是右边对象。
      其中分号“;”代表一条语句的结束符。
      赋值语句与ROM的内在关系。赋值语句是行为,凡是程序的行为指令都存储在单片机的ROM区。C编译器会把一条赋值语句翻译成对应的一条或者几条机器码,机器码指令也是以字节为单位的。下载程序的时候,这些机器码就会被下载进单片机的ROM区。比如以下这行赋值语句:
      a=b;
      经过C编译器编译后会生成以字节为单位的机器码。这些机器码记录着这些信息:变量aRAM地址,变量bRAM地址,以及把b变量RAM地址里面的内容赋值到a变量地址里面的RAM空间。
      变量定义的初始化。讲了赋值语句之后,再回过头来讲变量定义的初始化。变量定义之后,等于被C编译器分配了一个RAM空间,那么这个空间里面存储的数据是什么?如果没有刻意给它初始化,那么RAM空间里面存储的数据是不太确定的,是默认的。有些场合,需要在给变量分配RAM空间时就给它一个固定的初始值,这就是变量定义的初始化。变量初始化的语法格式由3部分组成:关键字,变量名赋值,分号。比如:
      unsigned char a=9;
     其中unsigned char就是关键字。
     其中a=9就是变量名赋值。a从被C编译器分配RAM空间那一刻起,就默认是存了9这个数据。
     分号”;”就是一条语句的结束符号。
     接下来练习一个程序实例。直接复制前面章节中第十节的模板程序,只需要在main函数里编写练习代码,编译后,把程序下载进坚鸿51学习板,通过按S1或者S5按键即可在数码管上观察不同的变量数值。其它部分的模板程序代码就不贴出来了,详细的main函数源代码讲解如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;   //定义一个变量a,并且分配了一个字节的RAM空间,里面保存的数据是默认值0.
  unsigned char b;   //定义一个变量b,并且分配了一个字节的RAM空间,里面保存的数据是默认值0.
  unsigned char c;   //定义一个变量c,并且分配了一个字节的RAM空间,里面保存的数据是默认值0.  
  unsigned char d=9; //定义一个变量d,并且分配了一个字节的RAM空间,里面保存的数据被初始化成9.

  b=3;  //把3赋值给变量b,b原来的默认数据是0被覆盖了,此时变量b保存的数值是3
  c=b;  //把右边变量b的内容复制一份赋值给左边的变量c,c原来的默认数据0被覆盖了,此时,c保存的数值跟b的数值一样,都是3.

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

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

}


       上坚鸿51学习板观察程序执行的结果:
       变量a的数值是0
       变量b的数值是3
       变量c的数值是3
       变量d的数值是9

       下节预告:两个变量的数据交换。
(未完待续)


使用特权

评论回复
46
wejoncy| | 2015-4-7 10:39 | 只看该作者
学习中

使用特权

评论回复
47
jianhong_wu|  楼主 | 2015-4-10 12:28 | 只看该作者
本帖最后由 jianhong_wu 于 2015-6-3 17:04 编辑

第十二节两个变量的数据交换。
为了加深理解赋值语句的一个重要特性“覆盖性”,本节利用赋值语句“=”做一个实验。要求把变量a与b的两个数据进行交换,假设a原来的数据是1,b原来的数据是5,交换数据后,a的数据应该变为5,b的数据应该变为1。
很多初学者刚看到这么简单的题目,会想当然的根据我们日常生活的思路,你把你的东西给我,我把我的东西给你,就两个步骤,so easy!请直接复制第十节的模板程序,仅修改main函数后,main函数源代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a=1;   //定义一个变量a,并且分配了一个字节的RAM空间,里面保存的数据被初始化成1.
  unsigned char b=5;   //定义一个变量b,并且分配了一个字节的RAM空间,里面保存的数据被初始化成5.

        b=a; //第一步:为了交换,先把a的数赋值给b。
        a=b; //第二步:为了交换,再把b的数赋值给a。

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

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

}

       上坚鸿51学习板观察程序执行的结果:
       变量a的数值是1。
       变量b的数值是1。
     上述实验结果并没有达到交换数据的目的,为什么?因为赋值语句有一个重要的特性,就是覆盖性。分析如下:
         b=a; //第一步
     分析点评:执行第一步后,此时虽然b得到了a的数据1,但是b原来自己的数据5已经被覆盖丢失了!
         a=b; //第二步
     分析点评:由于b的数据在执行第一步后变成了1,执行第二步后,此时相当于把1赋值给a,并没有5!所以a和b的数据都是1,不能达到交换后“a为5,b为1”的目的。
     上述交换数据的程序宣告失败!怎么办?既然赋值语句具有覆盖性,那么两变量想交换数据,就必须借助第三方寄存,此时只需要多定义一个第三方变量t。main函数源代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a=1;   //定义一个变量a,并且分配了一个字节的RAM空间,里面保存的数据被初始化成1.
  unsigned char b=5;   //定义一个变量b,并且分配了一个字节的RAM空间,里面保存的数据被初始化成5.
  unsigned char t;     //定义一个变量t,并且分配了一个字节的RAM空间,里面默认是什么数据不重要。
        
        t=b; //第一步:为了避免b的数据在执行第二步后被覆盖丢失,先把b的数据寄存在第三方变量t那里。
        b=a; //第二步:把a的数赋值给b,b原来的数据虽然被覆盖丢失,但是b在t变量那里有备份,再也不用担心了。
        a=t; //第三步:由于此时b已经获得了a的数据,如果想交换,此时只能把b在t变量里的备份赋值给a,而不能用b。

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

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

}

       上坚鸿51学习板观察程序执行的结果:
       变量a的数值是5。
       变量b的数值是1。
      交换成功!

       下节预告:二进制与字节单位。
(未完待续)


使用特权

评论回复
48
奶油草莓味| | 2015-4-11 19:49 | 只看该作者
学习,12节

使用特权

评论回复
49
supaopcb| | 2015-4-15 17:03 | 只看该作者
学习了

使用特权

评论回复
50
wsnsyy| | 2015-4-15 17:17 | 只看该作者
mark

使用特权

评论回复
51
yangceadr| | 2015-4-16 09:57 | 只看该作者
学习,学习,前辈的经验值得参考

使用特权

评论回复
52
jianhong_wu|  楼主 | 2015-4-16 19:54 | 只看该作者
本帖最后由 jianhong_wu 于 2015-6-3 17:07 编辑

第十三节:二进制与字节单位,以及各种定义变量的取值范围。
       为什么是二进制?人类日常生活明明是十进制的,为何数字电子领域偏要选择二进制?这是由数字硬件电路决定的。人有十个手指头,人可以发出十种不同声音来命名0,1,2,3...9这些数字,人可以肉眼识别十种不同状态的信息,但是数字电路要直接处理十进制却很难,相对来说,二进制就轻松多了。一颗LED灯的亮与灭,一根IO口的输出是高电平和低电平,读取某一个点的电压是高于2V还是低于0.8V,只需要用三极管等元器件就可把处理电路搭建起来,二进制广泛应用在数字电路的存储,通讯和运算等领域,想学好单片机就必须掌握它。
二进制如何表示成千上万的数值?现在用LED灯的亮和灭来跟大家讲解。
     (11LED灯:
灭   第0种状态
亮   第1种状态
合计:共2种状态。
    (22LED灯挨着:
灭灭   第0种状态
灭亮   第1种状态
亮灭   第2种状态
亮亮   第3种状态
合计:共4种状态。
    (33LED灯挨着:
灭灭灭   第0种状态
灭灭亮   第1种状态
灭亮灭   第2种状态
灭亮亮   第3种状态
亮灭灭   第4种状态
亮灭亮   第5种状态
亮亮灭   第6种状态
亮亮亮   第7种状态
合计:共8种状态。
    (48LED灯挨着:
灭灭灭灭灭灭灭灭   第0种状态
灭灭灭灭灭灭灭亮   第1种状态
......
亮亮亮亮亮亮亮灭   第254种状态
亮亮亮亮亮亮亮亮   第255种状态
合计:共256种状态。
    (516LED灯挨着:
灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭   第0种状态
灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭亮   第1种状态
......
亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮灭   第65534种状态
亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮   第65535种状态
合计:共65536种状态。
     (632LED灯挨着:
灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭   
0种状态
灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭灭亮   
1种状态
......
亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮灭   
4294967294种状态
亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮亮   
4294967295种状态
合计:共4294967296种状态。


       什么是位?以上一个LED灯就代表一位,8LED灯就代表8位。一个变量的位数越大就意味着这个变量的取值范围越大。一个单片机的位数越多大,就说明这个单片机一次处理的数据范围就越大,意味着运算和处理速度就越快。我们日常所说的8位单片机,32位单片机,就是这个位的概念。为什么32位的单片机比8位单片机的处理和运算能力强,就是这个原因。位的英文名是用bit来表示。
       什么是字节?字节是计算机很重要的一个基本单位,一个字节有8位。8LED灯挨着能代表多少种状态,就意味着一个字节的数据范围有多大。从上面举的例子中,我们知道8LED灯挨着,能表示从0255种状态,所以一个字节的取值范围就是从0255
       各种定义变量的取值范围。前面第十一节讲了常用变量的定义有3种,unsigned charunsigned int ,unsigned long。但是没有讲到它们的取值范围,现在讲到二进制和字节了,可以回过头来跟大家讲讲这3种变量的取值范围,而且很重要。
unsigned char的变量占用1个字节RAM,共8位,根据前面LED灯的例子,取值范围是从0255
Unsigned int的变量占用2个字节RAM,共16位,根据前面LED灯的例子,取值范围是从065535
Unsigned long的变量占用4个字节RAM,共32位,根据前面LED灯的例子,取值范围是从04294967295
       现在我们编写一个程序来验证unsigned charunsigned int的取值范围。定义两个unsigned char变量aba赋值255b赋值256255256恰好处于unsigned char的取值边界。另外再定义两个unsigned int变量cdc赋值65535d赋值655366553565536恰好处于unsigned int的取值边界。最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;   //定义一个变量a,并且分配了1个字节的RAM空间。
  unsigned char b;   //定义一个变量b,并且分配了1个字节的RAM空间。
  unsigned int c;    //定义一个变量c,并且分配了2个字节的RAM空间。
  unsigned int d;    //定义一个变量d,并且分配了2个字节的RAM空间。

        a=255;//把255赋值给变量a,a此时会是什么数?会超范围溢出吗?
        b=256;//把256赋值给变量b,b此时会是什么数?会超范围溢出吗?
        c=65535;//把65535赋值给变量c,c此时会是什么数?会超范围溢出吗?
        d=65536;//把65536赋值给变量d,d此时会是什么数?会超范围溢出吗?
        
        
  GuiWdData0=a;   //把变量a这个数值放到窗口变量0里面显示
  GuiWdData1=b;   //把变量b这个数值放到窗口变量1里面显示
  GuiWdData2=c;   //把变量c这个数值放到窗口变量2里面显示
  GuiWdData3=d;   //把变量d这个数值放到窗口变量3里面显示

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

}

        上坚鸿51学习板观察程序执行的结果如下:
    unsigned char变量a的数值是255。
     unsigned char变量b的数值是0。
    unsigned int  变量c的数值是65535。
     unsigned int  变量d的数值是0。
        通过以上现象分析,我们知道unsigned char变量最大能取值到255,如果非要赋值256就会超出范围溢出后变成了0。而unsigned int变量最大能取值到65535,如果非要赋值65536就会超出范围溢出后变成了0。
    多说一句,至于unsigned long的取值范围,大家暂时不用尝试,因为我现在给大家用的模板程序能观察的最大变量是16位的unsigned int类型,暂时不支持32位的unsigned long类型。
       下节预告:二进制与十六进制。
(未完待续)



使用特权

评论回复
53
luochangqing112| | 2015-4-16 22:12 | 只看该作者
mark 收藏学习。

使用特权

评论回复
54
zjs1102| | 2015-4-17 09:23 | 只看该作者
牛X人物写的东西就是不一样啊!!

使用特权

评论回复
55
jianhong_wu|  楼主 | 2015-4-19 11:39 | 只看该作者
本帖最后由 jianhong_wu 于 2015-6-3 17:09 编辑

第十四节:二进制与十六进制。
       C51编译器并不支持二进制的书写格式,即使添加某个头文件后能支持二进制的书写格式,二进制的书写还是有个弊端,就是数字太多太长了,写起来非常费劲不方便,怎么办?解决办法就是用十六进制。十六进制是二进制的缩写,之所以称它为二进制的缩写,是因为它们的转换关系非常简单直观,不需要借助计算器即可相互转换。
       何谓十六进制?欲搞清楚这个问题,还得先从十进制说起。所谓十进制,就是用一位字符可以表示从09这十个数字。所谓二进制,就是用一位字符可以表示从01这二个数字。所谓十六进制,当然也就是用一位字符可以表示从015这十六个数字。但是马上就会面临一个问题,十六进制的10156个数其实是有两位字符组成的,并不是一位呀?于是C语言用一个字符A,B,C,D,E,F分别替代10,11,12,13,14,156个数,10前面的09还是跟十进制的字符一致。A,B,C,D,E,F也可以用小写a,b,c,d,e,f来替代,不区分大小写。
       前面提到了十六进制是二进制的缩写,它们的转换关系非常简单直观,每1位十六进制的字符,对应4位二进制的字符。关系如下:
十进制       二进制      十六进制
0               0000        0
1               0001        1
2               0010        2
3               0011        3
4               0100        4
5               0101        5
6               0110        6
7               0111        7
8              1000        8
9              1001        9
10            1010        A
11            1011        B
12            1100        C
13            1101        D
14            1110        E
15            1111        F

       二进制转换成十六进制的时候,如果不是4位的倍数,则最左边高位默认补上0凑合成4位的倍数。比如二进制101001,可以在左边补上20变成00101001,然后把每4位字符转成1个十六进制的字符。左边高40010对应十六进制的2,右边低41001对应十六进制的9,所以合起来最终的十六进制是29
       十六进制的标准书写格式。刚才提到的十六进制29,在C语言里不能直接写29,否则就跟十进制的写法混淆了。为了把十六进制和十进制的书写格式进行区分,C语言规定凡是十六进制必须加一个数字0和一个字母x作为前缀,也就是十六进制必须以0x作为前缀,刚才的十六进制29就应该写成0x29。凡是不加前缀的就默认为十进制。
       现在我们编写一个程序来观察十六进制和二进制的关系,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:


void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;    //定义一个变量a,并且分配了1个字节的RAM空间。
  unsigned char b;    //定义一个变量b,并且分配了1个字节的RAM空间。
  unsigned char c;    //定义一个变量c,并且分配了1个字节的RAM空间。
  unsigned char d;    //定义一个变量d,并且分配了1个字节的RAM空间。

  a=0x06;   //十六进制前记得加0x前缀,超过9部分的字母不分大小写。
  b=0x0A;   //十六进制前记得加0x前缀,超过9部分的字母不分大小写。
  c=0x0e;   //十六进制前记得加0x前缀,超过9部分的字母不分大小写。
  d=0x2C;   //十六进制前记得加0x前缀,超过9部分的字母不分大小写。
        
        
  GuiWdData0=a;   //把变量a这个数值放到窗口变量0里面显示
  GuiWdData1=b;   //把变量b这个数值放到窗口变量1里面显示
  GuiWdData2=c;   //把变量c这个数值放到窗口变量2里面显示
  GuiWdData3=d;   //把变量d这个数值放到窗口变量3里面显示

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

}


        如何在坚鸿51学习板上观察十六进制和二进制?S1S5按键是切换窗口按键。按住S9按键不松手,就可以观察当前窗口数据的十六进制格式了。松开S9按键就是当前窗口的十进制数据格式。而坚鸿51学习板右上角的16LED灯就代表了当前窗口的二进制,亮的代表1,灭的代表0
       上朱兆祺51学习板观察程序执行的结果如下:
                                   十六进制         二进制         十进制     
unsigned char变量a      6                     0000 0110       6
unsigned char变量b      A                    0000 1010       10
unsigned char变量c      E                    0000 1110       14
unsigned char变量d      2C                  0010 1100       44

       多说一句,在程序里,可以用十六进制,也可以用十进制,比如:
d=0x2Cd=44的含义是一样的。十六进制的0x2C和十进制的44最终都会被C51编译器翻译成二进制00101100
       下节预告:十进制与十六进制。
(未完待续)





使用特权

评论回复
56
简单是福112233| | 2015-4-22 17:07 | 只看该作者
学习学习

使用特权

评论回复
57
代码小卒| | 2015-4-22 23:53 | 只看该作者
刚看到,看完再发表想法

使用特权

评论回复
58
白色滴丶| | 2015-4-23 10:28 | 只看该作者
太棒了   谢谢前辈分享        

使用特权

评论回复
59
aaron96031| | 2015-4-23 10:44 | 只看该作者
强!支持LZ, 有些很实用的工具大家不知道有用到,有些汉字在编译时发现不能在LCD液晶屏上显示,还以为是LCD屏的问题呢, 其实这是Keil OFDH 内码编译的BUG问题,大家是怎样解决这个BUG的,我们的方法是打个补丁,按照安装步骤 执行就解决了 ; 我的帖子上有解决步骤,碰到此问题的朋友自己去下载下: https://bbs.21ic.com/forum.php?mo ... 1&extra=#pid5393822

使用特权

评论回复
60
jianhong_wu|  楼主 | 2015-4-23 23:29 | 只看该作者
本帖最后由 jianhong_wu 于 2015-6-3 17:10 编辑

第十五节:十进制与十六进制。
    十六进制是二进制的缩写形式,而C语言程序里只用了十进制和十六进制这两种书写格式。它们各有什么应用特点?十六进制方便人理解机器,通常应用在配置寄存器,底层通讯驱动,底层IO口驱动,以及数据的移位,转换和合并等场合。而十进制方便人理解值的大小,在应用层经常用总之,进制数据的表现形式而已。
    十进制与十六进制如何相互转换?其实很多教科书上有介绍它们之间如何通过手工计算进行转换的方法。但是实际应用中,我从来没有用过这种手工计算方法,我用的方法是最简单直接的,就是借助电脑自带的计算器进行转换即可。现在把这种方法介绍给大家。
    第一步:点击电脑左下角“开始”菜单,在下拉菜单中把鼠标移动到“所有程序”,在下拉菜单中把鼠标移动到“附件”,在下拉菜单中点击“计算器”,此时会弹出“计算器” 的窗口。
    第二步:点击计算器窗口上面的“查看”菜单,在下拉菜单中点击“科学型”,此时“计算器” 的窗口会变长。按键上方出现“十六进制”,“十进制”,“八进制”,“二进制”等单选项。
    第三步:在按键上方“十六进制”,“十进制”,“八进制”,“二进制”等单选项中,单击所要切换到的进制,然后按数字按键输入数据。输完数据后,再单击切换到所要转换的进制中,即可完成各进制的数据切换。注意,在切换到“十六进制”的时候,在右边“四字”,“双字”,“单字”,“字节”中选中“四字”。
    第四步:把十进制转换到十六进制的方法如下:单击切换到“十进制”,然后按数字按键输入数据。输完数据后,再单击切换到“十六进制”,即可完成进制的转换。比如输入十进制的“230”,切换到十六进制就变成了“E6”。
    第五步:把十六进制转换到十进制的方法如下:单击切换到“十六进制”,然后按数字按键输入数据。输完数据后,再单击切换到“十进制”,即可完成进制的转换。比如输入十六进制的“AC”,切换到十进制就变成了“172”。
现在我们编写一个程序来观察十进制和十六进制的关系,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:

void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
        
  unsigned char a;    //定义一个变量a,并且分配了1个字节的RAM空间。
  unsigned char b;    //定义一个变量b,并且分配了1个字节的RAM空间。

  a=230;    //把十进制的230赋值给变量a,在朱兆祺51学习板上观察一下它的十六进制是不是E6。
  b=0xAC;   //把十六进制的AC赋值给变量b,在朱兆祺51学习板上观察一下它的十进制是不是172。
         
  GuiWdData0=a;   //把变量a这个数值放到窗口变量0里面显示
  GuiWdData1=b;   //把变量b这个数值放到窗口变量1里面显示

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

}


如何在坚鸿51学习板上观察十进制和十六进制?S1S5按键是切换窗口按键。按住S9按键不松手,就可以观察当前窗口数据的十六进制格式了。松开S9按键就是当前窗口的十进制数据格式。而坚鸿51学习板右上角的16LED灯就代表了当前窗口的二进制,亮的代表1,灭的代表0
坚鸿51学习板观察程序执行的结果如下:
                      十六进制        十进制     
unsigned char变量a      E6            230
unsigned char变量b      AC            172

     下节预告:判断语句“if”和等于关系符“==”。
(未完待续)



使用特权

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

本版积分规则