rookieli 发表于 2012-4-13 13:01:51

各位大神!!懂指针的进

    首先在51中P1的物理地址是90H,如果我不通过用《reg51.h》或者sfr之类的直接用指针,应该
也是可以对P1口进行操作的。
代码如下
void main()
{   
   unsigned char*p;
   p=( volatile unsigned char *)(0x90);
   *p=0xf0;
   while(1);
}
如果上面的代码正确的话,那么8个led是一半亮一半不亮啊,纳闷的是这个程序运行的时候没一点反应,望各位大侠多多指教!!十分感谢

jingyong 发表于 2012-4-13 13:09:38

不是很懂指针 但是我觉得*P是数据指针吧 不是程序指针 用汇编去理解

NemoGu 发表于 2012-4-13 13:10:04

典型的没事找事
0x90只是SFR地址 SFR定义到SRAM中地址不一定是0x90

bangbangji 发表于 2012-4-13 13:12:19

本帖最后由 bangbangji 于 2012-4-13 13:13 编辑

先确定硬件没问题,再确定你的程序确实下进去了
另外51是哈佛结构的,程序和数据是分开编址的,这里是不是有问题

NemoGu 发表于 2012-4-13 13:16:04

bangbangji 发表于 2012-4-13 13:12 static/image/common/back.gif
先确定硬件没问题,再确定你的程序确实下进去了
另外51是哈佛结构的,程序和数据是分开编址的,这里是不是 ...

51是冯诺依曼结构的 AVR才是哈佛结构

y574924080 发表于 2012-4-13 13:17:40

; .\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

y574924080 发表于 2012-4-13 13:19:19

这是我用at89c51在keil里把程序转换为汇编的代码

y574924080 发表于 2012-4-13 13:22:57

jingyong 发表于 2012-4-13 13:09 static/image/common/back.gif
不是很懂指针 但是我觉得*P是数据指针吧 不是程序指针 用汇编去理解

没有说明区别时,在keil里是通用指针,占三个字节

这个在keil的用户手册那里有说明~~~~~

shi_90 发表于 2012-4-13 13:34:47

第四行错了吧!!你是想把0x90这个地址放进指针里吧!!P=0x90,你可以这样写试试!!!

墨非 发表于 2012-4-13 13:55:43

记得 51 的128字节SFR 与RAM高128字节是地址重叠的吧
p=( volatile unsigned char *)(0x90); 指向的RAM区0x90非SFR区的。

rookieli 发表于 2012-4-13 14:13:15

墨非 发表于 2012-4-13 13:55 static/image/common/back.gif
记得 51 的128字节SFR 与RAM高128字节是地址重叠的吧
p=( volatile unsigned char *)(0x90); 指向的RAM区 ...

首先谢谢大家了,你说得对,那么怎么指向SFR区呢?谢谢了{:handshake:}

rookieli 发表于 2012-4-13 14:14:39

NemoGu 发表于 2012-4-13 13:10 static/image/common/back.gif
典型的没事找事
0x90只是SFR地址 SFR定义到SRAM中地址不一定是0x90

呵呵 那是多少,望大虾解答一下,谢谢了{:handshake:}

784956936 发表于 2012-4-13 14:22:31

应该指针指向不对,我不懂汇编,用c语言的话应该是:
*p=P0;或者p=&P0;它就表示指向P0
在给它赋值才对

Garbage614 发表于 2012-4-13 14:27:03

回头再看

墨非 发表于 2012-4-13 14:58:44

rookieli 发表于 2012-4-13 14:13 static/image/common/back.gif
首先谢谢大家了,你说得对,那么怎么指向SFR区呢?谢谢了

SFR指令是C51为了访问特殊功能寄存器而做的扩展,你现在想跳过它,貌似很难哦!

catvevs 发表于 2012-4-13 15:16:24

本帖最后由 catvevs 于 2012-4-13 22:24 编辑

avr是冯诺依曼结构的 51才是哈佛结构间接寻址不能访问特殊功能寄存器
unsigned char*p;只能访问内部RAM

NemoGu 发表于 2012-4-13 15:37:26

rookieli 发表于 2012-4-13 14:14 static/image/common/back.gif
呵呵 那是多少,望大虾解答一下,谢谢了

不同的单片机不一样啊
例如 CC1111的内部8051把SFR映射到0xDF80~0xDFFF

