IO 与 MM模式

本文深入探讨了51单片机的IO扩展模式与MM(存储器映射)扩展模式,详细解释了如何通过位定义直接对端口进行赋值,并介绍了在MM模式下如何像操作外部RAM一样操作外部接口器件。文章还提供了蓝桥杯CT107D单片机综合训练平台的实例,展示了如何使用absacc.h头文件进行外部设备的地址访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IO扩展模式

IO模式,我们最开始学习51单片机的时候。

   sbit   P0_0 = P0^0;   //位定义
   P0_0 = 1;             //直接对端口进行赋值。

而P0^0在 reg51.h 中 sfr P0 = 0x80。地址0x80为特殊寄存器。
直接对寄存器赋值。

MM(存储器映射)扩展模式

以传统得8051单片机为例,它具有16位的地址总线和8位数据总线,其中P0口作为数据和地址低字节的复用端口,P2口作为高8位地址总线。以蓝桥杯CT107D单片机综合训练平台为例,MM模式是一种可以像操作外部RAM储存器一样,操作外部接口器件。
所需要包含的头文件: absacc.h (Keil软件自带的库函数)
肯定有对8051单片机的存储地址空间划分不清楚的。下面这个链接可以参考一下。
https://www.cnblogs.com/smartjourneys/p/7487997.html

/*--------------------------------------------------------------------------
ABSACC.H

 直接访问8051,扩展8051和NXP8051MX内存区域..
--------------------------------------------------------------------------*/

#ifndef __ABSACC_H__
#define __ABSACC_H__

#define CBYTE ((unsigned char volatile code  *) 0)
// code ->程序储存区(64K地址范围)
#define DBYTE ((unsigned char volatile data  *) 0)
// data 可寻址片内RAM
#if !defined (__CX2__)
#define PBYTE ((unsigned char volatile pdata *) 0)
// pdata 分页寻址片外RAM
#endif
#define XBYTE ((unsigned char volatile xdata *) 0)
// xdata 可寻址片外RAM

#define CWORD ((unsigned int volatile code  *) 0)
#define DWORD ((unsigned int volatile data  *) 0)
#if !defined (__CX2__)
#define PWORD ((unsigned int volatile pdata *) 0)
#endif
#define XWORD ((unsigned int volatile xdata *) 0)


#if defined (__CX51__) || defined (__CX2__)
#define FVAR(object, addr)   (*((object volatile far *) (addr)))
#define FARRAY(object, base) ((object volatile far *) (base))
#define FCVAR(object, addr)   (*((object const far *) (addr)))
#define FCARRAY(object, base) ((object const far *) (base))
#else
#define FVAR(object, addr)    (*((object volatile far *) ((addr)+0x10000L)))
#define FCVAR(object, addr)   (*((object const far *) ((addr)+0x810000L)))
#define FARRAY(object, base)  ((object volatile far *) ((base)+0x10000L))
#define FCARRAY(object, base) ((object const far *) ((base)+0x810000L))
#endif

#if defined (__CX2__)
#define HBYTE ((unsigned char volatile huge *)  0)
#define HWORD ((unsigned int volatile huge *)  0)
#define HVAR(object, addr)   (*((object volatile huge *) (addr)))
#define HARRAY(object, base) ((object volatile huge *) (base))
#endif

#define CVAR(object, addr)   (*((object volatile code *) (addr)))
#define CARRAY(object, base) ((object volatile code *) (base))
#define DVAR(object, addr)   (*((object volatile data *) (addr)))
#define DARRAY(object, base) ((object volatile data *) (base))
#define XVAR(object, addr)   (*((object volatile xdata *) (addr)))
#define XARRAY(object, base) ((object volatile xdata *) (base))

#endif

蓝桥杯CT107D原理图如下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
不难得出:
Y4C 的地址为:8000H
Y5C 的地址为:A000H
Y6C 的地址为:C000H
Y7C 的地址为:E000H
说白了,类似于片选信号。但是不一样,我的理解是xXBYTE[8000]=0x00。这条指令包含地址信息8000H的锁存和0x00数据的输送。类比8086控制外部接口。

### IO模式内存映射(Memory-Mapped)模式区别 #### 输入输出(IO模式的特点 传统的输入输出(IO模式通常涉及显式的读取写入调用,这些操作由操作系统内核处理。每次执行读或写请求时,都会触发一次上下文切换至内核态,完成数据传输后再切回用户态继续运行应用逻辑。这种过程虽然稳定可靠,但在频繁的小规模数据交换场景下会产生较高的性能损耗。 对于标准的文件IO,在Java中一般采用`RandomAccessFile`类或是NIO库里的`FileChannel.transferTo()`/`transferFrom()`方法来进行大块数据搬运工作;而对于网络通信,则更多依赖于Socket API及其变种形式[^1]。 #### 内存映射(Memory-Mapped)模式的优势 相比之下,内存映射(MMIO/MMF)则提供了一种更为高效便捷的方式去访问外部资源。它允许将整个文件或者部分区域直接映射成进程地址空间的一部分,从而让程序员能够如同对待普通变量那样轻松地对其进行随机访问而无需关心底层细节。具体来说: - **减少系统调用次数**:由于不再需要反复发起read/write指令,因此显著降低了因陷入内核所带来的额外负担; - **简化编程模型**:借助指针算术即可定位目标位置并实施相应动作,极大地方便了复杂结构体序列化等任务; - **提升缓存命中率**:当连续区间被加载进RAM之后,后续对该范围内的任何改动都将自动反映到持久层上,反之亦然,这有助于充分利用现代CPU多级Cache体系带来的好处[^2]。 ```java // Java NIO 中创建一个只读的内存映射文件的例子 import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class MemoryMappedExample { public static void main(String[] args) throws Exception { try (RandomAccessFile file = new RandomAccessFile("example.txt", "r"); FileChannel channel = file.getChannel()) { // 映射文件到内存 MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); // 使用buffer.get() 方法读取字节 while(buffer.hasRemaining()){ System.out.print((char)buffer.get()); } } } } ``` #### 应用场景对比 | 特征 | 常规IO方式 | 内存映射 | | --- | --- | --- | | 数据量大小 | 小型到中型适合批量处理 | 大型文件特别适用 | | 访问频率 | 高频次短时间间隔 | 较低频但可能长时间占用 | | 编程难度 | 简单直观易于理解掌握 | 初期学习曲线稍陡峭一些 | | 性能表现 | 受限于OS调度机制影响较大 | 更加贴近硬件层面发挥潜力 | 综上所述,选择哪种方式进行开发取决于具体的业务需求技术栈考量因素。如果追求极致的速度并且项目环境支持的话,那么显然应该优先考虑后者即内存映射方案;而在其他情况下,传统做法也完全可以胜任大多数日常工作任务[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值