广州周立功单片机发展有限公司Te:(020)38730916387309173870976387097Fax389305 位寻址,可以通过包含 float和1ong的联合来实现 列表0-4 //定义联合类型 unsigned long lvalue //长整型32位 float fvalue //浮点数32位 ybit float //联合名 bit float bdata myfloat: //在 BDATA段中声名联合 bit float ld=myfloat 31 定义位变量名 下面的代码访问状态寄存器的特定位。把访问定义在DATA段中的一个字节和通过位名 和位号访问同样的可位寻址字节的位的代码对比。注意,对变量位进行寻址产生的汇编代 码比检测定义在DATA段的状态字节位所产生的汇编代码要好。如果你对定义在 BDATA段中 的状态字节中的位采用偏移量进行寻址,而不是用先前定义的位变量名时,编译后的代码 是错误的。下面的例子中 use bitnum status的汇编代码比 use byte status的代码要 大 列表0-5 //定义一个字节宽状态寄存器 unsigned char data byte status=0x43; //定义一个可位寻址状态寄存器 unsigned char bdata bit status=0x43 6 //把 bit status的第3位设为位变量 sbit status 3=bit status 3 bit use bitnum status (void) bit use byte status(void) 15 unsigned char temp=O if( use bit status0){//如果第3位置位temp加1 if(use_ byte status0){//如果第3位置位temp再加1 f( use bitnum status(){/如果第3位置位temp再加1 bit use bit status(void)I n (bit(
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925 21 位寻址 可以通过包含 float 和 long 的联合来实现 列表 0-4 typedef union{ //定义联合类型 unsigned long lvalue; //长整型 32 位 float fvalue; //浮点数 32 位 }bit_float; //联合名 bit_float bdata myfloat; //在 BDATA 段中声名联合 sbit float_ld=myfloat^31 //定义位变量名 下面的代码访问状态寄存器的特定位 把访问定义在 DATA 段中的一个字节和通过位名 和位号访问同样的可位寻址字节的位的代码对比 注意 对变量位进行寻址产生的汇编代 码比检测定义在 DATA 段的状态字节位所产生的汇编代码要好 如果你对定义在 BDATA 段中 的状态字节中的位采用偏移量进行寻址 而不是用先前定义的位变量名时 编译后的代码 是错误的 下面的例子中 use_bitnum_status 的汇编代码比 use_byte_status 的代码要 大 列表 0-5 1 //定义一个字节宽状态寄存器 2 unsigned char data byte_status=0x43; 3 4 //定义一个可位寻址状态寄存器 5 unsigned char bdata bit_status=0x43; 6 //把 bit_status 的第 3 位设为位变量 7 sbit status_3=bit_status^3; 8 9 bit use_bit_status(void); 10 11 bit use_bitnum_status(void); 12 13 bit use_byte_status(void); 14 15 void main(void){ 16 unsigned char temp=0; 17 if (use_bit_status()){ //如果第 3 位置位 temp 加 1 18 temp++; 19 } 20 if (use_byte_status()){ //如果第 3 位置位 temp 再加 1 21 temp++; 22 } 23 if (use_bitnum_status()){ //如果第 3 位置位 temp 再加 1 24 temp++; 25 } 26 } 27 28 bit use_bit_status(void){ 29 return(bit)(status_3);
广州周立功单片机发展有限公司Tel:(020)38730916387309173873097638730977Fax:38730925 233 bit use bitnum status(void)( return(bit)(bit status 3) bit use byte status (void)i return byte status&0x04 目标代码列表 FUNCTION main(BEGIN) SOURCE LINE 15 SOURCE LINE #16 0000E4 LR A 0001F500R Mov temp, A SOURCE LINE #17 0003120000R LCaLL use bit status 00065002 JNC ?C0001 SOURCE LINE #18 00080500R SOURCE LINE #19 000A C0001 SOURCE LINE 20 000A120000 LCALL use byte status 000D5002 JNC ?C0002 SOURCE LINE 21 000F0500R SOURCE LINE 22 0011 ?C0002: SOURCE LINE 23 0011120000R LCALL use bitnum status 00145002 NC?C0004 SOURCE LINE #24 00160500R INC temp SOURCE LINE 25 SOURCE LINE 26 ?00004: 001822 RET FUNCTION main(END) UNCTION use bit status (BEGIN) SOURCE LINE #28 SOURCE LINE 29 0000A200R Mov C status 3 SOURCE LINE 30
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925 22 30 } 31 32 bit use_bitnum_status(void){ 33 return(bit)(bit_status^3); 34 } 35 36 bit use_byte_status(void){ 37 return byte _status&0x04; 38 } 目标代码列表 ; FUNCTION main (BEGIN) ; SOURCE LINE # 15 ; SOURCE LINE # 16 0000 E4 CLR A 0001 F500 R MOV temp,A ; SOURCE LINE # 17 0003 120000 R LCALL use_bit_status 0006 5002 JNC ?C0001 ; SOURCE LINE # 18 0008 0500 R INC temp ; SOURCE LINE # 19 000A ?C0001: ; SOURCE LINE # 20 000A 120000 R LCALL use_byte_status 000D 5002 JNC ?C0002 ; SOURCE LINE # 21 000F 0500 R INC temp ; SOURCE LINE # 22 0011 ?C0002: ; SOURCE LINE # 23 0011 120000 R LCALL use_bitnum_status 0014 5002 JNC ?C0004 ; SOURCE LINE # 24 0016 0500 R INC temp ; SOURCE LINE # 25 ; SOURCE LINE # 26 0018 ?C0004: 0018 22 RET ; FUNCTION main (END) ; FUNCTION use_bit_status (BEGIN) ; SOURCE LINE # 28 ; SOURCE LINE # 29 0000 A200 R MOV C,status_3 ; SOURCE LINE # 30
广州周立功单片机发展有限公司Te:(020)38730916387309173870976387097Fax389305 0002 ?C0005 000222 RET FUNCTION use bit status (END) FUNCTiON use bitnum status (bEgIN The compiler obtains the desired bit by using the entire byte instead of using a bit address SOURCE LINE 32 SOURCE LINE 33 0000E500R Mov A bit status 00026403 KRL A#03H 000424FF ADD A #OFFH SOURCE LINE 34 ?C0006 000622 FUNCTIoN use bitnum status (END FUNCTION use byte status(BEGIN) SOURCE LINE 36 SOURCE LINE 37 0000E500R Mov A, byte status 0002A2E2 MOv C ACC. 2 SOURCE LINE 38 0004 ?C0007: 00042 FUNCTION use byte status(END) 记住在处理位变量时,要使用声明的位变量名,而不要使用偏移量 4.31DATA段 IDATA段也可存放使用比较频繁的变量,使用寄存器作为指针进行寻址。在寄存器中 设置8位地址,进行间接寻址。和外部存储器寻址比较,它的指令执行周期和代码长度都 比较短 unsigned char idata system status=0 unsigned int idata unit id[2] char idata inp string[16] float idata outp value 4.4 PDATA和 XDATA段 在这两个段声明变量和在其它段的语法是一样的。 PDATA段只有256个字节,而 XDATA 段可达65536个字节。下面是一些例子 unsigned char xdata system status=0 unsigned int pdata unit id[2] char xdata inp string[16] float pdata outp value 对 PDATA和 XDATA的操作是相似的。对 PDATA段寻址比对 XDATA段寻址要快,因为, 对 PDATA段寻址只需要装入8位地址,而对ⅫDATA段寻址需装入16位地址。所以尽量把外
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925 23 0002 ?C0005: 0002 22 RET ; FUNCTION use_bit_status (END) ; FUNCTION use_bitnum_status (BEGIN) The compiler obtains the desired bit by using the entire byte instead of using a bit address. ; SOURCE LINE # 32 ; SOURCE LINE # 33 0000 E500 R MOV A,bit_status 0002 6403 XRL A,#03H 0004 24FF ADD A,#0FFH ; SOURCE LINE # 34 0006 ?C0006: 0006 22 RET ; FUNCTION use_bitnum_status (END) ; FUNCTION use_byte_status (BEGIN) ; SOURCE LINE # 36 ; SOURCE LINE # 37 0000 E500 R MOV A,byte_status 0002 A2E2 MOV C,ACC.2 ; SOURCE LINE # 38 0004 ?C0007: 0004 22 RET ; FUNCTION use_byte_status (END) 记住在处理位变量时 要使用声明的位变量名 而不要使用偏移量 4.3 IDATA 段 IDATA 段也可存放使用比较频繁的变量 使用寄存器作为指针进行寻址 在寄存器中 设置 8 位地址 进行间接寻址 和外部存储器寻址比较 它的指令执行周期和代码长度都 比较短 unsigned char idata system_status=0; unsigned int idata unit_id[2]; char idata inp_string[16]; float idata outp_value; 4.4 PDATA 和 XDATA 段 在这两个段声明变量和在其它段的语法是一样的 PDATA 段只有 256 个字节 而 XDATA 段可达 65536 个字节 下面是一些例子 unsigned char xdata system_status=0; unsigned int pdata unit_id[2]; char xdata inp_string[16]; float pdata outp_value; 对 PDATA 和 XDATA 的操作是相似的 对 PDATA 段寻址比对 XDATA 段寻址要快 因为 对 PDATA 段寻址只需要装入 8 位地址 而对 XDATA 段寻址需装入 16 位地址 所以尽量把外
广州周立功单片机发展有限公司Te:(020)38730916387309173870976387097Fax389305 部数据存储在 PDATA段中。对 PDATA和 XDATA寻址要使用MoWX指令,需要两个处理周期 列表0-6 1 #include <reg51. h> 3 unisgned char pdata inp regl 5 unsigned char xdata inp reg2 7 void main(void) inp regl=Pl 9 inp reg2=P3 10} 产生的目标代码列表 FUNcTIoN main (BEGIN) SOURCE LINE 7 SOURCE LINE 8 注意' inp regl=P1’需要4个指令周期 00007800R MOV RO, #inp regl 0002E590 A. Pl 0004 MOVX @RO.A SOURCE LINE 9 注意' inp reg2=P3’需要5个指令周期 0005900000R MOV DPTR, #inp reg2 0008E5B0 MOV A. P3 000AF0 MOVX DPTR. A SOURCE LINE 10 000B22 FUNCTION main (END) 经常,外部地址段中除了包含存储器地址外还包含I/0器件的地址。对外部器件寻址 可通过指针或C51提供的宏。我建议使用宏对外部器件进行寻址,因为这样更有可读性。 宏定义使得存储段看上去像char和int类型的数组。下面是一些绝对寄存器寻址的例子。 列表0-7 inp byte= XBYTE[0x8500]:从地址8500H读一个字节 inp word= XWORD[0x4000];/从地址4000H读一个字和2001H c=*(( char xdata*)0x0000);//从地址000读一个字节 XBYTE[Ox7500]=out val /写一个字节到7500H 可对除 BDATA和BT段之外的其它数据段采用以上方法寻址。通过包含头文件 absacc. h 来进行绝对地址访问 4.500DE段 代码段的数据是不可改变的,8051的代码段不可重写。一般,代码段中可存放数据表
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925 24 部数据存储在 PDATA 段中 对 PDATA 和 XDATA 寻址要使用 MOVX 指令 需要两个处理周期 列表 0-6 1 #include <reg51.h> 2 3 unisgned char pdata inp_reg1; 4 5 unsigned char xdata inp_reg2; 6 7 void main(void){ 8 inp_reg1=P1; 9 inp_reg2=P3; 10 } 产生的目标代码列表 ; FUNCTION main (BEGIN) ; SOURCE LINE # 7 ; SOURCE LINE # 8 注意 'inp_reg1=P1' 需要4个指令周期 0000 7800 R MOV R0,#inp_reg1 0002 E590 MOV A,P1 0004 F2 MOVX @R0,A ; SOURCE LINE # 9 注意 'inp_reg2=P3' 需要5个指令周期 0005 900000 R MOV DPTR,#inp_reg2 0008 E5B0 MOV A,P3 000A F0 MOVX @DPTR,A ; SOURCE LINE # 10 000B 22 RET ; FUNCTION main (END) 经常 外部地址段中除了包含存储器地址外还包含 I/O 器件的地址 对外部器件寻址 可通过指针或 C51 提供的宏 我建议使用宏对外部器件进行寻址 因为这样更有可读性 宏定义使得存储段看上去像 char 和 int 类型的数组 下面是一些绝对寄存器寻址的例子 列表 0-7 inp_byte=XBYTE[0x8500]; // 从地址8500H读一个字节 inp_word=XWORD[0x4000]; // 从地址4000H读一个字和2001H c=*((char xdata *) 0x0000); // 从地址0000读一个字节 XBYTE[0x7500]=out_val; // 写一个字节到 7500H 可对除BDATA和BIT段之外的其它数据段采用以上方法寻址 通过包含头文件 absacc.h 来进行绝对地址访问 4.5 CODE 段 代码段的数据是不可改变的 8051 的代码段不可重写 一般 代码段中可存放数据表
广州周立功单片机发展有限公司Te:(020)38730916387309173870976387097Fax389305 跳转向量和状态表。对CODE段的访问和对XATA段的访问的时间是一样的。代码段中的对 象在编译的时候初始化,否则,你就得不到你想要的值。下面是代码段的声明例子 unsigned int code unit id[2]=1234 unsigned char 0x00,0x01,0x02,0x03, 0x05, 0x07, 0x08,0x09,0x10,0x11 0x15 5指针 C51提供一个3字节的通用存储器指针。通用指针的头一个字节表明指针所指的存储 区空间。另外两个字节存储16位偏移量。对于 DATA, IDATA和 PDATA段,只需要8位偏移量。 指针类型 大小 通用指针 Kei1允许使用者规定指针指向的存储段。(XA指针 这种指针叫具体指针。使用具体指针的好处是【CODE指针 节省了存储空间。编译器不用为存储器选择和DAA指针 1字节 决定正确的存储器操作指令产生代码,这样就 pdatA指针 1字节 使代码更加简短,但你必须保证指针不指向你 表0-5 所声明的存储区以外的地方,否则会产生错误 而且很难调试。 下面的例子反映出使用具体指针比使用通用指针更加高效。使用通用指针的第一个循 环需要378个处理周期,使用具体指针只需要151个处理周期 列表0-8 #include <absacc h 123456789 har data xd pt har mystring [="Test output maino t 101 generic ptr=mystring 111 while (*generic ptr) XBYTE[Ox0000]=*generic_ptr; generic_ptr++ 142 151 161 xd ptr=mysti KBYTE [OX0000]=*xd ptr xd ptr++ 编译产生的汇编代码
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925 25 跳转向量和状态表 对 CODE 段的访问和对 XDATA 段的访问的时间是一样的 代码段中的对 象在编译的时候初始化 否则 你就得不到你想要的值 下面是代码段的声明例子 unsigned int code unit_id[2]=1234; unsigned char 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 }; 5 指针 C51 提供一个 3 字节的通用存储器指针 通用指针的头一个字节表明指针所指的存储 区空间 另外两个字节存储 16 位偏移量 对于 DATA IDATA 和 PDATA 段 只需要 8 位偏移量 Keil 允许使用者规定指针指向的存储段 这种指针叫具体指针 使用具体指针的好处是 节省了存储空间 编译器不用为存储器选择和 决定正确的存储器操作指令产生代码 这样就 使代码更加简短 但你必须保证指针不指向你 所声明的存储区以外的地方 否则会产生错误 而且很难调试 下面的例子反映出使用具体指针比使用通用指针更加高效 使用通用指针的第一个循 环需要 378 个处理周期 使用具体指针只需要 151 个处理周期 列表 0-8 1 #include <absacc.h> 2 3 char *generic_ptr; 4 5 char data *xd_ptr; 6 7 char mystring[]="Test output"; 8 9 main() { 10 1 generic_ptr=mystring; 11 1 while (*generic_ptr) { 12 2 XBYTE[0x0000]=*generic_ptr; 13 2 generic_ptr++; 14 2 } 15 1 16 1 xd_ptr=mystring; 17 1 while (*xd_ptr) { 18 2 XBYTE[0x0000]=*xd_ptr; 19 2 xd_ptr++; 20 2 } 21 1 } 编译产生的汇编代码 指针类型 大小 通用指针 3 字节 XDATA 指针 2 字节 CODE 指针 2 字节 IDATA 指针 1 字节 DATA 指针 1 字节 PDATA 指针 1 字节 表 0-5