当前位置:   article > 正文

51单片机学习过程中的常见疑惑_stc89c5xrc.h

stc89c5xrc.h

一、什么是51单片机?AT89C51、STC89C51、BF7615BM28这些都是51单片机吗?

        答:51单片机兼容Intel 8051指令系统的单片机的总称,与具体生产厂商和单片机型号没有直接关联。上述单片机都使用了Intel 8051指令系统(含自主增加指令的增强型),所以都是51单片机。

二、MCS-51和8051是否是相同的意思?

答:MCS是Intel公司单片机的系列符号,有MCS-48、MCS-51、MCS-96等系列,而经典的MCS-51系列包含三个基本型80C31、8051、8751,以及对应的低功耗型号80C31、8051、87C51,因而MCS-51特指Intel的这几种型号。由于2007年后Intel停止了MCS系列单片机的生产,所以准确来说,后面其他厂商生产的AT89C51等单片机不属于MCS-51系列。

        8051一般是指Intel 8051指令系统(指令集),只要单片机仍使用Intel 8051指令系统,那么仍可称为8051单片机,简称51单片机。

---参考资料《MCS51和8051是否相同?》

三、8051经典内部结构是怎样的?

 四、AT89C51是51单片机,那么AT89C52是52单片机吗?

        答:不是,51单片机是指使用了Intel 8051指令系统(指令集)的单片机,一般没有52单片机的说法。之所以存在AT89C52这一型号的单片机,是因为在早期AT89C51单片机的基础上额外增加了一个定时器/计数器T2,并且升级了RAM和ROM的内存,所以AT89C52可以视作为AT89C51的强化版。

 五、学生时代,国内常见的51单片机为STC公司产的STC89C52RC,编程时需要注意什么?

        答:STC89C52RC是STC(宏晶科技)公司基于8051内核推出的一款51单片机,编程前需要通过STC推出的ISP下载软件将器件包注入Keil软件安装目录下,准确选择单片机型号。

        当然,由于都使用了8051指令系统,单片机型号选择为AT89C52也可以编译,但是STC多出的部分特殊功能寄存器无法直接使用(头文件未声明部分寄存器),需要自行使用SFR声明。

 六、时常看见程序开头有内置头文件,#include<REG51.h>和#include<REG52.h>有何不同?

        答:其实头文件中写的很明白,相关描述如下:

        REG51.h:Header file for generic 80C51 and 80C31 microcontroller.

        REG52.h:Header file for generic 80C52 and 80C32 microcontroller.

        通过WinMerge对比分析这两个文件,我们可以清晰地发现    REG52.h在REG51.h的基础上增加了对定时器/计数器T2相关寄存器的声明。也就是说,如果在程序中使用了定时器/计数器T2相关寄存器,#include<REG51.h>时就需要自行对相关寄存器声明,否则编译器就会报错。头文件REG52.h中已经对相关寄存器做出声明,在程序中可直接使用。

 七、#include<REG51.h>和#include"REG52.h"有何不同?

        答:尖括号包含的头文件是编译器自带的头文件,这一类文件通常放在编译器安装目录下。英文双引号包含的头文件一般是自己编写的头文件,通常放在工程文件目录下,当程序编译时找不到该文件时也会到编译器安装目录下找一遍,但是还是建议按照规范编程。

 八、为什么有时候程序中看不到#include<REG51.h>或#include"REG52.h",这样的程序也可以运行吗?

        答:头文件不是必要的,如果不嫌麻烦,在程序中自行声明自己用到的寄存器也可以。

 九、为什么有时候程序中会见到#include <STC89C5xRC.H>,却没有#include<REG52.h>?

        答:STC89C5xRC.H其实是STC(宏晶科技)自己在REG51F.H的基础上增添了部分自行设计的特殊功能寄存器,内置STC89C5xRC.H时就无需再声明STC自行增添的寄存器。简单来说,REG51F.H是STC89C5xRC.H的真子集。

 十、如果厂商对每一款单片机都有定义头文件,但是我不知道名字该如何添加到程序中呢?

        答:其实只需在程序中单击右键,就能看到插入头文件的相关提示了。 

十一、新建工程时,会有提示将标准8051启动文件代码到工程中,这个是必要的文件吗?

        答:是的,单片机上电时候一般需要对堆栈、引脚等初始化,这些都需要依靠使用汇编编写的启动代码来执行。

11.1 启动文件添加提示
11.2 缺失启动文件生成的汇编指令
11.3 添加启动文件生成的汇编指令

 十二、源文件底下的头文件是如何添加进去的呢?

        答:在源文件中使用#include"xxx.h"就可以添加进去,不过在编译之前得让编译器知道这个头文件在哪儿,这就需要添加头文件路径,方式如图12.1所示:

