找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5600|回复: 10
收起左侧

关于单片机P0,P1,P2,P3之间关系的疑问

[复制链接]
ID:703395 发表于 2020-3-9 09:37 | 显示全部楼层 |阅读模式
50黑币
昨天我拿到了51单片机开发板兴冲冲的去点亮了LED和流水灯
兴奋之余我打开了 reg52.h 这个头文件
我发现

P0的定义 = 0x80 (1000 0000)

P2的定义 = 0xA0 (1010 0000)

令我困惑的地方是,我对P2每个位进行操作的时候。为什么没有影响到 P0,P1,P3呢

例如

  1. for(i = 1; i <= max; i++)
  2.         {
  3.                 P2 = (0xff >> i);
  4.                 delay(d);
  5.         }
复制代码

如果P2是一个16位及以上的变量,我还能理解。例如:
1010 0000 xxxx xxxx
利用后面的 xxxx xxxx 来控制8个LED灯。前面的 1010 0000 来说明是P2
可现在问题就是
我将P2 设置成 0x80的时候。它竟然还是在控制着某一个LED灯。


最佳答案

查看完整内容

你提供的 P0的定义 = 0x80 (1000 0000) 0x80是端口P0地址 P2的定义 = 0xA0 (1010 0000) 0xA0是端口P2地址 好象进超市购物你手提包存放的80号柜,而 P2 = (0xff >> i);是操作的你的手提包,与柜子编号80没有关系,只是说明你要到手提包里拿钱,必须对应找到80号柜
回复

使用道具 举报

ID:235200 发表于 2020-3-9 09:37 | 显示全部楼层
你提供的
P0的定义 = 0x80 (1000 0000)   0x80是端口P0地址

P2的定义 = 0xA0 (1010 0000)  0xA0是端口P2地址

好象进超市购物你手提包存放的80号柜,而
P2 = (0xff >> i);是操作的你的手提包,与柜子编号80没有关系,只是说明你要到手提包里拿钱,必须对应找到80号柜
回复

使用道具 举报

ID:691449 发表于 2020-3-9 12:45 | 显示全部楼层
本帖最后由 xianming 于 2020-3-9 12:53 编辑

你好。
P0和P2的定义是定义的地址,不是像10000000这样具体的数。
在单片机里,P0,P1,P2,P3是四个特殊的寄存器。0x80就是P0这个寄存器的地址。
也就是说,你往P0里面写数,相当于往0x80这个存储单元里面写数,往P2写就相当于往0xA0这个存储单元写。

而0x80里面的数是怎么到P0口输出的,就是单片机的内部电路了。其实就是你只要往0x80里面写一个数,单片机的内部电路就会把这个数送到P0口输出。
P0口定义的地址是不能变的,P0口就得定义成0x80,因为单片机只把0x80的数输出到P0。

reg52文件应该写的是 sfr P0=0x80;
你在程序里往P0写,编译之后就会往0x80这个地址写。

c语言一个是sfr,一个是#define,sfr定义的是地址,#define定义的是具体的数据。
希望能帮到你。

评分

参与人数 1黑币 +25 收起 理由
钱木头 + 25 赞一个!

查看全部评分

回复

使用道具 举报

ID:703395 发表于 2020-3-9 13:51 | 显示全部楼层
csmyldl 发表于 2020-3-9 11:49
你提供的
P0的定义 = 0x80 (1000 0000)   0x80是端口P0地址

