第8章 C51的预处理命令和

合集下载

C51单片机基础学习教程

C51单片机基础学习教程

C51单片机基础学习教程C51单片机是一种常用的8位单片机,广泛应用于工业控制、家用电器和电子产品等领域。

若想学习C51单片机,首先需要掌握C语言的基础知识。

以下是一个C51单片机基础学习教程,介绍了C语言的相关内容,并给出了一个简单的例子。

一、C语言基础1.数据类型:C语言中主要有整型、字符型、浮点型等数据类型。

可以使用关键字来定义变量并赋值。

示例:int num = 10;char ch = 'A';float f = 3.14;2.运算符:C语言中有算术运算符、逻辑运算符、关系运算符等。

可以用于对变量进行运算和比较。

示例:int a = 10, b = 5;int sum = a + b;int result = (a > b) ? a : b;3.控制语句:C语言中有顺序结构、分支结构和循环结构。

可以用于控制程序的执行流程。

示例:if (num > 0)printf("The number is positive.");} else if (num < 0)printf("The number is negative.");} elseprintf("The number is zero.");4.函数:C语言中可以使用函数将代码模块化,并且可以通过参数和返回值传递数据。

示例:int add(int a, int b)return a + b;二、C51单片机入门2. 创建新项目:在Keil软件中创建一个新的项目,并选择C51单片机作为目标芯片。

3. 编写程序:在新建的项目中打开main.c文件,编写C语言程序。

可以使用C语言的代码编写方式。

示例:#include <reg51.h>//定义LED端口sbit LED = P1^0;void mai//设置LED口为输出LED=0;while (1)//LED闪烁LED=~LED;//延时for (int j = 0; j < 100; j++)}}}5. 调试程序:在Keil软件中打开调试窗口,可以对程序进行单步调试,查看程序的执行流程和变量的值。

C51的基本运算

C51的基本运算

C51的基本运算1)C51的算术和赋值运算(1)算术运算符和算术表达式在C51语言中把用算术运算符和括号将运算对象连接起来的式子称为算术表达式,运算对象包括常量、变量、函数、数组和结构等。

在算术表达式中需要遵守一定的运算优先级,规定先乘(余),后加减,括号优先级最高,同级别从左到右,规律和数学计算相同。

2)赋值运算符和赋值表达式赋值运算符包括普通赋值运算符和复合赋值运算符两种,普通的赋值运算符使用“=”,复合赋值运算符是在普通赋值运算符之前加上其他运算符所构成的赋值符。

使用赋值运算符连接的变量和表达式构成赋值表达式。

赋值运算表达式举例:a=3*z;a+=b;/*等同于a=a+b*赋值运算涉及变量类型的转换,一般分为两种:一种是自动转换,一种是强制转换。

自动转换:不使用强制类型转化符,而是直接将赋值运算符号右边表达式或变量的值类型转化为左边的类型,一般是从“低字节宽度”向“高字节宽度”转换。

量类型相同。

强制类型转化举例double(y);/*将y转化为double类型*/int(x);z=unsigned char(x+y);/*将double类型数据y和int类型数据x相加之后转化为unsigned char类型赋给z/*1)逻辑运算C51语言有3种逻辑运算符。

①逻辑与:&&。

②逻辑或:‖。

③逻辑非:!。

使用逻辑运算符将表达式或变量连接起来的表达式称为逻辑表达式,逻辑运算内部运算次序是先逻辑非后逻辑与和逻辑或,相同等级时从左到右,逻辑表达式的值为“真”或“假”,在C51系统中使用“0”代表“假”,使用“非0”代表逻辑“真”,但是逻辑运算表达式结果只能使用“1”来表示“真”。

逻辑表达式。

若a=3,b=6,则!a=0;/*a=3,为真,则!a为假0*/a&&b=1;a‖b=1;3)关系运算C51语言有6种关系运算,如下所示。

①小于:<。

②大于:>。

③小于等于:≤。

④大于等于:≥。

单片机C51语言及程序设计

