51单片机的问题,读引脚和读引脚寄存器的问题

程序如下:
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
sbit KEY=P1^0; //定义按键输入端口
sbit LED=P1^1; //定义led输出端口
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{

KEY=1; //按键输入端口电平置高
while (1) //主循环
{
CY=KEY;
KEY=CY;
if(!KEY) //如果检测到低电平,说明按键按下
LED=0;
else
LED=1; //这里使用if判断,如果按键按下led点亮,否则熄灭
//上述4句可以用一句替代 LED=KEY;
//主循环中添加其他需要一直工作的程序
}
}

程序加上 下面这两条语句和没加结果完全不同,求解释
CY=KEY;
KEY=CY;
(程序已经加上这两语句)

你既然已经把KEY即P1^0口作为输入了,用CY=KEY这个没问题。
为什么还要加这一句 KEY=CY 把KEY这个端口又设置成输出呢?
你既然是需要这个端口做输入,就不要加KEY=CY这个语句进去,不然有可能导致程序出现问题的。
因为51单片机不和AVR一样,51单片机没有设定输入输出的寄存器。
而且要把51单片机的IO口设置成输入的话,貌似必须要先让这个引脚先设置成1。追问

我就想知道为什么会出问题,51的io口即可做输入也可以做输出的,问题不在这,CY=KEY,CY=KEY执行之后KEY应该不会有所改变才对,只是改变了CY的值
至于引脚先置1再读取,按电路来看是要的,反而加上CY=KEY,CY=KEY这两句后符合先置1在读取

追答

CY=KEY是只改变了CY的值,但是你KEY=CY就是把KEY的IO口设置成了输出的状态,KEY这个IO口就输出CY的值。这样,KEY这个口在后面的程序里面如果没上拉电阻使它置1的话,貌似就不会变成输入状态,从而不能检测到按键状态,导致不能正常做出动作。
总而言之是你KEY=CY这句话是有问题的,如果删去,程序应该就正常了
如果照你这么说,把P1.0口输出1,P1.1口输出0,然后P1.1口和P1.0口用导线连接起来,在此期间,加入一个按钮。然后在P1.0口放一个上拉电阻,之后按下按钮你会发现P1.0口会被拉成低电平,而P1.1口却不会变成高电平。这就说明了,如果IO口做输入,不先置1的话,就只能做输出用,如果置1了的话,才能做输入口用

追问

P1口是有内置上拉电阻的,而且,你把那个io口先置1再读取数据的过程,不就是把它先当作输出口再当成输入口吗?按键按下后,P1.0=0,这时我松开按键,想当于P1.0引脚空置
CY=KEY(汇编MOV)语句会认为KEY等于0,
if(!KEY) (汇编JB)认为KEY等于1
这是书上一段话:,已向P1一P3端口线输出过0,则再要输入时,必须先写1后再读引脚,才能得到正确的信息。

追答

对不起,我有个问题是错误的。就是不管上拉电阻的事。
IO口先写1后,再读引脚,这个是对的,只有先写1了,那个IO口才能当成输入状态。
而且你书上那段话也是正确的。
开机没按键的时候,KEY=1 CY=KEY,的确是让CY等于1,KEY也等于1;同时就算KEY=CY,此时KEY依然是被赋值为CY的值,也就是KEY也是等于1的,这样,KEY是设置成了输入状态,可以接收到你按键的信号的。但是没按键的时候,if语句运行的是 LED=1,就是说没按键的时候灯是灭的。
如果当你按键按下的时候,KEY就会变成低电平。CY=KEY这个语句会使CY等于0,然后紧跟着KEY=CY,就会使 KEY输出0 了,此时KEY就变成了输出模式。然后if语句就会执行 LED=0 ,使灯点亮。
但是你有没想过之后呢?因为 KEY=CY即 KEY=0 这条语句,使KEY变成了输出模式,并且都是输出0而不是输出1,这样KEY就不能变回输入模式,就不能采集你按键信号了,故而以后不管你按键有没有按,灯都是一直亮的了

追问

恩,你讲的是对的,非常感谢

追答

不客气,大家讨论下,加深印象。这个问题主要体现到 矩阵键盘 的编程里面。需要理解输入输出状态。
你所说的CY=KEY会让KEY等于0,而if(!KEY) 认为KEY会等于1.这个是不对的
if(!KEY) 语句里面 KEY的值依然是0,不会变得。
! 不会改变KEY的值的。 KEY的值为0 !KEY的值为1. 而if(1) 就说明了if语句始终为真,故而你那程序始终会让灯点亮

温馨提示:内容为网友见解,仅供参考
第1个回答  2012-09-19
CY=KEY; 这句是把P1.0 读入并放进 CY中
KEY=CY; 这句是导致程序问题的根本原因

