打印

keil中制作LIB

[复制链接]
14878|32
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
myfaith|  楼主 | 2008-4-20 12:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
wxj1952| | 2008-4-20 14:19 | 只看该作者

keil C51 中有做库选项。

1、在#include  xxx.h 中配置/说明管脚名代表什么;
2、在#define  管脚名  管脚N(修改项)
3、以管脚N做函数参数。

将库文件放入项目(一起链接)即可。

使用特权

评论回复
板凳
myfaith|  楼主 | 2008-4-20 20:25 | 只看该作者

不太明白

xxx.h代表什么头文件?
在选项中选择CREATE LIB 文件后,编译就生成了LIB文件,但是我想请问,编译的这个C文件后一般的C文件是完全一样的吗?如果其它程序调用这个LIB里的函数,需要用"#INCLUDE XXX.LIB"这样把LIB包含进来吗?

使用特权

评论回复
地板
wxj1952| | 2008-4-21 10:03 | 只看该作者

XXX.h是你自己起的头文件名字

XXX.h里显然是你对自己库文件中的函数的说明。(不事先说明说明就调用,编译器也通不过。)

在任何需要调用自己库函数的独立(编译)模块中,都需要对库函数类型重新说明,也就是要重新把XXX.h包含进来。除非编译器能够理解你的前一个XXX.h足以说明当前被调用的库函数类型。

函数库里的OBJ文件与原来外部的OBJ文件一样,但是函数库里还有函数名表等一些其他利于调用识别的格式化内容,与链接器相应的。有兴趣可以用库管理器LIB51提出来看。

使用特权

评论回复
5
wxj1952| | 2008-4-21 10:21 | 只看该作者

有意思。

“需要用"#INCLUDE XXX.LIB"这样把LIB包含进来吗?”

行吗?把一个库文件包含到当前位置?

还是想不说明就定义?

即使这样的概念可行,但是这样做相当于把没用到的库函数也链接到当前模块里了?假设你的主程序只有40B,函数库有2KB,最终程序长度=?

当然,这根本不可行!编译器通不过,为什么**要那样做?

使用特权

评论回复
6
三块石头| | 2008-4-21 12:44 | 只看该作者

顺便追问楼上一个问题

我记得在哪儿看过,好像一般的C语言连接器是吧库函数里所有函数都链进来了
,而KEIL C51只是把用到的库函数连接进来了,是这样吗?

使用特权

评论回复
7
wxj1952| | 2008-4-21 13:13 | 只看该作者

怎么合理连接器怎么做。

“把库函数里所有函数都链进来了?”

   嵌入式系统不可能这么干。那样不光是用户最终程序体积问题,还有调试时程序的易读性等等。做编译器/连接器的人不会这么设计。

我倒是曾经发现过无关库函数被链接到用户程序这种情况,最后总结编译器/连接器它总是有道理的:有些连接进来的库函数看似无关,其实它是与显性被调用函数A相关的隐性函数B,即:当用户主调函数调用库函数A时,A函数还需要B函数支持,——嵌套调用。

另外还发现Keil C51有动态链接库 *.dll,  那样是为了使用户程序更简洁吧。

使用特权

评论回复
8
myfaith|  楼主 | 2008-4-21 18:54 | 只看该作者

调用的时候用头文件把这个工程的头文件包含进来就行了

"这个工程的头文件"是什么文件?能否具体举例说明怎么得到库函数,怎么调用库函数里的函数?看你们说的一头雾水,比如说,想把下面这个函数作为库:
#include <reg51.h>
void fun(void)
{
...
}
把上面的函数单独编译,生成MY.LIB文件,然后在别的工程程序中怎么使用fun()函数?只需要声明extern fun();就可以使用了吗?

使用特权

评论回复
9
3.3v| | 2008-4-21 18:57 | 只看该作者

你问的太对了,对外的端口都写在一个头文件中 extern了事

就跟早期做手机,代码为了限制改写都做成LIB,不让你改,能改的就是LCD,KEY...

使用特权

评论回复
10
三块石头| | 2008-5-19 19:45 | 只看该作者

那如何让连接器知道我要调用的库文件是哪个?在哪?

就是说,我要做什么设置,才能让KEIL知道我使用了自己的库文件?而且要让他知道库文件在哪,是哪个

使用特权

评论回复
11
三块石头| | 2008-5-19 20:36 | 只看该作者

re

刚才仔细读了2楼wxj1952的回复,发现原来把库文件加入工程,和source group里的C文件一样,列在项目管理器中即可;同时在调用文件前include进必要的头文件。这样编译连接通过,仿真运行没有错误。

