1、第三章第三章 单片机的单片机的 C C语言程序设计及调试语言程序设计及调试C C语言编程语言编程特点:编写简单、直观易读、便于维护、通用性好、可移特点:编写简单、直观易读、便于维护、通用性好、可移植性强、更符合人们的思考习惯植性强、更符合人们的思考习惯但同学们一定会有这样的疑问,我们学过了C语言,该如何用它操作单片机呢?不要着急,接下来,让我们一起学习不要着急,接下来,让我们一起学习单片机的单片机的C C语言程序语言程序设计与调试设计与调试。限于篇幅,本章不介绍标准限于篇幅,本章不介绍标准C C语言的语句及语法规则,只语言的语句及语法规则,只介绍介绍C C语言在语言在IAP15W4K58S4I
2、AP15W4K58S4单片机程序设计中的单片机程序设计中的特殊性问特殊性问题题,包括,包括C51C51编程语言编程语言(简称(简称C51C51)与与ANSI CANSI C的区别的区别、单片单片机机C C语言程序的设计语言程序的设计等内容。等内容。关系运算符关系运算符关系运算符用于关系运算符用于比较两个常数或者表达式的大小比较两个常数或者表达式的大小。关系运。关系运算的结果算的结果只能是只能是0 0或或1 1。关系运算符的值为真时,结果值为。关系运算符的值为真时,结果值为1 1;关系运算符的值为假时,结果值为;关系运算符的值为假时,结果值为0 0。 = = != = = !=特别注意,判断两个
3、常数或者表达式相等时,使用特别注意,判断两个常数或者表达式相等时,使用“=”,不要使用单个的不要使用单个的“= =”。否则,。否则,判断两个数是否相等判断两个数是否相等就变就变成了成了赋值语句赋值语句。逻辑运算符逻辑运算符逻辑运算符包括逻辑运算符包括与(与(&)、或()、或(|)、非()、非(! !)三种,用三种,用于对包含关系运算符的表达式进行合并或取非。于对包含关系运算符的表达式进行合并或取非。使用逻辑运算符的表达式,使用逻辑运算符的表达式,返回返回0 0表示表示“假假”,返回,返回1 1表示表示“真真”。位运算符位运算符按位与(按位与(& &)、按位或()、按位或(| |)、按位异或()
4、、按位异或( )、取反()、取反( )、)、左移(左移()应用:应用:按位与按位与运算通常用来对某些运算通常用来对某些位清位清0 0按位或按位或运算通常用来对某些运算通常用来对某些位置位置1 1按位异或按位异或运算通常用来对某些运算通常用来对某些位取反位取反预处理预处理- -宏定义宏定义(define)(define)在语言源程序中允许用一个标识符来表示一个字符串,在语言源程序中允许用一个标识符来表示一个字符串,称为宏。称为宏。无参无参宏定义的一般形式如下:宏定义的一般形式如下:#define #define 标识符标识符 字符串字符串带参带参宏定义的一般形式如下:宏定义的一般形式如下:#de
5、fine #define 宏名宏名( (形参表形参表) ) 字符串字符串如要终止宏定义,可使用如要终止宏定义,可使用# undef# undef命令。命令。预处理预处理- -文件包含(文件包含(includeinclude)文件包含的一般形式如下:文件包含的一般形式如下:#include #include 文件名文件名 你知道吗?包含命令中的文件名可以用双引号括起来,也可以用尖括号包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。括起来。两者有何不同呢?两者有何不同呢?#include math.h#include math.h#include #include 预处理预处理- -条
6、件编译(条件编译(1 1)条件编译就是条件编译就是按不同的条件去编译不同的程序部分按不同的条件去编译不同的程序部分,从而,从而产生不同的目标代码文件。产生不同的目标代码文件。1 1)第一种形式)第一种形式#ifdef #ifdef 标识符标识符 程序段程序段1 1#else #else 程序段程序段2 2#endif #endif 预处理预处理- -条件编译(条件编译(2 2)2 2)第二种形式)第二种形式#ifndef #ifndef 标识符标识符 程序段程序段1 1#else#else 程序段程序段2 2#endif#endif预处理预处理- -条件编译(条件编译(3 3)3 3)第二种形
7、式)第二种形式#if #if 常量表达式常量表达式 程序段程序段1 1#else#else 程序段程序段2 2#endif#endifKeil C51Keil C51扩展关键字扩展关键字C51C51有以下有以下1919个扩展关键字:个扩展关键字:_at_at_、sbitsbit、sfrsfr、bitbit、sfr16sfr16、idataidata、bdatabdata、xdataxdata、pdatapdata、datadata、codecode、alienalien、smallsmall、compactcompact、largelarge、usingusing、reentrantreent
8、rant、interruptinterrupt、_task_task_常见的关键字常见的关键字- -内存区域的指定内存区域的指定1 1)程序存储器)程序存储器codecode:程序存储区。可以使用程序存储区。可以使用codecode定义表格常数定义表格常数2 2)内部)内部RAMRAMdatadata:直接寻址区,内部直接寻址区,内部RAMRAM的低的低128128字节,地址字节,地址范围为范围为00H00H7FH7FHidataidata:间接寻址区,包括整个内部间接寻址区,包括整个内部RAMRAM区区256256字字节,地址范围为节,地址范围为00H00H0FFH0FFHbdatabdat
9、a:可位寻址区,地址范围为可位寻址区,地址范围为20H20H2FH2FH常见的关键字常见的关键字- -内存区域的指定内存区域的指定3 3)外部数据存储器)外部数据存储器xdataxdata:可指定多达可指定多达64KB64KB的外部直接寻址区,地的外部直接寻址区,地址范围址范围0000H0000H0FFFFH0FFFFH4 4)特殊功能寄存器()特殊功能寄存器(SFRSFR)sfrsfr:字节寻址字节寻址 sfr sfr_name=int_constant;sfr sfr_name=int_constant;sfr16sfr16:字寻址字寻址 sfr16 DPTR=0 x82;sfr16 DP
10、TR=0 x82;sbitsbit:位寻址:位寻址 sbit bitname=sfr_namebit_number;sbit bitname=sfr_namebit_number;常见的关键字常见的关键字- -变量或数据类型变量或数据类型C51C51提供以下几种扩展数据类型:提供以下几种扩展数据类型:bitbit:位变量,值为位变量,值为0 0或或1 1sbitsbit:从字节中定义的位变量(从字节中定义的位变量(0 0或或1 1)sfrsfr:sfrsfr字节地址(字节地址(0 x800 x800 xff0 xff)sfr16sfr16:sfrsfr字地址(字地址(0 x800 x800 x
11、ff0 xff,其实是占用两,其实是占用两个连续的地址)个连续的地址)其余的数据类型如其余的数据类型如charchar、enumenum、shortshort、intint、longlong、float float 等与等与ANSI CANSI C相同相同常见的关键字常见的关键字-Keil C51-Keil C51指针指针Keil C51Keil C51支持一般指针(支持一般指针(Generic PointerGeneric Pointer)和存储器指针)和存储器指针(Memory Specific PointerMemory Specific Pointer)。一般指针的声明和使用均)。一般
12、指针的声明和使用均与标准与标准C C相同,同时还可以说明指针的存储类型。相同,同时还可以说明指针的存储类型。例如:例如:unsigned char xdata unsigned char xdata * *pt;pt; /pt/pt本身依存储模式存放本身依存储模式存放unsigned char xdata unsigned char xdata * * data pt; data pt;/pt/pt被保存在内部被保存在内部RAMRAM中中unsigned char xdata unsigned char xdata * * xdata pt; xdata pt; /pt/pt被保存在外部被保存
13、在外部RAMRAM中中常见的关键字常见的关键字-Keil C51-Keil C51指针指针除了和标准除了和标准C C语言一样使用指针外,指针还可以用来访问外语言一样使用指针外,指针还可以用来访问外部并行扩展的器件。部并行扩展的器件。例如:例如:为了方便地访问外部存储器及为了方便地访问外部存储器及I/OI/O端口,在端口,在C51C51中的中的absacc.habsacc.h头文件做了如下定义,利用这些定义可以方便地访头文件做了如下定义,利用这些定义可以方便地访问外部问外部I/OI/O端口。端口。#define CBYTE (unsigned char volatile code #define
14、 CBYTE (unsigned char volatile code * *) 0) 0)#define DBYTE (unsigned char volatile data #define DBYTE (unsigned char volatile data * *) 0) 0)#define PBYTE (unsigned char volatile pdata #define PBYTE (unsigned char volatile pdata * *) 0) 0)#define XBYTE (unsigned char volatile xdata #define XBYTE (u
15、nsigned char volatile xdata * *) 0) 0)Keil C51Keil C51函数函数- -中断函数声明中断函数声明中断函数通过使用中断函数通过使用interruptinterrupt关键字和关键字和中断号中断号(0 03131)来)来声明。声明。中 断 号 告 诉 编 译 器 中 断 服 务 程 序 的中 断 号 告 诉 编 译 器 中 断 服 务 程 序 的 入 口 地 址入 口 地 址 。IAP15W4K58S4IAP15W4K58S4单片机的中断号及中断服务程序入口地址见单片机的中断号及中断服务程序入口地址见教材教材5858页表页表3-33-3。中断函数具
16、体是哪个中断的函数,中断函数具体是哪个中断的函数,与中断号有关,而与函与中断号有关,而与函数名无关数名无关。Keil C51Keil C51函数函数- -中断函数声明中断函数声明例如:例如:串行口串行口1 1的中断函数可以声明如下的中断函数可以声明如下void UART1_ISR (void) interrupt 4 using 1void UART1_ISR (void) interrupt 4 using 1 / /* * 中断服务程序的代码中断服务程序的代码 * */ / 【例 3-1】 编程实现通过延时函数,由编程实现通过延时函数,由P2.0P2.0输出方波信号,输出方波信号,并通过示
17、波器观察程序输出波形的周期。并通过示波器观察程序输出波形的周期。#include #include “stc15.hstc15.h” sbit P20=P20;sbit P20=P20;/定义定义P2.0P2.0引脚引脚void delay(unsigned long cnt);void delay(unsigned long cnt);/延时函数声明延时函数声明void main(void) void main(void) P2M1=0; P2M1=0; P2M0=0; P2M0=0;/将整个将整个P2P2口所有口线设置为准双向口模式口所有口线设置为准双向口模式P20=1;P20=1;【例
18、3-1】 while(1) while(1) /主程序循环主程序循环 delay(60000); delay(60000); P20=P20; P20=P20; void delay(unsigned long cnt)void delay(unsigned long cnt) / /延时函数延时函数 while(cnt0) cnt-; while(cnt0) cnt-; IAP15W4K58S4 IAP15W4K58S4单片机单片机C C语言程序调试语言程序调试编写好程序代码并编译成功编写好程序代码并编译成功(没有错误和警告)后,可以(没有错误和警告)后,可以使用集成开发环境(使用集成开发环境(IDEIDE)对单片机程序进行)对单片机程序进行调试调试。调试的方法分为两种,一种是使用开发环境本身提供的调试的方法分为两种,一种是使用开发环境本身提供的软软件模拟仿真器件模拟仿真器调试;另一种是使用调试;另一种是使用仿真器仿真仿真器仿真调试。调试。