单片机C51语言及程序设计
数据类型——被指向变量的数据类型,不能缺省 存储类型1——被指向变量所在的存储区类型,缺省时根据该变量的定义
语句确定 存储类型2——指针变量所在的存储区类型,缺省时根据C51编译模式的
默认值确定 指针变量名——按C51变量名的规则选取
举例说明C51指针定义的用法 (SMALL编译模式下)
例1 char xdata a = ‘A’; char * ptr = &a;
static char m, n; //定义m和n为2个位于data区中的有符号字符型静态变量。
2. C51的指针
标准C语言指针的一般定义形式为: ➢ 定数义据了类一型个*指指向针由变“量数名据;类型”说明的变量的指针变 量; ➢ 被指向变量和指针变量位于C编译器默认的内存区域 中例。如: int a =’A’;
二、C51的标识符与关键字
• 标识符即特定的字符或字符串,用来给变量、函数、符号 常量、自定义类型等命名。用标识符给C语言程序中各种对 象命名时,要用字母、下划线和数字组成的字符序列,并 要求首字符是字母或下划线,不能是数字。字母的大小写 是有区别的。
• 通常下划线开头的标识符是编译系统专用的,因此在编写C 语言源程序时一般不使用以下划线开头的标识符,而将下 划线用作分段符。C51编译器规定标识符最长可达255个字 符,但只有前32个字符在编译时有效,因此标识符的长度 一般不要超过32个字符。
FF00
D5H
D0^4
RRSS11
D4H
D0^3
RRSS00
D3H
D0^2
OOVV
D2H
D0^1
FF11
D1H
D0^0
PP
D0H
两种位地址表达形式:绝对位地址、相对位地址

C51几个预编译指令的用法

C51几个预编译指令的用法

C51几个预编译指令的用法标签:指令用法编译2009-07-31 10:47预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。

可见预处理过程先于编译器对源代码进行处理。

在C语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。

要完成这些工作,就需要使用预处理程序。

尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。

预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。

预处理过程还会删除程序中的注释和多余的空白字符。

预处理指令是以#号开头的代码行。

#号必须是该行除了任何空白字符外的第一个字符。

#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。

整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

下面是部分预处理指令:指令用途#空指令,无任何效果#include包含一个源代码文件#define定义宏#undef取消已定义的宏#if如果给定条件为真,则编译下面代码#ifdef如果宏已经定义,则编译下面代码#ifndef如果宏没有定义,则编译下面代码#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码#endif结束一个#if……#else条件编译块#error停止编译并显示错误信息一、文件包含#include预处理指令的作用是在指令处展开被包含的文件。

包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。

标准C编译器至少支持八重嵌套包含。

预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。

这样就可以在多次包含同一个头文件时,通过给定编译时的条件来达到不同的效果。

例如:#define AAA#include "t.c"#undef AAA#include "t.c"为了避免那些只能包含一次的头文件被多次包含,可以在头文件中用编译时条件来进行控制。

单片机C51语言及程序设计

单片机C51语言及程序设计
1)将SFR的绝对位地址定义为位变量名



C51编译器在头文件“REG51.H”中定义了全部sfr/sfr16和sbit变量。 用一条预处理命令#include <REG51.H>把这个头文件包含到C51程序中,无需重新定义即可直接使用它们的名称。
应用举例:
片内数据存储器,片外数据存储器和程序存储器。
通常下划线开头的标识符是编译系统专用的,因此在编写C语言源程序时一般不使用以下划线开头的标识符,而将下划线用作分段符。C51编译器规定标识符最长可达255个字符,但只有前32个字符在编译时有效,因此标识符的长度一般不要超过32个字符。
关键字是一种已被系统使用过的具有特定含义的标识符。用户不得再用关键字给变量等命名。C语言关键字较少,ANSI C标准一共规定了32个关键字,见表
变量名具有字母大小写的敏感性,如SUM和sum代表不同的变量。
【存储类别】 数据类型 【存储器类型】 变量名
变量名不得使用标准C语言和C51语言的关键字。
unsigned char data system_status = 0;
//定义system_status为无符号字符型自动变量,该变量位于data区中且初值为0。
sfr或sfr16型 51MCU中有21个SFR,如何定义与这些单元相关的变量?
例如,sfr P0 = 0x80; //定义P0口地址80H sfr PCON = 0x87; //定义PCON地址87H sfr16 DPTR=0x82; //定义DPTR的低端地址82H
单精度浮点数
for
程序语句
构成for循环结构
goto
程序语句
构成goto转移结构
if
程序语句

C51程序设计的基本技巧

