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:\KEIL\C51\INC下 ,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 <reg51.h>
extern void f(void)
#endif
//步骤二:建立fc.c
#include "fc.h"
#include <reg51.h>
//还需要什么头文件自己添加
自己编写一个C语言头文件,把自己常用的一些函数放进去。所看到文章做法和一般C语言头文件写法基本一样,自己学着试了一下,老是不成功。后来去图书馆查书,才知道原来keil 的C语言比较特别,引用同一工程其他文件中的函数需要在声明函数前加extern。 以下是一个例子:
//步骤一:建立fc.h
#ifndef FC_H
#define FC_H
#include <reg51.h>
extern void f(void)
#endif
//步骤二:建立fc.c
#include "fc.h"
#include <reg51.h>
//还需要什么头文件自己添加
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 <reg51.h>
#include "fc.h"
void main()
{
//要什么程序自己添加
}
步骤三:将f.h和f.c放在工程的文件夹里,并在keil 中将f.c添加到工程中(右键左边的Source Group n,
选择Add file to group 'Source group n'),要用到f()函数的话就include“fC.h”就行了,例如:
#include <reg51.h>
#include "fc.h"
void main()
{
f();
while(1);
}
结果大功告成,成功编译,但是并没有想象中那么实用,例如 fc.c 中如果定义了函数但没有
f();
while(1);
}
结果大功告成,成功编译,但是并没有想象中那么实用,例如 fc.c 中如果定义了函数但没有
被引用的话,
keil 会发出警告,虽然可以编译,但是一大堆警告很烦人,也和容易让人忽视其他很重要警告。我想自己
编写头文件主要是适用于大型工程吧。很多人编写各自不同的函数,然后通过头文件的引用把函数给主程
序或者其他子程序引用。
注:fc.h也可以放在keil/C51/INC下,引用时变为#include <fc.h>
keil 会发出警告,虽然可以编译,但是一大堆警告很烦人,也和容易让人忽视其他很重要警告。我想自己
编写头文件主要是适用于大型工程吧。很多人编写各自不同的函数,然后通过头文件的引用把函数给主程
序或者其他子程序引用。
注:fc.h也可以放在keil/C51/INC下,引用时变为#include <fc.h>
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*/
}
函数名:system的头文件 _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()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论