正因为 0x80 是P0的地址(或者叫做端口,请原谅我的不专业)
我才会有一系列的疑惑。
因为我将P2 = 0x80的时候。它也是在控制LED灯
下面是我拿到的单片机第一节教程点亮LED灯,这些就比较容易理解。
sbit led1 = P2 ^ 0;  // 我测试过直接使用 sbit led1 = 0xA0 ^ 0 - 7,效果相同
sbit led2 = P2 ^ 1;
sbit led3 = P2 ^ 2;
当 led1 = 0; 的时候第一个灯被点亮
通过搜索 "sbit是什么"  : sbit 位变量名=地址值
我理解为下面的内存模型
mem addr  | value
1010 0000 | 1
1010 0001 | 1
1010 0010 | 1
1010 0011 | 1
1010 0100 | 1
1010 0101 | 1
1010 0110 | 1
1010 0111 | 1
上面内存模型中的某个地址的值被设置为0的时候(低电平)。LED等则被点亮
可以很清楚的看到 :
P2 = 0xA0
0xA0 ^ 0 = 0xA0 | 1010 0000
0xA0 ^ 1 = 0xA1 | 1010 0001
0xA0 ^ 2 = 0xA2 | 1010 0010
0xA0 ^ 3 = 0xA3 | 1010 0011

0xA0 ^ 4 = 0xA4 | 1010 0100
0xA0 ^ 5 = 0xA5 | 1010 0101
0xA0 ^ 6 = 0xA6 | 1010 0110
0xA0 ^ 7 = 0xA7 | 1010 0111

上面的8个地址分别代表着8个LED灯的地址. 但是高位都是 1010 也就是 0xA0 = P2

现在为题来了 :
如果我将P2的值修改成 0x80 也就是说 P2 不在等于 1010 0000,而是 1000 000。
地址已经发生了变化为什么还可以控制LED灯呢?
回复

使用道具 举报

ID:691449 发表于 2020-3-9 14:06 | 显示全部楼层
钱木头 发表于 2020-3-9 13:51
正因为 0x80 是P0的地址(或者叫做端口,请原谅我的不专业)
我才会有一系列的疑惑。
因为我将P2 = 0x80的 ...

你把P2的地址改成了0x80,0x80是P0的地址,你再往P2写数就写到P0了。
回复

使用道具 举报

ID:213173 发表于 2020-3-9 14:11 | 显示全部楼层
回复

使用道具 举报

ID:419968 发表于 2020-3-9 14:12 | 显示全部楼层
sbit 是51才有的位寻址 对应的地址为 20H~2FH
回复

使用道具 举报

ID:703395 发表于 2020-3-9 14:15 | 显示全部楼层
感谢上面两位大佬的解惑,我明白了
终于想通了,我蠢死了

其实 sfr P2    = 0xA0;
这句我修改成 P2 = 0x80的过程应该是下面这种
*(char*)0xA0 = 0x80;
回复

使用道具 举报

ID:691449 发表于 2020-3-10 15:34 | 显示全部楼层
钱木头 发表于 2020-3-9 14:15
感谢上面两位大佬的解惑,我明白了
终于想通了,我蠢死了

你把sfr改成P2 = 0x80,单片机P2仍然输出吗?

其实代码里本来没有P0到P3,P0到P0都是sfr定义的。
修改成 P2 = 0x80不应该是*(char*)0xA0 = 0x80;,因为你把P2从A0改成80,你再给 P2赋值,就相当于给新的80赋值,没有a0的事了。
原来给P2赋值,数据到A0,是因为有sfr P2=0xA0,现在改了,数据就到改之后的地方了。
回复

使用道具 举报

ID:703395 发表于 2020-3-10 17:42 | 显示全部楼层
xianming 发表于 2020-3-10 15:34
你把sfr改成P2 = 0x80,单片机P2仍然输出吗?

其实代码里本来没有P0到P3,P0到P0都是sfr定义的。

抱歉没说清楚,我并没有在 reg52.h 文件中修改
sfr P2    = 0xA0; 的 定义为 sfr P2    = 0x80;

只是程序运行之后在main()函数当中动态设置为
P2 = 0x80;
是的,还是可以控制LED灯
所以我打个不形象的比喻
*(char*)0xA0 = 0x80;
回复

使用道具 举报

ID:513213 发表于 2021-5-11 11:40 | 显示全部楼层
钱木头 发表于 2020-3-9 14:15
感谢上面两位大佬的解惑,我明白了
终于想通了,我蠢死了

sfr P2    = 0xA0;定义地址,或者理解为给地址起了个名字
P2 = *****,时给给这个变量(名字)对应得地址赋值----把值放进这个地址里。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表