还有有一个问题,为什么系统提供的库函数(比如printf等)不需要把库文件加进来呢?

使用特权

评论回复
12
ayb_ice| | 2008-5-20 09:57 | 只看该作者

库文件中的管脚是不可以改变的

因为SFR其实是绝对定位的RAM空间

使用特权

评论回复
13
wxj1952| | 2008-5-20 19:33 | 只看该作者

回12楼

连接器会自动从C51LIB下寻找相应的库及库函数。既然连你都知道调用printf时必须包含<stdio.h>,链接器L51就更知道相应的库文件是什么了。不信你把KEILC51LIB目录里的C51S.LIB换名或者移走,看看会有什么连接结果。

忘了说:还需要通过环境设置中设定LIB的默认寻找目录。默认是KEILC51LIB。还有在链接选项中自己写下你的库文件名,这样就不用吧自己的库放在项目文件里了。编译器会自动根据你的设置去查找。
    书上都写了,就不多说了。没有书我再帮你细查。

使用特权

评论回复
14
wxj1952| | 2008-5-20 22:54 | 只看该作者

请教13楼

“ 库文件中的管脚是不可以改变的 

因为SFR其实是绝对定位的RAM空间”

做程序的人不会连这点灵活性都不考虑吧。实际是库函数内只采用变量名或者管脚名(标识符),而管脚名的定义却在库外。以你说的SFR 为例,SFR的绝对地址空间定义难道不是在“REG51.h”中定义并可以在程序链接库函数之前任意修改的吗?
 
 

使用特权

评论回复
15
ayb_ice| | 2008-5-21 08:37 | 只看该作者

15L

不信你去试试。。。

使用特权

评论回复
16
wxj1952| | 2008-5-21 14:02 | 只看该作者

能不能举个足以说服人的程序例子?

以事实为依据。我也举一个。如果我的程序不能说服人,我将向你道歉。

你呢?

使用特权

评论回复
17
ayb_ice| | 2008-5-21 14:43 | 只看该作者

我以前试过不行

如果你的可行,我感到非常高兴,因为我又学到一点。。。
有时间我再去试试。

使用特权

评论回复
18
wxj1952| | 2008-5-21 16:30 | 只看该作者

这对LZ有用么?

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

   Main.C (v1.00)

  ------------------------------------------------------------------

   Test program for pattern PORT I-O
 
   Illustrating the use of bitwise operators

   Reading and writing individual bits
   NOTE: Both bits on  port1
程序将P1端口管脚0读入并写到管脚1.
-*------------------------------------------------------------------*/

#include <reg52.h>  

void Write_Bit_P1(unsigned char, bit);
bit Read_Bit_P1(unsigned char);

/* ............................................................... */

void main (void)
   {
   bit x;
   
   for(;;)                      // Forever...
     {
     x = Read_Bit_Px(0);   // Read Port 1, Pin 0
     Write_Bit_Px(1,x);    // Write to Port 1, Pin 1
     }
   }
//  以下是库函数,可以看到,它们不依赖于具体绝对地址。Pin 是形参,而实参是库外来的,
可以在运行前设定/配置的。例如在reg52.h中修改 sfr P1= 0xC0;没什么不可以。本程序可以移植到任何51核单片机。
/* --------------------------------------------------------------- */

void Write_Bit_Px(unsigned char Pin, bit Value)
   {
   unsigned char p = 1;
   p <<= Pin;  // Left shift
   
   // If we want 1 output at this pin
   if (Value)
      {
      P1 |= p;  // Bitwise OR
      return;
      }
   
   // If we want 0 output at this pin
   p = ~p;  // Complement
   P1 &= p; // Bitwise AND  
   }

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

bit Read_Bit_Px(unsigned char Pin)
   {
   unsigned char p = 1;
   p <<= Pin;  // Left shift
   
   // Write a 1 to the pin (to set up for reading)
   Write_Bit_Px(Pin, 1);
   return (P1 & p); // Read the pin
   }

/*------------------------------------------------------------------*-
  ---- END OF FILE -------------------------------------------------
-*------------------------------------------------------------------*/

使用特权

评论回复
19
农民讲习所| | 2008-5-21 16:42 | 只看该作者

可能的隐患

中断在P1 |= p时发生,并对P1口某位操作,BUG会发生。

做库的时候很简单,使用回调函数,在外面操作硬件即可。

使用特权

评论回复
20
ayb_ice| | 2008-5-21 20:35 | 只看该作者

今天试了一下,不行

有图片为证
第一张:创建库的图片
第二张:编译库的图片,修改了LED的定义,已经有了警告
第三张:调试库函数,可以看到改变的还是P00

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

468

帖子

0

粉丝