Как разбить программу на несколько файлов
- Войдите на сайт для отправки комментариев
Пнд, 22/04/2013 - 15:41
Доброго времени суток!
Помогите разбить программу на три файла.
Вот известный пример:
01 | //Sample using LiquidCrystal library |
02 | #include <LiquidCrystal.h> |
03 | /******************************************************* |
04 | This program will test the LCD panel and the buttons |
05 | Mark Bramwell, July 2010 |
06 | ********************************************************/ |
07 | // select the pins used on the LCD panel |
08 | LiquidCrystal lcd(8, 9, 4, 5, 6, 7); |
09 | // define some values used by the panel and buttons |
10 | int lcd_key = 0; |
11 | int adc_key_in = 0; |
12 | #define btnRIGHT 0 |
13 | #define btnUP 1 |
14 | #define btnDOWN 2 |
15 | #define btnLEFT 3 |
16 | #define btnSELECT 4 |
17 | #define btnNONE 5 |
18 | // read the buttons |
19 | int read_LCD_buttons() |
20 | { |
21 | adc_key_in = analogRead(0); // read the value from the sensor |
22 | // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 |
23 | // we add approx 50 to those values and check to see if we are close |
24 | if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result |
25 | if (adc_key_in < 50) return btnRIGHT; |
26 | if (adc_key_in < 195) return btnUP; |
27 | if (adc_key_in < 380) return btnDOWN; |
28 | if (adc_key_in < 555) return btnLEFT; |
29 | if (adc_key_in < 790) return btnSELECT; |
30 | return btnNONE; // when all others fail, return this... |
31 | } |
32 | void setup () |
33 | { |
34 | lcd.begin(16, 2); // start the library |
35 | lcd.setCursor(0,0); |
36 | lcd.print( "Push the buttons" ); // print a simple message |
37 | } |
38 | void loop () |
39 | { |
40 | lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over |
41 | lcd.print(millis()/1000); // display seconds elapsed since power-up |
42 | lcd.setCursor(0,1); // move to the begining of the second line |
43 | lcd_key = read_LCD_buttons(); // read the buttons |
44 | switch (lcd_key) // depending on which button was pushed, we perform an action |
45 | { |
46 | case btnRIGHT: |
47 | { |
48 | lcd.print( "RIGHT " ); |
49 | break ; |
50 | } |
51 | case btnLEFT: |
52 | { |
53 | lcd.print( "LEFT " ); |
54 | break ; |
55 | } |
56 | case btnUP: |
57 | { |
58 | lcd.print( "UP " ); |
59 | break ; |
60 | } |
61 | case btnDOWN: |
62 | { |
63 | lcd.print( "DOWN " ); |
64 | break ; |
65 | } |
66 | case btnSELECT: |
67 | { |
68 | lcd.print( "SELECT" ); |
69 | break ; |
70 | } |
71 | case btnNONE: |
72 | { |
73 | lcd.print( "NONE " ); |
74 | break ; |
75 | } |
76 | } |
77 | } |
Хочу разделить его на файлы примерно так:
File_1.ino
01 | /******************************************************* |
02 | This program will test the LCD panel and the buttons |
03 | Mark Bramwell, July 2010 |
04 | ********************************************************/ |
05 | void setup () |
06 | { |
07 | |
08 | init_LCD(); |
09 | } |
10 | void loop () |
11 | { |
12 | lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over |
13 | lcd.print(millis()/1000); // display seconds elapsed since power-up |
14 | lcd.setCursor(0,1); // move to the begining of the second line |
15 | lcd_key = read_LCD_buttons(); // read the buttons |
16 | switch (lcd_key) // depending on which button was pushed, we perform an action |
17 | { |
18 | case btnRIGHT: |
19 | { |
20 | lcd.print( "RIGHT " ); |
21 | break ; |
22 | } |
23 | case btnLEFT: |
24 | { |
25 | lcd.print( "LEFT " ); |
26 | break ; |
27 | } |
28 | case btnUP: |
29 | { |
30 | lcd.print( "UP " ); |
31 | break ; |
32 | } |
33 | case btnDOWN: |
34 | { |
35 | lcd.print( "DOWN " ); |
36 | break ; |
37 | } |
38 | case btnSELECT: |
39 | { |
40 | lcd.print( "SELECT" ); |
41 | break ; |
42 | } |
43 | case btnNONE: |
44 | { |
45 | lcd.print( "NONE " ); |
46 | break ; |
47 | } |
48 | } |
49 | } |
File_2.cpp
01 | #include <LiquidCrystal.h> |
02 | LiquidCrystal lcd(8, 9, 4, 5, 6, 7); |
03 | // define some values used by the panel and buttons |
04 | int lcd_key = 0; |
05 | int adc_key_in = 0; |
06 | #define btnRIGHT 0 |
07 | #define btnUP 1 |
08 | #define btnDOWN 2 |
09 | #define btnLEFT 3 |
10 | #define btnSELECT 4 |
11 | #define btnNONE 5 |
File_3.cpp
01 | int read_LCD_buttons() |
02 | { |
03 | adc_key_in = analogRead(0); // read the value from the sensor |
04 | // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 |
05 | // we add approx 50 to those values and check to see if we are close |
06 | if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result |
07 | if (adc_key_in < 50) return btnRIGHT; |
08 | if (adc_key_in < 195) return btnUP; |
09 | if (adc_key_in < 380) return btnDOWN; |
10 | if (adc_key_in < 555) return btnLEFT; |
11 | if (adc_key_in < 790) return btnSELECT; |
12 | return btnNONE; // when all others fail, return this... |
13 | } |
14 |
15 | void init_LCD() |
16 | { |
17 | lcd.begin(16, 2); // start the library |
18 | lcd.setCursor(0,0); |
19 | lcd.print( "Push the buttons" ); // print a simple message |
20 | } |
сделайте библиотеку
http://www.arduino.ru/Hacking/LibraryTutorial
В программировании на C++ не силен. Пробовал сделать библиотеку. Не получилось. Да и не очень это удобно с точки зрения Arduino.
Мне надо просто разбить на файлы, которые будут лежать в одном каталоге.
Если не трудно: не надо давать советов, лучше покажите как это делается. Как оформить так, что бы не выдавало ошибок. Идея такая: один файл главный, один файл с описанием глобальных переменных (путь это будет *.h или *.cpp) и один или несколько файлов для функций, которые используют глобальные переменные.
Как из данного примера сделать то, что я хочу?
Покажите пожалуйста на конкретном примере.
Это
не надо давать советов
и это
как бы противоречит друг другу...
Поэтому на вопрос
Как из данного примера сделать то, что я хочу?
Покажите пожалуйста на конкретном примере.
посоветую разнести куски в разные .pde-файлы, причем главный из них (с функциями setup() и loop()) должен иметь то же имя, что и каталог проекта.
Показывать не буду - для следования вышеуказанному совету не требуется особых познаний/умений.
И еще посоветую - пользоваться в IDE кнопочкой вверху справа ("стрелка вправо"). Там как раз скрывается меню, необходимое для создания/удаления файлов проекта.
Мдяааа... Все с точностью наоборот.
Попросил не советывать - посветывали. Попросил показать - не показали.
Спасибо!
Неужели так трудно привести пример кода, который можно скопировать и запустить?
"пример кода, который можно скопировать и запустить" - в вашем первом посте.
Осталось положить куски в три файла с расширением .pde
Начиная с версии IDE 1.0 файлы имеют расширение .ino
эээм,вомозжно просто скажем делите ваш проэкт на 3 файла,один из них основной (содержит setup() и loop())
остальным двум присваиваете имена с окончанием .h или .c (хотя думаю там вообще не принципиально с каким окончанием можно даже .txt)и затем в основном файле прописываете
1
#include " имя первого файла,включая окончание"
2
#include "имя второго файла,включая окончание"
3
//естественно файлы должны лежать в одной папке с основным файлом
думаю как то так,хотя не проверял
Ну так проверьте, а после того как не скомпилируется отпишитесь... Делается как написал step962 только с разными расширениями в зависимости от версии IDE.
Если это было бы так просто, я бы не задавал вопросы.
Попробуйте сами скомпилировать пример из первого поста. Выдвет кучу ошибок. Это и понятно, поскольку надо все это еще оформить. Вот я и прошу, помогите избавиться от ошибок.
эээм,вомозжно просто скажем делите ваш проэкт на 3 файла,один из них основной (содержит setup() и loop())
остальным двум присваиваете имена с окончанием .h или .c (хотя думаю там вообще не принципиально с каким окончанием можно даже .txt)и затем в основном файле прописываете
1
#include " имя первого файла,включая окончание"
2
#include "имя второго файла,включая окончание"
3
//естественно файлы должны лежать в одной папке с основным файлом
думаю как то так,хотя не проверял
Это не поможет! Попробуйте
ой.. а чего так сложно-то?
Все гораздо проще реализуется.
1. Создаете (или открываете готовый) скетч
2. Нажимаете комбинацию кнопок CTRL+Shift+N (или мышкой правее вкладки на выпадающий список - "Новая закладка")
3. Вводите имя "дополнительного" файла (только имя, расширение файла среда сама подставит). И нажимаете "ОК".
Все. Проект разнесен на несколько файлов. Переключение между ними с помощью закладок в среде. В компляции участвуют все.
Да не покажешь, не выложешь это на форум. Потому как сильно зависит имено от файловой системы. И начинайте разбиратся не громоздким примером (где вы могли нахомутать в чем-то помимо разбиения на файлы), а с каким-то простеньким. Где в отдельный файл вынесена функция типа printHelloWorld(), и в главно - она вызывается.
Общая идея "разбивки" - такая.
1. Главный файл (в котором setup() и loop()) должен по имени совпадать с именем папки в котором все это лежит. Это самое главное.
2. Все остальные .ino/.pde, .cpp,.h - просто ложим в ту же папку.
3. .h файлы - нужно подключать через include.
4. .ino/.pde файлы - "подключатся сами" (в момент компиляции IDE просто объеденит их с главным файлом, для компилятора это будет "один большой скетч". Правда порядок подключения - IDE будет сама выбирать (скорее всего - тупо по алфавиту).
5. В .h файлах, возможно еще потребутеся делать #include "Arduino.h" или #include "WProgram.h" (в зависимости от того какая у вас версия), что-бы использоватся в .h/.cpp ардуиновские типы, константы, функции.
Вообщем если хотите что-бы вам помогли, то
1. Не рассказывайте как именно должны помогать. Возможно и со способом помощи вы ошибаетесь.
2. Скажите конкретно какие именно ошибки вы видите.
2. Сделайте упрощенный скетч. Использующий только Serial. Без всяких экранов и стронних библиотек проч. - что-бы любой мог запустить его у себя и увидеть те же ошибки что и вы. Вообщем вывернете наоборот свое "привести пример кода, который можно скопировать и запустить". Вы его приведите, а мы посмотрим "что с ним не так".
А по поводу "вашего примера" из стартового поста. Вам нужно либо читать как соотносятся .h/.cpp. Кроме .cpp файлов - нужно создать соотвествующие им .h файлы, где эти функции будут объявлены.
Либо... попробуйте просто переименовать File_2.cpp и File3_.cpp в File_2.ino и File3_.ino
Разбил программу на 4 файла:
Test.ino
01
//Sample using LiquidCrystal library
02
#include <LiquidCrystal.h>
03
#include "Test1.cpp"
04
#include "Test2.cpp"
05
#include "Test3.cpp"/
06
*******************************************************
07
This program will test the LCD panel and the buttons
08
Mark Bramwell, July 2010
09
********************************************************/
10
void
setup
()
11
{
12
print_lcd();
13
}
14
15
void
loop
()
16
{
17
lcd.setCursor(9,1);
// move cursor to second line "1" and 9 spaces over
18
lcd.print(millis()/1000);
// display seconds elapsed since power-up
19
lcd.setCursor(0,1);
// move to the begining of the second line
20
lcd_key = read_LCD_buttons();
// read the buttons
21
switch
(lcd_key)
// depending on which button was pushed, we perform an action
22
{
23
case
btnRIGHT:
24
{
25
lcd.print(
"RIGHT "
);
26
break
;
27
}
28
case
btnLEFT:
29
{
30
lcd.print(
"LEFT "
);
31
break
;
32
}
33
case
btnUP:
34
{
35
lcd.print(
"UP "
);
36
break
;
37
}
38
case
btnDOWN:
39
{
40
lcd.print(
"DOWN "
);
41
break
;
42
}
43
case
btnSELECT:
44
{
45
lcd.print(
"SELECT"
);
46
break
;
47
}
48
case
btnNONE:
49
{
50
lcd.print(
"NONE "
);
51
break
;
52
}
53
}
54
}
Test1.cpp
01
// select the pins used on the LCD panel
02
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
03
// define some values used by the panel and buttons
04
int
lcd_key = 0;
05
int
adc_key_in = 0;
06
#define btnRIGHT 0
07
#define btnUP 1
08
#define btnDOWN 2
09
#define btnLEFT 3
10
#define btnSELECT 4
11
#define btnNONE 5
Test2.cpp
01
// read the buttons
02
int
read_LCD_buttons()
03
{
04
adc_key_in = analogRead(0);
// read the value from the sensor
05
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
06
// we add approx 50 to those values and check to see if we are close
07
if
(adc_key_in > 1000)
return
btnNONE;
// We make this the 1st option for speed reasons since it will be the most likely result
08
if
(adc_key_in < 50)
return
btnRIGHT;
09
if
(adc_key_in < 195)
return
btnUP;
10
if
(adc_key_in < 380)
return
btnDOWN;
11
if
(adc_key_in < 555)
return
btnLEFT;
12
if
(adc_key_in < 790)
return
btnSELECT;
13
return
btnNONE;
// when all others fail, return this...
14
}
Test3.cpp
1
void
print_lcd()
2
{
3
lcd.begin(16, 2);
// start the library
4
lcd.setCursor(0,0);
5
lcd.print(
"Push the buttons"
);
// print a simple message
6
}
Выдает ошибку:
In file included from Test.ino:4:
/Test2.cpp: In function 'int read_LCD_buttons()':
Test2.cpp:4: error: 'analogRead' was not declared in this scope
не видит. попробуйте уговорить что она есть. объявите ее в самом начале.
типа так.
#include <LiquidCrystal.h>
int read_LCD_buttons(void);
#include "d:\test\test\Test1.cpp"
#include "d:\test\test\Test2.cpp"
#include "d:\test\test\Test3.cpp"
Test.ino
01
//Sample using LiquidCrystal library
02
#include <LiquidCrystal.h>
03
#include "Test1.cpp"
04
#include "Test2.cpp"
05
#include "Test3.cpp"
06
/*******************************************************
07
This program will test the LCD panel and the buttons
08
Mark Bramwell, July 2010
09
********************************************************/
10
void
setup
()
11
{
12
print_lcd();
13
}
14
15
void
loop
()
16
{
17
lcd.setCursor(9,1);
// move cursor to second line "1" and 9 spaces over
18
lcd.print(millis()/1000);
// display seconds elapsed since power-up
19
lcd.setCursor(0,1);
// move to the begining of the second line
20
lcd_key = read_LCD_buttons();
// read the buttons
21
switch
(lcd_key)
// depending on which button was pushed, we perform an action
22
{
23
case
btnRIGHT:
24
{
25
lcd.print(
"RIGHT "
);
26
break
;
27
}
28
case
btnLEFT:
29
{
30
lcd.print(
"LEFT "
);
31
break
;
32
}
33
case
btnUP:
34
{
35
lcd.print(
"UP "
);
36
break
;
37
}
38
case
btnDOWN:
39
{
40
lcd.print(
"DOWN "
);
41
break
;
42
}
43
case
btnSELECT:
44
{
45
lcd.print(
"SELECT"
);
46
break
;
47
}
48
case
btnNONE:
49
{
50
lcd.print(
"NONE "
);
51
break
;
52
}
53
}
54
}
Test1.cpp
01
#include <LiquidCrystal.h>
02
03
// select the pins used on the LCD panel
04
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
05
// define some values used by the panel and buttons
06
int
lcd_key = 0;
07
int
adc_key_in = 0;
08
#define btnRIGHT 0
09
#define btnUP 1
10
#define btnDOWN 2
11
#define btnLEFT 3
12
#define btnSELECT 4
13
#define btnNONE 5
Test2.cpp
01
#include "Arduino.h"
02
// read the buttons
03
int
read_LCD_buttons()
04
{
05
adc_key_in = analogRead(0);
// read the value from the sensor
06
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
07
// we add approx 50 to those values and check to see if we are close
08
if
(adc_key_in > 1000)
return
btnNONE;
// We make this the 1st option for speed reasons since it will be the most likely result
09
if
(adc_key_in < 50)
return
btnRIGHT;
10
if
(adc_key_in < 195)
return
btnUP;
11
if
(adc_key_in < 380)
return
btnDOWN;
12
if
(adc_key_in < 555)
return
btnLEFT;
13
if
(adc_key_in < 790)
return
btnSELECT;
14
return
btnNONE;
// when all others fail, return this...
15
}
Test3.cpp
1
void
print_lcd()
2
{
3
lcd.begin(16, 2);
// start the library
4
lcd.setCursor(0,0);
5
lcd.print(
"Push the buttons"
);
// print a simple message
6
}
Ошибка:
Test2.cpp: In function 'int read_LCD_buttons()':
Test2.cpp:5: error: 'adc_key_in' was not declared in this scope
Test2.cpp:8: error: 'btnNONE' was not declared in this scope
Test2.cpp:9: error: 'btnRIGHT' was not declared in this scope
Test2.cpp:10: error: 'btnUP' was not declared in this scope
Test2.cpp:11: error: 'btnDOWN' was not declared in this scope
Test2.cpp:12: error: 'btnLEFT' was not declared in this scope
Test2.cpp:13: error: 'btnSELECT' was not declared in this scope
Test2.cpp:14: error: 'btnNONE' was not declared in this scope
Перестаньте заниматься херней!!! хотя... можете продолжать если нравится. Вам уже 4 человека (ustas, step962, leshak и я) написали как это делается, а вы все .cpp файлы пытаетесь подключить...
Глобальные переменные должны быть объявлены в основном файле:
01
#include <LiquidCrystal.h>
02
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
03
/*******************************************************
04
* This program will test the LCD panel and the buttons
05
* Mark Bramwell, July 2010
06
********************************************************/
07
08
// define some values used by the panel and buttons
09
int
lcd_key = 0;
10
int
adc_key_in = 0;
11
12
void
setup
()
13
{
14
init_LCD();
15
}
16
void
loop
()
17
{
18
lcd.setCursor(9,1);
// move cursor to second line "1" and 9 spaces over
19
lcd.print(millis()/1000);
// display seconds elapsed since power-up
20
lcd.setCursor(0,1);
// move to the begining of the second line
21
lcd_key = read_LCD_buttons();
// read the buttons
22
Print();
23
}
File_1.ino
1
#define btnRIGHT 0
2
#define btnUP 1
3
#define btnDOWN 2
4
#define btnLEFT 3
5
#define btnSELECT 4
6
#define btnNONE 5
File_2.ino
01
int
read_LCD_buttons()
02
{
03
adc_key_in = analogRead(0);
// read the value from the sensor
04
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
05
// we add approx 50 to those values and check to see if we are close
06
if
(adc_key_in > 1000)
return
btnNONE;
// We make this the 1st option for speed reasons since it will be the most likely result
07
if
(adc_key_in < 50)
return
btnRIGHT;
08
if
(adc_key_in < 195)
return
btnUP;
09
if
(adc_key_in < 380)
return
btnDOWN;
10
if
(adc_key_in < 555)
return
btnLEFT;
11
if
(adc_key_in < 790)
return
btnSELECT;
12
return
btnNONE;
// when all others fail, return this...
13
}
14
15
void
init_LCD()
16
{
17
lcd.begin(16, 2);
// start the library
18
lcd.setCursor(0,0);
19
lcd.print(
"Push the buttons"
);
// print a simple message
20
}
21
22
void
Print()
23
{
24
switch
(lcd_key)
// depending on which button was pushed, we perform an action
25
{
26
case
btnRIGHT:
27
{
28
lcd.print(
"RIGHT "
);
29
break
;
30
}
31
case
btnLEFT:
32
{
33
lcd.print(
"LEFT "
);
34
break
;
35
}
36
case
btnUP:
37
{
38
lcd.print(
"UP "
);
39
break
;
40
}
41
case
btnDOWN:
42
{
43
lcd.print(
"DOWN "
);
44
break
;
45
}
46
case
btnSELECT:
47
{
48
lcd.print(
"SELECT"
);
49
break
;
50
}
51
case
btnNONE:
52
{
53
lcd.print(
"NONE "
);
54
break
;
55
}
56
}
57
}
Я кажись понял в чем фигня. ИДЕ подтягивает все файлы в папке, инклуд игнорит. Кладем их в отдельную папку и дело в шляпе, тогда они подтянуться через инклуд. Тогда лучше смело спрыгивать с иде на голый winavr, зачем такие извращения.
Перестаньте заниматься херней!!! хотя... можете продолжать если нравится. Вам уже 4 человека (ustas, step962, leshak и я) написали как это делается, а вы все .cpp файлы пытаетесь подключить...
Извините, но я по-моему говорил, что С не знаю, и вообще я не программист. Поэтому мне что cpp, что ino все равно. По человечески ведь прошу, приведите работающий код. Если это трудно, то лучше не отвечайте и закроем тему. И не надо ругаться. Если будет работающий пример, то потом по тихоньку буду его разбирать. А следующим этапом перейду на создание классов.
Максим-то ругается не потому что вы не знаете, а потому что не читаете что вам пишут. "не программист" - не является оправданием в нежелании разбиратся. Вот вы загуглили, за это время что такое .h и как они работают в паре с .cpp? Похоже что нет.
Вам то может и нет разницы, что .cpp, что .ino . А вот компилятору - есть. И что-то мне подсказывает что из двух вариантов:
1. Уговорить компилятор не видеть разницы и
2. Вам разобратся в разнице и использовать нужно расширение
второй вариант выглядит реальней.
Вот я написал что инклудами подключаются только .h файлы, почему вы пытались .cpp подключить?
Я написал каждому .cpp файлу нужен свой .h файл (и его подключать), вы завели его (а для этого нужно таки загуглить что это за зверь)?
Ладно. Специально для тех кто не хочет разбиратся (хотя если вы хотите с классами, в будущем работать все равно прийдется) - есть специально "Арудино Путь". Просто сделать расширение файло .ino (и ничего не инклудить). Все файлы .ino из папки прикомпиляции IDE невидимо для вас объединит в одну (и это тоже писал).
Вот Максим прочитал "Либо... попробуйте просто переименовать File_2.cpp и File3_.cpp в File_2.ino и File3_.ino" и сделал это. И у него скомпилировалось (хотя, конечно он знал это и без чтения). Потому что он програмист?
Кстати перед тем как переходить к разбирательству с классами почитать Создание библиотек для Arduino из раздела сайта Программирование
Собственно это и есть пример "как создать класс". Разница только в том - куда вы положите .h/.cpp файлы. Если в папку с проектом, то это будет обычный классы. Если же вы положите в какую-то подпапку arduino/libraries - то они же станут носить гордое имя "библиотеки".
Если совсем кратко:
1. .h файл - заголовочный. Содержит "декларацию", какие типы, функции, классы у нас есть. Это как-бы обещание "мы вот эти функции/классы где-нибудь реализуем". Вот его и нужно инклудить.
2. .cpp файл. А это - выполнение обещаний. В него мы ложим реализацию функций/классов (и он - тоже должен делать инклуд .h файла). Сам .cpp инклудить не нужно. Достаточно что-бы он лежал в папке скетча.
Вот если мы в .h файле что-то "пообещаем", а ни в одном .cpp файле не выполним обещание - тогда будет ошибка.
В качестве "примера" - вы можете пойти в папку arduino, зайти в libraries и походить по библиотекам. Посмотреть как выглядят внутри .h / .cpp файлы.
Кстати - весьма эффективный способ учится. Смотреть чужой код. Если не понятно/не известно - гуглить "а че это за штука такая и зачем она тут".
Вам то может и нет разницы, что .cpp, что .ino . А вот компилятору - есть. И что-то мне подсказывает что из двух вариантов:
Нет. Копилятору тоже побарабану расширение файлов. Это только для людей. Компилятор всё равно создает один большой файл из всех разных, включая эти разные файлы там где есть include.
Вот если мы в .h файле что-то "пообещаем", а ни в одном .cpp файле не выполним обещание - тогда будет ошибка.
Наоборот, если сделаем не пообещав, то будет ошибка.
Даже не так. Если мы будем вызывать функции, которые выше главной функции main, то можно не "обещать", если ниже, то надо описать прототип функуции. и не важно в каком файле, главное выше main.
Вот Максим прочитал "Либо... попробуйте просто переименовать File_2.cpp и File3_.cpp в File_2.ino и File3_.ino" и сделал это. И у него скомпилировалось (хотя, конечно он знал это и без чтения). Потому что он програмист?
Ну я вот (на скрине видно) и .cpp скомпилил... я не программист?
Все файлы .ino из папки прикомпиляции IDE невидимо для вас объединит в одну (и это тоже писал).
А вот и правильный ответ! С какого буя эта ИДЕ компилит всё что в папке? Стандарт Си предпологает компиляцию файлов, которые указаны в include. И тот-же winavr, что использует эта иде, тоже стандартный.
Поэтому я задал вполне логичный вопрос, зачем морочиться с этой ИДЕ, если человек хочет делать как положено?
Но то, что этот человек не видит ответов это да, есть.
Библиотека с примером. только смените расширение на rar и разверните в каталог с библиотеками
/sites/default/files/u4655/testlib.jpg
Очень много букв написали. В книгах букв еще больше! По поводу желания разбираться: интересно, а я чем занимаюсь?
Теперь резюме:
Наконец то я получил работающий код собранный из нескольких файлов. Да действительно расширение играет роль, т.к. если взять эти файлы с работающим кодом и переименовать их с расширением cpp (только первому оставить ino), то копиляция уже будет с ошибками. А делал я это потому, что в одной очень умной книжке прочитал, что все остальные подключаемые файлы должны быть написаны на C++ и иметь соответствующие имена.
Теперь о порядке подключения и именования файлов: если писать в такой упрощенной методике как у меня, то файлы должны именоваться в алфавитном порядке в соответствии с их употреблением. Файл, содержащий описание переменных должен идти первым по алфавиту. "Инклюдить" ничего не надо!!! Если именовать файлы в другом порядке, то приходится делать ссылки типа extern.
Вот собственно и все правила. Потрачено три дня переписки и разборок. Если бы уважаемый maksim раньше привел свой пример, времени бы было потрачено меньше. Что собственно я и добивался от вас всех.
Теперь о том, что я не умею читать. Внимательно перечитайте сами, что я у вас всех просил и что вы мне написали и сравните что ответил уважаемый maksim. Ему спасибо, хоть он и не очень хорошо выражается.
Да вот еще __Alexander тоже натолкнул меня на некоторые мысли. Тоже спасибо!
Все тема закрыта.
Категорически не согласен - требую продолжения банкета и рассказа о разбиении программы на 2,5 файла!
Доброго времени суток. Заинтересовался разбивкой файла на части. Вроде понял один способ и попробовал вынести в новый Таб (вкладку) часть файла, например, нужную функцию. При этом Ардуино Иде сама сохраняет нужную вкладку с расширением ino и все компилируется без вопросов. Но интересно разбить на файлы с расширением .h/.cpp. Пока не получается. Хотя какой-то простенький работает, типа:
Главный файл
01
#include "file1.h"
02
03
void
setup
() {
04
// put your setup code here, to run once:
05
Serial
.begin(9600);
06
ppp();
07
}
08
09
void
loop
() {
10
// put your main code here, to run repeatedly:
11
12
}
file1.h
1
#include "Arduino.h"
2
3
void
ppp();
file1.cpp
1
#include "file1.h"
2
3
void
ppp() {
4
Serial
.println(
"da-da-da"
);
5
}
Но разбить свой файл по тому же принципу пока не получилось. Может кто глянет и покажет как разбить мой файл?
01
#include <ESP8266WiFi.h> // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
02
#include <WiFiClient.h>
03
04
char
* array_ssid[] = {
"ssid1"
,
"ssid2"
,
"ssid3"
,
"ssid4"
};
// Массив необходимых ссидов
05
char
* array_pass[] = {
"pass1"
,
"pass2"
,
"pass3"
,
"pass4"
};
// Массив необходимых паролей к этим ссидам
06
07
int
count_ssid =
sizeof
(array_ssid) /
sizeof
(array_ssid[0]);
// Размер массива ссидов
08
09
// Функция скарирования и подключения к найденной известной сети из нашего списка, другие будут игнорится
10
void
conekt_to_wifi(
int
networksFound) {
//
11
uint8_t tries = 100;
// Количество попыток подключения
12
if
(WiFi.status() != WL_CONNECTED) {
// Проверяем, есть ли вообще подключение, если нет, то в следующей строке запускаем сканирование
13
Serial
.println(
"not connekt"
);
14
for
(
int
i = 0; i < networksFound; i++) {
// Перебираем полученные точки доступа
15
for
(
int
j = 0; j < count_ssid; j++) {
// Перебираем в нашем списке точек доступа и проверяем условия
16
17
if
(WiFi.status() == WL_CONNECTED) {
// Сперва проверяем, если все же есть подключение, то выходим из цикла. Нужно для проверки при разрывах
18
break
;
19
// WiFi.scanDelete();
20
// return true;
21
}
22
else
if
(WiFi.SSID(i) == array_ssid[j]) {
// Если нет подключения, то сравниваем с нашим списком
23
Serial
.println(
"\nOne of our ssid was found = "
+ WiFi.SSID(i));
24
WiFi.begin(array_ssid[j], array_pass[j]);
// Стартуем подключение к точке доступа
25
Serial
.printf(
"waiting"
);
26
while
(--tries){
27
while
(WiFi.status() != WL_CONNECTED) {
// Зупускаем ожидание поднятия вайфай сервера
28
delay(1000);
29
Serial
.print(
"."
);
30
}
31
}
32
Serial
.println(
"connekt"
+ String(array_ssid[j]));
33
Serial
.println(WiFi.localIP());
// Распечатываем полученный айпишник
34
}
35
}
36
}
37
if
(WiFi.status() != WL_CONNECTED) {
// Доп. роверка и отчет, если нет точек из нашего списка
38
Serial
.println(
"\nNo famouse wifi"
);
39
}
40
}
else
{
41
Serial
.println(
"connekt"
);
42
}
43
}
44
45
void
setup
() {
46
WiFi.persistent(
false
);
47
Serial
.begin(9600);
48
WiFi.mode(WIFI_OFF);
// Останавливаем вайфай
49
delay(1000);
50
WiFi.mode(WIFI_STA);
// Запускаем вайфай в режиме клиента
51
Serial
.println(
"\nOur mac = "
+ WiFi.macAddress());
// Выводим мак адрес
52
conekt_to_wifi(WiFi.scanNetworks());
// Стартуем функцию сканирования сети и поиска нужной сети
53
}
54
55
void
loop
() {
56
conekt_to_wifi(WiFi.scanNetworks());
// Стартуем в цикле функцию сканирования сети и поиска нужной сети
57
}
Что именно не получилось?
Хотел вынести функцию conekt_to_wifi() в отдельный файл и подключить его. Пробовал разные варианты, получал разные ошибки. То дважды объявлял переменные, то наоборот не объявлены, то ещё какие-то.
Руководствуйтесь этим правилом: все переменные, функции и объекты должны быть объявлены ранее их использования.
Хотел вынести функцию conekt_to_wifi() в отдельный файл и подключить его. Пробовал разные варианты, получал разные ошибки.
главное правило - выносимая в отдельный файл функция не должна использовать никаких "внешних" переменных, структур, данных... а у вас ваша функция нуждается в массивах ssid и pass, например.
Если функции нужны какие-то данные из других частей программы - они должны передаваться как параметры. Глобальные переменные в других файлах НЕ РАБОТАЮТ!
То же самое с результатом работы функции - функция не должна менять какие-то глобальные переменные, все что она выполнила - должно передаваться через возвращаемые значения или через параметры, переданные по ссылке.
Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?
Вообще, чтобы разбивать программу на отдельные файлы - ее, программу, надо с самого начала проектировать с расчетом на это.
Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?
В принципе никто не мешает. Я делал такой вариант, были другие ошибки. С другой стороны, хотелось бы в одном месте видеть все вводимые, получаемые данные, а их обработку делать в другом месте. Тем более, что уж если начать разделять файл, то потом его нужно будет поделить больше чем на две части, разбить на группы функций.
И в принципе понимаю, что программу нужно планировать с самого начала. Но я ведь только учусь. Я эту программу не сразу написал. И она требует доработки. Хотя уже в такой стадии, что уже можно пробовать её разбивать. Вот когда научусь писать программы, тогда и начну изначально писать именно с разбивкой, если она того будет требовать.
Пробую, только не совсем понятно, что в каком порядке объявляется, когда файл разбит. Возможно я не правильно понял ситуацию, но ведь для этого и делают два файла .h/.cpp. В одном объявляют, в другом реализуют/используют. А вот как они соотносятся с главным файлом, для меня пока не понятно
Глобальные переменные в других файлах НЕ РАБОТАЮТ!
Как так? А модификатор extern ?
test.ino:
01
#include "ext.h"
02
03
uint32_t ExternalVarible;
04
05
void
setup
() {
06
Serial
.begin(9600);
07
ExternalVarible = 0;
08
tt ();
09
}
10
11
void
loop
() {
12
13
}
ext.h:
1
extern
uint32_t ExternalVarible;
2
3
void
tt ( ) {
4
ExternalVarible = 7;
5
Serial
.print(ExternalVarible);
6
}
Не проверял, но компилируется и где-то уже использовал подобное...
Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?
В принципе никто не мешает. Я делал такой вариант, были другие ошибки. С другой стороны, хотелось бы в одном месте видеть все вводимые, получаемые данные, а их обработку делать в другом месте.
другой путь - передавать нужные данные из основной программы в функцию как параметры. Но тогда надо думать о правильной организации данных. Например все те же массивы ssid и pass у вас организованы не слишком удобно - как массивы неопределенного числа ссылок на строки неизвестного размера... придется передавать не только ссылки на данные, но и их размер как отдельный параметр. Впрочем, для ссылок на массивы это стандартная практика
Лень читать.) Нужно разбивать на файлы по логике. К примеру led.cpp и led.h описание и т.д. Это как положено. Другое дело что Арудино позволяет создавать множество ino файлов, которые собирает автоматом. Это для ленивых, но временами, удобно.)
другой путь - передавать нужные данные из основной программы в функцию как параметры. Но тогда надо думать о правильной организации данных. Например все те же массивы ssid и pass у вас организованы не слишком удобно - как массивы неопределенного числа ссылок на строки неизвестного размера... придется передавать не только ссылки на данные, но и их размер как отдельный параметр. Впрочем, для ссылок на массивы это стандартная практика
Сейчас как раз пробую с этим разобраться и ещё с многомерными массивами. Ну как сейчас... Типа в ближайших планах. Но пока примеров маловато. Не все понимаю.
Лень читать.) Нужно разбивать на файлы по логике. К примеру led.cpp и led.h описание и т.д. Это как положено. Другое дело что Арудино позволяет создавать множество ino файлов, которые собирает автоматом. Это для ленивых, но временами, удобно.)
Это вы про себя, что вам лень читать? Бывает. Только не понятно, что конкретно вам лень читать.
Я то с вами согласен. Самый простой способ тупо разбить файл на нужное число частей, допустим по одному файлу на одну функцию и сохранить с расширением ino. Об этом варианте я написал выше. Он работает. Но мне интересно разобраться с разбивкой на файлы .h/.cpp
многомерные массивы.... не увлекайтесь ими.
Массивы a[2][2] и b[4] организованы в памяти одинаково и занимают одинаковое место, но если передавать данные между процедурами или писать на носители - одномерный значительно проще и удобнее
Пока что я не понял, как организовать цикл перебора многомерного массива, а там будет видно. И конечно, может окажется, что в данной ситуации одномерный выгоднее. Но очень хотелось бы больше удобств при добавлении данных. Чтоб не по отдельности добавлять ссид в один массив, потом к нему пароль в другой массив, а сразу парой, типа ключ:значение или индекс:значение или словарь:список. Кому как удобней и привычней понимать.
Да и если вдруг как-то эти данные придется использовать в джсоне, то удобней именно многмерный массив. Но я до конца структуру программы не продумал. Это ж для Ардуино, фактически Си. Мне тут все новое.
Тем более, что читал, вроде есть возможность на некоторые платы делать заливку через вэб. Да и вообще, мало ли что захочу передать через вэб. Вот, пока тренируюсь
Дядя Гена, тренируйтесь. "Не дойдёт через голову - дойдёт через..." руки. А не дойдёт - тогда ой.(