C51资料_头文件

C51资料_头文件


2024年2月16日发(作者:)

c51头文件的作用与c头文件的作用类似。

absacc.h---包含允许直接访问8051不同存储区的宏定义

assert.h---文件定义assert宏,可以用来建立程序的测试条件

ctype.h---字符转换和分类程序

intins.h---文件包含指示编译器产生嵌入式固有代码的程序的原型

math.h---数学程序

reg51.h---51的特殊寄存器

reg52.h---52的特殊寄存器

setjmp.h---定义jmp_buf类型和setjmp和longjmp程序的原型

stdarg.h---可变长度参数列表程序

stdlib.h---存储器分配程序

stdio.h---流输入和输出程序

string.h---字符转操作程序,缓冲区操作程序

单片机中用c编程时头文件reg51.h及reg52.h解析

我们在用c语言编程是往往第一行就是reg51.h或者其他的自定义头文件,我们怎么样来理解呢?

1)“文件包含”处理。

程序的第一行是一个“文件包含”处理。

所谓“文件包含”是指一个文件将另外一个文件的内容全部包含进来。程序中包含REG51.h

文件的目的是为了要使用P1 (还有其他更多的符号)这个符号,即通知C 编译器,程序中所写的P1 是指80C51 单片机的P1 端口而不是其它变量。这是如何做到的呢?

打开reg51.h 可以看到这样的一些内容:

(此文件一般在C:KEILC51INC下 ,INC文件夹根目录里有不少头文件,并且里面还有很多以公司分类的文件夹,里面也都是相关产品的头文件。如果我们要使用自己写的头文件,使用的时候只需把对应头文件拷贝到INC文件夹里就可以了。)

#ifndef __REG51_H__

#define __REG51_H__

sfr P0 = 0x80;

。。。。。。。。。。。。。。。。。。。。。。。。。。。

sbit TI = 0x99;

sbit RI = 0x98;

#endif

熟悉80C51 内部结构的读者不难看出,这里都是一些符号的定义,即规定符号名与地

址的对应关系。注意其中有

sfr P1 = 0x90;

这样的一行,即定义P1 与地址0x90 对应,P1 口的地址就是0x90

(0x90 是C 语言中十六进制数的写法,相当于汇编语言中写90H)。

从这里还可以看到一个频繁出现的词:sfr

sfr 并非标准C 语言的关键字,而是Keil 为能直接访问80C51 中的SFR 而提供了一个新

的关键词,其用法是:

sfrt 变量名=地址值。

2)符号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 一类的名字,只要下面程序中也随之更改就行了。

keil 中自己编写C语言头文件

自己编写一个C语言头文件,把自己常用的一些函数放进去。所看到文章做法和一般C语言头文件写法基本一样,自己学着试了一下,老是不成功。后来去图书馆查书,才知道原来keil 的C语言比较特别,引用同一工程其他文件中的函数需要在声明函数前加extern。 以下是一个例子:

//步骤一:建立fc.h

#ifndef FC_H

#define FC_H

#include

extern void f(void)

#endif

//步骤二:建立fc.c

#include "fc.h"

#include

//还需要什么头文件自己添加

void f(void)

{

//要什么程序自己添加

}

步骤三:将f.h和f.c放在工程的文件夹里,并在keil 中将f.c添加到工程中(右键左边的Source Group n,

选择Add file to group 'Source group n'),要用到f()函数的话就include“fC.h”就行了,例如:

#include

#include "fc.h"

void main()

{

f();

while(1);

}

结果大功告成,成功编译,但是并没有想象中那么实用,例如 fc.c 中如果定义了函数但没有被引用的话,

keil 会发出警告,虽然可以编译,但是一大堆警告很烦人,也和容易让人忽视其他很重要警告。我想自己

编写头文件主要是适用于大型工程吧。很多人编写各自不同的函数,然后通过头文件的引用把函数给主程

序或者其他子程序引用。

注:fc.h也可以放在keil/C51/INC下,引用时变为#include

C51编程:头文件条件编译

程序移植到另外一个CPU上,其中头文件要更改。如想做一个兼容的,可用条件编译来控制头文件的编译。

假如有两个头文件my1.h和my2.h,在CPU1上编译my1.h,在CPU2上编译my2.h,则:

#define CPU1 // 在使用CPU1时打开该定义,反之关闭该定义;该定义放在公共入口头文件的顶头

#ifdefine CPU1

#include "my1.h"

#else

#include "my2.h"

#endif

如还有更多文件呢,如system.h,hard.h,这些在两个系统中都要有的,则有区别的就放在这里面,相同的就放在外面

#ifdef CPU1

#include "my1.h"

#include "system1.h"

