社区导航

 

搜索
查看: 7205|回复: 15

用C语言给51单片机编程时,怎么给外部单元的地址赋值(单片机的指针问题)

[复制链接]

120

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-18 02:12 | 显示全部楼层 |阅读模式
初学51单片机,有些问题请教!
我知道在标准c语言里面是不能给指定的一个地址单元赋值的,但是不知道单片机这里能不能这样。
问题1:keil c51中怎么才能使用DPTR寄存器?用keil时包含后我可以使用DPH和DPL但是不能使用DPTR,难道单片机的c里面不能用DPTR?
问题2:单片机的c中指针是多少位的?在标准c里任何类型的指针都是4个字节,即32位(虽然这和操作系统还有编译器有关但一般来说都是32位),但是51单片机好像片内与片外的地址不是一样长的啊(片内8位,片外16位),那么用c给它编程时,其中的指针是多长呢?
问题3:如果我要给一个外部单元,比如0x853f,向这个单元里面写入数据。该怎么办?在标准c里面是不容许直接给一个地址赋值的,但是我在keil里面直接赋值还是能够编译通过,这是否能说这在单片机的编程里面是可以的?
此帖出自编程基础论坛

90

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-18 14:05 | 显示全部楼层
问题1:keil c51中怎么才能使用DPTR寄存器?用keil时包含后我可以使用DPH和DPL但是不能使用DPTR,难道单片机的c里面不能用DPTR?

C里面不推荐直接操作寄存器...

问题2:单片机的c中指针是多少位的?在标准c里任何类型的指针都是4个字节,即32位(虽然这和操作系统还有编译器有关但一般来说都是32位),但是51单片机好像片内与片外的地址不是一样长的啊(片内8位,片外16位),那么用c给它编程时,其中的指针是多长呢?

单片机里的指针分两类,
一类是通用指针,它是三个字节,一个字节是存储区域类型,另外两个字节是地址
一类是确定区域的指针,由于区域确定,那它直接就是一个地址值.有可能是两个字节或是一个字节

问题3:如果我要给一个外部单元,比如0x853f,向这个单元里面写入数据。该怎么办?在标准c里面是不容许直接给一个地址赋值的,但是我在keil里面直接赋值还是能够编译通过,这是否能说这在单片机的编程里面是可以的?
单片机里面没有那些讨厌的高级内存特性,大家都知道的空间,你写就是了,呵呵
但是,这不是一个好的习惯,自己权衡一下哈

回复

使用道具 举报

111

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-18 17:13 | 显示全部楼层

弱问一下,学习51单片机有没有前途啊 ??


回复

使用道具 举报

122

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-19 00:20 | 显示全部楼层
一般类型指针:存储器类型+高位偏移+低位偏移(与标准C相同,不过同时还可以说明指针的存储类型)
如:
long *tate;      //为一个指向 long 型整数的指针,而 tate本身则依存储模式存放
char *xrata ptr; //为一个指向 char数据的指针而 ptr本身放于外部RAM区
例如:
  char *cp;
  int  *ip;
  long *lp;
  
  char data dc='A';
  int data di=12;
  long data dl=2007;
  
  cp=&dc;
  ip=&ip;
  lp=&dl;
同时也可以访问 code存储器,xdata存储器
----------------------------------------------------
存储器指针: 总是指向特定的存储区
如: char data *str;  //str指向data 区中的 char型数据
    int xdata *pow;  //pow指向外部RAM的int 类型数据  
例如:
    char data *cp;   //指向 data存储器中的  char 型变量的指针
    int xdata *ip;   //指向 xdata 存储器中的int  型变量的指针
    long code *lp;   //指向 code 存储器中的 long 型变量的指针

    char data dc='A';
    int xdata buf[3]={'A',12,2007};
    long code lx=2007;
   
    cp=&dc;
    ip=&buf[1];
    lp=&lx;

回复

使用道具 举报

111

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-19 10:20 | 显示全部楼层
……在标准c里面是不容许直接给一个地址赋值的……

我怎么觉得是允许的呢。

回复

使用道具 举报

108

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-20 01:49 | 显示全部楼层
Top  
TheSaviour(恶贯满盈) ( ) 信誉:98  2007-8-19 10:20:18  得分: 0  


   
……在标准c里面是不容许直接给一个地址赋值的……

我怎么觉得是允许的呢。

  

=======================================================
我的意思是说标准c里面不能指定地址。比如给0x9a9590ff地址单元写入数据,你可以?

回复

使用道具 举报

112

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-20 15:58 | 显示全部楼层
Dos时代,经常有为了加速显示直接写显存的勾当,你不知道,不要说人家不能。

回复

使用道具 举报

88

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-21 08:33 | 显示全部楼层
*((unsigned int *)0x9a9590ff) = 0x1000; /* 这算不算指定地址 */

