Отговори на тема  [ 22 мнения ]  Отиди на страница 1, 2  Следваща
Разделяне на подпрограмите в .с фаилове. 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение Разделяне на подпрограмите в .с фаилове.
Здавейте.
До момента всеки път като съм писал софтуер за PIC18/С18 съм хакал всички функции и дифиниции в един фаил например main.c.
Но когато подпрограмите, функциите и т.н. станаха много, вече е неудобно да скролвам, а и искам да си ги отделя като отделни фаилове, така че да ги ползвам като готови функции.
Пероблема е следния.
definitions.h
Код:
#include <p18f452.h>
#include <delays.h>
#include <adc.h>
#include <stdlib.h>

#pragma udata access my_access
extern volatile near struct {
   unsigned inmenu2:1;
   unsigned rpgbp:1;
} flags;
#pragma udata


#define LCDRS    LATEbits.LATE0
#define LCDE    LATEbits.LATE1
#define LCDRW    LATEbits.LATE2   
#define PWMR   LATCbits.LATC0   //RED PWM
#define tmrval   105   //Задава периода на всеки подпериод на ШИМ
//=============Prototipi===============
void gene(void);
unsigned char checkbf(void);
void lcdcmd(unsigned char cmd);
void initlcd(void);
void lcdchar(unsigned char datachar);
void printlcdt(const rom char *buffer);
void printlcd(char *buffer);
void loadvals(void);
void chartbs(void);
unsigned char rpgdir(void);
unsigned char rpgbut(void);
void high_isr_h(void);   //handling high iterrupt
void low_isr_h(void);   //handling low interrupts
//================Използвани глобални променливи=============================================
extern volatile unsigned char oldrpg,rpgbuf,newrpg,mpos;
extern volatile unsigned char rpgdirv;


А това е кода на rpg.c .
Код:
#include "definitions.h"
#include <p18f452.h>

unsigned char rpgdir(void)
{   newrpg=PORTB&0x03;
   if(newrpg==oldrpg)
   {return 0;}
   oldrpg=newrpg;
   STATUSbits.C=0;
   _asm    
      movlb    rpgbuf
      rlcf    rpgbuf,1,1
      bcf      STATUS,0,0
      rlcf   rpgbuf,1,1
    _endasm
   rpgbuf|=newrpg;
   
   if(rpgbuf==0x4b)
   {rpgbuf=0x00;return 2;}
   if(rpgbuf==0x87)
   {rpgbuf=0x00;return 1;}
   return 0;
}

unsigned char rpgbut(void)
{
   if(PORTBbits.RB2==0)
   {flags.rpgbp=1;return 0;}
   if(PORTBbits.RB2==1 && flags.rpgbp==1)
   {flags.rpgbp=0;return 1;}
}


Идеята ми е всички глобални променливи заедно с прототипите на функците да са в "definition.h", но постоянно ми дава грешка "Error - could not find definition of symbol 'newrpg' in file './rpg.o'."

Насочете ме или направо ми кажете къде греша!


Съб Фев 20, 2010 6:15 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
Еми къде е дефинирано newrpg?


Съб Фев 20, 2010 7:38 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 
Реконструктор написа:
Еми къде е дефинирано newrpg?


В "definition.h".


Съб Фев 20, 2010 7:46 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Юни 01, 2008 9:54 pm
Мнения: 1503
Местоположение: Пловдив
Мнение 
ммм, не е. значи ако декларираш една променлива някъде ок, да кажем unsigned char x и искаш да я използваш някъде другаде (в различен файл от този в който е декларирана) я добавяш 1:1 с декларацията, но добавяш extern. става extern unsigned char x, което указва на компилатора, че тя *вече* е декларирана някъде и той трябва да я намери извън текущият файл, но това с extern само по себе си НЕ декларира променливата. разбираш?


Съб Фев 20, 2010 7:54 pm
Профил WWW
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 
head_up написа:
ммм, не е. значи ако декларираш една променлива някъде ок, да кажем unsigned char x и искаш да я използваш някъде другаде (в различен файл от този в който е декларирана) я добавяш 1:1 с декларацията, но добавяш extern. става extern unsigned char x, което указва на компилатора, че тя *вече* е декларирана някъде и той трябва да я намери извън текущият файл, но това с extern само по себе си НЕ декларира променливата. разбираш?

