找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

89c52关于volatile和地址

查看数: 787 | 评论数: 8 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2025-9-26 22:43

正文摘要:

回复

ID:879809 发表于 2025-9-28 11:07
那就是C51用@Ri(i=0,1)指令冒充指针,这个指令无法访问SFR。
ID:996773 发表于 2025-9-27 19:42
特殊功能寄存器是开启其他用途的,有的是io口大电流强拉功能,有的是开启扩展大ram,怎么可能随便写
数据进去呢,这些硬件结构不了解怎么玩编程
ID:73992 发表于 2025-9-27 19:39
angmall 发表于 2025-9-27 11:10
你的现象和疑惑主要来自以下几点8051 C的“data/volatile/特殊功能寄存器指针”混用特点和陷阱:[/backcolo ...

谢谢,
仔细查了一下资料。sfr没有间址访问指令。想动态直接访问sfr不容易做到。
ID:57657 发表于 2025-9-27 15:13
此型号较老,大部分特殊功能寄存器地址都是空白不可写。
具体把源码粘贴完整才能知道是什么问题造成的。
ID:879809 发表于 2025-9-27 14:32
看汇编呗!你也是研究了好多年ARM汇编的烈士,看51汇编还不是小菜一碟?
ID:73992 发表于 2025-9-27 14:27
c语言指针方式访问不了特殊功能寄存器。【已解决】
ID:155507 发表于 2025-9-27 11:10
[color=oklch(0.3039 0.04 213.68)][backcolor=oklch(0.9902 0.004 106.47)]你的现象和疑惑主要来自以下几点8051 C的“data/volatile/特殊功能寄存器指针”混用特点和陷阱:

1. data修饰符和data空间的指针
  • unsigned char data *i; 表示i指向8051内部128B“data”RAM。
  • 但“data”空间不能像xdata/idata那样灵活用指针访问(只能指向data区),很多C51编译器不支持unsigned char data *i指向特殊功能寄存器SFR区。
  • 某些8051编译器(如Keil/A51)对指针的空间必须严格匹配,若i指向非法或未初始化,*i等操作是未定义行为。


2. volatile修饰作用
  • volatile 强制每次都从实际地址读/写,防止编译器优化。
  • 但它仅确保不会被寄存器优化;对于8051结构,“volatile unsigned char data *”/“volatile unsigned char *”并不会强制访存到SFR,指针空间依然要对。
  • 指针类型和空间匹配,决定访问到哪块内存(data/xdata/idata/bit/SFR等)。


3. 写SFR的正确方式与陷阱
  • SFR(特殊功能寄存器)必须用__sfr或特定映射(如Keil的#define SBUF (*((volatile unsigned char xdata *)0x99)))。
  • 不建议用data *指针写SFR,因为data区和SFR物理分区,虽然低地址重叠,但直接赋值是未定义行为。
  • “去掉data修饰后能正确访问”说明默认指针为idata,读写到某些普通RAM区域;SFR必须显式用SFR或映射。


4. 你的问题总结建议
  • 写RAM用“data”或"idata"指针,写SFR(如P1OUT、SBUF等)用__sfr/__at/特定映射。
  • “data *”只能访问内部data RAM,不要用来访问SFR,否则结果不确定。
  • volatile正确用法是修饰SFR/多任务通信的全局变量。
  • 指针未初始化直接用*i也是未定义,需i = (unsigned char data*)0xXX;后再用。

  • 普通RAM用“data”/“idata”修饰,SFR须显式区分,用volatile修饰SFR/全局变量更保险。


总结
  • 8051的“data”指针不能写SFR区,SFR要用对应修饰。
  • “volatile”能防止代码优化丢失硬寄存器IO,但要配合内存区修饰符。
  • 指针空间错误时,编译器不会自动抛错,但是实际指令不会正确定址,导致写不进去或数据异常。

[color=oklch(0.3039 0.04 213.68)][backcolor=oklch(0.9902 0.004 106.47)]你的问题实际和51单片机的内存分区、C指针空间修饰和volatile的用途紧密相关:

8051 data/xdata 指针和SFR的本质
  • “unsigned char data *i;”为data区指针,只能指向8051的内部128B RAM,不能指向SFR特殊功能寄存器区。
  • SFR区(0x80~0xFF)只能用sfr关键字或指向SFR区的特殊指针访问,data属性不能越区。
  • MCU支持的"data"等空间关键字要求指针和被它指的对象空间一致,否则结果未定义。
  • 写普通RAM,普通指针或data修饰均可;写SFR必须用sfr或xdata/特殊映射。
  • 去掉data后,C编译器一般用默认idata/xdata指针,此时RAM可正常,SFR又可能无效。


volatile的实际作用
  • volatile只保证变量每次都真实访存,不被寄存器缓存或优化。
  • 对于SFR,要保证写入寄存器,每次操作需要同时volatile和正确空间修饰。
  • 写普通RAM不需要volatile,写SFR/外设/与中断访问一致的全局变量需加volatile。


实用建议
  • 正确访问SFR:用sfr宏定义(如sfr P1 = 0x90;)或 #define SBUF (*((volatile unsigned char xdata *)0x99))。
  • 不要用data修饰指针去操作SFR。
  • volatile通常只修饰外设映射和ISR共享变量。



总结
  • data类指针不能写SFR区
  • volatile修饰不能替代空间修饰,空间要对,SFR需专有定义宏
  • RAM变量正常用指针,SFR只能专用通道
  • “去掉data修饰写内存正确,SFR不对”本质是指针空间错


ID:1109793 发表于 2025-9-27 07:48
不太懂,就是为了学习指针操作才这么搞的吗?另外哪位前辈给说说为何在形参中使用volatile?

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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