点评

很好!  详情 回复 发表于 2017-11-13 16:57

回复

使用道具 举报

103

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-21 08:34 | 显示全部楼层
对了,这个地址可能不正确,没有字对齐

回复

使用道具 举报

137

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-21 08:34 | 显示全部楼层
*((char *)0x9a9590ff) = 'a';

回复

使用道具 举报

99

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2007-8-23 09:30 | 显示全部楼层
也可以在编译时控制定义变量的地址

然后给该变量赋值,也可达到效果

不过用起来有点麻烦

回复

使用道具 举报

7913

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-11-13 16:56 | 显示全部楼层
嘿嘿,虽然我很久不用51,但这真的是一个好问题哦,,,,1029

回复

使用道具 举报

7913

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2017-11-13 16:57 | 显示全部楼层
hemp 发表于 2007-8-21 08:33
*((unsigned int *)0x9a9590ff) = 0x1000; /* 这算不算指定地址 */

很好!

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

998

TA的帖子

1

TA的资源

禁止发言

发表于 2018-5-10 15:57 | 显示全部楼层
存储芯片/MCU/SRAM/PSRAM/DDR/FLASH/MRAM。web.www.sramsun.com  QQ3161422826 TEL:13751192923

回复

使用道具 举报

7913

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2018-5-13 15:22 | 显示全部楼层
我知道在标准c语言里面是不能给指定的一个地址单元赋值的,但是不知道单片机这里能不能这样。

你所谓的 标准C语言,我想,很大程度上你理解的是基于PC操作系统,也就是windows,linux这类的,你的结论是对的,但坦白说我也不知道为什么,我想也许理由是,这类操作系统因为有MMU的存在,因此并不直接操作物理地址。
单片机里能不能这样?
能。
在51里,其实有一个特别的操作语法,__at__(地址)可以完美解决。
但是,在更加“正经”的单片机,比如STM32里,是没有这个东西的——事实上,除了51这个异类,都不太可能有。
那么,怎么办呢?
*(char *)0x8356 = 0x23;

问题1:keil c51中怎么才能使用DPTR寄存器?用keil时包含后我可以使用DPH和DPL但是不能使用DPTR,难道单片机的c里面不能用DPTR?

我忘了这是个什么寄存器,但看起来反正就是个16位寄存器呗。
其实单片机的C里——确切的说,是不同版本的C编译器和C标准库。
并没有所谓的不能直接操作寄存器的说法。
关键是,有没有开放。
基于上一个问题相同的理由,我不了解WINDOWS LINUX下的C这方面的规定。
但是,在单片机里是可以的。
而其实不管对于51还是对于STM32,最终对于所谓寄存器的操作都等同于 对直接地址的操作,如此而已。
PS一句,在C里,没有什么是可不可以,推荐不推荐的,C很灵活很底层,只是,你要知道自己在做什么。
当然,这些不推荐,也是有道理的,通常是为了获得更好地通用性和降低对硬件的依赖和复杂度。
但如果你知道自己在做什么,没什么不可以的。
就像,如果有人突然问我,倚天剑可不可以叉一只野鸡来烤,你猜我会怎么说?

问题2:单片机的c中指针是多少位的?在标准c里任何类型的指针都是4个字节,即32位(虽然这和操作系统还有编译器有关但一般来说都是32位),但是51单片机好像片内与片外的地址不是一样长的啊(片内8位,片外16位),那么用c给它编程时,其中的指针是多长呢?

还是那句话,你所谓的标准C,看来可以进一步指定为 32位X86机器。
其实,指针的宽度,在我看来,可以粗糙的认为,取决于 机器的机器字长。
有点类似于int的字长。对于8位机51,指针和int都是2字节,对于STM32等通用32位机,那就是4字节。
在单片机里我没见过64位机,所以未曾见过8字节的。

问题3:如果我要给一个外部单元,比如0x853f,向这个单元里面写入数据。该怎么办?在标准c里面是不容许直接给一个地址赋值的,但是我在keil里面直接赋值还是能够编译通过,这是否能说这在单片机的编程里面是可以的?

还是那个解释。
重点在于你的C编译器允不允许你直接操作地址,允许操作什么范围的地址。
在你的标准C里,只有heap上分配的内存允许你直接操作地址,其他都不允许。
而单片机里,我不知道原因,但似乎它都开放了。

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

2

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2018-6-9 10:54 | 显示全部楼层
piaofu 发表于 2007-8-18 17:13
弱问一下,学习51单片机有没有前途啊 ??

前途如何,看你能用这款单片机实现什么功能。看你是实现空调,风扇,洗衣机,等等能满足一大批人的需求的产品。还是只是认识51单片机这个名字。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 1/4 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-6-7 16:58 , Processed in 0.508188 second(s), 36 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表