在没有按键时, 是不会出现问题的
但有按键时, KEY=0 的时候, 问题就出来了, 比过这两句程序之间 P1.0变成了0, 程序一直在这里面循环, 所以P1.0一直是0了, 也就读不到P1.0的其他状态了追问

按键按下后,P1.0=0,这时我松开按键,想当于P1.0引脚空置,CY=KEY(汇编MOV)语句会认为KEY等于0,
if(!KEY) (汇编JB)认为KEY等于1,那按你所说,汇编也应该认为是0才对

追答

是的, 前面只要KEY=0输出过一次, 以后就都是0了, 它自己是不会变回1的, 除非你重置KEY=1才行, 不然读进KEY就一直是0了, 汇编也一样

追问

问题是按下按键后(即KEY=0后)再松开,if(!KEY)会认为KEY等于1啊,我就想知道为什么

第2个回答  2012-09-19
没使用指针代码追问

什么指针代码

追答

逻辑错误

51单片机读引脚与读锁存器的问题
51单片机的P1读的是引脚上的电平 即使你把io口置位 也可能被外部电路拉低 所以有没有外设读到的电平可能会不一样 因为51单片机io口没有三态 所以读io口时要先将io口置位

51单片机 读引脚与读锁存器的问题
P1口有上拉,读的时候就会直接读到上拉的点,接了外设,由于外设的原因造成端口被拉低,读取的时候就会读到低电平。如果外设的接口也是高电平,那就是高电平。

在单片机中,当P0口作为输入口使用时,为什么要区分" 读引脚" 和"读锁...
不光是P0口,标准51单片机的所有IO口都有“读引脚”和“读锁存器”的问题。其实这类问题也很好解释,自己去看看51单片机的IO脚框图就豁然开朗了。读引脚的意思就是直接读P0外部引脚的电位,而读端口(锁存器)读的是内部与数据总线链接的锁存器的电位。一般来说,读取P0的数据,都是读引脚,目的是...

51单片机C语言里有读引脚和读锁存器之分吗?这个P1 = P1 || 5; 请问...
1.读引脚是通过读锁存器的值来读取的 2.这不是读语句,是改变P1口的状态(P1=1),使P1.0输出高电平。3.需要写1的,C编程不会自动写1是复位后,I\/O自动被置位高电平。4.分辨一个端口是输入或者输出,是根据读这个端口(作为输入),或这写这个端口(输出口)来区分的。如P1=0x08;P1做...

c51单片机怎样读引脚
首先 你要知道对于单片机的管脚在系统上电复位的情况下 各个管脚都是高电平的 所以不用你写P1.0也是1,这时候你可以先让P1.0=0再重新写1。读引脚的意思就是直接读P0外部引脚的电位,而读端口(锁存器)读的是内部与数据总线链接的锁存器的电位。inc P0;给p0加1 执行这个语句时 ,采用“读-...

关于单片机P1口读所存器与读引脚!
,所以MOV A,P1就是一次读8个引脚, maxiurui说的逻辑指令可以一次读一个引脚。若设置设置P1口为低电平时,MOV A,P1读锁存器。需要注意的是,一些新型51单片机设置了专用的引脚功能选择寄存器,这时MOV A,P1读的是输出寄存器还是引脚就需要考虑专用的引脚功能选择寄存器的设置了。

关于单片机的引脚和输入输出问题
51 单片机,所有IO口都可以作为输入和输出,但不是"同时" 作为输入时,要先向其端口写1 然后再读取 如程序中设定P0=0xF0,然后在外部将P0^7接地,也就是置为零,此时读取P0的话,得到P0=0x70 即最高位确实是0 但P0口内部没有上拉电阻的, 如果IO口外部不经电阻接电源的话,虽然你置1了...

在单片机中,什么叫读引脚,什么叫读端口,它们有什么区别?
原因如下:如果你想先输出1,再读取引脚的状态,就会出错,因为由于引脚外元件的特殊作用,电压有可能会不正常,单片机可能会误读到0,这与原先输出的1不符合,所以要想读到原先的值,就得去读端口寄存器中的值(寄存器不受外部影响),这就产生了“读端口”参考资料:拜托分高点,否则你的问题会被...

在51单片机,判断引脚上的状态,使用位寻址指令,为什么不需要输出一个高...
因为单片机上电初始化各I\/O状态都是输出高电平,因此P3.0可以省略输出高电平那一步。这个程序里判断P3.0如果为低电平(键按下),则P1.0输同低电平,灯亮。

当读51单片机引脚时,端口是高阻状态吗?
阻态,这样P0口上数据就会从读引脚的三态缓冲器上正确的输入,如果 不写1,那么锁存器上次锁存的可能为0,那么反向端有可能出现1,这样 和反向端相接的MOS管就倒通,也就是直接拉到地,那么不管你P0口上输 入什么信号都会拉成低电平,输入就错了 双向口与准双向口的区别主要是:准双向口I\/O口...

相似回答
大家正在搜