Дам разбрах и тръгна като ги дефинирах в main.c(без extern), но това исках да избегна :), т.е. мислих, че има начин след като се дефинира на едно място без да се дефинират на ново да се ползват т.к. са глобални, ама явно няма начин :).

Друго..."definition.h" вече изглежда така :
Код:

#pragma udata access my_access
volatile near struct {
   unsigned inmenu2:1;
   unsigned rpgbp:1;
} flags;
#pragma udata

volatile unsigned char oldrpg,rpgbuf,newrpg,mpos;

rpg.c
Код:
extern volatile unsigned char oldrpg,rpgbuf,newrpg;
extern volatile near struct {
   unsigned inmenu2:1;
   unsigned rpgbp:1;
} flags;

Но дава грешка "Error - symbol 'flags' has multiple definitions." А тази структура не е дефинирана никъде освен в "definition.h" .Когато е дефинирана в "main.c" проблеми няма.Има ли начин да я оставя в .h фаила?


Съб Фев 20, 2010 9:29 pm
Профил ICQ
Ранг: Популярен
Ранг: Популярен

Регистриран на: Съб Ное 28, 2009 5:50 am
Мнения: 391
Местоположение: Варна
Мнение 
ами според мен трябва да имаш само unsigned char oldrpg,rpgbuf,newrpg,mpos; в definitions.h
не ти трябва extern май! :)

_________________
Ангел Димитров 95


Съб Фев 20, 2010 10:49 pm
Профил WWW
Ранг: Ориентиран
Ранг: Ориентиран

Регистриран на: Вто Фев 06, 2007 2:45 am
Мнения: 263
Мнение 
Как трябва e:

Код:
"Example.h":

extern volatile unsigned char newrpg;


Код:
"Example.c":

#include <Example.h>

volatile unsigned char newrpg;


Всичко, което трябва да се вижда навън - декларирано в хедъра като extern.
Останалото - в .с файла и без extern.


Съб Фев 20, 2010 10:56 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 
tolstolob написа:
Как трябва e:

Код:
"Example.h":

extern volatile unsigned char newrpg;


Код:
"Example.c":

#include <Example.h>

volatile unsigned char newrpg;


Всичко, което трябва да се вижда навън - декларирано в хедъра като extern.
Останалото - в .с файла и без extern.


Сега ще пробвам това последното :).


Съб Фев 20, 2010 11:03 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 24, 2005 11:41 pm
Мнения: 1049
Местоположение: Pz
Мнение 
Както ти е в първия пост, разкарай това "extern" от декларацийте и работата ще стане! :-)
Сега, ако имаш друг *.с файл (test.c) в който ще ползваш някоя променлива, декларирана в definitions.h, ще стане така:

Код:
test.c

#include <p18f452.h>
unsigned char test(void) ;
extern volatile unsigned char mpos;

unsigned char test(void)
{
   if(mpos==0x30) return 0xff;
}


Нед Фев 21, 2010 1:23 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
edi написа:
Но дава грешка "Error - symbol 'flags' has multiple definitions." А тази структура не е дефинирана никъде освен в "definition.h" .Когато е дефинирана в "main.c" проблеми няма.Има ли начин да я оставя в .h фаила?


extern е за валидност на декларации, обявени в други object, lib, so или каквито се сетиш още байнъри файлове.
По принцип никога не се декларира променлива в хедър файл, защото в един момент почти сигурно е, че ще се получи двойна дефиниция.


Нед Фев 21, 2010 9:25 am
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 
Реконструктор написа:
extern е за валидност на декларации, обявени в други object, lib, so или каквито се сетиш още байнъри файлове.
По принцип никога не се декларира променлива в хедър файл, защото в един момент почти сигурно е, че ще се получи двойна дефиниция.


Ясно разбрах каква е логиката :).


