单片机的C 语言轻松入门.pdf
单片机的单片机的 C 语言轻松入门语言轻松入门 随着单片机开发技术的不断发展, 目前已有越来越多的人从普遍使用汇编语言到逐渐使 用高级语言开发,其中主要是以 C 语言为主,市场上几种常见的单片机均有其 C 语言开发 环境。这里以最为流行的 80C51 单片机为例来学习单片机的 C 语言编程技术。 本书共分六章,每章一个专题,以一些待完成的任务为中心,围绕该任务介绍 C 语言 的一些知识,每一个任务都是可以独立完成的,每完成一个任务,都能掌握一定的知识,等 到所有的任务都完成后,即可以完成 C 语言的入门工作。 第第 1 章 章 C 语言概述及其开发环境的建立语言概述及其开发环境的建立 学习一种编程语言,最重要的是建立一个练习环境,边学边练才能学好。Keil 软件是目 前最流行开发 80C51 系列单片机的软件,Keil 提供了包括 C 编译器、宏汇编、连接器、库 管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境 (Vision)将这些部份组合在一起。 在学会使用汇编语言后,学习 C 语言编程是一件比较容易的事,我们将通过一系列的 实例介绍 C 语言编程的方法。图 1-1 所示电路图使用 89S52 单片机作为主芯片,这种单片 机性属于 80C51 系列,其内部有 8K 的 FLASH ROM,可以反复擦写,并有 ISP 功能,支 持在线下载,非常适于做实验。89S52 的 P1 引脚上接 8 个发光二极管,P3.2P3.4 引脚上接 4 个按钮开关,我们的任务是让接在 P1 引脚上的发光二极管按要求发光。 1..1 简单的 简单的 C 程序介绍程序介绍 例 1-1 让接在 P1.0 引脚上的 LED 发光。 /************************************************* 平凡单片机工作室 Copyright 2003 pingfans mcustudio All rights Reserved 作者周坚 dddl.c 单灯点亮程序 *************************************************/ 图 1-1 接有 LED 的单片机基本电路 P1.0 EA/VPP VCC XTAL2 XTAL1 GND RST 5V5V R1 E1 10K 10U CY 27P 27P 1KPZ1 D8 D1 89 include “reg51.h” sbit P1_0P10; void main { P1_10; } 这个程序的作用是让接在 P1.0 引脚上的 LED 点亮。 下面来分析一下这个 C 语言程序包 含了哪些信息。 1) “文件包含”处理。) “文件包含”处理。 程序的第一行是一个“文件包含”处理。 所谓“文件包含”是指一个文件将另外一个文件的内容全部包含进来,所以这里的程序 虽然只有 4 行, 但 C 编译器在处理的时候却要处理几十或几百行。 这里程序中包含 REG51.h 文件的目的是为了要使用 P1 这个符号,即通知 C 编译器,程序中所写的 P1 是指 80C51 单 片机的 P1 端口而不是其它变量。这是如何做到的呢 打开 reg51.h 可以看到这样的一些内容 /*------------------------------------------------------------------------- REG51.H Header file for generic 80C51 and 80C31 microcontroller. Copyright c 1988-2001 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ /* BYTE Register */ sfr P0 0 x80; sfr P1 0 x90; sfr P2 0 xA0; sfr P3 0 xB0; sfr PSW 0 xD0; sfr ACC 0 xE0; sfr B 0 xF0; sfr SP 0 x81; sfr DPL 0 x82; sfr DPH 0 x83; sfr PCON 0 x87; sfr TCON 0 x88; sfr TMOD 0 x89; sfr TL0 0 x8A; sfr TL1 0 x8B; sfr TH0 0 x8C; sfr TH1 0 x8D; sfr IE 0 xA8; sfr IP 0 xB8; sfr SCON 0 x98; sfr SBUF 0 x99; /* BIT Register */ /* PSW */ sbit CY 0 xD7; sbit AC 0 xD6; sbit F0 0 xD5; sbit RS1 0 xD4; sbit RS0 0 xD3; sbit OV 0 xD2; sbit P 0 xD0; /* TCON */ sbit TF1 0 x8F; sbit TR1 0 x8E; sbit TF0 0 x8D; sbit TR0 0 x8C; sbit IE1 0 x8B; sbit IT1 0 x8A; sbit IE0 0 x89; sbit IT0 0 x88; /* IE */ sbit EA 0 xAF; sbit ES 0 xAC; sbit ET1 0 xAB; sbit EX1 0 xAA; sbit ET0 0 xA9; sbit EX0 0 xA8; /* IP */ sbit PS 0 xBC; sbit PT1 0 xBB; sbit PX1 0 xBA; sbit PT0 0 xB9; sbit PX0 0 xB8; /* P3 */ sbit RD 0 xB7; sbit WR 0 xB6; sbit T1 0 xB5; sbit T0 0 xB4; sbit INT1 0 xB3; sbit INT0 0 xB2; sbit TXD 0 xB1; sbit RXD 0 xB0; /* SCON */ sbit SM0 0 x9F; sbit SM1 0 x9E; sbit SM2 0 x9D; sbit REN 0 x9C; sbit TB8 0 x9B; sbit RB8 0 x9A; sbit TI 0 x99; sbit RI 0 x98; 熟悉 80C51 内部结构的读者不难看出,这里都是一些符号的定义,即规定符号名与地 址的对应关系。注意其中有 sfr P1 0 x90; 这样的一行(上文中用黑体表示) ,即定义 P1 与地址 0 x90 对应,P1 口的地址就是 0 x90 (0 x90 是 C 语言中十六进制数的写法,相当于汇编语言中写 90H) 。 从这里还可以看到一个频繁出现的词sfr sfr 并标准 C 语言的关键字,而是 Keil 为能直接访问 80C51 中的 SFR 而提供了一个新 的关键词,其用法是 sfrt 变量名地址值。 2)符号)符号 P1_0 来表示来表示 P1.0 引脚。引脚。 在 C 语言里,如果直接写 P1.0,C 编译器并不能识别,而且 P1.0 也不是一个合法的 C 语言变量名,所以得给它另起一个名字,这里起的名为 P1_0,可是 P1_0 是不是就是 P1.0 呢你这么认为,C 编译器可不这么认为,所以必须给它们建立联系,这里使用了 Keil C 的关键字 sbit 来定义,sbit 的用法有三种 第一种方法sbit 位变量名=地址值 第二种方法sbit 位变量名=SFR 名称变量位地址值 第三种方法sbit 位变量名=SFR 地址值变量位地址值 如定义 PSW 中的 OV 可以用以下三种方法 sbit OV0 xd2 (1)说明0 xd2 是 OV 的位地址值 sbit OVPSW2 (2)说明其中 PSW 必须先用 sfr 定义好 sbit OV0 xD02 (3)说明0 xD0 就是 PSW 的地址值 因此这里用 sfr P1_0P10;就是定义用符号 P1_0 来表示 P1.0 引脚,如果你愿意也可以 起 P10 一类的名字,只要下面程序中也随之更改就行了。 3))main 称为“主函数” 。称为“主函数” 。 每一个 C 语言程序有且只有一个主函数,函数后面一定有一对大括号“{}” ,在大括号 里面书写其它程序。 从上面的分析我们了解了部分 C 语言的特性,下面再看一个稍复杂一点的例子。 例 1-2 让接在 P1.0 引脚上的 LED 闪烁发光 /************************************************* 平凡单片机工作室 Copyright 2003 pingfans mcustudio All rights Reserved 作者周坚 ddss.c 单灯闪烁程序 *************************************************/ include “reg51.h“ define uchar unsigned char define uint unsigned int sbit P10P10; /*延时程序 由 Delay 参数确定延迟时间 */ void mDelayunsigned int Delay { unsigned int i; for;Delay0;Delay-- { fori0;iNew Project”菜单,出现对话框,要求给将要建立的工程起一个名字, 这里起名为 exam2,不需要输入扩展名。点击“保存”按钮,出现第二个对话框,如图 1-2 所示,这个对话框要求选择目标 CPU(即你所用芯片的型号) ,Keil 支持的 CPU 很多,这 里选择 Atmel 公司的 89S52 芯片。 点击 ATMEL 前面的 “” 号, 展开该层, 点击其中的 89S52, 然后再点击“确定”按钮,回到主窗口,此时,在工程窗口的文件页中,出现了“Target 1” , 前面有“”号,点击“”号展开,可以看到下一层的“Source Group1” ,这时的工程还是 一个空的工程,里面什么文件也没有,需要手动把刚才编写好的源程序加入,点击“Source Group1”使其反白显示,然后,点击鼠标右键,出现一个下拉菜单,如图 1-3 所示,选中其 中的“Add file to Group”Source Group1” ,出现一个对话框,要求寻找源文件。 双击 exam2.c 文件,将文件加入项目,注意,在文件加入项目后,该对话框并不消失, 等待继续加入其它文件, 但初学时常会误认为操作没有成功而再次双击同一文件, 这时会出 现如图 1-4 所示的对话框,提示你所选文件已在列表中,此时应点击“确定” ,返回前一对 话框, 然后点击 “Close” 即可返回主接口, 返回后, 点击 “Source Group 1” 前的加号, exam3.c 文件已在其中。双击文件名,即打开该源程序。 1..3 工程的详细设置 工程的详细设置 工程建立好以后,还要对工程进行进一步的设置,以满足要求。 首先点击左边 Project 窗口的 Target 1, 然后使用菜单 “Project-Option for target ‘target1’” 即出现对工程设置的对话框,这个对话框共有 8 个页面,大部份设置项取默认值就行了。 Target 页页 图 1-2 选择单片机型号 图 1-3 加入文件 如图 1-5 所示,Xtal 后面的数值是晶振频率值,默认值是所选目标 CPU 的最高可用频 率值,该值与最终产生的目标代码无关,仅用于软件模拟调试时显示程序执行时间。正确设 置该数值可使显示时间与实际所用时间一致,一般将其设置成与你的硬件所用晶振频率相 同,如果没必要了解程序执行的时间,也可以不设。 Memory Model 用于设置 RAM 使用情况,有三个选择项 Small 所有变量都在单片机的内部 RAM 中; Compact可以使用一页(256 字节)外部扩展 RAM; Larget 可以使用全部外部的扩展 RAM。 Code Model 用于设置 ROM 空间的使用,同样也有三个选择项 Small只用低于 2K 的程序空间; Compact单个函数的代码量不能超过 2K,整个程序可以使用 64K 程序空间; Larget可用全部 64K 空间; 这些选择项必须根据所用硬件来决定,由于本例是单片应用,所以均不重新选择,按默 认值设置。 Operating选择是否使用操作系统,可以选择 Keil 提供了两种操作系统Rtx tiny 和 Rtx full,也可以不用操作系统(None) ,这里使用默认项 None,即不用操作系统。 图 1-5 设置目标 图 1-4 重复加入源程序得到的提示 OutPut 页页 如图 1-6 所示,这里面也有多个选择项,其中 Creat Hex file 用于生成可执行代码文件, 该文件可以用编程器写入单片机芯片,其格式为 intelHEX 格式,文件的扩展名为.HEX,默 认情况下该项未被选中,如果要写片做硬件实验,就必须选中该项。 工程设置对话框中的其它各页面与 C51 编译选项、A51 的汇编选项、BL51 连接器的连 接选项等用法有关,这里均取默认值,不作任何修改。以下仅对一些有关页面中常用的选项 作一个简单介绍。 Listing 页页 该页用于调整生成的列表文件选项。在汇编或编译完成后将产生(*.lst)的列表文件, 在连接完成后也将产生(*.m51)的列表文件,该页用于对列表文件的内容和形式进行细致 的调节,其中比较常用的选项是“C Compile Listing”下的“Assamble Code”项,选中该项 可以在列表文件中生成 C 语言源程序所对应的汇编代码,建议会使用汇编语言的 C 初学者 选中该项,在编译完成后多观察相应的 List 文件,查看 C 源代码与对应汇编代码,对于提 高 C 语言编程能力大有好处。 C51 页页 该页用于对 Keil 的 C51 编译器的编译过程进行控制,其中比较常用的是“Code Optimization”组,如图 1.7 所示,该组中 Level 是优化等级,C51 在对源程序进行编译时, 可以对代码多至 9 级优化,默认使用第 8 级,一般不必修改,如果在编译中出现一些问题, 可以降低优化级别试一试。Emphasis 是选择编译优先方式,第一项是代码量优化(最终生 成的代码量小) ;第二项是速度优先(最终生成的代码速度快) ;第三项是缺省。默认采用速 度优先,可根据需要更改。 图 1-6 设置输出文件 Debug 页页 该页用于设置调试器,Keil 提供了仿真器和一些硬件调试方法,如果没有相应的硬件调 试器,应选择 Use Simulator,其余设置一般不必更改,有关该页的详细情况将在程序调试部 分再详细介绍。 至此,设置完成,下面介绍如何编译、连接程序以获得目标代码,以及如何进行程序的 调试工作。 1..4 编译、连接 编译、连接 下面我们通过一个例子来介绍 C 程序编译、连接的过程。这个例子使 P1 口所接 LED 以流水灯状态显示。 将下面的源程序输入,命名为 exam3.c,并建立名为 exam3 的工程文件,将 exam3.c 文 件加入该工程中,设置工程,在 Target 页将 Xtal 后的值由 24.0 改为 12.0,以便后面调试时 观察延时时间是否正确,本项目中还要用到我们所提供的实验仿真板,为此需在 Debug 页 对 Dialog DLL 对话框作一个设置,在进行项目设置时点击 Debug,打开 Debug 页,可以看 到 Dialog DLL 对话框后的 Parmeter输入框中已有默认值-pAT52,在其后键入空格后再输入 -dledkey,如图 1-8 所示。 例 1-3 使 P1 口所接 LED 以流水灯状态显示 /************************************************** ; 平凡单片机工作室 ; ; Copyright 2003 pingfans McuStudio ; All rights Reserved 图 1-7C51 编译器选项 ;作者周坚 ;lsd.c ;流水灯程序 **************************************************/ include “reg51.h“ include “intrins.h“ define uchar unsigned char define uint unsigned int /*延时程序 由 Delay 参数确定延迟时间 */ void mDelayunsigned int Delay { unsigned int i; for;Delay0;Delay-- { fori0;iBuild target,对当前工程进行 连接,如果当前文件已修改,将先对该文件进行编译,然后再连接以产生目标代码;如果选 择 Rebuild All target files 将会对当前工程中的所有文件重新进行编译然后再连接,确保最终 生产的目标代码是最新的,而 Translate .项则仅对当前文件进行编译,不进行连接。以上 操作也可以通过工具栏按钮直接进行。图 1-9 是有关编译、设置的工具栏按钮,从左到右分 别是编译、编译连接、全部重建、停止编译和对工程进行设置。 编译过程中的信息将出现在输出窗口中的 Build 页中,如果源程序中有语法错误,会有 错误报告出现,双击该行,可以定位到出错的位置,对源程序修改之后再次编译,最终要得 到如图 1-10 所示的结果,提示获得了名为 exam3.hex 的文件,该文件即可被编程器读入并 写到芯片中,同时还可看到,该程序的代码量(code63) ,内部 RAM 的使用量(data9) , 外部 RAM 的使用量(xdata0)等一些信息。除此之外,编译、连接还产生了一些其它相关 的文件,可被用于 Keil 的仿真与调试,到了这一步后即进行调试。 1..5 程序的调试 程序的调试 在对工程成功地进行汇编、 连接以后, 按 CtrlF5 或者使用菜单 Debug-Start/Stop Debug Session 即可进入调试状态,Keil 内建了一个仿真 CPU 用来模拟执行程序,该仿真 CPU 功 能强大,可以在没有硬件和仿真机的情况下进行程序的调试。 进入调试状态后,Debug 菜单项中原来不能用的命令现在已可以使用了,多出一个用于 运行和调试的工具条,如图 1-11 所示,Debug 菜单上的大部份命令可以在此找到对应的快 捷按钮,从左到右依次是复位、运行、暂停、单步、过程单步、执行完当前子程序、运行到 当前行、下一状态、打开跟踪、观察跟踪、反汇编窗口、观察窗口、代码作用范围分析、1 #串行窗口、内存窗口、性能分析、工具按钮等命令。 点击菜单 Peripherals,即会多出一项“键盘 LED 仿真板(K) ” ,选中该项,即会出现如 图 1-9 有关编译、连接、项目设置的工具条 图 1-11 调试工具条 图 1-10 编译、连接后得到目标代码 图 1-12 所示界面。 使用菜单STEP或相应的命令按钮或使用快捷键F11可以单步执行程序, 使用菜单STEP OVER 或功能键 F10 可以以过程单步形式执行命令,所谓过程单步,是指把 C 语言中的一 个函数作为一条语句来全速执行。 按下 F11 键, 可以看到源程序窗口的左边出现了一个黄色调试箭头, 指向源程序的第一 行。每按一次 F11,即执行该箭头所指程序行,然后箭头指向下一行,当箭头指向 “mDelay1000;”行时,再次按下 F11,会发现,箭头指向了延时子程序 mDelay 的第一行。 不断按 F11 键,即可逐步执行延时子程序。 如果 mDelay 程序有错误,可以通过单步执行来查找错误,但是如果 mDelay 程序已正 确,每次进行程序调试都要反复执行这些程序行,会使得调试效率很低,为此可以在调试时 使用 F10 来替代 F11,在 main 函数中执行到 mDelay1000时将该行作为一条语句快速执行 完毕。 Keil 软件还提供了一些窗口, 用以观察一些系统中重要的寄存器或变量的值, 这也是很 重要的调试方法。 以下通过一个对延时程序的延迟时间的调整来对这些调试方法作一个简单的介绍。 这个程序中用到了延时程序 mDelay,如果使用汇编语言编程,每段程序的延迟时间可 以非常精确地计算出来,而使用 C 语言编程,就没有办法事先计算了。为此,可以使用观 察程序执行时间的方法了来解。 进入调试状态后, 窗口左侧是寄存器和一些重要的系统变量 的窗口,其中有一项是 sec,即统计从开始执行到目前为止用去的时间。按 F10,以过程单 步的形式执行程序, 在执行到 mDelay1000这一行之前停下, 查看 sec 的值 (把鼠标停在 sec 后的数值上即可看到完整的数值) ,记下该数值,然后按下 F10,执行完 mDelay1000后再 次观察 sec 值, 如图 1-13 所示, 这里前后两次观察到的值分别是 0.00040400 和 1.01442600, 其差值为 1.014022s,如果将该值改为 124 可获得更接近于 1s 的数值,而当该值取 123 时所 获得的延时值将小于 1s,因此,最佳的取值应该是 124。 图 1-12 51 单片机实验仿真板 1..6 C 语言的一些特点语言的一些特点 通过上述的几个例子,可以得出一些结论 1、C 程序是由函数构成的,一个 C 源程序至少包括一个函数,一个 C 源程序有且只有 一个名为 main的函数,也可能包含其它函数,因此,函数是 C 程序的基本单位。主程序 通过直接书写语句和调用其它函数来实现有关功能,这些其它函数可以是由 C 语言本身提 供给我们的(如例 3 中的_crol_()函数) ,这样的函数称之为库函数,也可以是用户自 己编写的(如例 2、3 中用的 mDelay()函数) ,这样的函数称之为用户自定义函数。那 么库函数和用户自定义函数有什么区别呢简单地说,任何使用 Keil C 语言的人,都可以 直接调用 C 的库函数而不需要为这个函数写任何代码,只需要包含具有该函数说明的相应 的头文件即可;而自定义函数则是完全个性化的,是用户根据自己需要而编写的。Keil C 提 供了 100 多个库函数供我们直接使用。 2、一个函数由两部份组成 (1)函数的首部、即函数的第一行。包括函数名、函数类型、函数属性、函数参数(形 参)名、参数类型。 例如void mDelay unsigned int DelayTime 一个函数名后面必须跟一对圆括号,即便没有任何参数也是如此。 (2)函数体,即函数首部下面的大括号“{}”内的部份。如果一个函数内有多个大括 号,则最外层的一对“{}”为函数体的范围。 函数体一般包括 声明部份在这部份中定义所用到的变量,例 1.2 中 unsigned char j。 执行部份由若干个语句组成。 在某此情况下也可以没有声明部份,甚至即没有声明部份,也没有执行部份,如 void mDelay {} 这是一个空函数,什么也不干,但它是合法的。 在编写程序时, 可以利用空函数, 比如主程序需要调用一个延时函数, 可具体延时多少, 怎么个延时法,暂时还不清楚,我们可以主程序的框架结构弄清,先编译通过,把架子搭起 来再说,至于里面的细节,可以在以后慢慢地填,这时利用空函数,先写这么一个函数,这 样在主程序中就可以调用它了。 3、一个 C 语言程序,总是从 main 函数开始执行的,而不管物理位置上这个 main放 在什么地方。例 1.2 中就是放在了最后,事实上这往往是最常用的一种方式。 图 1-13 观察 sec 确定延时时间 4、主程序中的 mDelay 如果写成 mdelay 就会编译出错,即 C 语言区分大小写,这一点 往往让初学者非常困惑,尤其是学过一门其它语言的人,有人喜欢,有人不喜欢,但不管怎 样,你得遵守这一规定。 5、C 语言书写的格式自由,可以在一行写多个语句,也可以把一个语句写在多行。没 有行号(但可以有标号) ,书写的缩进没有要求。但是建议读者自己按一定的规范来写,可 以给自己带来方便。 6、每个语句和资料定义的最后必须有一个分号,分号是 C 语句的必要组成部份。 7、可以用/*..*/的形式为 C 程序的任何一部份作注释,在“/*”开始后,一直到“*/” 为止的中间的任何内容都被认为是注释, 所以在书写特别是修改源程序时特别要注意, 有时 无意之中删掉一个“*/” ,结果,从这里开始一直要遇到下一个“*/”中的全部内容都被认 为是注释了。原本好好的一个程序,编译已过通过了,稍作修改,一下出现了几十甚至上百 个错误,初学 C 的人往往对此深感头痛,这时就要检查一下,是不是有这样的情况,如果 有的话,赶紧把这个“*/”补上。 特别地特别地,Keil C 也支持 C风格的注释,就是用“//”引导的后面的语句是注释,例 P1_0P1_0; //取反 P1.0 这种风格的注释,只对本行有效,所以不会出现上面的问题,而且书写比较方便,所以 在只需要一行注释的时候,我们往往采用这种格式。但要注意,只有 Keil C 支持这种格式, 早期的 Franklin C 以及 PC 机上用的 TC 都不支持这种格式的注释,用上这种注释,编译时 通不过,会报告编译错误。 第第 2 章 分支程序设计章 分支程序设计 第一部分课程学习了如何建立 Keil C 的编程环境,并了解了一些 C 语言的基础知识, 这一部分将通过一个键控流水灯程序的分析来学习分支程序设计。 2..1 程序功能与实现 程序功能与实现 硬件电路描述如下89S52 单片机的 P1 口接有 8 个 LED,当某一端口输出为“0”时, 相应的 LED 点亮,P3.2、P3.3、P3.4、P3.5 分别接有四个按钮 K1K4,按下按钮时,相应 引脚被接地。现要求编写可键控的流水灯程序,当 K1 按下时,开始流动,K2 按下时停止 流动,全部灯灭,K3 使灯由上往下流动,K4 使灯由下往上流动。 下面首先给出程序,然后再进行分析。 例 2-1键控流水灯的程序 include “reg51.h“ include “intrins.h“ define uchar unsigned char void mDelayunsigned int DelayTime { unsigned int j0; for;DelayTime0;DelayTime-- { forj0;j2 的结果为真,而 3b,abbc, (a3)(b5)等都是合法的关系表达式。关系表达式的值只有两种 可能,即“真”和“假” 。在 C 语言中,没有专门的逻辑型变量,如果运算的结果是“真” , 用数值“1”表示,而运算的结果是“假”则用数值“0”表示。 如式子x132 的结果是 x1 等于 1,原因是 32 的结果是“真” ,即其结果为 1,该结 果被“=”号赋给了 x1,这里须注意, “=”不是等于之意(C 语言中等于用“==”表示) , 而是赋值号,即将该号后面的值赋给该号前面的变量,所以最终结果是 x1 等于 1。 式子x230;DelayTime-- 单片机的 C 语言轻松入门 25 { forj0;j125;j {;} } } 在 main 函数中用 mDelay1000的形式调用该函数时,延时时间约为 1s。如果将该函数 中的 unsigned int j 改为 unsigned char j,其他任何地方都不作更改,重新编译、连接 后,可以发现延迟时间变为约 0.38s。int 和 char 是 C 语言中的两种不同的数据类型,可见 程序中仅改变数据类型就会得到不同的结果。 那么int和char型的数据究竟有什么区别呢 3..3..1 整型数据 整型数据 1.整型数据在内存中的存放形式.整型数据在内存中的存放形式 如果定义了一个 int 型变量 i int i10; /*定义 i 为整型变量,并将 10 赋给该变量*/ 在 Keil C 中规定使用二个字节表示 int 型数据,因此,变量 i 在内存中的实际占用情况 如下 0000,0000,0000,1010 也就是整型数据总是用 2 个字节存放,不足部分用 0 补齐。 事实上,数据是以补码的形式存在的。一个正数的补码和其原码的形式是相同的。如果 数值是负的,补码的形式就不一样了。求负数的补码的方法是将该数的绝对值的二进制形 式取反加 1.例如,-10,第一步取-10 的绝对值 10,其二进制编码是 1010,由于是整型数占 2 个字节(16 位) ,所以其二进制形式实为 0000,0000,0000,1010,取反,即变为 1111, 1111,1111,0101,然后再加 1 变成了 1111,1111,1111,0110,这个就是数-10 在内存中 的存放形式。这里其实只要搞清一点,就是必须补足 16 位,其它的都不难理解。 2.整型变量的分类.整型变量的分类 整型变量的基本类型是 int,可以加上有关数值范围的修饰符。这些修饰符分两类,一 类是 short 和 long,另一类是 unsigned,这两类可以同时使用。下面就来看有关这些修饰符 的内容。 在 int 前加上 short 或 long 是表示数的大小的,对于 keil C 来说,加 short 和不加 short 是一模一样的(在有一些 C 语言编译系统中是不一样的) ,所以,short 就不加讨论了。如果 在 int 前加上 long 的修饰符,那么这个数就被称之为长整数,在 keil C 中,长整数要用4个 字节来存放(基本的 int 型是2个字节) 。显然,长整数所能表达的范围比整数要大,一个 长整数表达的范围可以有 -231x0;DelayTime-- { forj0;j0;DelayTime-- { forj0;j0;DelayTime-- { forj0;j0;DelayTime-- { forj0;j125;j {;} } } void main { unsigned char OutData0 xfe; unsigned char i; while1 { P3|0 x3c; ifP3|0 xfb0 xff //K1 键被按下 { OutData0 xfe; fori0;i8;i { mDelay1000; /*延时 1000 毫秒*/ tmp0 xfe; 单片机的 C 语言轻松入门 33