12.1 添加头文件路径

         注:使用编译器自带的头文件(即:#include<xxx.h>)无需执行此操作。

  十三、sfr、sfr16、sbit 这3个关键字作用是什么?

        答:sfr、sfr16、sbit 这3个关键字并不属于C99规范,只在Keil C51中可以使用。研究过8051存储结构的都知道,8051特殊功能寄存器和内部RAM区的0x80~0xff共用相同的地址(但是物理存储单元各自独立),这在执行读写时就需要通过寻址方式做出区分。根据规定,特殊功能寄存器读写使用直接寻址(部分可位寻址),内部RAM区的0x80~0xff只能使用间接寻址。

13.1 存储结构

        sfr、sfr16、sbit 这3个关键字就承担起特殊功能寄存器区变量的声明,sfr用于声明8位变量,sfr声明16位变量,sbit用于声明位变量。特殊功能寄存器中,地址为8的整数倍的变量支持位寻址(如:0x80、0x88),也就是说支持用sbit声明位变量,具体如图13.2所示。

13.2 位寻址区

   十四、sbit 和bit有什么不同之处?

         答:sbit是用于对支持位寻址的特殊功能寄存器变量进行声明的,bit则是用于定义位变量的,定义的位变量存储在内部通用RAM区(内部RAM地址址区(0x20~0x2f)支持位寻址)。如果还不理解,下面通过生成的汇编指令解答疑惑。

sbit 常用用法:

  1. C语言:sbit P0_0 = P0^0;        P0_0=1//P0已通过sfr声明,其地址为0x80
  2. 汇编指令:SETB P0_0(0x80.0)

sbit 常用用法:

  1. C语言:bit P0_0; P0_0=1//为了演示效果,变量特意重名
  2. 汇编指令:SETB P0_0(0x20.0)

        可以看出,bit定义的变量存储在低128字节内部RAM中(地址0x20.0,注意.0不可忽视),sbit声明的变量存储在SFRs区且地址为8的整数倍(如示例中的0x80)。

        为了验证sbit只能在地址为8的整数倍的SFRs区声明,下面通过实际具体加以验证。通过图13.3可知,基地址确实不能任意给定。

14.1 sbit基地址报错

    十五、可以通过指针访问特殊功能寄存器区吗?

        答:我试了一下,结果是不可以。不排除有其他办法,欢迎批评指正。

相关代码对比如下:

15.1使用指针变量访问时:

  1. C语言:unsigned char *P0=0x80;*P0=0x0C;
  2. 汇编指令:
  3. // 12: unsigned char *P0=0x80;
  4. C:0x0003 7B00 MOV R3,#0x00
  5. C:0x0005 7A00 MOV R2,#0x00
  6. C:0x0007 7980 MOV R1,#P0(0x80)
  7. C:0x0009 8B08 MOV 0x08,R3
  8. C:0x000B 8A09 MOV 0x09,R2
  9. C:0x000D 890A MOV 0x0A,R1
  10. // 13: *P0=0x0C;
  11. C:0x000F AB08 MOV R3,0x08
  12. C:0x0011 AA09 MOV R2,0x09
  13. C:0x0013 A90A MOV R1,0x0A
  14. C:0x0015 740C MOV A,#0x0C
  15. C:0x0017 120020 LCALL C?CSTPTR(C:0020)
  16. C?CSTPTR:
  17. C:0x0020 BB0106 CJNE R3,#0x01,C:0029
  18. C:0x0023 8982 MOV DPL(0x82),R1
  19. C:0x0025 8A83 MOV DPH(0x83),R2
  20. C:0x0027 F0 MOVX @DPTR,A
  21. C:0x0028 22 RET
  22. C:0x0029 5002 JNC C:002D
  23. C:0x002B F7 MOV @R1,A
  24. C:0x002C 22 RET
  25. C:0x002D BBFE01 CJNE R3,#0xFE,C:0031
  26. C:0x0030 F3 MOVX @R1,A
  27. C:0x0031 22 RET

15.2使用SFR访问时:

  1. C语言:sfr P0 = 0x80; P0 = 0x0c;
  2. 汇编指令:
  3. // 12: P0=0x0C;
  4. C:0x000F 75800C MOV P0(0x80),#0x0C

15.3内置ABSACC.H,使用绝对地址访问时:

  1. 头文件部分:
  2. #define CBYTE ((unsigned char volatile code *) 0)
  3. #define DBYTE ((unsigned char volatile data *) 0)
  4. #if !defined (__CX2__)
  5. #define PBYTE ((unsigned char volatile pdata *) 0)
  6. #endif
  7. #define XBYTE ((unsigned char volatile xdata *) 0)
  8. #define CWORD ((unsigned int volatile code *) 0)
  9. #define DWORD ((unsigned int volatile data *) 0)
  10. #if !defined (__CX2__)
  11. #define PWORD ((unsigned int volatile pdata *) 0)
  12. #endif
  13. C语言用户代码:
  14. DBYTE[0x80]=0x0c;
  15. 其实没有验证的必要,code指向代码FLASH区,data指向通用RAM区(0x00~0xff),
  16. xdata指向片内拓展通用RAM区(0x0000~0xffff),pdata指向片外拓展64K内存区,都不指向SFRs

    十六、可以在多处使用sfr对特殊功能寄存器声明吗?

        答:不可以,会提示重复定义( redefinition)。

    十七、sbit对特殊功能寄存器声明时为何存在多种写法?

        答:解释如下,常见的写法如下:

  1. 方式1:sbit P0_2 = P0^2; //前提:P0已通过sfr声明
  2. 方式2:sbit P0_2 = 0x80^2; //0x80就是特殊功能寄存器中支持位寻址的寄存器
  3. 方式3:sbit P0_2 = 0x82; //此0x82为直接寻址中的位地址,需要和直接寻址中的字节地址区分开
  4. 注:^ 叫异或,可以了解一下他的运算规则

    十八、51单片机支持DEBUG(仿真)吗?

        答:支持。keil C51支持虚拟仿真(simulator)和实物仿真,STC的IAP系列还能抛开仿真器进行片上仿真,实际方法见其他博主的《宏晶STC单片机片上仿真法》

    十九、Keil C51中相较于C99标准,多出哪些扩展关键词?

        答:多出部分如下表所示:

_at_  alien  bdata     bit     code   compac     data
far   idata  interrupt  large   pdata   _priority_   reentrant
sbit   sfr    sfr16     small  _task_  usingxdata

------参考资料《KeilC51基本关键字》

    二十、Keil C51中可以观察程序的运行时间嘛?

        答:可以,在仿真模式下观察Register一栏中sec的变化量(单位为秒)即可。

二十一、Keil C51中可以观察引脚电平的变化嘛?

        答:可以,在仿真模式下,右击变量名称,将需要观察的变量添加到逻辑分析仪即可。

         配置好要查看的变量名称、显示类型、数值范围、位于操作、左移位数,点击程序运行按钮即可观察到变量变化情况。

二十二、Keil C51中可以观察变量变化情况嘛?

        答:可以,在仿真模式下,将需要查看的变量添加到watch窗口即可。

二十二、可以查看某个地址下面的具体值嘛?

        答:可以,通过Memory窗口查看,根据查看的物理地址分区不同,需要输入的前缀也不同。

代码区(CODE)输入C:绝对地址(如:C:0X20)
低128字节通用RAM区(DATA)输入D:绝对地址(如:D:0X20)
高128字节通用RAM区(IDATA)输入I:绝对地址(如:I:0X80)
内部扩展1024字节通用RAM区(XDATA)输入X:绝对地址(如:X:0X80)

二十三、使用位段(位域)操作和使用为变量实现原理有何不同?

23.1位域实现位操作:

  1. C语言:
  2. #include <STC89C5xRC.H>
  3. #include<absacc.h>
  4. union BYTE
  5. {
  6. unsigned char byte;
  7. struct
  8. {
  9. unsigned char bit0:1;
  10. unsigned char bit1:1;
  11. unsigned char bit2:1;
  12. unsigned char bit3:1;
  13. unsigned char bit4:1;
  14. unsigned char bit5:1;
  15. unsigned char bit6:1;
  16. unsigned char bit7:1;
  17. }BIT;
  18. };
  19. int main()
  20. {
  21. union BYTE data value;
  22. value.BIT.bit0 = 1;
  23. return 0;
  24. }
  25. 汇编代码:
  26. 126: ?C_STARTUP: LJMP STARTUP1
  27. 127:
  28. 128: RSEG ?C_C51STARTUP
  29. 129:
  30. 130: STARTUP1:
  31. 131:
  32. 132: IF IDATALEN <> 0
  33. C:0x0000 020003 LJMP STARTUP1(C:0003)
  34. 133: MOV R0,#IDATALEN - 1
  35. C:0x0003 787F MOV R0,#0x7F
  36. 134: CLR A
  37. C:0x0005 E4 CLR A
  38. 135: IDATALOOP: MOV @R0,A
  39. C:0x0006 F6 MOV @R0,A
  40. 136: DJNZ R0,IDATALOOP
  41. C:0x0007 D8FD DJNZ R0,IDATALOOP(C:0006)
  42. 185: MOV SP,#?STACK-1
  43. 186:
  44. 187: ; This code is required if you use L51_BANK.A51 with Banking Mode 4
  45. 188: ;<h> Code Banking
  46. 189: ; <q> Select Bank 0 for L51_BANK.A51 Mode 4
  47. 190: #if 0
  48. 191: ; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4.
  49. 192: EXTRN CODE (?B_SWITCH0)
  50. 193: CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
  51. 194: #endif
  52. 195: ;</h>
  53. C:0x0009 758108 MOV SP(0x81),#0x08
  54. 196: LJMP ?C_START
  55. C:0x000C 02000F LJMP main(C:000F)
  56. 20: int main()
  57. 21: {
  58. 22: union BYTE data value;
  59. 23: value.BIT.bit0 = 1;
  60. 24:
  61. C:0x000F 430801 ORL 0x08,#0x01
  62. 25: return 0;
  63. C:0x0012 E4 CLR A
  64. C:0x0013 7E00 MOV R6,#0x00
  65. C:0x0015 7F00 MOV R7,#0x00
  66. 26: }
  67. C:0x0017 22 RET

23.2位变量实现位操作:

  1. C语言:
  2. #include <STC89C5xRC.H>
  3. #include<absacc.h>
  4. int main()
  5. {
  6. bit bit0 = 1;
  7. return 0;
  8. }
  9. 汇编指令:
  10. 126: ?C_STARTUP: LJMP STARTUP1
  11. 127:
  12. 128: RSEG ?C_C51STARTUP
  13. 129:
  14. 130: STARTUP1:
  15. 131:
  16. 132: IF IDATALEN <> 0
  17. C:0x0000 020003 LJMP STARTUP1(C:0003)
  18. 133: MOV R0,#IDATALEN - 1
  19. C:0x0003 787F MOV R0,#0x7F
  20. 134: CLR A
  21. C:0x0005 E4 CLR A
  22. 135: IDATALOOP: MOV @R0,A
  23. C:0x0006 F6 MOV @R0,A
  24. 136: DJNZ R0,IDATALOOP
  25. C:0x0007 D8FD DJNZ R0,IDATALOOP(C:0006)
  26. 185: MOV SP,#?STACK-1
  27. 186:
  28. 187: ; This code is required if you use L51_BANK.A51 with Banking Mode 4
  29. 188: ;<h> Code Banking
  30. 189: ; <q> Select Bank 0 for L51_BANK.A51 Mode 4
  31. 190: #if 0
  32. 191: ; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4.
  33. 192: EXTRN CODE (?B_SWITCH0)
  34. 193: CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
  35. 194: #endif
  36. 195: ;</h>
  37. C:0x0009 758120 MOV SP(0x81),#0x20
  38. 196: LJMP ?C_START
  39. C:0x000C 02000F LJMP main(C:000F)
  40. 20: int main()
  41. 21: {
  42. 24: bit bit0 = 1;
  43. C:0x000F D200 SETB 0x20.0
  44. 25: return 0;
  45. C:0x0011 E4 CLR A
  46. C:0x0012 7E00 MOV R6,#0x00
  47. C:0x0014 7F00 MOV R7,#0x00
  48. 26: }
  49. C:0x0016 22 RET

差异:

  1. 位域实现原理:ORL 0x08,#0x01
  2. 位操作实现原理:SETB 0x20.0

        可以对比,使用位域定义的变量并未存放在支持位寻址地址区,通过ORL将立即数(0x01)与直接地址单元(0x08)进行或操作,指令代码占用3字节,需要耗费24个机器周期(12MHz晶振下需要24us时间)。使用位寻址定义的变量通过SETB直接对地址0x20.0进行置位,指令代码占用2字节,需要耗费12个机器周期(12MHz晶振下需要12us时间)。

        由此可见,二者实现原理并不相同,使用硬件位寻址定义的变量操作起来更快,占用内存更小。位域操作需要先读取变量值进行逻辑操作,再重新存入地址,数据读写过程中受内外因素干扰,存在数据紊乱的可能。

二十四、51单片机有可供使用的RTOS嘛?

        答:51单片机是支持RTOS的,但是他匮乏的硬件资源注定支持的RTOS非常轻量化。在Keil_C51\C51\RtxTiny2下有一个名称叫RTX51的RTOS,但是已经被封装成LIB库了,我们看不到具体的源代码。根据库的精简程度,又分为全功能版的RTX51-FULL和精简功能的RTX51-TINY。RTX51-FULL在RTX51-TINY的基础上支持了任务的优先级设定,相关工程配置可参考其他博主介绍。

24.1 经典12T单片机工程配置:硬件平台为STC89C52RC,软件为Keil C51

24.2 增强1T单片机工程配置:硬件平台为STC15W1K16S,软件为Keil C51

24.3 RTX51-TINY使用手册

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/493769
推荐阅读
相关标签
  

闽ICP备14008679号