论坛风格切换切换到宽版
  • 3910阅读
  • 28回复

上个c语言程序,看看哪里错了? [复制链接]

上一主题 下一主题
离线bg4jj
 
发帖
5094
只看楼主 倒序阅读 0楼 发表于: 2005-01-11
#include <reg51.h>

void main()

{   bit k0;bit k1;
     
     k0 = p1^0; k1 = p1^1;

}


keil编译后的结果很奇怪
离线bg4jj
发帖
5094
只看该作者 1楼 发表于: 2005-01-11
设想中应该编译成这样:"
  mov c,0x90.0
    mov 0x20.0 ,c
    mov c,0x90.1
    mov 0x20.1 ,c
"
离线BG4UVR
发帖
11288
只看该作者 2楼 发表于: 2005-01-12
我也是学了C51不长时间,我研究了好半天,终于发现问题所在。

首先,你这个的编译结果是没有错的。只是没有像你想像的那样。

p1^0,是指p1的0位,这样KEIL在编译的时候,会先把p1读出来,取出0位来运算。

那问题出在哪呢?出在了你p1^0这种表达方式,这种表达方式本身就已经是一种运算了。

那如何解决呢?
用p1_0这样的方法来解决,编译出错是吧?那就对了,因为这个reg51.h里面没有定义p1_0。换成at89x51.h,就可以了。因为at89x51.h中是这样定义的:
/*------------------------------------------------
p1 bit registers
------------------------------------------------*/
sbit p1_0 = 0x90;
sbit p1_1 = 0x91;
sbit p1_2 = 0x92;
sbit p1_3 = 0x93;
sbit p1_4 = 0x94;
sbit p1_5 = 0x95;
sbit p1_6 = 0x96;
sbit p1_7 = 0x97;

这回再编译一下,结果和你想的一样了吧?
离线bg4jj
发帖
5094
只看该作者 3楼 发表于: 2005-01-12
p1^0这种表达方式本身就已经是一种运算了。
具体是什么运算,怎么运算的呢?请详细分析一下,谢谢!
离线BG4UVR
发帖
11288
只看该作者 4楼 发表于: 2005-01-12
虽然这只是个测试,但还是要说一下。在实用中,如果你这样使用还是可能会产生问题的。原因在于实用中,p1口目前的状态未知(因为实用中你的程序肯定不只这几行),所以在执行你这个程序前,必须要p1=0xff才行。
离线BG4UVR
发帖
11288
只看该作者 5楼 发表于: 2005-01-12
'
p1^0这种表达方式本身就已经是一种运算了。
具体是什么运算,怎么运算的呢?请详细分析一下,谢谢!
'

p1^0表示,取p1的0位。和p1_0的不同在于,p1_0是直接对可位寻址位进行操作,而这个要先把整个的p1读进来,再取0位进行操作。这样就失去了可位寻址的意义了。
离线bg4jj
发帖
5094
只看该作者 6楼 发表于: 2005-01-12
最奇怪的是:
这样就正常了-----
#include <reg51.h>

void main()

sbit pa=p1^0;

sbit pb=p1^1;

{ bit k0;bit k1;

k0 = pa; k1 = pb;

}

道理何在呢?
离线BG4UVR
发帖
11288
只看该作者 7楼 发表于: 2005-01-12
'
最奇怪的是:
这样就正常了-----
#include <reg51.h>
void main()
sbit pa=p1^0;
sbit pb=p1^1;
{ bit k0;bit k1;
k0 = pa; k1 = pb;
}
道理何在呢?
'

对啊对啊,因为sbit作用和at89x51.h中那个定义是一样的原理啊。查一下sbit的说明看看,sbit是定义特殊位寄存器啊。
离线bg4jj
发帖
5094
只看该作者 8楼 发表于: 2005-01-12
'
最奇怪的是:
这样就正常了-----
#include <reg51.h>
void main()
sbit pa=p1^0;
sbit pb=p1^1;
{ bit k0;bit k1;
k0 = pa; k1 = pb;
}
道理何在呢?
'