C51程序设计的基本技巧
图1 TLC1549管脚图
1549的管脚图和时序图分别如图1和图2所示,假定DATA OUT接P1.0,CS 接P1.1,CLOCK接P1.2。
1549的具体特性请查阅有关资料。
图2 TLC1549时序图
例2 C语言程序与汇编语言程序的调用,其子程序如下:
#elif flag = = 0
#define fosc 8M
delay=12;
#else
#define fosc 12M
delay=20;
#endif
main()
{
for(I=0;I
}
这样源程序不作任何修改就可适用于不同时钟频率的单片机系统,并可根据情况的不同取不同的delay值,完成不同的目的。
PUBLIC AD ;入口地址
SEG_AD SEGMENT CODE ;程序段
RSEG SEG_AD
USING 0
AD: MOV R6,#00
MOV R7,#00
SETB P1.1
ACALL DELAY
CLR P1.1
ACALL DELAY
4 结论
C51编译器不但可以缩短单片机控制系统的开发周期,而且易于调试和维护。此外,C51语言还有许多强大的功能,如提供丰富的库函数供用户直接调用,完整的编译控制指令为程序调试提供必要的符号信息等等。总之,C51语言是广大单片机开发人员的强有力的工具
2 C51语言与汇编语言程序的混合编程
C51编译器能对C语言源程序进行高效率的编译,生成高效简洁的代码,在绝大多数场合采用C语言编程即可完成预期的目的。但有时为了编程直观或某些特殊地址的处理,还须采用一定的汇编语言编程。而在另一些场合,出于某种目的,汇编语言也可调用C语言。在这种混合编程中,关键是参数的传递和函数的返回值。它们必须有完整的约定,否则数据的交换就可能出错。下面就以力源公司的10位串行A/D转换器TLC1549 为例说明C语言程序与汇编语言程序的调用。

C51指令代码

C51指令代码

一、ACALL addr11指令名称:绝对挪用指令指令代码:A10 A9 A8 10001 A7 A6 A5 A4 A3 A2 A1 A0指令功能:构造目的地址,进行子程序挪用。

其方式是以指令提供的11位地址(al0~a0),取代PC的低11位,PC的高5位不变。

操作内容:PC←(PC)+2SP←(SP)+1(SP)←(PC)7~0SP←(SP)+1(SP)←(PC)15~8PC10~0←addrl0~0字节数: 2机械周期:2利用说明:由于指令只给出子程序入口地址的低11位,因此挪用范围是2KB。

二、ADD A,Rn指令名称:寄放器加法指令指令代码:28H~2FH指令功能:累加器内容与寄放器内容相加操作内容:A←(A)+(Rn), n=0~7字节数: 1机械周期;1阻碍标志位:C,AC,OV3、ADD A,direct指令名称:直接寻址加法指令指令代码:25H指令功能:累加器内容与内部RAM单元或专用寄放器内容相加操作内容:A←(A)+(direct)字节数: 2机械周期:1阻碍标志位:C,AC,OV4、ADD A,@Ri ’指令名称:间接寻址加法指令指令代码:26H~27H指令功能:累加器内容与内部RAM低128单元内容相加操作内容:A←(A)+((Ri)), i=0,1字节数: 1机械周期:1阻碍标志位:C,AC,OV五、ADD A,#data指令名称:当即数加法指令指令代码:24H指令功能:累加器内容与当即数相加操作内容:A←(A)+data字节数: 2机械周期:1阻碍标志位:C,AC,OV六、ADDC A,Rn指令名称:寄放器带进位加法指令指令代码:38H~3FH指令功能:累加器内容、寄放器内容和进位位相加操作内容:A←(A)+(Rn)+(C), n=0~7字节数: 1机械周期:1阻碍标志位:C,AC,OV7、ADDC A,direct指令名称:直接寻址带进位加法指令指令代码:35H指令功能:累加器内容、内部RAM低128单元或专用寄放器内容与进位位加操作内容:A←(A)+(direct)+(C)字节数: 2机械周期:1阻碍标志位:C,AC,OV八、ADDC A,@Ri指令名称:间接寻址带进位加法指令指令代码:36H~37H指令功能:累加器内容、内部RAM低128单元内容及进位位相加操作内容:A←(A)+((Ri))+(C), i=0,1字节数: 1机械周期:1阻碍标志位:C,AC,OV九、ADDC A,#data指令名称:当即数带进位加法指令指令代码:34H指令功能:累加器内容、当即数及进位位相加操作内容:A←(A)+data+(C)字节数: 2机械周期:1阻碍标志位:C,AC,OV10、AJMP addr11指令名称:绝对转移指令指令代码:A10 A9 A8 1 0 0 0 1 A7 A6 A5 A4 A3 A2 A1 A0指令功能:构造目的地址,实现程序转移。

单片机的C语言程序设计

单片机的C语言程序设计
C51是专门用于MCS51系列单片机的C语言,与电脑上的C语言类似,但针对单片机的特性进行了优化。使用C51进行单片机编程,相较于汇编语言,具有更高的编程效率和更好的可读性。例如,给P1口传送数据54,汇编语言需要复杂的指令,而C51只需简单的赋值操作。同时,C51的“if”语句比汇编语言的条件判断更加直观易懂。虽然C51编好的程序在运行效率上可能不如汇编语言,但其编程效率高、语言简洁、使用方便灵活、表达能力强,且开发资源丰富,应用广泛。此外,C51还有多种版本可供选择,如Franklin C51和Keil C51等,它们都采用ANSI标准的C语言。以Keil C51为例,一个简单的串行口发送程序展示了C51程序的基本结构,包括预处理命令、函数定义和主函数等。通过Keil C51,我们可以方便地初始化串行口,发送数据,实现单片机的各种功能。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


• • • • • • •
{ printf("COUNT =%d\n", COUNT); //输出COUNT =50 #undef COUNT //撤销COUNT宏定义 //printf("COUNT =%d\n", COUNT); //此时再引用COUNT是错误的 }
8.4 条件编译指令
• 在默认情况下,源程序中的所有程序代码都要进 行编译。但是有时需要某些语句行在条件满足的 情况下,才进行编译,此时便用到条件编译指令。 目前商业软件公司广泛应用条件编译来制作某个 程序的不同用户的版本,例如专业版、个人版、 试用版等,从而可以限制软件的某些功能。 • 条件编译指令是指对源程序的代码有选择地进行 编译。采用条件编译,可以提高程序的广泛的适 用性,缩小目标源代码的大小,加快程序执行的 速度。C51的条件编译指令有#if、#else、#ifdef、 #ifndef、#endif这几个命令。下面分别介绍这些 命令的用法。
第8章 C51的预处理命令和用户配置文件
• 用户编写的C51程序代码只能控制程序的执行流程, 若要对编译程序进行操作,就要用到预处理命令。 在编译环境对源程序进行编译前,先对程序中的 预处理命令进行处理,然后将处理结果和源程序 一起进行编译。 • 预处理命令通常只进行一些符号的处理,其并不 执行具体的单片机硬件操作。C51语言中的预处理 命令包括文件包含指令、宏定义指令和条件编译 指令等,还有其他一些指令在程序调试时使用。 本章将详细介绍各种常用的预处理命令的用法, 同时还介绍了C51的用户配置文件相关的内容。
8.1 C51的预处理命令概述
• C51语言中提供了各种预处理命令,其作用类似于汇编程序中的伪指令。一般来说,在对C51源程序 进行编译前,编译器需要先对程序中的预处理命令进行处理,然后将预处理的结果和源代码一并进 行编译,最后产生目标代码。预处理命令通常只进行一些符号的处理,其并不执行具体的硬件操作。 为了与C51源代码中的程序语句相区别,预处理命令前要加一个“#”。C51语言中的预处理命令, 如表所示。
8.4.3 #ifdef、#ifndef命令
• #ifdef与#ifndef命令用于判断宏名是否被定义过, 并根据判断的情况进行条件编译。#ifdef命令的 一般形式是: • #ifdef 宏名 • 语句段; • #else • 语句段; • #endif
8.5 其他编译指令
• • • • • • • • • #line命令用于修改_LINE_与_FILE_的内容。其中“_LINE_”和“_FILE_” 是在编译程序中预先定义的标识符,分别表示行号和源文件。#line命令 主要用于调试及其他一些特殊的应用。使用#line命令的一般形式如下: #line 数字["文件名"] 其中,“数字”为任意正整数,表示源程序中当前语句的行号;“文件名” 为可选的任意有效文件标识符,表示源文件的名字。使用#line命令的程 序示例如下: #include <stdio.h> //头文件 #line 300 //初始化行计数器 void main() //行号300 { //行号301 printf("Line Number=%d\n",__LINE__); //行号302 }
8.4.2 #elif命令
• #elif命令用于进行在多种编译条件下进行选择编译的情况。 其含义与“else if”相同,形成一个阶梯状编译语句。使 用#elif命令的一般形式如下: • #if 表达式0 • 语句段; • #elif 表达式1 • 语句段; • #elif 表达式2 • 语句段; • „ • #elif 表达式n • 语句段; • #endif
C51的预处理命令 用途 预处理命令 #define #error #include 用于宏定义 用于程序调试 用于文件包含

#if
#else #elif #endif #ifdef #ifndef
用于条件编译
用于条件编译 用于多种条件编译选择 用于条件编译 用于条件编译 用于条件编译
#undef
#line #pragma
8.2.1 #include命令
• • • • • • • • • • 在C51语言中,文件包含指令的一般形式如下: #include "头文件.h" #include <头文件.h> #include 宏定义标识符 其中,“#include”表示文件包含指令、双引号或尖括号括起来 的文件名是要引入的源文件。典型的文件包含指令示例如下: #include "myfile.h" //引用自定义文件myfile #include <studio.h> //引用库函数文件studio #include <reg51.h> //引用寄存器文件 define MATH_FILE "C\keil\inc\math1.h" //宏定义自定义文件MATH_FILE #include MATH_FILE //引用自定义文件MATH_FILE
//条件编译 printf("SCORE is defined!\n"); //如果宏SCORE存在,则执行该语句
#ifndef GREED #error "GREED is not defined!\n" GREED存在,则执行该处 #else printf("GREED is defined!\n"); //如果宏GREED不存在,则执行该语句 #endif }
8.5.1 #line命令
• • • • • • • • • • • • • • • • • • • • #else #error "SCORE is not defined!\n" SCORE不存在,则执行该处 #endif //如果宏 #error命令用于强制使编译程序停止编译操作的编译指令,并同时输出错误信息提示。该命令主要用于程序调试。其 使用的一般形式如下: #error “message” 其中,“message”为显示的错误提示的信息。#error命令的程序示例如下: #include <stdio.h> //头文件 #define SCORE 85 //宏定义 void main() { #ifdef SCORE //主函数
//如果宏
8.5.2 #error命令
• #pragma命令用于向编译程序传送各种C51编译器的控制指 令。根据#pragma指令后面的字符串,编译系统将按照特定 的方式来编译C51的字符串和函数。其使用的一般形式如下: • #pragma 字符串 • 其中,#pragma指令后面的字符串,可以大写,也可以小写。 #pragma指令示例如下: • #pragma sfr //在C51中使用SFR • #pragma access //在C51中使用绝对地址 • #pragma asm //在C51中插入汇编语句
8.4.1 #if、#else和#endif命令
• #if、#else和#endif命令是一组常用的条件编译 指令,用于进行条件编译,其一般形式如下: • #if 常量表达式 • 语句段; • #else • 语句段; • #endif • 其中,“#if”、“#else”、“#endif”为条件 编译指令,“常量表达式”为进行条件编译的判 断条件,语句段为进行条件编译的程序代码段。
8.3.2 #undef命令
• • • • • #undef命令用于取消前面用#define命令定义过的宏名。一般形式为: #undef 宏名 其中,“#undef”是取消宏定义指令,“宏名”为前面用#define命令定义过的标识 符。 使用#undef命令的目的是将宏名局限在指定的代码段中,这样可以限制宏定义的使用 范围。使用#undef命令的程序示例如下: #include <stdio.h> //头文件 #define COUNT 50 //宏定义 void main() //主函数
用于宏定义
用于更改行号 用于传送控制指令
8.2 文件包含指令
• 文件包含指令,即#include命令,通常位于C51源 程序的开头,利用#include命令可以将其他的文 件引入当前的C51源文件。其中被包含的文件通常 是头文件、宏定义等。使用文件包含指令,有利 于更好地调试C51源文件。当需要调试修改文件时, 只要修改某一包含文件即可,而无需对所有文件 进行修改。
8.5.3 #ragma命令
• #pragma命令用于向编译程序传送各种C51编译器的控制指 令。根据#pragma指令后面的字符串,编译系统将按照特定 的方式来编译C51的字符串和函数。其使用的一般形式如下: • #pragma 字符串 • 其中,#pragma指令后面的字符串,可以大写,也可以小写。 #pragma指令示例如下: • #pragma sfr //在C51中使用SFR • #pragma access //在C51中使用绝对地址 • #pragma asm //在C51中插入汇编语句
8.6 C51的用户配置文件
• C51的用户配置文件是用来在程序执行前,配置单片机系统 的一些相关设置。在C51中,用户可以根据需要适当修改配 置文件以满足不同的硬件环境需要。这些用户配置文件存 放在Keil\C51\LIB文件夹中。C51编译器在对用户创建的项 目进行编译连接时,会自动将用户配置文件中的代码添加 到用户程序中去。 • 如果用户要对配置文件进行修改,可以通过Keil μ Vision3的项目窗口,先将需要修改的配置文件添加到自 己的项目文件组中,然后在编辑窗口进行修改,最后再进 行总体编译连接,这样就可以将修改后的用户配置文件代 码连接到自己的源程序代码中。 • C51的用户配置文件包括启动代码文件、变量初始化文件、 基本I/O函数文件、分组配置文件几类。下面分别介绍这几 类用户配置文件。
相关文档
最新文档