,单片微机原理及应用,教学课件第六讲,C-51程序设计本讲重点:
C-51的数据类型和存储类型;
指针和中断的使用;
通过实例消化理解 C-51的编程方法;
尝试将实验课中的 ASM-51程序转为 C-51程序,
,单片微机原理及应用,教学课件
C语言作为一种非常方便的语言而得到广泛的支持,
C语言程序本身不依赖于机器硬件系统,基本上不作修改就可将程序从不同的单片机中移植过来。
C提供了很多数学函数并支持浮点运算,开发效率高,故可缩短开发时间,增加程序可读性和可维护性。
㈠ C-51简介
,单片微机原理及应用,教学课件
C-51与 ASM-51相比,有如下优点:
1,对单片机的指令系统不要求了解,仅要求对
8051 的存贮器结构有初步了解;
2,寄存器分配、不同存贮器的寻址及数据类型等细节可由编译器管理;
3,程序有规范的结构,可分成不同的函数,这种方式可使程序结构化;
4,具有将可变的选择与特殊操作组合在一起的能力,改善了程序的可读性;
5,提供的库包含许多标准子程序,具有较强的数据处理能力;
6,由于具有方便的模块化编程技术,使已编好程序可容量地植入新程序;
,单片微机原理及应用,教学课件
㈢ C- 51的数据类型常用的数据类型有:
㈡ C- 51的程序结构与一般 C语言的结构相同,以 main()函数为程序人口,程序体中包含若干语句还可以包含若干函数。
位型 字符型 整型 长整型 浮点型
bit char int long int float
1位 1字节 2字节 4字节 4字节数组型 指针型
,单片微机原理及应用,教学课件
㈣ C-51数据的存储类型名 存储空间位置 长度 数据范围
data 直接寻址片内 RAM 8位 0~ 255
bdata 可位寻址片内 RAM 1位 0/1
idata 间接寻址片内 RAM 8位 0~ 255
xdata 片外 RAM 16位 0~ 65535
㈤ C-51的包含的头文件通常有,reg51.h math.h ctype.h stdio.h stdlib.h absacc.h
常用有,reg51.h (定义特殊功能寄存器和位寄存器);
math.h (定义常用数学运算);
,单片微机原理及应用,教学课件
㈥ C-51的运算符与 C语言基本相同:
+ - * / (加 减 乘 除)
> >= < <= (大于 大于等于 小于 小于等于)
== != (测试等于 测试不等于)
&& || ! (逻辑与 逻辑或 逻辑非 )
>> << (位右移 位左移)
& | (按位与 按位或 )
^ ~ (按位异或 按位取反 )
,单片微机原理及应用,教学课件
㈦ C-51的基本语句与标准 C语言基本相同:
if 选择语言
switch/case 多分支选择语言
while 循环语言
do-while 循环语言
for 循环语言
,单片微机原理及应用,教学课件
㈧ 实例
ORG 0000H
MOV R0,#0DCH ;指向字形口
MOV A,#80H ;确定字形代码
MOVX @R0,A ;输出字形代码
MOV R1,#0DDH ;指向字位口
MOV A,#20H ;从最高位开始
LEDO:
MOVX @R1,A ;输出字位代码
MOV R2,#18H ;确定延时常数
ACALL DEYS ;调延时子程序
RL A ;右移一位
SJMP LEDO ;循环演示; 延时子程序
DEYS,PUSH 02H
DEY0,PUSH 02H
DEY1,PUSH 02H
DJNZ R2,$
POP 02H
DJNZ R2,DEY1
POP 02H
DJNZ R2,DEY0
POP 02H
DJNZ R2,DEYS
RET
END
例 1.“8”字符循环演示 (字形口为 DCH; 字位口为 DDH)
★ 汇编语言程序
,单片微机原理及应用,教学课件
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
/* 字形口 */
#define PORTA XBYTE[0xffdc]
/* 字位口 */
#define PORTB XBYTE[0xffdd]
/* 延时 1MS子程序 */
void msce(unsigned int x)
{ unsigned char j;
while((x--)!=0)
{for(j=0;j<60;j++); }
}
main( )
{ uchar rr,i;
for(;;)
{ rr=0x01;/* 从最右一位开始 */
for(i=0;i<6;i++) {
PORTA =0x80;/*输出字形代码 */
PORTB =rr; /*输出字位代码 */
msce(150); /*调延时子程序 */
rr=rr<<1; /*循环左移一位 */
}
}
★,8”字符循环演示 的 C- 51程序
,单片微机原理及应用,教学课件
★ C- 51程序
#include <reg51.h>
main( )
{ int i;
unsigned char xdata *p=0x2000; /* 指针指向 2000H单元 */
for(i=0;i<256;i++) /*清零 2000H-20FFH单元 */
{*p=0; p++;}
}
例 2.清零程序 (将 2000H—20FFH的内容清零 )
★ 汇编语言程序
ORG 0000H
SE01,MOV R0,#00H
MOV DPTR,#2000H ;(0000H)送 DPTR
LOO1,CLR A
MOVX @DPTR,A ;0送 (DPTR)
INC DPTR ;DPTR+1
INC R0 ;字节数加 1
CJNE R0,#00H,LOO1 ;不到 FF个字节再清
LOOP,SJMP LOOP
,单片微机原理及应用,教学课件例 3.拆字程序
(将 2000H的内容拆开,高位送 2001H低位,低位送 2002H低位)
★ 汇编语言程序
ORG 0000H
SE02,MOV DPTR,#2000H
MOVX A,@DPTR
MOV B,A ;(2000)→A→B
SWAP A ;交换
ANL A,#0FH ;屏敝高位
INC DPTR
MOVX @DPTR,A ;送 2001H
INC DPTR
MOV A,B
ANL A,#0FH ;(2000)内容屏敝高位
MOVX @DPTR,A ;送 2002H
SJMP $
,单片微机原理及应用,教学课件
★ 拆字 C- 51程序
#include <reg51.h>
main( )
{unsigned char xdata *p=0x2000;/*指针指向 2000H单元 */
/* 2002H单元高 4位清零,低 4位装 2000H单元低 4位 */
*(p+2)=(*p)&0x0f;
/* 2001H单元高 4位清零,低 4位装 2000H单元高 4位 */
*(p+1)=(*p)>>4;
}
,单片微机原理及应用,教学课件
★ 汇编语言程序
ORG 0000H
L00,MOV R0,#10H ;查找 16个字节
MOV R1,#00H
MOV DPTR,#2000H
L11,MOVX A,@DPTR
CJNE A,#00H,L16 ;取出内容与 00H相等吗?
INC R1 ;取出个数加 1
L16,INC DPTR
DJNZ R0,L11 ;未完继续
MOV DPTR,#2100H
MOV A,R1
MOVX @DPTR,A ;相同数个数送 2100H
L1E,SJMP L1E
例 4.查找零的个数 (在 2000H--200FH中查出有几个字 节是零,把个数放在 2100H单元中)
,单片微机原理及应用,教学课件
★ 查找零的个数 C- 51程序
#include <reg51.h>
main ( )
{ unsigned char xdata *p=0x2000;/*指针 p指向 2000H单元 */
int n=0,i;
for(i=0;i<16;i++)
{ if(*p==0) n++; /* 若该单元内容为零,则 n+1 */
p++; /* 指针指向下一单元 */
}
p=0x2100; /* 指针 p指向 2100H单元 */
*p=n; /* 把个数放在 2100H单元中 */
}
,单片微机原理及应用,教学课件
★ 汇编程序
ORG 0000H
MOV A,R3
MOV B,R7
MUL AB ;R3*R7
XCH A,R7 ;R7=(R3*R7)低字节
MOV R5,B ;R5=(R3*R7)高字节
MOV B,R2
MUL AB ;R2*R7
ADD A,R5
MOV R4,A
CLR A
ADDC A,B
MOV R5,A ;R5=(R2*R7)高字节
MOV A,R6
MOV B,R3
MUL AB ;R3*R6
ADD A,R4
XCH A,B
ADDC A,R5
MOV R5,A
MOV PSW.5,C ;存 CY
MOV A,R2
MUL AB ;R2*R6
ADD A,R5
MOV R5,A
CLR A
MOV ACC.0,C
MOV C,PSW.5 ;加上次加法的位
ADDC A,B
MOV R4,A
JMP $
例 5.双字节无符号整数快速乘法
,单片微机原理及应用,教学课件
★ C- 51程序
#include <reg51.h>
main( )
{unsigned int xdata *p1=0x2000;/*双字节被乘数在 2000H单元 */
unsigned int xdata *p2=0x2002;/*双字节乘数在 2002H单元 */
unsigned long xdata *p3=0x2010;/*4字节乘积放在 2010H单元 */
*p3=(*p1)*(*p2);
}
,单片微机原理及应用,教学课件例 6.工业顺序控制 C-51程序
#include <reg51.h>
sbit P1_7=0x97; /* 定义 P1.7口地址 */
unsigned char TT;
void Delay(unsigned int value) /* 延时子程序 */
{ while(value!=0) value--; }
void Serint1()interrupt 2 /*中断服务程序 --暂停并报警 */
{ int i;
TT=P1; /* 保护现场 */
P1=0x7f; /* 关输出 */
while(!INT1) /* 若故障未消除,则报警 */
{ for(i=0;i<0xa0;i++) /* 给蜂鸣器发震荡脉冲 */
{ P1_7=1;Delay(50); P1_7=0;Delay(50);}
P1_7=0;Delay(6550);
}
P1=TT; /*恢复现场 */
}
,单片微机原理及应用,教学课件
main ( )
{ IE=0x84; /* CPU开中断,INT1开中断 */
while(T0==0); /* 等待 P3.4变高 */
for(;;)
{ P1=0xfe; Delay(60000); /* 工序 1 */
P1=0xfd; Delay(60000); /* 工序 2 */
P1=0xfb; Delay(60000); /* 工序 3 */
P1=0xf7; Delay(60000); /* 工序 4 */
P1=0xef; Delay(60000); /* 工序 5 */
P1=0xdf; Delay(60000); /* 工序 6 */
P1=0x8f; Delay(60000); /* 工序 7 */
}
}
(续前)
,单片微机原理及应用,教学课件例 7.电脑时钟
( 用定时器产生 0.1秒定时中断,对时钟计数器计数并送数码管显示)
★ C- 51程序
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
#define LEDwp XBYTE[0xffdc]
#define LEDwb XBYTE[0xffdd]
uchar code
table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar hour=1,min=23,sec=45,m=0,n,i; /* 给时钟赋初值 */
uchar xdata *p;
void Delay(unsigned int value) /*延时子程序 */
{while(value!=0) value--;}
,单片微机原理及应用,教学课件
void Trans(void) /*时间数据转换子程序 */
{ if(sec==60) {min++;sec=0; }
if(min==60) {hour++;min=0;}
if(hour==24) {hour=0; }
*(p+0)=hour/10; /* 时的十分位 */
*(p+1)=hour%10; /* 时的个位 */
*(p+2)=min/10; /* 分的十分位 */
*(p+3)=min%10; /* 分的个位 */
*(p+4)=sec/10; /* 秒的十分位 */
*(p+5)=sec%10; /* 秒的个位 */
}
void Show(void) /*循环显示子程序 */
{ for(;;)
{ Trans( );
LEDwb=n=0x20;
for(i=0;i<6;i++)
{ LEDwp=table[*(p+i)];LEDwb=n;Delay(100); n=n>>1; }
}
}
,单片微机原理及应用,教学课件
/* 中断服务子程序( 0.1秒中断一次) */
void time() interrupt 1
{ m++;
TH0=0x3c; TL0=0xb7; /* 给 T0 赋计数初值 */
if(m==10) { sec=sec+1; m=0; }
}
main( )
{ p=0x2000;
TMOD=0X01; /* T/C0工作在定时器方式 1 */
TH0=0x3c;
TL0=0xb7; /* 给 T0 赋计数初值 */
EA=1; /* CPU开中断 */
TR0=1; /* 启动 T/C0开始定时 */
ET0=1; /* T/C0开中断 */
Show( );
}
,单片微机原理及应用,教学课件
OVER !
C-51的数据类型和存储类型;
指针和中断的使用;
通过实例消化理解 C-51的编程方法;
尝试将实验课中的 ASM-51程序转为 C-51程序,
,单片微机原理及应用,教学课件
C语言作为一种非常方便的语言而得到广泛的支持,
C语言程序本身不依赖于机器硬件系统,基本上不作修改就可将程序从不同的单片机中移植过来。
C提供了很多数学函数并支持浮点运算,开发效率高,故可缩短开发时间,增加程序可读性和可维护性。
㈠ C-51简介
,单片微机原理及应用,教学课件
C-51与 ASM-51相比,有如下优点:
1,对单片机的指令系统不要求了解,仅要求对
8051 的存贮器结构有初步了解;
2,寄存器分配、不同存贮器的寻址及数据类型等细节可由编译器管理;
3,程序有规范的结构,可分成不同的函数,这种方式可使程序结构化;
4,具有将可变的选择与特殊操作组合在一起的能力,改善了程序的可读性;
5,提供的库包含许多标准子程序,具有较强的数据处理能力;
6,由于具有方便的模块化编程技术,使已编好程序可容量地植入新程序;
,单片微机原理及应用,教学课件
㈢ C- 51的数据类型常用的数据类型有:
㈡ C- 51的程序结构与一般 C语言的结构相同,以 main()函数为程序人口,程序体中包含若干语句还可以包含若干函数。
位型 字符型 整型 长整型 浮点型
bit char int long int float
1位 1字节 2字节 4字节 4字节数组型 指针型
,单片微机原理及应用,教学课件
㈣ C-51数据的存储类型名 存储空间位置 长度 数据范围
data 直接寻址片内 RAM 8位 0~ 255
bdata 可位寻址片内 RAM 1位 0/1
idata 间接寻址片内 RAM 8位 0~ 255
xdata 片外 RAM 16位 0~ 65535
㈤ C-51的包含的头文件通常有,reg51.h math.h ctype.h stdio.h stdlib.h absacc.h
常用有,reg51.h (定义特殊功能寄存器和位寄存器);
math.h (定义常用数学运算);
,单片微机原理及应用,教学课件
㈥ C-51的运算符与 C语言基本相同:
+ - * / (加 减 乘 除)
> >= < <= (大于 大于等于 小于 小于等于)
== != (测试等于 测试不等于)
&& || ! (逻辑与 逻辑或 逻辑非 )
>> << (位右移 位左移)
& | (按位与 按位或 )
^ ~ (按位异或 按位取反 )
,单片微机原理及应用,教学课件
㈦ C-51的基本语句与标准 C语言基本相同:
if 选择语言
switch/case 多分支选择语言
while 循环语言
do-while 循环语言
for 循环语言
,单片微机原理及应用,教学课件
㈧ 实例
ORG 0000H
MOV R0,#0DCH ;指向字形口
MOV A,#80H ;确定字形代码
MOVX @R0,A ;输出字形代码
MOV R1,#0DDH ;指向字位口
MOV A,#20H ;从最高位开始
LEDO:
MOVX @R1,A ;输出字位代码
MOV R2,#18H ;确定延时常数
ACALL DEYS ;调延时子程序
RL A ;右移一位
SJMP LEDO ;循环演示; 延时子程序
DEYS,PUSH 02H
DEY0,PUSH 02H
DEY1,PUSH 02H
DJNZ R2,$
POP 02H
DJNZ R2,DEY1
POP 02H
DJNZ R2,DEY0
POP 02H
DJNZ R2,DEYS
RET
END
例 1.“8”字符循环演示 (字形口为 DCH; 字位口为 DDH)
★ 汇编语言程序
,单片微机原理及应用,教学课件
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
/* 字形口 */
#define PORTA XBYTE[0xffdc]
/* 字位口 */
#define PORTB XBYTE[0xffdd]
/* 延时 1MS子程序 */
void msce(unsigned int x)
{ unsigned char j;
while((x--)!=0)
{for(j=0;j<60;j++); }
}
main( )
{ uchar rr,i;
for(;;)
{ rr=0x01;/* 从最右一位开始 */
for(i=0;i<6;i++) {
PORTA =0x80;/*输出字形代码 */
PORTB =rr; /*输出字位代码 */
msce(150); /*调延时子程序 */
rr=rr<<1; /*循环左移一位 */
}
}
★,8”字符循环演示 的 C- 51程序
,单片微机原理及应用,教学课件
★ C- 51程序
#include <reg51.h>
main( )
{ int i;
unsigned char xdata *p=0x2000; /* 指针指向 2000H单元 */
for(i=0;i<256;i++) /*清零 2000H-20FFH单元 */
{*p=0; p++;}
}
例 2.清零程序 (将 2000H—20FFH的内容清零 )
★ 汇编语言程序
ORG 0000H
SE01,MOV R0,#00H
MOV DPTR,#2000H ;(0000H)送 DPTR
LOO1,CLR A
MOVX @DPTR,A ;0送 (DPTR)
INC DPTR ;DPTR+1
INC R0 ;字节数加 1
CJNE R0,#00H,LOO1 ;不到 FF个字节再清
LOOP,SJMP LOOP
,单片微机原理及应用,教学课件例 3.拆字程序
(将 2000H的内容拆开,高位送 2001H低位,低位送 2002H低位)
★ 汇编语言程序
ORG 0000H
SE02,MOV DPTR,#2000H
MOVX A,@DPTR
MOV B,A ;(2000)→A→B
SWAP A ;交换
ANL A,#0FH ;屏敝高位
INC DPTR
MOVX @DPTR,A ;送 2001H
INC DPTR
MOV A,B
ANL A,#0FH ;(2000)内容屏敝高位
MOVX @DPTR,A ;送 2002H
SJMP $
,单片微机原理及应用,教学课件
★ 拆字 C- 51程序
#include <reg51.h>
main( )
{unsigned char xdata *p=0x2000;/*指针指向 2000H单元 */
/* 2002H单元高 4位清零,低 4位装 2000H单元低 4位 */
*(p+2)=(*p)&0x0f;
/* 2001H单元高 4位清零,低 4位装 2000H单元高 4位 */
*(p+1)=(*p)>>4;
}
,单片微机原理及应用,教学课件
★ 汇编语言程序
ORG 0000H
L00,MOV R0,#10H ;查找 16个字节
MOV R1,#00H
MOV DPTR,#2000H
L11,MOVX A,@DPTR
CJNE A,#00H,L16 ;取出内容与 00H相等吗?
INC R1 ;取出个数加 1
L16,INC DPTR
DJNZ R0,L11 ;未完继续
MOV DPTR,#2100H
MOV A,R1
MOVX @DPTR,A ;相同数个数送 2100H
L1E,SJMP L1E
例 4.查找零的个数 (在 2000H--200FH中查出有几个字 节是零,把个数放在 2100H单元中)
,单片微机原理及应用,教学课件
★ 查找零的个数 C- 51程序
#include <reg51.h>
main ( )
{ unsigned char xdata *p=0x2000;/*指针 p指向 2000H单元 */
int n=0,i;
for(i=0;i<16;i++)
{ if(*p==0) n++; /* 若该单元内容为零,则 n+1 */
p++; /* 指针指向下一单元 */
}
p=0x2100; /* 指针 p指向 2100H单元 */
*p=n; /* 把个数放在 2100H单元中 */
}
,单片微机原理及应用,教学课件
★ 汇编程序
ORG 0000H
MOV A,R3
MOV B,R7
MUL AB ;R3*R7
XCH A,R7 ;R7=(R3*R7)低字节
MOV R5,B ;R5=(R3*R7)高字节
MOV B,R2
MUL AB ;R2*R7
ADD A,R5
MOV R4,A
CLR A
ADDC A,B
MOV R5,A ;R5=(R2*R7)高字节
MOV A,R6
MOV B,R3
MUL AB ;R3*R6
ADD A,R4
XCH A,B
ADDC A,R5
MOV R5,A
MOV PSW.5,C ;存 CY
MOV A,R2
MUL AB ;R2*R6
ADD A,R5
MOV R5,A
CLR A
MOV ACC.0,C
MOV C,PSW.5 ;加上次加法的位
ADDC A,B
MOV R4,A
JMP $
例 5.双字节无符号整数快速乘法
,单片微机原理及应用,教学课件
★ C- 51程序
#include <reg51.h>
main( )
{unsigned int xdata *p1=0x2000;/*双字节被乘数在 2000H单元 */
unsigned int xdata *p2=0x2002;/*双字节乘数在 2002H单元 */
unsigned long xdata *p3=0x2010;/*4字节乘积放在 2010H单元 */
*p3=(*p1)*(*p2);
}
,单片微机原理及应用,教学课件例 6.工业顺序控制 C-51程序
#include <reg51.h>
sbit P1_7=0x97; /* 定义 P1.7口地址 */
unsigned char TT;
void Delay(unsigned int value) /* 延时子程序 */
{ while(value!=0) value--; }
void Serint1()interrupt 2 /*中断服务程序 --暂停并报警 */
{ int i;
TT=P1; /* 保护现场 */
P1=0x7f; /* 关输出 */
while(!INT1) /* 若故障未消除,则报警 */
{ for(i=0;i<0xa0;i++) /* 给蜂鸣器发震荡脉冲 */
{ P1_7=1;Delay(50); P1_7=0;Delay(50);}
P1_7=0;Delay(6550);
}
P1=TT; /*恢复现场 */
}
,单片微机原理及应用,教学课件
main ( )
{ IE=0x84; /* CPU开中断,INT1开中断 */
while(T0==0); /* 等待 P3.4变高 */
for(;;)
{ P1=0xfe; Delay(60000); /* 工序 1 */
P1=0xfd; Delay(60000); /* 工序 2 */
P1=0xfb; Delay(60000); /* 工序 3 */
P1=0xf7; Delay(60000); /* 工序 4 */
P1=0xef; Delay(60000); /* 工序 5 */
P1=0xdf; Delay(60000); /* 工序 6 */
P1=0x8f; Delay(60000); /* 工序 7 */
}
}
(续前)
,单片微机原理及应用,教学课件例 7.电脑时钟
( 用定时器产生 0.1秒定时中断,对时钟计数器计数并送数码管显示)
★ C- 51程序
#include <reg51.h>
#include <absacc.h>
#define uchar unsigned char
#define LEDwp XBYTE[0xffdc]
#define LEDwb XBYTE[0xffdd]
uchar code
table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar hour=1,min=23,sec=45,m=0,n,i; /* 给时钟赋初值 */
uchar xdata *p;
void Delay(unsigned int value) /*延时子程序 */
{while(value!=0) value--;}
,单片微机原理及应用,教学课件
void Trans(void) /*时间数据转换子程序 */
{ if(sec==60) {min++;sec=0; }
if(min==60) {hour++;min=0;}
if(hour==24) {hour=0; }
*(p+0)=hour/10; /* 时的十分位 */
*(p+1)=hour%10; /* 时的个位 */
*(p+2)=min/10; /* 分的十分位 */
*(p+3)=min%10; /* 分的个位 */
*(p+4)=sec/10; /* 秒的十分位 */
*(p+5)=sec%10; /* 秒的个位 */
}
void Show(void) /*循环显示子程序 */
{ for(;;)
{ Trans( );
LEDwb=n=0x20;
for(i=0;i<6;i++)
{ LEDwp=table[*(p+i)];LEDwb=n;Delay(100); n=n>>1; }
}
}
,单片微机原理及应用,教学课件
/* 中断服务子程序( 0.1秒中断一次) */
void time() interrupt 1
{ m++;
TH0=0x3c; TL0=0xb7; /* 给 T0 赋计数初值 */
if(m==10) { sec=sec+1; m=0; }
}
main( )
{ p=0x2000;
TMOD=0X01; /* T/C0工作在定时器方式 1 */
TH0=0x3c;
TL0=0xb7; /* 给 T0 赋计数初值 */
EA=1; /* CPU开中断 */
TR0=1; /* 启动 T/C0开始定时 */
ET0=1; /* T/C0开中断 */
Show( );
}
,单片微机原理及应用,教学课件
OVER !