原创 在avrstudio + winavr的系统中制作并调用库

2011-2-11 13:01 3992 9 9 分类: MCU/ 嵌入式

      给人打工的工程师都知道老板要你开发完一个产品都要向你要源程序,这个没什么大问题。但是使用C语言以上高级语言设备驱动程序都是可以重复利用的,你给这个老板开发一个产品一般并不是从驱动开始开发的,而是利用你以前就做好的驱动加上其它控制程序组合起来的。那么就是说你现在的老板并没有支付你以前做的驱动程序的工资,但是他向你要源程序怎么办呢?都给他吧,可能会觉得自己吃亏,不给他吧程序编译不过去,老板又不答应,怎么办呢?

winavr提供了一个解决这个问题的办法,就是做静态库,把库加入到工程中既能让程序正常编译并使用库中的程序,又没法查看生成库的源程序。这个过程说起来容易做起来难啊!我好几年前就想实现这个目标,可试了许多次都失败了,原因很简单没有详细的资料可以参考,主要是加载库没有说明,制作库的方法在芯艺写的《gcc avr程序设计》有详细的说明,我按照上面说的方法实现了库的生成。一下截取自芯艺写的《gcc avr程序设计》

*************************************************************************************************************

3.2 生成静态连接库
静态连接库是代码重复利用的方式之一。它是编译后生成的目标文件(.o)的集合,在
GCC 中管理静态库的工具叫 ar  ,相应的在 WINAVR 中有一可执行文件 avr-ar.exe 用于生成
静态库。
要构造一个静态连接库, 先从源文件按正常的编译方式生成目标文件 (.o) , 之后用 avr-ar
将这些目标文件组合到一起,静态连接库的命名习惯是以 “lib”开头,以 “.a”为扩展名,
avr-libc (GCC AVR 内核 C 运行时库)都是按这种规则命名的。下面是一个简单的例子它将说
明如何生成静态连接库并在应用程序中使用。
 
文件 lib1.c 用于生成静态库的源文件一,它仅包一个函数,就是将 Mega8 PB1 口连接
的发光管闪烁一次的 FlashLedRed。

/*
  文件名:lib1.c
  静态库源程序
  硬件:CA-M8
 2004-11-25 
*/
 
#include <avr/io.h>
#include <avr/delay.h>
 
#define SET_RED_LED PORTB&=~_BV(PB1)
#define CLR_RED_LED PORTB|=_BV(PB1)
 
//主程序里的延时函数声明
void DelayMs(unsigned int t);
 
void FlashLedRed(void)
{
 SET_RED_LED;
 DelayMs(500);
 CLR_RED_LED;
 DelayMs(500); }

文件 lib2.c 用于生成静态库的源文件二,它同样包一个简单函数 FlashLedYel,用于在
Mega8 PB0 口连接的发光管闪烁一次。

/* 芯 艺 作  品
  37
  文件名:lib2.c
  静态库源程序
  硬件:CA-M8
 2004-11-25
*/
 
#include <avr/io.h>
#include <avr/delay.h>
 
#define SET_YEL_LED PORTB&=~_BV(PB0)
#define CLR_YEL_LED PORTB|=_BV(PB0)
 
//主程序里的延时函数声明
void DelayMs(unsigned int t);
 
void FlashLedYel(void)
{
 SET_YEL_LED;
 DelayMs(500);
 CLR_YEL_LED;
 DelayMs(500); }

接下来的工作就是将这两个文件编译后生成一个库文件, 之前先看一下调用库里函数的
主程序文件,它将调用 FlashLedRed 、 FlashLedYel 两个函数实现两个发光管不断的闪烁,
文件 main.c 的内容如下:

/*
  文件名:main.c
  功   能:静态库测试程序
  硬件  : CA-M8(ChipArt-Mega8)
  编   译: WinAVR-20040720
  时   钟:外部 4MHz
 
  更改记录:
 2004-11-25       
*/
 
#include <avr/io.h>
#include <avr/delay.h>
 
#define uchar unsigned char

#define uint unsigned int
 
//静态库函数声明
void FlashLedRed(void);
void FlashLedYel(void);
 
void DelayMs(uint t)
{
 uint i;
 for(i=0;i<t;i++)
  _delay_loop_2(4 * 250);
}
 
int main(void)
{
 //I/O初始化
 PORTB=_BV(PB0)|_BV(PB1);
 DDRB=_BV(PB0)|_BV(PB1);
 
 while(1)
 {
  FlashLedRed();
  FlashLedYel(); }

}

在命令行先选择当前目录为源文件所在目录,输入命令:
 
avr-gcc -c -mmcu=atmega8 lib1.c lib2.c
 
  这样就生成了两个文件相应的目标文件 lib1.o  和 lib2.o,再输入:
 
 avr-ar -r mylib.a lib1.o lib2.o 
 
  参数-r用于指定库文件名,上面的命令将两个目标文件组合到一个库 mylib.a 中。
有了库文件就可以在应用中调用库中的函数了。
 
 avr-gcc -mmcu=atmega8 main.c mylib.a -o main.elf
 
上面的一行命令将编译 main.c 并与 mylib.a 一起连接后生成可执行文件 main.elf,再用工具
avr-objcopy从 elf文件中提取 flash 内的代码生成可写入单片机的 hex 格式文件。命令如下: 
 
avr-objcopy -O ihex -R .eeprom main.elf main.hex

**********************************************************************************************************

按照上面说的我生成了mylib.a,但是由于我并不是完全用命令行模式产生烧写文件,所以下面的过程就没法验证了,我想在avrstudio中编译生成烧写文件,这个过程我查了很多资料,逛了很多论坛,在google和百度中搜了几个来回,很多人说在avrstudio的编译设置添加库文件,我试过了不行。又有的人说在编译命令里面添加-L -LM什么的我也统统试过还是不行。

终于在http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=751928&bbs_page_no=365&bbs_id=1000这个帖子中找到了灵感,得到了启发。把我做的库连接到程序里了。这个帖子的4楼上官金虹是这样说的:

************************************************************************************

AVR_STUDIO点“Build"后,default文件夹里面就会生成一个MAKEFILE。

在AVR_STUDIO默认生成的MAKEFIEL里加上:
LIBS = 库文件名(含绝对路径或者相对路径)
如:
LIBS =C:/avrx/avrx.a  
或者:
LIBS =../avrx.a  

编译成功。
*************************************************************************************

刚刚试验成功就发上来,可能不成熟,有待继续验证,欢迎看过的朋友和我交流。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /3 下一条