前言
心血来潮说捣鼓捣鼓基于51单片机的超声波模块,也就是市面上买的模块HC-SR04,从网上找了驱动代码,自己新建keil工程打开一看发现,这个头文件AT89X52.H,我就奇怪了,平常学的51单片机视频不都是reg52.h么?这两者又有什么区别呢?于是上网看资料,看了一些写的不错的文章,下面给出总结:(说了一大堆终于要正题了)
问题摘要
reg52.h是c51(用于单片机开发的一种C语言)的头文件。类似于头文件AT89X52.H。这两个头文件基本是一样的,只是在使用时对每个位的定义不一样。
AT89X52.H文件中对P1.1的操作是写成P1_1;而reg52.h文件中的操作则写成P1^1,表示方法不一样而已表示方法不一样而已。另外AT89X52.H是特指ATMEL公司的52系列单片机,reg52.h指所有52系列的单片机。
我们在用c语言编程的时候往往第一行就是reg52.h或者其他的自定义头文件,这些头文件我们怎么来理解呢?
- “文件包含”处理
程序的第一行是一个“文件包含”处理。所谓“文件包含”是指一个文件将另外一个文件的内容全部包含进来。
程序中包含reg52.h文件的目的是为了要使用P1还有其他更多的符号)这个符号,即通知C编译器,
程序中所写的P1是指80C51单片机的P1端口而不是其它变量。
这是如何做到的呢?打开reg51.h 可以看到这样的一些内容:
(此文件一般在C:\KEIL\C51\INC下,INC文件夹根目录里有不少头文件,并且里面还有
很多以公司分类的文件夹,里面也都是相关产品的头文件。
如果我们要使用自己写的头文件,使用的时候只需把对应头文件拷贝到INC文件夹里就可以了。)
#ifndef __REG51_H__
#define __REG51_H__
-----------------------------------------------------------------
sfr P0 = 0x80; //P0口
sfr P1 = 0x90; //P1口
sfr P2 = 0xA0; //P2口
sfr P3 = 0xB0; //P3口
sfr PSW = 0xD0; //程序状态字,具体位意义见位定义
sfr ACC = 0xE0; //累加器,程序员最常用的
sfr B = 0xF0; //寄存器,主要用于乘除
sfr SP = 0x81; //堆栈指针,初始化为07;先加1后压栈,先出栈再减1,
sfr DPL = 0x82;
sfr DPH = 0x83; //数据指针,用途大
sfr PCON = 0x87; //电源控制
sfr TCON = 0x88; //Timer/Counter控制
sfr TMOD = 0x89; //Timer/Counter方式控制
sfr TL0 = 0x8A;
sfr TL1 = 0x8B; //
sfr TH0 = 0x8C; //存着当前的计数值
sfr TH1 = 0x8D; //我就想不明白,当时设计的时候,为什么不把TH0,TL0放在连续的地址!
sfr IE = 0xA8; //好东西,中断控制
sfr IP = 0xB8; //中断优先级控制,没有设计过要求时间严格的系统,所以至今没有用过
sfr SCON = 0x98; //哇,熟悉,串口控制寄存器
sfr SBUF = 0x99; //哇,更熟悉,串口缓冲寄存器
-----------------------------------------------------------------
sbit CY = 0xD7; //进位或借位,有就是1,没有就是0
sbit AC = 0xD6; //辅助进借位,(麻烦b)
sbit F0 = 0xD5; //没有具体用途,可以由用户决定他的意义,所以它就没有意义
sbit RS1 = 0xD4;
sbit RS0 = 0xD3; //工作寄存器选择,这个在下面解释
sbit OV = 0xD2; //over!溢出,有是1,没有是0
sbit P = 0xD0; //奇偶校验,奇数个1是1
-----------------------------------------------------------------
sbit TF1 = 0x8F; //T1的中断请求标志
sbit TR1 = 0x8E; //Timer 1 running,好记吧~
sbit TF0 = 0x8D; //
sbit TR0 = 0x8C; //Timer 0running
sbit IE1 = 0x8B; //interrupt external 1 外中断请求标志
sbit IT1 = 0x8A; //interrupt triggle 1 外中断触发方式
sbit IE0 = 0x89; //interrupt external 0 外中断触发方式
sbit IT0 = 0x88; //interrupt triggle 0 外中断触发方式
-----------------------------------------------------------------
sbit EA = 0xAF; //Enable all哇,重要,全局中断控制,光着他,哈哈,什么都不用作了,就像放假一样
sbit ES = 0xAC; //Enable Serial,开串口中断
sbit ET1 = 0xAB; //Enable Timer/Counter 1
sbit EX1 = 0xAA; //Enable External 1
sbit ET0 = 0xA9; //Enable Timer/counter 0
sbit EX0 = 0xA8; //Enable External 0
-----------------------------------------------------------------
sbit PS = 0xBC; //串行中断优先级
sbit PT1 = 0xBB; //T1优先级
sbit PX1 = 0xBA; //外部中断1优先级
sbit PT0 = 0xB9; //
sbit PX0 = 0xB8; //上面两个1换成0
-----------------------------------------------------------------
//控制寄存器!!!!
sbit RD = 0xB7; //读
sbit WR = 0xB6; //写
sbit T1 = 0xB5; //T/C1
sbit T0 = 0xB4; //T/C0
sbit INT1 = 0xB3; //外中断1
sbit INT0 = 0xB2; //外中断0
sbit TXD = 0xB1; //串行发送
sbit RXD = 0xB0; //串行接收
-----------------------------------------------------------------
sbit SM0 = 0x9F; //
sbit SM1 = 0x9E; //串口工作方式
sbit SM2 = 0x9D; //多机通信控制位
sbit REN = 0x9C; //串行接收允许
sbit TB8 = 0x9B; //收到的第九位
sbit RB8 = 0x9A; //要发的第九位
sbit TI = 0x99; //哇,熟悉吧,发送完成中断标志
sbit RI = 0x98; //接收完成中断标志
-----------------------------------------------------------------
sfr TH0 = 0x8C;
-----------------------------------------------------------------
熟悉80C51 内部结构的读者不难看出,这里都是一些符号的定义,即规定符号名与地址的对应关系。
注意其中有sfr P1=0x90;这样的一行,即定义P1与地址0x90对应,P1口的地址就是0x90(0x90 是C 语言中十六进制数的写法,
相当于汇编语言中写90H)。从这里还可以看到一个频繁出现的词:sfr,sfr并非标准C语言的关键字,
而是Keil为能直接访问80C51中的SFR而提供了一个新的关键词,其用法是:sfrt 变量名=地址值。
- 符号P1_0 来表示P1.0 引脚
在C语言里,如果直接写P1.0,C编译器并不能识别,而且P1.0也不是一个合法的C语言变量名,所以得给它另起一个名字,
这里起的名为P1_0,可是P1_0 是不是就是P1.0呢?你这么认为,C编译器可不这么认为,
所以必须给它们建立联系,这里使用了Keil C的关键字sbit来定义,sbit的用法有三种:
第一种方法:sbit 位变量名=地址值
第二种方法:sbit 位变量名=SFR 名称^变量位地址值
第三种方法:sbit 位变量名=SFR 地址值^变量位地址值
如定义PSW 中的OV 可以用以下三种方法:
sbit OV=0xd2 (1)说明:0xd2 是OV 的位地址值
sbit OV=PSW^2 (2)说明:其中PSW 必须先用sfr 定义好
sbit OV=0xD0^2 (3)说明:0xD0 就是PSW 的地址值
因此这里用sfr P1_0=P1^0;就是定义用符号P1_0 来表示P1.0 引脚,如果你愿意也可以起P10 一类的名字,只要下面程序中也随之更改就行了。
下面是reg52.h头文件的内容:
#ifndef __REG52_H__
#define __REG52_H__
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
-----------------------------------------------------------------
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD;
-----------------------------------------------------------------
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only
-----------------------------------------------------------------
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
-----------------------------------------------------------------
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0;
-----------------------------------------------------------------
sbit PT2 = IP^5;
sbit PS = IP^4;
sbit PT1 = IP^3;
sbit PX1 = IP^2;
sbit PT0 = IP^1;
sbit PX0 = IP^0;
-----------------------------------------------------------------
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0;
-----------------------------------------------------------------
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;
附加内容
还有就是我自己从代码里单击头文件右键 open document看到AT89X51.H头文件包含的东西
/*--------------------------------------------------------------------------
AT89X51.H
Header file for the low voltage Flash Atmel AT89C51 and AT89LV51.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __AT89X51_H__
#define __AT89X51_H__
/*------------------------------------------------
Byte Registers
------------------------------------------------*/
sfr P0 = 0x80;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr P1 = 0x90;
sfr SCON = 0x98;
sfr SBUF = 0x99;
sfr P2 = 0xA0;
sfr IE = 0xA8;
sfr P3 = 0xB0;
sfr IP = 0xB8;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
/*------------------------------------------------
P0 Bit Registers
------------------------------------------------*/
sbit P0_0 = 0x80;
sbit P0_1 = 0x81;
sbit P0_2 = 0x82;
sbit P0_3 = 0x83;
sbit P0_4 = 0x84;
sbit P0_5 = 0x85;
sbit P0_6 = 0x86;
sbit P0_7 = 0x87;
/*------------------------------------------------
PCON Bit Values
------------------------------------------------*/
#define IDL_ 0x01
#define STOP_ 0x02
#define PD_ 0x02 /* Alternate definition
#define GF0_ 0x04
#define GF1_ 0x08
#define SMOD_ 0x80
/*------------------------------------------------
TCON Bit Registers
------------------------------------------------*/
sbit IT0 = 0x88;
sbit IE0 = 0x89;
sbit IT1 = 0x8A;
sbit IE1 = 0x8B;
sbit TR0 = 0x8C;
sbit TF0 = 0x8D;
sbit TR1 = 0x8E;
sbit TF1 = 0x8F;
/*------------------------------------------------
TMOD Bit Values
------------------------------------------------*/
#define T0_M0_ 0x01
#define T0_M1_ 0x02
#define T0_CT_ 0x04
#define T0_GATE_ 0x08
#define T1_M0_ 0x10
#define T1_M1_ 0x20
#define T1_CT_ 0x40
#define T1_GATE_ 0x80
#define T1_MASK_ 0xF0
#define T0_MASK_ 0x0F
/*------------------------------------------------
P1 Bit Registers
------------------------------------------------*/
sbit P1_0 = 0x90;
sbit P1_1 = 0x91;
sbit P1_2 = 0x92;
sbit P1_3 = 0x93;
sbit P1_4 = 0x94;
sbit P1_5 = 0x95;
sbit P1_6 = 0x96;
sbit P1_7 = 0x97
/*------------------------------------------------
SCON Bit Registers
------------------------------------------------*/
sbit RI = 0x98;
sbit TI = 0x99;
sbit RB8 = 0x9A;
sbit TB8 = 0x9B;
sbit REN = 0x9C;
sbit SM2 = 0x9D;
sbit SM1 = 0x9E;
sbit SM0 = 0x9F;
/*------------------------------------------------
P2 Bit Registers
------------------------------------------------*/
sbit P2_0 = 0xA0;
sbit P2_1 = 0xA1;
sbit P2_2 = 0xA2;
sbit P2_3 = 0xA3;
sbit P2_4 = 0xA4;
sbit P2_5 = 0xA5;
sbit P2_6 = 0xA6;
sbit P2_7 = 0xA7;
/*------------------------------------------------
IE Bit Registers
------------------------------------------------*/
sbit EX0 = 0xA8; /* 1=Enable External interrupt 0 */
sbit ET0 = 0xA9; /* 1=Enable Timer 0 interrupt */
sbit EX1 = 0xAA; /* 1=Enable External interrupt 1 */
sbit ET1 = 0xAB; /* 1=Enable Timer 1 interrupt */
sbit ES = 0xAC; /*1=Enable Serial port interrupt */
sbit ET2 = 0xAD; /* 1=Enable Timer 2 interrupt */
sbit EA = 0xAF; /* 0=Disable all interrupts */
/*------------------------------------------------
P3 Bit Registers (Mnemonics & Ports)
------------------------------------------------*/
sbit P3_0 = 0xB0;
sbit P3_1 = 0xB1;
sbit P3_2 = 0xB2;
sbit P3_3 = 0xB3;
sbit P3_4 = 0xB4;
sbit P3_5 = 0xB5;
sbit P3_6 = 0xB6;
sbit P3_7 = 0xB7;
sbit RXD = 0xB0; /* Serial data input */
sbit TXD = 0xB1; /* Serial data output */
sbit INT0 = 0xB2; /* Externalinterrupt 0 */
sbit INT1 = 0xB3; /* Externalinterrupt 1 */
sbit T0 = 0xB4; /* Timer 0 external input */
sbit T1 = 0xB5; /* Timer 1 external input */
sbit WR = 0xB6; /* External data memory write strobe */
sbit RD = 0xB7; /* External data memory read strobe */
/*------------------------------------------------
IP Bit Registers
------------------------------------------------*/
sbit PX0 = 0xB8;
sbit PT0 = 0xB9;
sbit PX1 = 0xBA;
sbit PT1 = 0xBB;
sbit PS = 0xBC;
sbit PT2 = 0xBD
/*------------------------------------------------
PSW Bit Registers
------------------------------------------------*/
sbit P = 0xD0;
sbit F1 = 0xD1;
sbit OV = 0xD2;
sbit RS0 = 0xD3;
sbit RS1 = 0xD4;
sbit F0 = 0xD5;
sbit AC = 0xD6;
sbit CY = 0xD7;
/*------------------------------------------------
Interrupt Vectors:
Interrupt Address = (Number * 8) + 3
------------------------------------------------*/
#define IE0_VECTOR 0 /* 0x03 External Interrupt 0 */
#define TF0_VECTOR 1 /* 0x0B Timer 0 */
#define IE1_VECTOR 2 /* 0x13 External Interrupt 1 */
#define TF1_VECTOR 3 /* 0x1B Timer 1 */
#define SIO_VECTOR 4 /* 0x23 Serial port *
#endif
后记
所以看完这些之后感觉清晰了很多,写代码,改代码也很有底气了,是不是?这些也算是当时学51单片机不扎实所留下来的小漏洞,写下总结希望和大家一起进步,第一次写博客还是小兴奋!对Markdown编辑器的格式也不太熟悉,就凑合着看看吧,(不知道为何我使用Markdown编辑器在网页上用了一段时间莫名的卡到炸,只能刷新之后才能正常使用,各种反复刷新。。。。。。)个人的能力有限难免有错误纰漏,也欢迎大家指出!对了放出参考大神文章的地址:
http://blog.sina.com.cn/s/blog_77f33f9a01019jqt.html
点击下面的直达
头文件reg51.h与reg52.h的区别