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

小马   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里面直接赋值还是能够编译通过,这是否能说这在单片机的编程里面是可以的?

回复评论 (15)

问题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里面直接赋值还是能够编译通过,这是否能说这在单片机的编程里面是可以的?
单片机里面没有那些讨厌的高级内存特性,大家都知道的空间,你写就是了,呵呵
但是,这不是一个好的习惯,自己权衡一下哈
点赞  2007-8-18 14:05

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

点赞  2007-8-18 17:13
一般类型指针:存储器类型+高位偏移+低位偏移(与标准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;
点赞  2007-8-19 00:20
……在标准c里面是不容许直接给一个地址赋值的……

我怎么觉得是允许的呢。
点赞  2007-8-19 10:20
Top  
TheSaviour(恶贯满盈) ( ) 信誉:98  2007-8-19 10:20:18  得分: 0  


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

我怎么觉得是允许的呢。

  

=======================================================
我的意思是说标准c里面不能指定地址。比如给0x9a9590ff地址单元写入数据,你可以?
点赞  2007-8-20 01:49
Dos时代,经常有为了加速显示直接写显存的勾当,你不知道,不要说人家不能。
点赞  2007-8-20 15:58
*((unsigned int *)0x9a9590ff) = 0x1000; /* 这算不算指定地址 */
点赞  2007-8-21 08:33
对了,这个地址可能不正确,没有字对齐
点赞  2007-8-21 08:34
*((char *)0x9a9590ff) = 'a';
点赞  2007-8-21 08:34
也可以在编译时控制定义变量的地址

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

不过用起来有点麻烦
点赞  2007-8-23 09:30
嘿嘿,虽然我很久不用51,但这真的是一个好问题哦,,,,1029
点赞  2017-11-13 16:56
引用: hemp 发表于 2007-8-21 08:33
*((unsigned int *)0x9a9590ff) = 0x1000; /* 这算不算指定地址 */

很好!
强者为尊,弱者,死无葬身之地
点赞  2017-11-13 16:57
存储芯片/MCU/SRAM/PSRAM/DDR/FLASH/MRAM。web.www.sramsun.com  QQ3161422826 TEL:13751192923
点赞  2018-5-10 15:57
引用: 我知道在标准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上分配的内存允许你直接操作地址,其他都不允许。
而单片机里,我不知道原因,但似乎它都开放了。
强者为尊,弱者,死无葬身之地
点赞  2018-5-13 15:22
引用: piaofu 发表于 2007-8-18 17:13
弱问一下,学习51单片机有没有前途啊 ??

前途如何,看你能用这款单片机实现什么功能。看你是实现空调,风扇,洗衣机,等等能满足一大批人的需求的产品。还是只是认识51单片机这个名字。
点赞  2018-6-9 10:54
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复