各位大神!!懂指针的进
首先在51中P1的物理地址是90H,如果我不通过用《reg51.h》或者sfr之类的直接用指针,应该也是可以对P1口进行操作的。
代码如下
void main()
{
unsigned char*p;
p=( volatile unsigned char *)(0x90);
*p=0xf0;
while(1);
}
如果上面的代码正确的话,那么8个led是一半亮一半不亮啊,纳闷的是这个程序运行的时候没一点反应,望各位大侠多多指教!!十分感谢 不是很懂指针 但是我觉得*P是数据指针吧 不是程序指针 用汇编去理解 典型的没事找事
0x90只是SFR地址 SFR定义到SRAM中地址不一定是0x90 本帖最后由 bangbangji 于 2012-4-13 13:13 编辑
先确定硬件没问题,再确定你的程序确实下进去了
另外51是哈佛结构的,程序和数据是分开编址的,这里是不是有问题 bangbangji 发表于 2012-4-13 13:12 static/image/common/back.gif
先确定硬件没问题,再确定你的程序确实下进去了
另外51是哈佛结构的,程序和数据是分开编址的,这里是不是 ...
51是冯诺依曼结构的 AVR才是哈佛结构 ; .\test.SRC generated from: test.c
; COMPILER INVOKED BY:
; C:\Keil\C51\BIN\C51.EXE test.c BROWSE DEBUG OBJECTEXTEND SRC(.\test.SRC)
NAME TEST
?PR?main?TEST SEGMENT CODE
EXTRN CODE (?C_STARTUP)
EXTRN CODE (?C?CSTPTR)
PUBLIC main
; void main()
RSEG?PR?main?TEST
main:
USING 0
; SOURCE LINE # 1
; {
; SOURCE LINE # 2
; unsigned char *p;
; p=( volatile unsigned char *)(0x90);
; SOURCE LINE # 4
MOV R3,#00H
MOV R2,#00H
MOV R1,#090H
;---- Variable 'p?040' assigned to Register 'R1/R2/R3' ----
; *p=0xf0;
; SOURCE LINE # 5
MOV A,#0F0H
LCALL ?C?CSTPTR
?C0001:
; while(1);
; SOURCE LINE # 6
SJMP ?C0001
; END OF main
END
这是我用at89c51在keil里把程序转换为汇编的代码 jingyong 发表于 2012-4-13 13:09 static/image/common/back.gif
不是很懂指针 但是我觉得*P是数据指针吧 不是程序指针 用汇编去理解
没有说明区别时,在keil里是通用指针,占三个字节
这个在keil的用户手册那里有说明~~~~~ 第四行错了吧!!你是想把0x90这个地址放进指针里吧!!P=0x90,你可以这样写试试!!! 记得 51 的128字节SFR 与RAM高128字节是地址重叠的吧
p=( volatile unsigned char *)(0x90); 指向的RAM区0x90非SFR区的。 墨非 发表于 2012-4-13 13:55 static/image/common/back.gif
记得 51 的128字节SFR 与RAM高128字节是地址重叠的吧
p=( volatile unsigned char *)(0x90); 指向的RAM区 ...
首先谢谢大家了,你说得对,那么怎么指向SFR区呢?谢谢了{:handshake:} NemoGu 发表于 2012-4-13 13:10 static/image/common/back.gif
典型的没事找事
0x90只是SFR地址 SFR定义到SRAM中地址不一定是0x90
呵呵 那是多少,望大虾解答一下,谢谢了{:handshake:} 应该指针指向不对,我不懂汇编,用c语言的话应该是:
*p=P0;或者p=&P0;它就表示指向P0
在给它赋值才对 回头再看 rookieli 发表于 2012-4-13 14:13 static/image/common/back.gif
首先谢谢大家了,你说得对,那么怎么指向SFR区呢?谢谢了
SFR指令是C51为了访问特殊功能寄存器而做的扩展,你现在想跳过它,貌似很难哦! 本帖最后由 catvevs 于 2012-4-13 22:24 编辑
avr是冯诺依曼结构的 51才是哈佛结构间接寻址不能访问特殊功能寄存器
unsigned char*p;只能访问内部RAM
rookieli 发表于 2012-4-13 14:14 static/image/common/back.gif
呵呵 那是多少,望大虾解答一下,谢谢了
不同的单片机不一样啊
例如 CC1111的内部8051把SFR映射到0xDF80~0xDFFF NemoGu 发表于 2012-4-13 15:37 static/image/common/back.gif
不同的单片机不一样啊
例如 CC1111的内部8051把SFR映射到0xDF80~0xDFFF
那stc89c52呢
{:tongue:} rookieli 发表于 2012-4-13 16:01 static/image/common/back.gif
那stc89c52呢
查看datasheet 没办法,除非你自已写个编译器,定义一个特殊指针,专门对SFR进行操作。 如果这种方法可行,不是更好吗,而且ARM等单片机都是这样搞的,干嘛还要搞出sfr来,所以,想想都知道啦 pish 发表于 2012-4-13 17:10 static/image/common/back.gif
如果这种方法可行,不是更好吗,而且ARM等单片机都是这样搞的,干嘛还要搞出sfr来,所以,想想都知道啦 ...
这样设方便你自己,要不然还5要去记地址。 看来是没办法咯,可能要去看编译原理才能解决这个问题{:mad:} 楼主用的到底是什么单片机啊?具体型号
既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr中,但对于52等ram增强型51单片机中,大于7fh的空间是与sfr重合的,用不同的寻址方式来定位具体那块地址。彻底的解决办法你在keil里面查看下ram就可以了 weixinal 发表于 2012-4-13 19:28 static/image/common/back.gif
楼主用的到底是什么单片机啊?具体型号
既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr ...
我用的是stc89c52{:smile:} weixinal 发表于 2012-4-13 19:28 static/image/common/back.gif
楼主用的到底是什么单片机啊?具体型号
既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr ...
谢谢你的回复,是这样的,谢谢了 weixinal 发表于 2012-4-13 19:28 static/image/common/back.gif
楼主用的到底是什么单片机啊?具体型号
既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr ...
“”SFR是特种指令寄存器,地址0x80~0xFF是SFR与RAM地址重叠复用的存储区域。如果用直接寻址的指令访问该区域,则表示SFR;如果用间接寻址(通过@Ri)的指令访问该区域,则表示RAM。物理上不重合,有256字节的RAM和128字节的SFR地址。“”
那么怎么用c语言实现呢
没试过用c实现,看来是欲了解内部结构而不再实际应用,那何必用c呢,用汇编岂不更方便。非得这么做的话,你在c中嵌入汇编试下,这块没有深究 51是冯诺依曼结构的?{:smile:} 是哈弗结构的,因为数据和代码编码地址不统一。 51代码空间和数据空间是分开的,所以还是哈佛结构。
51或者52的寄存器地址 和 RAM 地址是有重复的貌似访问他们是要用不同的指令区别的指针 是访问不到的 ! 51的架构比较怪异,SFR区寄存器只能直接访问,不能通过指针间接访问的。
另外,51是哈佛结构。是哈佛结构的原因并不仅仅因为他不是统一编址的,而主要是程序和内存在内部是采用分开的总线实现的。
更高级的单片机比如ARM,外部表现全部都是统一编址,但CM0就是冯诺依曼结构,CM3就是哈佛结构。 故事又回到了开头。sfr不能在c语言中靠地址访问。只能用嵌入汇编,即楼主提到的《reg51.h》或者sfr之类。 访问SFR时,使用sfr关键字标识变量,如
sfr IOA = 0x80;
如果要使用SFR位寻址,则为
sbit IOA0 = 0x80+0;
或者
sbit IOA0 = IOA ^ 0;
这是Keil的定义,只要你这样声明,Keil会自动用SFR寻址。
能不用汇编尽量不要使用汇编,有大炮了何必再换鸟枪?怀旧?而且你能保证你的所有函数的调用和返回都符合Keil定义?
页:
[1]