470 likes | 734 Views
第三章 C51 程序设计 -1. 为什么要用高级语言?. 汇编语言的缺点 : 可读性和可维护性 可移植性 可重用性 C 语言 易于阅读可维护 可移植性好 很好的结构化和模块化 使程序员尽量少地对硬件操作,很多处理器都支持 C 编译器. 差. C51 编译器. Keil C51 德国公司 Keil 推出,是使用最广泛、性能最优的 C51 编译器之一,目前已经成为开发 51 体系单片机最优的选择。 Keil C51 编译器具有代码紧凑高效、工作稳定、使用方便等特点。
E N D
为什么要用高级语言? • 汇编语言的缺点: • 可读性和可维护性 • 可移植性 • 可重用性 • C语言 • 易于阅读可维护 • 可移植性好 • 很好的结构化和模块化 • 使程序员尽量少地对硬件操作,很多处理器都支持C编译器 差
C51编译器 • Keil C51 • 德国公司Keil推出,是使用最广泛、性能最优的C51编译器之一,目前已经成为开发51体系单片机最优的选择。 • Keil C51编译器具有代码紧凑高效、工作稳定、使用方便等特点。 • Keil C51完全支持C的标准指令和许多用来优化8051指令结构的C的扩展指令。
Keil C51 开发工具清单 • Vision2或3项目管理器和编译器:集成开发环境,将项目管理、源代码编辑、连接和程序调试等组合在一个集成环境中。 • C51编译器:从C源代码产生可重定位的目标模块。 • A51编译器:从8051汇编源代码产生目标模块。 • BL51连接器/定位器:组合由C51和A51产生的可重定位的目标模块,生成绝对目标模块。 • LIB51库管理器:从目标模块生成连接器可以使用的库文件。 • HEX转换器:从绝对目标模块生成Intel HEX文件。
Keil C51中的基本数据类型 sbit 1 0或1 sfr 8 0~255 sfr16 16 0~65565
使用缩写形式定义数据类型 • 编程时为了书写方便 • #define uchar unsigned char • #define u16 unsigned int • #define u32 unsigned long • 则后续程序可以用uchar代替 unsigned char, u16代替 unsigned int,定义变量。
存储类型 关键字 寻 址 范 围 备 注 程序存储器 code 0000H~0FFFFH 片内数据存 储 器 data 可直接寻址的片内RAM低128字节, 00H~7FH idata 可间接寻址的片内RAM 256字节, 00H~FFH bdata 片内位寻址RAM16字节, 20H~2FH 外部数据存 储 器 xdata 片外64KB数据存储器,0000H~0FFFFH pdata 分页寻址片外数据存储器,1页(256Bytes) 用于紧凑模式 (Compact Mode) C51数据的存储类型
C51中带存储类型的变量定义 • 格式:数据类型 存储类型 变量名 • code:当使用code存储类型定义数据时,C51编译器会将其定位在程序存储器空间。 • unsigned char code tab[16]={ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; • char code text[ ]=“enter password”; • data:使用data存储类型定义数据时,C51编译器会将其定位在片内存储器空间。 • unsigned char data system_status=0; • unsigned int data unit_id[8]; • char data inp_str[16];
C51中带存储类型的变量定义 • xdata:当使用xdata存储类型定义常量和变量时,C51编译器会将其定位在片外数据存储器空间,该空间的最大寻址范围为64 KB。片外数据存储器主要用于存放不常使用的变量值、较大量的数据。 • pdata:pdata存储类型属于xdata类型,但它可用工作寄存器R0或R1间接分页访问,即对pdata寻址只需要装入8位地址,而对xdata寻址需装入16位地址,因此pdata访问速度较xdata快。 • Include <reg51.h> • unsigend char pdata in_reg1; • unsigned char xdata in_reg2; • void main(void) • { • In_reg1 = P1; • In_reg2 = P2; • }
存储(编译)模式 存储模式决定了没有指定存储类型的变量、函数参数等的缺省存储区域。存储模式在C51编译器选项中选择。 1.Small模式所有缺省变量参数均装入内部RAM,优点是访问速度快,缺点是空间有限,适用于小程序。 2.Compact模式所有缺省变量均位于外部RAM区的一页(256Bytes),具体哪一页可由P2口指定,在STARTUP.A51文件中说明,也可用pdata指定,优点是空间较Small为宽裕速度较Small慢,较large要快,是一种中间状态。 3.Large模式所有缺省变量可放在多达64KB的外部RAM区,优点是空间大,可存变量多,缺点是速度较慢。
C51特殊功能寄存器的定义 • sfr: • 字节寻址。如: sfr P0=0x80; P0口地址为80H,“=”后是80H~FFH之间的常数,不能是表达式。 • sfr16: • 字寻址。如: sfr16 T2=0xCC;指定T2地址, T2L=0xCC T2H=0xCD • 要求低字节和高字节 连续存储,在变量定义中出现的是低字节 • sbit: • 可位寻址的sfr或其他可位寻址对象。 • sfr PSW=0xD0; //定义PSW地址为D0H • sbit OV = PSW^2; //OV位为PSW.2,地址为D2H • sbit CY = PSW^7; //CY位为PSW.7,地址为D7H
C51指针 • C51支持标准C中所有关于指针的操作 • 由于8051及其衍生处理器的独特结构,C51指针分为两种: • 普通指针(Generic Pointer) • 存储器特殊指针(Memory-specific pointer) • 定义方式 • 变量类型 [变量存储类型] * [指针存储类型] 指针变量名 • char data * xdata cp; • cp指向data区的char型数据,而cp指针本身存放在xdata区 • 若没有指定存储类型时,则由编译器在编译时确定
普通指针 • 普通指针的定义和使用均与标准C相同,不同的是还可以说明指针本身的存储类型。 例如:long * state; state为一个指向long型整数的指针,而state本身则依存储模式的规定存放。 • 可以指定指针的存储类别 • char * xdata ptr; ptr为一个指向char数据的指针,而ptr本身放于外部RAM区。 • 以上的两个指针指向的数据可存放于任何存储器中。 • C51使用三个字节保存普通指针:第一个字节用于表明存储器类型,后2个字节分别保存偏移量的高低字节。
指针类型 大小 普通指针 3字节 XDATA指针 2字节 CODE指针 2字节 IDATA指针 1字节 DATA指针 1字节 PDATA指针 1字节 存储器特殊指针 • 存储器特殊指针在说明时即指定了存贮类型,例如:char data * str; str指向data区中char型数据int xdata * pow; pow指向外部RAM的int型整数。 • 这种指针存放时,只需一个字节或2个字节就够了,因为只需存放偏移量。
MOVX • 由于在编译时要访问变量的存储空间已经确定,所以存储器特殊指针变量的访问速度较快,但灵活性较普通指针差。
C51函数 • C51函数声明对ANSI C作了扩展,具体包括: • 说明函数为中断处理子程序 • 选择寄存器组 • 选取存储类型 • 说明函数是否可重入 • 说明为alien(PL/M51)函数
指定函数的存储模式 • C51可由缺省的存储模式决定函数的参数及局部变量的存储位置。 unsigned int RdFromROM(unsigned char Address) • 也可在函数定义时显式地说明函数的存储模式。由small、compact 及large说明,例如:void fun1(void) small { }提示:small说明的函数内部变量全部使用内部RAM。关键的经常性的耗时的地方可以这样声明,以提高运行速度。
C51中的堆栈和函数参数传递 • C51中栈指针只能访问内部RAM,其最大使用范围可达0xFFH。 • C51为每个函数分配一块固定的存储空间存放要传递的参数。在函数调用时,堆栈中只存放函数的返回地址,而参数则通过寄存器或该存储空间来传递。对于中断函数,在堆栈中需保存寄存器组切换的信息及寄存器中的信息,因此需更多的堆栈空间。 • 为提高速度,C51通过寄存器传递函数参数,但最多只能通过寄存器传递三个参数。参数传递规则如下表所示:
CPU 寄存器总是用于函数返回值。下表列出了返回 类型和所用的寄存器。
C51中断处理子程序 • 当中断发生时,C51 编译器提供一个调用C 函数的方法这使用户可以用C 创建中断服务程序。用户只需要关心中断数和选择的寄存器组,编译器自动产生中断向量和进入及退出代码。 • C51的五个标准中断向量为(扩展的中断可达32个)
C51中断处理子程序 • 语法 返回值 函数名([参数]) interrupt m [using n] • Interrupt m用于选择中断号,为常数,不能为表达式,取值范围为0-4(扩展的为0-31) • Using n 选择工作寄存器组,n为工作寄存器组号(0~3)
使用C51应注意的问题 • 采用短变量 • 使用无符号类型 • 使用位变量 • 用局部变量代替全局变量 • 把变量定义成局部变量比全局变量更有效率。编译器为局部变量在内部存储区中分配存储空间,而为全局变量在外部存储区中分配存储空间,这会降低你的访问速度。另一个避免使用全局变量的原因是你必须在你系统的处理过程中调节使用全局变量,因为在中断系统和多任务系统中不止一个过程会使用全局变量。
C51库函数 • 专用寄存器include文件REG51.h • 包括了所有8051的SFR及其位定义,一般系统都必须包括本文件。 • 动态内存分配函数,位于stdlib.h中 • 缓冲区处理函数位于“string.h”中 • 其中包括对字符串和缓冲区进行操作的函数如: • memccpy、memchr、memcmp、memcpy、memmove、memset 这些函数 对缓冲区进行处理很方便。 • 输入输出流函数,位于“stdio.h”中
C51程序举例 (1) “走马灯”电路 设计一个实验电路,在AT89C51并行接口P1连接8个LED,要求这8个LED能循环点亮。电路如图。
“走马灯”电路程序清单 #include"reg51.h” void delay(int t) /*延时函数*/ { int i,j; /*采用默认的存储类型*/ /*用双重空循环延时*/ for(i=0; i<t; i++) for(j=0; j<10; j++); }
“走马灯”电路程序清单(续) void main() /*主函数*/ { char data i,s; while(1) /*无穷循环*/ { s=0xfe; /*设置初值,最低一位为0 */ P1=s; /*P1送据,令接P1.0的LED亮*/ delay(500); for(i=0; i<8; i++) { s = s<<1; /*s值左移一位,最低位补0 */ s = s | 0x01; /*将最低位置1 */ P1= s; /*由P1送出数据,令对应的LED亮*/ delay(500); } } }
中断处理程序设计要点: 1,简练,一般仅在中断服务程序中建立中断标志,而把中断处理过程放在主程序中,根据中断标志决定是否执行。 2,若不够简练(较长),则可能延时甚至丢掉低优先级的中断请求。
uVision2 IDE介绍 C51语言的程序设计之后,需要经过编译、优化、链接等过程,转换成在单片机上能运行的HEX文件,才能固化到程序存储器。 Keil公司的C51编译器是基于Windows环境下的产品,包括汇编器A51、编译器C51、连接器BL51和文件转换器OH51等工具,还有集成编译环境μVision2。用户在此环境下可以完成源程序的编写、编译、连接、仿真调试及项目管理等操作。
一、Keil C51的安装 安装步骤 执行 SETUP 指定的安 装目录 插入Keil C51 安装盘 安装 安装完成后此目录下有两个子目录: UV2 在UV2子目录中,有μVision2可执行文件UV2.EXE。 C51 在C51\BIN子目录中有汇编器A51、编译器C51、连接器BL51和文件转换器OH51等执行文件以及一些存放芯片驱动程序的动态链接库(.DLL); 在C51\INC子目录中,装有编译需要的头文件(*.H); 在C51\LIB子目录中,装有C51的标准函数库.LIB)。
二、C51程序的编写和调试 执行V2子目录中的UV2.EXE,启动μVision2,进入主窗口,用窗口中的文件编辑器编写C51程序,程序格式应遵循C语言的语法规则。 编写完C51程序后,在μVision51环境下就可以进行编译、连接,如果编译连接成功,还可以调用软件仿真器进行调试。
1. 编辑源文件 单击主菜单项【File】->【New】,弹出编辑窗口如图,可以在此窗口中编辑C51程序。
2.建立工程文件 编写好程序,执行主菜单Project】->【New Project】选项,在弹出的窗口中写入工程文件的名称,并加上后綴uv2,如ex1.uv2。 3. 选择目标器件 在Project窗口中的Target1项目上右击,选择【Select Device for Target ‘Target1’】,可弹出选择单片机型号对话框,从对话框中的厂家和单片机列表中选择目标系统所用的单片机型号,本例选择AT89C51,见下图。
4.设置生成Hex代码文件 设置方法:右击Target1,选择【Option for Target ‘Target1’】,选择output,然后在下拉有关output选项菜单中,对Create HEX File可选框中打√。 5.编译 执行主菜单【Project】->【Rebuild All Target Files】就能自动完成编译,生成后綴为obj、hex、m51、lst等文件。hex文件就是我们所需要的目标程序,可以利用编程器写入单片机的片内程序存储器。
6. 调试 μVision2环境可以对程序进行仿真调试,调试器有两种工作模式: Use Simulator工作模式 Use接口驱动工作模式 在右击【Option for Target ‘Target1’】弹出的对话框中选择Use Simulator模式,将调试器配置成纯软件模拟,不需要实际的硬件支持,就可以进行模拟调试。 若选择Use接口驱动模式,则需要在本机与相关硬件接口相连时才能使用。
调试步骤 1)执行主菜单【Debug】->【Start/Stop Debug Session】,进入调试窗口(如图)。同时会弹出反汇编窗口(如图)或执行主菜单【View】-【Disassembly Window】弹出反汇编窗口。在这个窗口里可以应用单步跟踪、设置断点、寄存器观察等手段进行调试。 2)在目标程序的执行过程中,可以利用各种窗口(Regs窗口、Watch窗口、Serial窗口等)观察程序存储器、数据存储器和串口的状态,以检查程序运行是否符合设计要求,可随时修正程序中的错误,优化程序和提高效率。 3)更详细的功能和操作,可查阅Keil C51手册和有关书籍。
Keil C实际应用演示 • 建立一个简单的project