用" #include<absacc.h> “ 即可使用其中定义的宏来访问绝对地址

本文详细介绍了51单片机通过8255和锁存器74LS273进行IO扩展的方法,重点解析了absacc.h头文件中的宏定义及其在访问外部RAM和程序存储器中的应用。

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

51单片机通过8255和锁存器74LS273来扩展IO时,经常用到头文件absacc.h

在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:CBYTE、XBYTE、

PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD

例如:
rval=CBYTE[0x0002];指向程序存贮器的0002h地址
rval=XWORD [0x0002];指向外RAM的0004h地址

================================================================================

KEIL中ABSACC.H定义如下:

#ifndef __ABSACC_H__
#define __ABSACC_H__

#define CBYTE  ((unsigned char volatile code *) 0)
#define DBYTE  ((unsigned char volatile data *) 0)
#define PBYTE  ((unsigned char volatile pdata *) 0)
#define XBYTE  ((unsigned char volatile xdata *) 0)

#define CWORD  ((unsigned int volatile code *) 0)
#define DWORD  ((unsigned int volatile data *) 0)
#define PWORD  ((unsigned int volatile pdata *) 0)
#define XWORD  ((unsigned int volatile xdata *) 0) /*
外部 RAM */


#ifdef __CX51__
#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

#endif

========================================================================

xdatalarge存储类型,volatile是通过硬件来改变指针指向的内容。

#define XBYTE    ((unsigned char volatile xdata *) 0)定义 XBYTE指向

xdata地址空间unsigned char数据类型的指针,指针值为0这样,

可以直接用XBYTE[0xnnnn]*(XBYTE+0xnnnn)访问外部RAM了。

/**********************************CBYTE********************************/

Q:

absacc.h里的宏
#define   CBYTE    ((unsigned char volatile code *) 0)
value = CBYTE[0x002];
这句该如何理解?

A1:

结果是将程序空间(code)地址为0x002单元的内容放到变量value中。
A2:

替换一下考虑
value = ((unsigned char volatile *) 0)[0x02];
替换一下考虑
unsigned char volatile *CBYTE = 0/*NULL*/;
这里CBYTE[0x02]= 1和*(CBYTE+0x02) = 1等价

#define   CBYTE   ((unsigned char volatile code *) 0)
是把CBYTE是指针,即code地址0
在这里,数组和指针是可以互用的。CBYTE[0x02]也就是*(CBYTE+0x02),都

是指的是地址0x02里的内容,并是unsignedchar 类型的。

#defineCBYTE   ((unsigned char volatile code *) 0)
考虑下这个define定义的内容
1、把CBYTE定义成一个0(0);
2、这个0是个地址(*号);
3、这个地址是代码段的地址(code);
4、并是unsignedchar类型的地址(unsigned char);
5、并这个地址的内容是易逝性的(volatile);

本质上是定义了一个地址(CBYTE)。指针就是地址。地址是内存的序号。
指针通过指向内存的序号访问内存。替换点是都是地址。

内部的括号用来强制类型转换用的,外部的的括号用来防止宏定义展开时错误的用法。

/*************************************************************************************/

再如:

#define COM8255 XBYTE[0X060FF] //后面若出现COM8255,

则单片机端口P0和P2联合输出0X060FF绝对物理地址(地址指向82C55指令寄存器)
#define PA8255 XBYTE[0X000FF] //后面若出现PA8255,

则单片机端口P0和P2联合输出0X000FF绝对物理地址(地址指向82C55的A组端口寄存器)
#define PB8255 XBYTE[0X020FF] //后面若出现PB8255,

则单片机端口P0和P2联合输出0X020FF绝对物理地址(地址指向82C55的B组端口寄存器)
#define PC8255 XBYTE[0X040FF] //后面若出现PC8255,

则单片机端口P0和P2联合输出0X040FF绝对物理地址(地址指向82C55的C组端口寄存器)

 

#include <reg51.h> #include <stdio.h> #include <absacc.h> #define display_function_switch_key 0x0F #define keyValue_address 0x9001 #define wx 0x9002 #define dx 0x9004 unsigned char display_array[6] = {16, 16, 16, 16, 16, 16}; unsigned char display_function_switch_flag = 0; unsigned char keyValue = 0xFF; unsigned char nixie_table[] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x80 }; void Delay1ms(int cnt) //@12.000MHz { unsigned char a,b,c; do{ for(c=1;c>0;c--) for(b=142;b>0;b--) for(a=2;a>0;a--); }while(--cnt); } unsigned char keyRow_table[4] ={0x07,0x0B,0x0D,0x0E}; unsigned char display_scanning(void) { unsigned char keyColumn = 0x01,i=0,j=0,p=0; for(i = 0; i < 6 ; i++) { if(display_function_switch_flag) p=i; XBYTE[dx] = 0x00; XBYTE[wx] = ~keyColumn; for(j = 0;j < 4;j++) { if((XBYTE[keyValue_address] % 0x0F) == keyRow_table[j]) { //Delay1ms(25); //if((XBYTE[keyValue_address] % 0x0F) != keypad_table[j]) return 0xFF; Delay1ms(10); if((XBYTE[keyValue_address] % 0x0F) == keyRow_table[j]) return 0xFF; switch((keyRow_table[j]<<4)+i) { case 0x75:return 0x07; case 0x74:return 0x08; case 0x73:return 0x09; case 0x72:return 0x0A; case 0xB5:return 0x04; case 0xB4:return 0x05; case 0xB3:return 0x06; case 0xB2:return 0x0B; case 0xD5:return 0x01; case 0xD4:return 0x02; case 0xD3:return 0x03; case 0xD2:return 0x0C; case 0xE5:return 0x00; case 0xE4:return 0x0F; case 0xE3:return 0x0E; case 0xE2:return 0x0D; //default: return 0x10; } } } XBYTE[dx] = nixie_table[display_array[p]]; XBYTE[wx] = 0x01<<(p); Delay1ms(1); keyColumn = keyColumn << 1; } return 0xFF; } void UART_send_data(unsigned char send_data) { if(send_data == display_function_switch_key) SBUF = '\n'; else if(send_data >= 0&&send_data <= 9) SBUF = send_data + '0'; else if(send_data >= 10&&send_data <= 15) SBUF = send_data - 10 + 'A'; while (!TI); TI =
03-12
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值