51的P0 - P3都是准双向I/O端口,作为输入端口时需要先将其置1,然后再读取引脚状态。
这里抛开汇编,单纯讲下C51编程时的哪种情况是读引脚、哪种情况是读端口,以及读引脚前为什么要置1,以防止大家出错。
1.读引脚:(下面是测试代码)
#include <reg51.h>
sbit LED = P0^0; //外加上拉电阻
sbit f = P0^1;
void main()
{
while(1)
{
if(f == 0) //如果P0.1是低电平的话就让LED亮
{
LED = 0;
}
}
}
单片机通电复位后,P1口的锁存器Q端都为1,对应的MOS管不导通,P1口在上拉电阻作用下全是高电平,所以LED不亮,用导线将P0.1口拉低,LED瞬间点亮;
说明 if(f == 0)判断的P0.1引脚的状态即读引脚,LED是否点亮受P0.1引脚状态影响。
51单片机通电复位后直接读引脚是没问题的。
但大家可能发现:先将P0.0置0,然后用导线将它拉高,单片机也可以读出此引脚是高电平,这种做法很危险!
将P0.0置0后,对应的MOS管导通,VCC和GND间通过这个MOS管连接,由于电流较大以及MOS管的电阻作用使得P0.0引脚被拉高(通过万用表可以测出这个高电平较正常情况下低一些,单片机的其他端口的电平状态可能也不正常了),但这会缩短单片机寿命,因此读引脚前一定要向该引脚写一!然后读取引脚电平。(可以说,先写1 就是为了避免这种情况)
2.读端口:(下面是测试代码)
#include <reg51.h>
sbit LED = P0^0;
void delay()
{
unsigned char i = 255;
while(--i);
}
void main()
{
//先将P0.0引脚用导线拉低
delay();
LED = ~LED; //LED低电平亮
//拔出导线,将P0.0接到LED负极上
}
P0.0开始被拉低了,那么对其取反之后,P0.0应该为1,LED应该不亮,但实际是LED亮了,因为这里
不是读引脚而是读端口(锁存器):单片机上电后P0口全是1,其内部的锁存器输出端Q也为1,虽然P0.0引脚被
拉低了,但是其锁存器Q端仍为1不变,对1取反后再赋值给P0.0口,点亮了LED。
可以总结下:
1. 51单片机里对某一个I/O口进行读--改--写(例如上面的取反后写回)操作时,读取的是与之对应的锁存器的输出,而不
是实际物理引脚的电平;其他非读--改--写(例如上面的f == 0)指令读取的是引脚电平。
2. 读引脚电平时一定要先向该端口写1,然后再读取引脚电平!