rookieli 发表于 2012-4-13 16:01:35

NemoGu 发表于 2012-4-13 15:37 static/image/common/back.gif
不同的单片机不一样啊
例如 CC1111的内部8051把SFR映射到0xDF80~0xDFFF

那stc89c52呢
{:tongue:}

NemoGu 发表于 2012-4-13 16:22:49

rookieli 发表于 2012-4-13 16:01 static/image/common/back.gif
那stc89c52呢

查看datasheet

banyai 发表于 2012-4-13 16:28:52

没办法,除非你自已写个编译器,定义一个特殊指针,专门对SFR进行操作。

pish 发表于 2012-4-13 17:10:54

如果这种方法可行,不是更好吗,而且ARM等单片机都是这样搞的,干嘛还要搞出sfr来,所以,想想都知道啦

hhxb 发表于 2012-4-13 17:52:24

pish 发表于 2012-4-13 17:10 static/image/common/back.gif
如果这种方法可行,不是更好吗,而且ARM等单片机都是这样搞的,干嘛还要搞出sfr来,所以,想想都知道啦 ...

这样设方便你自己,要不然还5要去记地址。

rookieli 发表于 2012-4-13 18:30:55

看来是没办法咯,可能要去看编译原理才能解决这个问题{:mad:}

weixinal 发表于 2012-4-13 19:28:11

楼主用的到底是什么单片机啊?具体型号

既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr中,但对于52等ram增强型51单片机中,大于7fh的空间是与sfr重合的,用不同的寻址方式来定位具体那块地址。彻底的解决办法你在keil里面查看下ram就可以了

rookieli 发表于 2012-4-13 21:09:57

weixinal 发表于 2012-4-13 19:28 static/image/common/back.gif
楼主用的到底是什么单片机啊?具体型号

既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr ...

我用的是stc89c52{:smile:}

rookieli 发表于 2012-4-13 21:13:15

weixinal 发表于 2012-4-13 19:28 static/image/common/back.gif
楼主用的到底是什么单片机啊?具体型号

既然能编译通过,就说明能找到这块地址,如果是51的话就绝对是在sfr ...

谢谢你的回复,是这样的,谢谢了

rookieli 发表于 2012-4-13 21:24:49

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语言实现呢

weixinal 发表于 2012-4-13 21:37:32

没试过用c实现,看来是欲了解内部结构而不再实际应用,那何必用c呢,用汇编岂不更方便。非得这么做的话,你在c中嵌入汇编试下,这块没有深究

lsy5110 发表于 2012-4-13 22:10:09

51是冯诺依曼结构的?{:smile:}

theophilus 发表于 2012-4-13 22:24:16

是哈弗结构的,因为数据和代码编码地址不统一。

xulong20006 发表于 2012-4-13 22:51:30

51代码空间和数据空间是分开的,所以还是哈佛结构。

728196 发表于 2012-4-13 22:58:25

51或者52的寄存器地址 和 RAM 地址是有重复的貌似访问他们是要用不同的指令区别的指针 是访问不到的 !

takashiki 发表于 2012-4-13 23:09:16

51的架构比较怪异,SFR区寄存器只能直接访问,不能通过指针间接访问的。

另外,51是哈佛结构。是哈佛结构的原因并不仅仅因为他不是统一编址的,而主要是程序和内存在内部是采用分开的总线实现的。
更高级的单片机比如ARM,外部表现全部都是统一编址,但CM0就是冯诺依曼结构,CM3就是哈佛结构。

xizi 发表于 2012-4-14 04:30:04

故事又回到了开头。sfr不能在c语言中靠地址访问。只能用嵌入汇编,即楼主提到的《reg51.h》或者sfr之类。

wye11083 发表于 2012-4-14 08:10:58

访问SFR时,使用sfr关键字标识变量,如
sfr IOA = 0x80;
如果要使用SFR位寻址,则为
sbit IOA0 = 0x80+0;
或者
sbit IOA0 = IOA ^ 0;
这是Keil的定义,只要你这样声明,Keil会自动用SFR寻址。
能不用汇编尽量不要使用汇编,有大炮了何必再换鸟枪?怀旧?而且你能保证你的所有函数的调用和返回都符合Keil定义?
页: [1]
查看完整版本: 各位大神!!懂指针的进