51单片机学习之数码管

段选和位选

例如,你要控制四个数码管,依次是1,2,3,4,你要选择哪一个数码管(一个数码管即为一个“日”)这就是位选,顾名思义为选择位置;之后你要让选择的数码管显示某一个数字或符号,你就要控制数码管的a,b,c,d,e,f,g这七个发光二极管,让其亮或灭,这就是段选,顾名思义为选择数码管的哪一段。

数据存储类型

  • 程序存储器(code)

    程序存储区(64KB),可直接理解为ROM,只读,可由汇编操作码MOVC @A DPTR访问,8051系列仅执行存储在code中的程序;

  • 内部数据存储

    对内部数据存储器的访问是非常快的,因为使用8位地址寻址;

    • data

      可直接寻址的内部数据存储器(128字节),可直接理解为内部RAM,读写速度最快;

    • idata

      间接可寻址内部数据存储器(256字节),其中前128字节和data的128字节完全相同,只是访问方法不一样;

    • bdata

      可位寻址的内部数据存储器(20h to 2Fh 16字节),支持混合位和字节访问。

  • 外部数据存储

    可读写,由于外部数据存储器是通过指针寄存器间接访问的,所以访问速度要比内部数据存储器慢,

    • xdata

      外部数据存储器(64KB),可直接理解外部RAM,可由汇编操作码MOVX @DPTR访问,Large Memory Model在此内存空间中定义变量;

    • pdata

      分页寻址外部数据存储器,其指定外部存储器中的一页(256字节),由操作码MOVX @Rn访问;Compact Memory Model在此内存空间中定义变量。

程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "reg52.h"
#include "intrins.h"
#define uint unsigned int


sbit a = P2 ^ 4;
sbit b = P2 ^ 5;
sbit c = P2 ^ 6;
sbit d = P2 ^ 7;

sbit fm = P2 ^ 3;

//定义数码管段选的方式
unsigned char code sz[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

/*
*延迟函数
*/
void Delay(uint ms){
uint i ,j;
for(i = ms; i > 0; i--){
for(j = 112; j>0; j--);
}
}

/*
*位选数码管函数
*/
void Led(int id){
switch(id){
case 1:
a = 1;b = 0;c = 0;d = 0;
break;
case 2:
a = 0;b = 1;c = 0;d = 0;
break;
case 3:
a = 0;b = 0;c = 1;d = 0;
break;
case 4:
a = 0;b = 0;c = 0;d = 1;
break;
default:
break;
}
}


void main(){
int i = 0;
Led(1);
while(1){
P1 = 0xfe;
for (i = 0; i < 8; i++){
Led(4 - (i%4));
P0 = sz[8 - i];
fm = 0;
Delay(100);
fm = 1;

Delay(1000);
P1 = _crol_(P1,1);

}
}
}

可以看看这个数组定义:

1
unsigned char code sz[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

其中code是一个域修饰符,它指定该数组存储在程序存储区,写入后不可更改。