#include "hard1.h"

#else

#include "my2.h"

#include "system2.h" 也可以是system1.h

#include "hard2.h"

#endif

#include "Public1.h"

...

也可以在各个头文件中把有差异的地方用

#ifdef CPU1

#else

#endif

来区分开来

不仅仅是头文件,其他输出设备以及电路板的不同版本都可采用条件编译

c51中的intrins.h库函数

1..怎么用C51写一个NOP语句呢?

把头文件intrins.h包含进来,然后在需用NOP处调用_nop_();函数即可。

2.c51中的intrins.h库函数

_crol_ 字符循环左移

_cror_ 字符循环右移

_irol_ 整数循环左移

_iror_ 整数循环右移

_lrol_ 长整数循环左移

_lror_ 长整数循环右移

_nop_ 空操作8051 NOP 指令

_testbit_ 测试并清零位8051 JBC 指令

详解:

函数名: _crol_,_irol_,_lrol_

原 型: unsigned char _crol_(unsigned char val,unsigned char n);

unsigned int _irol_(unsigned int val,unsigned char n);

unsigned int _lrol_(unsigned int val,unsigned char n);

功 能:_crol_,_irol_,_lrol_以位形式将val 左移n 位,该函数与8051“RLA”指令

相关,上面几个函数不同于参数类型。

例:

#include

main()

{

unsigned int y;

C-5 1 程序设计 37

y=0x00ff;

y=_irol_(y,4); /*y=0x0ff0*/

}

函数名: _cror_,_iror_,_lror_

原 型: unsigned char _cror_(unsigned char val,unsigned char n);

unsigned int _iror_(unsigned int val,unsigned char n);

unsigned int _lror_(unsigned int val,unsigned char n);

功 能:_cror_,_iror_,_lror_以位形式将val 右移n 位,该函数与8051“RRA”指令

相关,上面几个函数不同于参数类型。

例:

#include

main()

{

unsigned int y;

y=0x0ff00;

y=_iror_(y,4); /*y=0x0ff0*/

}

函数名: _nop_

原 型: void _nop_(void);

功 能:_nop_产生一个NOP 指令,该函数可用作C 程序的时间比较。C51 编译器在_nop_

函数工作期间不产生函数调用,即在程序中直接执行了NOP 指令。

例:

P()=1;

_nop_();

P()=0;

函数名: _testbit_

原 型:bit _testbit_(bit x);

功 能:_testbit_产生一个JBC 指令,该函数测试一个位,当置位时返回1,否则返回0。

如果该位置为1,则将该位复位为0。8051 的JBC 指令即用作此目的。

_testbit_只能用于可直接寻址的位;在表达式中使用是不允许的

伪本征函数——Keil C51头文件INTRINS.H的应用演示

#include "reg51.h"

#include "intrins.h"

unsigned char readdata(void)

{

unsigned char val;

for (val = 8; val > 0; val--)

{

_clrb_(TXD);

_nop_();

_movcb_(RXD);

_rrca_();

_setb_(TXD);

_nop_();

}

_movra_(val);

return val;

}

void writedata(unsigned char val)

{

_movar_(val);

for (val = 8; val > 0; val--)

{

_clrb_(TXD);

_rrca_();

_movbc_(RXD);

_setb_(TXD);

_nop_();

}

}

main()

{

unsigned char i;

/*----------------------------------

_movb0_();演示

-----------------------------------*/

i = 0x01;

_movb0_(TXD,i);

i = 0x02;

TXD = i & 0x01;

i = 0x03;

if (i & 0x01) TXD = 1;

else TXD = 0;

/*---------------------------------*/

/*----------------------------------

_movb7_();演示

-----------------------------------*/

i = 0x04;

_movb7_(RXD,i);

i = 0x05;

TXD = i & 0x80;

i = 0x06;

if (i & 0x80) TXD = 1;

else TXD = 0;

i = 0x07;

if (i > = 0x80) TXD = 1;

else TXD = 0;

/*---------------------------------*/

/*----------------------------------

_rlcar_();_movra_()组合演示

-----------------------------------*/

i = 0x08;

_setc_();

_movra_(i);

i < <= 1;

i |= 0x01;

i < <= 1;

i ++;

i += i;

i *= 2;

i ++;

/*---------------------------------*/

/*----------------------------------

_rrcar_();_movra_()组合演示

-----------------------------------*/

i = 0x09;

_setc_();

_rrcar_(i);

_movra_(i);

i > > = 1;

i |= 0x80;

/*---------------------------------*/

i = readdata();

writedata(i);

while(1);

}


发布者:admin,转转请注明出处:http://www.yc00.com/news/1708064619a1538278.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信