В своих программа, мы постоянно набираем одни и те же куски кода, например, - работа с Аналого – Цифровым Преобразователем, Приемо-Передатчиком и т.д. Чтобы не создавать постоянную «волокиту» с повторяющимся кодом, все это можно оформить в виде файлов библиотеки ( т.назыв. библитеки различного назначения ).
Создавать библиотечные файлы можно тремя способами:
• Связка файлов *.lib <-> *.h
• Связка файлов *.c <-> *.h
• Собственно файлом реализации *.c
Библиотечные файлы *.lib и *.h
В корневой папке CodeVisionAVR имеется каталог /lib, в котором находятся файлы с расширением *.lib ( например - LCD.LIB, DS1621.LIB и т.д. ), входящие в комплект поставки программы. Это Объектные файлы библиотеки ( Object File Library ). Они содержат определения функций – собственно реализацию.
В каталоге /inc находятся файлы с расширением *.h ( например - LCD.H, DS1621.H и т.д. ) входящие в комплект поставки программы. Это заголовочные файлы ( Header ); в них содержатся прототипы функций. Header файлы собственно и подключаются в основном проекте:
#include <LCD.H>
Взаимосвязь этих, двух файлов происходит посредством директивы #pragma library name.lib:
Заголовочный файл LCD.H
#ifndef _LCD_INCLUDED_
#define _LCD_INCLUDED_
#pragma used+
//прототипы функций
. . . .
void _lcd_write_data( unsigned char data );
. . . .
void lcd_putsf( char flash *str );
unsigned char lcd_init( unsigned char lcd_columns );
. . . .
#pragma used-
#pragma library lcd.lib //подключение объектного файла библиотеки
#endif
Объектный файл библиотеки LCD.LIB
. . . .
void _lcd_write_data( unsigned char data )
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf0 | ( 1<<__lcd_rs ) | ( 1<<__lcd_rd ) | ( 1<<__lcd_enable ) ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
#endasm
_lcd_write_nibble( ); //RD=0, write MSN
#asm
ld r26,y
swap r26
#endasm
_lcd_write_nibble( ); //write LSN
#asm
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}
. . . .
Как видно, С-шная функция с ассемблерными вставки: используются всеми известные ассемблерные команды. С ними можно ознакомиться, посмотрев последние страницы PDF-документации на какой – либо микроконтроллер, например,- Atmega8535.
На основе выше указанных разъяснений, создадим свою библиотеку для примера.
В каталоге /lib создадим текстовый файл ( text file.txt ) и не отменяя переименование назовем его как function.lib. Запишем в него две функции и определение пользовательского типа:
//пользовательский тип
enum select{ C,ASM }; //C - 0, ASM - 1
void light_On( unsigned char select )
{
switch( select )
{
case C: PORTD.0=1; break;
case ASM:
#asm
sbi 0x12,0
#endasm
break;
}
}
void light_Off( unsigned char select )
{
switch( select )
{
case C: PORTD.0=0; break;
case ASM:
#asm
cbi 0x12,0
#endasm
break;
}
}
В каталоге /inc создадим текстовый файл ( text file.txt ) и не отменяя переименование назовем его как function.h. Запишем в него прототипы функций:
#ifndef _LCD_FUNCTION_
#define _LCD_FUNCTION_
// Эта директива запрещает компилятору
// выдавать предупреждения о том, что функция
// объявлена, но в программе не используется.
#pragma used+
//прототипы функций
void light_On( unsigned char select );
void light_Off( unsigned char select );
#pragma used-
// Эта директива разрешает компилятору
// выдавать предупреждения о том, что функция
// объявлена, но в программе не используется.
//подключение библиотечного файла name.lib
#pragma library FUNCTION.lib
#endif
Создадим проект в среде CodeVisionAVR без мастера кода( CodeWizardAVR ). Эти этапы были описаны в статье CodeVisionAVR. Первый проект для микроконтроллера AVR.
В главный файл проекта main.c записаваем код программы. Подключаем Header файл библиотеки:
//Компиллятор cvavr не чувствителен к регистру при записи имен библиотек
//Можно записать как <function.h> так и <FUNCTION.H>
#include <function.h>
Главная функция main:
void main( void )
{
light_On( C ); delay_ms( 500 );
light_Off( C ); delay_ms( 500 );
light_On( ASM ); delay_ms( 500 );
light_Off( ASM ); delay_ms( 500 );
while( 1 );
}
Файлы проекта и библиотеки скачать можно здесь
Библиотечные файлы *.c и *.h
Это связка библиотечных файлов в языке С является общепринятой. *.h – заголовочный файл, который содержит прототипы функций. Header файл может также содержать любое разнообразие макросов, структур и всевозможных объявлений:
. . . .
extern unsigned char Buffer_UART[255]; //буфер приема/передачи UART
extern unsigned int ADC_Channel[7]; //каналы АЦП
. . . .
struct{
unsigned char control;
unsigned char dataOut;
unsigned char current;
unsigned ErrRcv: 1;
unsigned ErrCRC: 1;
unsigned DataRcv: 1; } device;
. . . .
#define setbit ( port,bits ) port.bits=1;
#define clearbit( port,bits ) port.bits=0;
. . . .
void port_init( void );
void adc_init( void );
Файл с расширением *.C содержит определение функции т.е. её полную реализацию:
void port_init( void )
{
DDRD=0x84;
PORTD=0xEF;
DDRC=0x04;
PORTC=0xf0;
}
void adc_init( void )
{
//Инициализация АЦП
ADMUX=MUX0; //ADC0
ADCSRA=0xCE;
SFIOR&=0xEF;
}
Удалим файл function.h от предыдущего варианта библиотеки. В каталоге /inc создадим два файла с расширением *.c и *.h.
В Header файле запишем код:
#pragma used+
void lightSetup( unsigned char swt );
void lightFadeInOut( unsigned char value );
#pragma used-
//подключаем файл реализации функций
#include <FUNCTION.C>
В Си файле реализации запишем код:
//пользовательский тип ON=0, OFF=1
enum select{ ON,OFF };
void lightSetup( unsigned char swt )
{
switch( swt )
{
case ON: PORTD.0=1; break;
case OFF: PORTD.0=0; break;
}
}
void lightFadeInOut( unsigned char value )
{
PORTC=value;
}
Код программы в файле проекта main.c:
#include <mega8535.h>
#include <function.h>
#include <delay.h>
void main( void )
{
lightSetup( ON ); delay_ms( 500 );
lightSetup( OFF ); delay_ms( 500 );
lightFadeInOut( 100 );
while( 1 );
}
Файлы проекта и библиотеки скачать можно здесь
Source файл реализации *.C
Создать библиотечный файл не применяя header - файлов, можно используя только файл реализации *.C. В нём прописываем необходимые определения переменных, структуры, прототипы функций и собственно их полную реализацию. На мой взгляд, это более простое решение в создании библиотечных файлов, и большинство программистов это используют( имеются знакомые программисты, которые так поступают! ).
Удалим файлы function.h и function.c от предыдущего варианта библиотеки и создадим source файл function.c, в который добавим код:
#pragma used+
//прототипы функций
//предварительное объявление
void lightSetup( unsigned char swt );
void lightFadeInOut( unsigned char value );
enum select{ ON,OFF };
//реализация функций ( определение )
//функции можно распологать и делать вызовы из других функций в любом порядке
void lightSetup( unsigned char swt )
{
switch( swt )
{
case ON: PORTD.0=1; break;
case OFF: PORTD.0=0; break;
}
}
void lightFadeInOut( unsigned char value )
{
PORTC=value;
}
#pragma used-
Код программы в файле проекта main.c:
#include <mega8535.h>
#include <function.c>
#include <delay.h>
void main( void )
{
lightSetup( ON ); delay_ms( 500 );
lightSetup( OFF ); delay_ms( 500 );
lightFadeInOut( 100 );
while( 1 );
}
Файлы проекта и библиотеки скачать можно здесь
|