51单片机学习C语言.docx
《51单片机学习C语言.docx》由会员分享,可在线阅读,更多相关《51单片机学习C语言.docx(58页珍藏版)》请在冰点文库上搜索。
51单片机学习C语言
第二课C51的数据和数据类型(P55)
2.1KEIL51数据类型
数
据
类
型
基本类型
位型(bit)
字符型(char)
有符号(signedchar)
无符号(unsignedchar)
整型(int)
有符号(signedint)
无符号(unsignedint)
长整型(long)
有符号(signedlong)
无符号(unsignedlong)
浮点型(float)
双精度浮点型(double)
构造类型
数组类型(array)
结构类型(struct)
共同体(union)
枚举(enum)
指针类型
空类型
2.2KEIL51数据类型
数据类型
长度
/bit
长度
/byte
值域
char
unsignedchar
8
1
0~255
signedchar
8
1
-128~+127
int
unsignedint
16
2
0~65535
signedint
16
2
-32768~+32767
long
unsignedlong
32
4
0~4294967295
signedlong
32
4
-2147483648~+2147483647
float
32
4
±1.175494E-38~±3.402823E+38(6位数字)
double
64
8
±1.175494E-38~±3.402823E+38(10位数字)
一般指针
*
1~3
bit
1
0或1
sbit
1
0或1
sfr
8
1
0~255
sfr16
16
2
0~65535
2.3KEIL51数据的存储类型与存储空间的对应关系
数据存储器
存储
类型
长度
byte
与存储空间的对应关系
片内数据存储器
data
1
片内RAM区低128字节,访问速度快
bdata
1
片内RAM位寻址区(20H~2FH),允许位与字节混合访问
idata
1
片内间接寻址区,可访问片内所有RAM地址空间(256字节)
片外数据存储器
xdata
2
片外数据存储区(64KB字节)空间,
由MOVX@DPTR访问
pdata
2
分页寻址片外数据存储区(256字节)
由MOVX@R0访问
片外程序存储器
code
代码存储区(64KB字节)
由MOVC@DPTR访问
第三课KEIL51数据的存储类型与存储器结构(P59)
3.1Cx51系列单片机在物理上有四个存储空间(见图3-1)
片内程序存储器空间
片外程序存储器空间
片内数据存储器空间
片外数据存储器空间
注:
使用片外程序存储器时,单片机引脚EA接地。
即
3.2通用寄存器区:
地址(00H~1FH)(P60)
组号
PSW.4/RS1
PSW.3/RS0
地址
0
0
0
00H~07H
1
0
1
08H~0FH
2
1
0
10H~17H
3
1
1
18H~1FH
3.3可位寻址区(20H~2FH)位地址:
00H~7FH共128位(P61)
RAM地址
位地址
2F
7F
7E
7D
7C
7B
7A
79
78
2E
77
76
75
74
73
72
71
70
2D
6F
6E
6D
6C
6B
6A
69
68
2C
67
66
65
64
63
62
61
60
2B
5F
5E
5D
5C
5B
5A
59
58
2A
57
56
55
54
53
52
51
50
29
4F
4E
4D
4C
4B
4A
49
48
28
47
46
45
44
43
42
41
40
27
3F
3E
3D
3C
3B
3A
39
38
26
37
36
35
34
33
32
31
30
25
2F
2E
2D
2C
2B
2A
29
28
24
27
26
25
24
23
22
21
20
23
1F
1E
1D
1C
1B
1A
19
18
22
17
16
15
14
13
12
11
10
21
0F
0E
0D
0C
0B
0A
09
08
20
07
06
05
04
03
02
01
00
3.4、用户RAM区
Cx51单片机用户RAM区(30H~7FH);
Cx52单片机用户RAM区(30H~FFH)。
注:
上电复位时,堆栈指针SP指向07H,C51单片机的栈顶和栈底是从小到大在使用汇编语言时,通常将栈顶定位在30H(MOVSP,#30H),在使用C语言编程时堆栈是系统自动分配的,不需用户考虑。
3.5特殊功能寄存器(SFR)(P64)
SFR
MSB位地址/位定义LSB
字节地址
*B
F0H
*ACC
E0H
*PSW
D7
D6
D5
D4
D3
D2
D1
D0
D0H
CY
AC
F0
RS1
RS0
OV
F1
P
*T2CON
CF
CE
CD
CC
CB
CA
C9
C8
C8H
TF2
EXF2
RCLK
TCLK
EXEN2
TR2
CP/RL2
*IP
BF
BE
BD
BC
BB
BA
B9
B8
B8H
-
-
-
PS
PT1
PX1
PT0
PX0
*P3
B7
B6
B5
B4
B3
B2
B1
B0
B0H
P3.7/
RD
P3.6/
WR
P3.5/
T1
P3.4/
T0
P3.3/
INT1
P3.2/
INT0
P3.1/
TXD
P3.0/
RXD
*IE
AF
AE
AD
AC
AB
AA
A9
A8
A8H
EA
-
-
ES
ET1
EX1
ET0
EX0
*P2
A7
A6
A5
A4
A3
A2
A1
A0
A0H
P2.7
P2.6
P2.5
P2.4
P2.3
P2.2
P2.1
P2.0
SBUF
99H
*SCON
9F
9E
9D
9C
9B
9A
99
98
98H
SM0
SM1
SM2
REN
TB8
RB8
TI
RI
*P1
97
96
95
94
93
92
91
90
90H
P1.7
P1.6
P1.5
P1.4
P1.3
P1.2
P1.1
P1.0
TH1
8DH
TH0
8CH
TL1
8BH
TL0
8AH
TMOD
GATE
M1
M0
GATE
M1
M0
89H
*TCON
8F
8E
8D
8C
8B
8A
89
88
88H
TF1
TR1
TF0
TR0
IE1
IT1
IE0
IT0
PCON
87H
DPH
83H
DPL
82H
SP
81H
*P0
87
86
85
84
83
82
81
80
80H
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
P0.0
注1:
*表示可以进行位操作
注2:
KEILCx51提供了一种自主形式的定义方法。
这种定义引入关键字“sfr”,语法如下:
sfrSCON=0x98;
sfrTMOD=0x89;/*见头文件reg51.h*/
注3:
定义datacharx与定义chardatax是等价的,但应该尽量使用后一种方法。
第四课常量和变量(P56)
4.1、常量---在程序运行的过程中,其值不能改变的量。
与变量一样,常量可以有不同的数据类型,可以用一个标识符代表一个常量,习惯上常量标识符用大写字母,例:
#defineCONST60/*即:
CONST=60*/
#definePAI3.1416/*即:
PAI=3.1416*/
4.2、变量---在程序运行的过程中,其值可以改变的量。
例:
#defineCONST60
main()
{intvar1,result;
var1=2;
result=var1*CONST;
while
(1)
}
运行结果result=120
4.3、变量在存储器中的物理排列(图4-1)
1)、位变量
2)、整型变量
3)、浮点型变量(1位符号位,8位指数位,23位尾数位)
地址
+0
+1
+2
+3
内容
SEEEEEEE
EMMMMMMM
MMMMMMMM
MMMMMMMM
其中,S符号位,1表示负,0表示正;
E:
阶码(在两个字节中)偏移为127;
M:
23位尾数,最高位为“1”。
一个整型变量值为0x1234,一个长整型变量值为0x12345678,
一个浮点变量值为-12.5的十六进制为0xC1480000,它们在内存的排列分别表示在4-1中
(书2P52)
注1:
AT89C51芯片中RAM只有低128位,而AT89C52芯片中RAM另外还有高128位,地址为80H到FFH,并和特殊寄存器SFR地址重叠。
注2:
在编写程序时,如是使用signed和unsigned两种数据类型,那么就得使用两种格式类型的库函数,这将使占用的存储空间成倍增长,因此在编程时,如是只强调程序的运算速度而又不进行负数运算,最好采用无符号(unsigned)格式。
注3:
尽量使用位变量。
注4:
缩写形式定义:
typedefunsignedcharucha
typedefunsigneduintuint
4.4存储模式及说明(P63)
存储模式
说明
SMALL
小模式
参数及局部变量放入可直接寻址的片内存储器(最大128字节,默认存储类型是data)
COMPACT
紧凑模式
参数及局部变量分页外存储器(最大256字节,默认存储类型是pdata),通过寄存器R0和R1间接寻址,棧空间位于单片机内部RAM。
LARGE
大模式
参数及局部变量直接放入片外数据存储器(最大64KB,默认存储类型是xdata),通过数据指针DPTR来寻址,访问效率低。
第五课8051并行接口及其Cx51定义(P66)
P0-P3口,32根I/O线;
输入缓冲器;输出缓冲器;引至芯片外的端口引脚;
P0、P1、P3为准双向口;P0为双向三态口;
向外扩展存储器要用P0口和P2口,P2口输出地址高8位(A15~A8),P0口数据和地址复用;
P0~P3可以字节寻址,也可以位寻址;
标准8051的端口没有数据方向寄存器。
P1、P2、和P3都有内部上拉,都可以作为输入或输出。
写端口就是写一个要送端口的值;
读端口,必须先向端口写“1”(单片机复位时口线的初值是全“1”)
第六课位变量(P68)
6.1、位变量的Cx51的语法及语义如下:
bitdir_bit;/*将dir_bit定义为位变量*/
6.2、函数可包含类型为bit的参数,也可以将其作为返回值。
例:
bitfunc(bitb0,bitb1)
{/*………*/
Return(b1);
}
6.3、对位变量定义的限制:
位变量不能定义成一个指针,如不能定义bit*bit_point;
不存在位数组,如不能定义bitb_array[];
6.4、可位寻址对象:
是指可以字节或位寻址的对象。
位于8051内部RAM中,因此存储类型为idata.
6.5、sbit位变量名=位地址
sbitP1_1=Ox91;
这样是把位的绝对地址赋给位变量。
同sfr一样sbit的位地址必须位于80H-FFH
之间。
6.6、sbit位变量名=特殊功能寄存器名^位位置
sftP1=0x90;
sbitP1_1=P1^1;//先定义一个特殊功能寄存器名再指定位变量名所在的位置
当可寻址位位于特殊功能寄存器中时可采用这种方法
6.7、sbit位变量名=字节地址^位位置
sbitP1_1=0x90^1;
sbitP1_0=P1^0;//而是自己定义特殊寄存器
sfrP1=0x90;//这里没有使用预定义文件,
sbitP1_7=0x90^7;//之前我们使用的预定义文件其实就是这个作用
sbitP1_1=0x91;//这里分别定义P1端口和P10,P11,P17引脚
第七课算术运算符及其表达式(P69)
7.1、Cx51算术运算符及其表达式
算术运算符
表达式
含义
+
a+b
加法运算符,或正值符号
-
a-b
减法运算符,或负值符号
*
a*b
乘法运算符,
/
a/b
除法运算符,
%
9%5余4
模(求余)运算符,或正值符号
7.2、Cx51关系运算符及其表达式
算术运算符
表达式
含义
〈
a〈b
小于
〉
a>b
大于
〈=
a<=b
小于或等于
〉=
a>=b
大于或等于
==
a==b
测试等于
!
=
a!
=b
测试不等于
7.3、Cx51逻辑运算符及其表达式
算术运算符
表达式
含义
&&
a&&b
逻辑“与”(AND)
||
a||b
逻辑“或”(OR)
!
a!
b
逻辑“非”(NOT)
7.4、Cx51位操作及其表达式
算术运算符
表达式
含义
&
a&b
按位与
|
a|b
按位或
^
a^b
按位异或
`
a~b
按位取反
<<
a<<7
左移7位
>>
a>>8
右移8位
注:
左移或右移,空出位补“0”,移出位丢掉。
7.5、Cx51自增减运算符及其表达式
自增减运算符
含义
++i,--i
在使用i之前,先使i值加(减)1
i++,i--
在使用i之后,再使i值加(减)1
7.6、Cx51复合运算符及其表达式
算术运算符
表达式
含义
+=
a+=b
a=a+b加法
-=
a-=b
a=a-b减法
*=
a*=b
a=a*b乘法
/=
a/=b
a=a/b除法
%=
a%=b
a=a%b求余
<<=
a<<=8
a=a<<8左移
>>=
a>>=8
a=a>>8右移
&=
a&=b
a=a&b按位与
^=
a^=b
a=a^b按位异或
|=
a|=b
a=a|b按位或
~=
a~=b
a=a~b按位取反
注:
优先级说明
第八课Cx51控制语句(P80)
8.1、循环语句
while
dowhile
if/else
switch/case
(P90)
for语句
for(表达式1;表达式2;表达式3)
for(i=0;i<50;i++)
特例1:
for(;i<50;i++)
缺省表达式1,不对i设初值
特例2:
for(i=1;;i++){sum=sum+i}
不判断循环条件,无休止地进行下去。
相当于
i=1;
while
(1)
{sum=sum+1;
i++;
}
特例3:
for(;i<100;){sum=sum+1;i++}
相当于
while(i<100)
{sum=sum+1;
i++;
}
特例4:
for(i=1;i<100;i++);
没有循环体,起延时作用
特例5:
for(;;)
{/*循环体*/
}
相当于
while
(1)
{/*循环体*/
}/*死循环体*/
为了使程序具有可读性,不主张使用for语句的特例
第九课Cx51T0中断(P182)
9.1、T0定时器/计数器操作模式
9.2、模式控制寄存器TMOD
T1模式
T0模式
GATE
M1
M0
GATE
M1
M2
GATE=0或INT0(INT1)引脚高电平,与TR0(或TR1)=1打开控制门
=1计数器模式;
=0定时器模式
M1M2=00,01,10,11分别对应模式0、1、2、3
9.3、控制寄存器TCON(可位寻址)
TF1
TR1
TF0
TR0
IE1
IT1
IE0
IT0
TCON.7
TCON.6
TCON.5
TCON.4
TCON.3
TCON.2
TCON.1
TCON.0
定时器1溢出标志,由硬件置位,进入中断后被硬件自动清除
定时器1运行控制位。
靠软件置“1”或清“0”
定时器0溢出标志,由硬件置位,进入中断后被硬件自动清除
定时器0运行控制位。
靠软件置“1”或清“0”
外部中断1请求标志。
由硬件置位,进入中断后被硬件自动清除
外部中断1类型控制位。
由软件置位或清除。
IT1=1下降沿触发,IT1=1低电平触发;
外部中断0请求标志。
由硬件置位,进入中断后被硬件自动清除
外部中断0类型控制位。
由软件置位或清除。
IT0=1下降沿触发,IT0=0低电平触发;
9.4、允许中断寄存器IE(可位寻址)
EA
-
ET2
ES
ET1
EX1
ET0
EX0
总允许
保留
定时器2
串行口
定时器1
外中断1
定时器0
外中断0
1:
开中断;0:
关中断
9.5、中断请求
9.6、中断优先级寄存器IP(可位寻址)
PS
PT1
PX1
PT0
PX0
串行口
定时器1
外中断1
定时器0
外中断0
1:
高优先级0:
低优先级
第十课串行移位寄存器HC595功能及编程
外中断(INT0或INT1)及编程
修改原理图:
将P13与INT1管脚连接在一起,
主程序条件:
P14=0;
IT1=1;/*下降沿触发*/
EX1=1;/*外中断1允许*/
EA=1;/*总中断允许*/
按下“设定”键,进中断1服务程序,进入中断程序后,再进行键盘扫描,求出键位值
如果发现按下“确认”键,则退出中断1服务程序。
第十一课KeliC控制流程:
以温度控制器为例画流程图
第十二课伟福仿真器支持51单片机的汇编语言
ORG0000H
LJMPSTART;主程序开始
ORG000BH
LJMPT0PRG;T0中断程序
ORG0023H;串行口中断程序
LJMPUART
ORG0100H;主程序入口地址
START:
MOVSP,#5FH
MOVR0,#08H
MOVR1,#5FH
CLRA
T0PRG:
CLRES;T0中断程序入口地址
MOVTL0,#0E0H
MOVTH0,#0B1H
RETI;中断返回
UART:
MOVR3,#8;串行口中断程序入口地址
movA,#5
TCNT:
RRA
DJNZR3,TCNT
RETI;中断返回
END;汇编程序结束
伟福仿真器编译汇编程序与编译C语言程序的过程是相同的,导入程序后按F9自动编译,连接,运行。
第十三课Cx51数组(P94)
13.1、一维数组的定义方法
类型说明符数组名[整型表达式]
charch[10];
13.2、一维数组初始化
1、在定义数组时给数组的全部元素赋值
ucharidatach[6]={0,1,2,3,4,5};
ch[0]=0,ch[1]=1,ch[2]=2,ch[3]=3,ch[4]=4,ch[5]=5
2、在定义数组时给数组的部分元素赋值
ucharidatach[6]={0,1,2,};
ch[0]=0,ch[1]=1,ch[2]=2,ch[3]=0,ch[4]=0,ch[5]=0
3、在定义数组时,若不对数组的全部元素赋值,则数组的全部元素被赋值为“0”
intidatach[6];
4、可以在程序运行过程中,用循环或键盘输入语句给数组赋值。
13.3、二维数组的定义方法
类型说明符数组名[整型表达式][整型表达式]
intch[3][5];
13.4、二维数组的存取顺序
ch[0][0]->ch[0][1]->ch[0][2]->ch[0][3]->ch[0][4]->
ch[1][0]->ch[1][1]->ch[1][2]->ch[1][3]->ch[1][4]->
ch[2][0]->ch[2][1]->ch[2][2]->ch[2][3]->ch[2][4]
13.5、二维数组初始化
1、在定义数组时给数组的全部元素赋值
intidatach[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
intidatach[3][4]={1,2,3,4},{5,6,7,8},{9,10,11,12};
2、在定义数组时给数组的部分元素赋值
inta[3][4]={{1},{5},{9}};/*赋值后数组元素如下*/
13.6、字符数组的定义方法
类型说明符数组名[整型表达式]
charch[10];
13.7、字符数组置初值
1、charch[10]={‘B’,’E’,’I’,’‘,’J’,’I’,’N’,’G’,’\0’};
/*‘\0’是结束符,如果定义时未加结束符,C编译器自动在其后面加入,所以定义字符数组的长度要比字符串中最长的串多一个字符,用于装入字符串的结束符’\0’*/
2、charch[10]={“BEIJING”};
3、cha