编译结果和想象中高度一致----
mov c,0x90.0
mov 0x20.0 ,c
mov c,0x90.1
mov 0x20.1 ,c

关键是不明白其中的道理   形式真的决定效果?
离线bg4jj
发帖
5094
只看该作者 9楼 发表于: 2005-01-12
在硬件上位操作也是要把8位都读进来进行操作的呀?有何不同可言呢?
离线BG4UVR
发帖
11288
只看该作者 10楼 发表于: 2005-01-12
'
在硬件上位操作也是要把8位都读进来进行操作的呀?有何不同可言呢?
'

不一样啊,硬件操作上不同!

可位寻址位是可以直接进行位操作的,不用8位都读进来的。
离线bg4jj
发帖
5094
只看该作者 11楼 发表于: 2005-01-12
在第1个程序中 如果p1=11111100   那么k0 = p1^0执行的具体细节是什么?
离线BG4UVR
发帖
11288
只看该作者 12楼 发表于: 2005-01-12
'
在第1个程序中 如果p1=11111100   那么k0 = p1^0执行的具体细节是什么?
'

这个在你第一楼的图中可以清楚的看到啊
离线BG4UVR
发帖
11288
只看该作者 13楼 发表于: 2005-01-12
参考:

sbit 可录址位
sbit 同位是c51 中的一种扩充数据类型,利用它可以访问芯片内部的ram 中的可寻址
位或特殊功能寄存器中的可寻址位
。如先前我们定义了
sfr p1 = 0x90; //因p1 端口的寄存器是可位寻址的,所以我们可以定义
sbit p1_1 = p1^1; //p1_1 为p1 中的p1.1 引脚
//同样我们可以用p1.1 的地址去写,如sbit p1_1 = 0x91;
这样我们在以后的程序语句中就可以用p1_1 来对p1.1 引脚进行读写操作了。通常这些
可以直接使用系统提供的预处理文件,里面已定义好各特殊功能寄存器的简单名字,直
接引用可以省去一点时间,我自己是一直用的。当然您也可以自己写自己的定义文件,
用您认为好记的名字。
离线bg4jj
发帖
5094
只看该作者 14楼 发表于: 2005-01-12
我的理解是 采用预处理文件与否应该效果是一样的 也就是说用p1^0 和 用pa 编译后是一样的才对。 可结果是不一样的 ???
离线bg4jj
发帖
5094
只看该作者 15楼 发表于: 2005-01-12
'
这个在你第一楼的图中可以清楚的看到啊
'

说的详细一些吧:开始运行时,设定p1=11111100   单步运行k0=p1^0   后,k0=1     而不是0!为什么?
离线bg4jj
发帖
5094
只看该作者 16楼 发表于: 2005-01-12
'
我也是学了C51不长时间,我研究了好半天,终于发现问题所在。
首先,你这个的编译结果是没有错的。只是没有像你想像的那样。
p1^0,是指p1的0位,这样KEIL在编译的时候,会先把p1读出来,取出0位来运算。
那问题出在哪呢?出在了你p1^0这种表达方式,这种表达方式本身就已经是一种运算了。
'
如果这个的编译结果是没有错的那么运行结果也应该正确才对,如何解释呢?请用p1=11111100 、p1=11111110。。。分别 运行一下试试看
离线BG4UVR
发帖
11288
只看该作者 17楼 发表于: 2005-01-12
'
我的理解是 采用预处理文件与否应该效果是一样的 也就是说用p1^0 和 用pa 编译后是一样的才对。 可结果是不一样的 ???
'

我编译了一下,说sbit pa=p1^0这句语法不对。
离线BG4UVR
发帖
11288
只看该作者 18楼 发表于: 2005-01-12
'
说的详细一些吧:开始运行时,设定p1=11111100   单步运行k0=p1^0   后,k0=1     而不是0!为什么?
'



正在研究。快下班了,下午给出结果。
离线bg4jj
发帖
5094
只看该作者 19楼 发表于: 2005-01-12
看看我的编译结果   :