Нед Фев 21, 2010 10:26 am
Профил ICQ
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Нед Сеп 17, 2006 12:00 pm
Мнения: 450
Местоположение: Plovdiv
Мнение 
В хедърния файл е добре да слагаш хедърът, чрез който се избягва зацикляне на препроцесора от вмъкването на файла едновременно от няколко места. Нали се сещаш:
Код:
#ifndef _DEFINITION_H
#define _DEFINITION_H
.....
#endif

Освен това както каза реконструктора никога не се слагат декларации на променливи в хедърен файл.


Нед Фев 21, 2010 1:49 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение 
MidNighT_SpiRiT написа:
Освен това както каза реконструктора никога не се слагат декларации на променливи в хедърен файл.


Много хора бъркат термините и така вместо да помогнат объркват още повече начинаещите...

Значи термините са "декларация" и "дефиниция".

Чрез дефиниция реално се създава дадена променлива или се кодира функция. Естествено е, че дефиницията е еднократна щото веднъж се създава дадения обект. При повторна дефиниция, компилатора ще се опита да създаде втори обект, стига да не е в същата област на валидност, щото в една област не може да има два обекта с едно и също име.
Пример за дефиниции:
Код:

char test;

char foo(void)
{
return  test++;
}



Чрез декларация се обявява даден обект и част от неговите атрибути като тип и т.н., без самият обект да се създава. С други думи декларацията е анонс на дефиниция, която е направена на друго място. Пример за декларации:
Код:

extern char test;

char foo(void);



Много често се бъркат термините (включително и на английски) и вместо дефиниция се използва декларация... Понякога хората ги бъркат неумишлено, но много често и поради незнание или неразбиране. Причината е, че за С-компилатора декларацията е по-важна от дефиницията. В смисъл за да се използва даден обект то той задължително трябва да бъде деклариран, но не е задължително да бъде дефиниран. Примерно може да си използвате променлива, която реално не съществува (не е дефинирана). Компилаторът ще ви го позволи и проблемът ще се появи чак на ниво линкер. Тук е другия проблем, че хората не правят разлика между компилатор и линкер, но това е друга тема ;-)

Както и да е... Накратко - дефиниция се прави веднъж, обикновено в .ц файл. Примерно ако си правиш библиотека за работа с PWM, то pwm.c ще съдържа дефинициите на всички променливи и функции. За да могат тия неща да се ползват от други места, ще трябва на всяко място да се декларират преди ползването. Би било неудобно на 100 места да декларираш едно и също нещо, затова се правят h-файлове и в тях се слагат съответните декларации. Примерно в pwm.h ще се сложат всички декларации на обектите от pwm.c който ще се ползват. Така ако искаш някъде да ползваш pwm просто вмъкваш #include "pwm.h" и това ти дава всички нужни декларации.

Още веднъж - дефиницията се прави веднъж, а декларацията толкова пъти, колкото е необходимо. Но с използване на хедър файлове се спестява многократното писане на едни и същи декларации.

Иначе в хедър файл може да се вкарват и дефиниции. Но това ще създава нов обект навсякъде където се вмъкне хедъра. Понякога това е целта. Примерно inline функциите се дефинират в h файлове, тъй като много компилатори изискват inline функциите да са статични.


Нед Фев 21, 2010 3:23 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Нед Сеп 17, 2006 12:00 pm
Мнения: 450
Местоположение: Plovdiv
Мнение 
Прав си miro_atc, извинявам се за грешката!


Пон Фев 22, 2010 9:02 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Окт 12, 2006 3:52 pm
Мнения: 21
Местоположение: Varna
Мнение 
Благодаря ти miro_atc за изчерпателния отговор :).
Друг въпрос, не много по темата.
Как мога да присвоя стойност на една 16битова променлива, като стойността и се образува от две 8 битови например :
Код:
unsigned int temp;
unsigned char varh,varl;
temp=varh:varl;

Нещо такова ми трябва.
Спомням си, че го четах това из C18 User Guide, но немога да го намеря :(.


Сря Фев 24, 2010 8:00 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 22 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 3 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни