struct array и PROGMEM - как записать структуру массива и сам строковый массив в Flash-память
- Войдите на сайт для отправки комментариев
Чт, 27/09/2018 - 17:52
Добрый вечер! Прошу знатоков подсказать правильное задание структуры строковых массивов и задание значений элементов массива с записью в Flash-память, нужно для экономии динамической памяти Arduino Nano.
Код, который применяю:
#include <avr/pgmspace.h>
struct listUsr_t
{
const char phoneNum[13];
const char phonePass[5];
const char phonePDU[13];
};
listUsr_t users[20] =
{
{ "+70000000000", "0000", "000000000000" },
{ "+71111111111", "0000", "000000000000" },
{ "+78881234567", "0000", "000000000000" },
{ "+78882345678", "0000", "000000000000" },
{ "+78883456789", "0000", "000000000000" },
{ "+78884567890", "0000", "000000000000" },
{ "+78885678901", "0000", "000000000000" },
{ "+78886789012", "0000", "000000000000" },
{ "+78887890123", "0000", "000000000000" },
{ "+78888901234", "0000", "000000000000" },
{ "+78880123456", "0000", "000000000000" },
{ "+78881123456", "0000", "000000000000" },
{ "+78881234567", "0000", "000000000000" },
{ "+78881345678", "0000", "000000000000" },
{ "+78881456789", "0000", "000000000000" },
{ "+78881567890", "0000", "000000000000" },
{ "+78881678901", "0000", "000000000000" },
{ "+78881789012", "0000", "000000000000" },
{ "+78881890123", "0000", "000000000000" },
{ "+78881901234", "0000", "000000000000" }
};
void setup()
{
Serial.begin(9600);
Serial.println(sizeof(users));
}
void loop()
{
;
}
Размер данных возвращается 620 байт, что соответствует действительности 13+5+13=31*20=620.
Подскажите, пожалуйста, как этот массив записать в Flash-память, при помощи pgmspace.h - я не могу разобраться, к сожалению... Заранее благодарен за помощь!
Записать строковый массив без структуры - нет проблем:
#include <avr/pgmspace.h> const char _phoneNum[2][13] PROGMEM = { "+70000000000", "+711111111111" };Нужен массив со структурой...
а const listUsr_t PROGMEM users[20] = .... не решает?
а const listUsr_t PROGMEM users[20] = .... не решает?
Огромное спасибо! Я не мог понять почему ругается компилятор - PROGMEM ставил в разные места, объявляя массив со структурой, но забывал про const, теперь, массив со структурой задается и располагается в Flash-памяти... еще раз - спасибо!
https://www.arduino.cc/reference/en/language/variables/utilities/progmem/
https://www.arduino.cc/reference/en/language/variables/utilities/progmem/
Спасибо! Я эту статью прочитал несколько раз, и не мог понять причину, искал в сторону pgmspace.h и синтаксиса этой библиотеки, а оказалось, я не правильно объявлял элемент, его нужно было как const объявлять.
По ссылке strarbit более правильный способ, ибо запихивание массива строк в pgmspace несколько специфичная задача.
Вроде вчера в другой теме было тоже самое и вновь опять #25
По ссылке strarbit более правильный способ, ибо запихивание массива строк в pgmspace несколько специфичная задача.
Именно из-за специфичности задачи я и обратился к помощи более опытных коллег. Задача состоит в том, чтобы в 2048 байта уместить код с многими логическими функциями, и прочим кодом, отвечающим за контроль работы привода.
Вроде вчера в другой теме было тоже самое и вновь опять #25
Я читал ветку, на которую Вы ссылаетесь, там не совсем аналогичная задача обсуждалась...
Записать строки с необходимыми данными в Flash-память получилось, это очень сильно сэкономило память контроллера. Однако, теперь у меня новый тупик, я не могу считать строки, считывается только первый символ и все... вот код:
#include <avr/pgmspace.h> const uint8_t cntLstPhones = 2; struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; const char plot[9]; }; const listUsr_t PROGMEM users[cntLstPhones] = { { "+78881890123", "0000", "000000000000", "plot #" }, { "+78881901234", "0000", "000000000000", "plot #" } }; void setup() { Serial.begin(57600); Serial.println(F("<== START of DATA ==>")); char val; val = (__FlashStringHelper*)(pgm_read_dword(&(users[1].phonePass))); Serial.println(val); Serial.println(F("<== END of DATA ==>")); } void loop() { ; }При этом компилятор выдает предупреждение: "warning: invalid conversion from '__FlashStringHelper*' to 'char' [-fpermissive]", и в монитор Serial-порта выводится только первый символ строки, записанной в Flash-память, куда копать не могу разобраться, прошу помощи!!!
вы пытаетесь считывать строку в переменную val, которая обьявлена как char - то есть имеет размер 1 символ. Что же еще туда может считаться, кроме 1 символа?
Я это понимаю, в глубине души, однако, при попытке задать размер строкового массива
компилятор возвращает ошибку и прекращает компиляцию: "error: incompatible types in assignment of '__FlashStringHelper*' to 'char [5]'", у меня тупик, если честно...
Использовать strcpy_P ещё не пробовал, но это не путь, т.к. strcpy_P требует объявлять переменные, как глобальные, а глобальные переменные "скушают" память, динамическую, и вся экономия при помощи PROGMEM будет зря... Заранее благодарен, если подскажите правильный код для решения моей задачи.
Ну, вам нужно свыкнуться с мыслью, что "в ноль" вы потери не выведете.
Просто радуйтесь тому, что строки, расположенные в progmem не будут перегружаться в RAM и не будет двойного удара по ресурсам.
И мне все еще кажется, что в PGM вы засунули неправильно. Почитайте статью по ссылке strarbit - там есть специальный раздел "Array of string". Нужно делать именно так, во всех деталях, с раздельными объявлениями строк в PGM, а потом сборе в общий массив. Может сейчас компилятор и умничает, а года два назад такой способ, как приведен у вас, лично мне никак не помогал экономить.
Использовать strcpy_P ещё не пробовал, но это не путь, т.к. strcpy_P требует объявлять переменные, как глобальные
во-первых, это не так - strcpy_P работает и с локальными переменными. Во-вторых, даже если использовать глобальную переменную буфера - то для strcpy_P она нужна всего одна на все ваши строки в ПРОГМЕМ, так что удар по ресурсам не так уж и велик.
Вам надо еще раз внимательно перечитать ссылки, которые вам дали выше. Вам кажется, что они не про ваш случай, что он уникален - но он получается уникальным именно потому, что вы подходите к хранению строк неправильно. Сделайте как по ссылке и все получится.
Если речь идет о том, что сначала необходимо задать строковые массивы, потом создать таблицу с указанием на созданные строковые массивы и считывать при помощи pgm_read_dword или pgm_read_word в буфер или созданную переменную (почему-то пишется, что только глобальную), то это я знаю, но в таком случае не будет структуры... НО и без структуры можно обойтись, весь проблемный для меня вопрос, это то, что один из строковых массивов имеет длину 250 символов, и если даже, я сделаю, как написано в описании работы (ссылка предложенная выше по этому обсуждению, то у меня получиться 20% сразу долой из памяти контроллера, это для меня не решение задачи.
Кроме того, как объяснить тот факт, что код вида:
#include <avr/pgmspace.h> const uint8_t cntLstPhones = 2; struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; const char plot[9]; }; const listUsr_t PROGMEM users[cntLstPhones] = { { "+78881890123", "0000", "000000000000", "plot #" }, { "+78881901234", "0000", "000000000000", "plot #" } }; void setup() { Serial.begin(57600); Serial.println(F("<== START of DATA ==>")); for (uint8_t i = 0; i < cntLstPhones; i++) { printUsr(users[i], i); } Serial.println(F("<== END of DATA ==>")); } void loop() { ; } void printUsr(const listUsr_t &user, uint8_t numPhone) { Serial.println(numPhone + 1); Serial.println((const __FlashStringHelper*)user.phoneNum); Serial.println((const __FlashStringHelper*)user.phonePass); Serial.println((const __FlashStringHelper*)user.phonePDU); Serial.println((const __FlashStringHelper*)user.Plot); }Этот код выводит в монитор Serial-порта все строки правильно... значит в Flash-память они помещены тоже правильно... Кто может помочь - буду благодарен!!!
Ну-ну. Похоже это башня из доминошек. Лишний чих и сново-здорово.
#include <avr/pgmspace.h> const uint8_t cntLstPhones = 2; struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; const char plot[9]; }; const listUsr_t PROGMEM users[cntLstPhones] = { { "+78881890123", "0000", "000000000000", "plot #" }, { "+78881901234", "00000", "000000000000", "plot #" } //<- а теперь ко второму элементу добавим лишний 0 }; void setup() { Serial.begin(9600); Serial.println(F("<== START of DATA ==>")); for (uint8_t i = 0; i < cntLstPhones; i++) { printUsr(users[i], i); } Serial.println(F("<== END of DATA ==>")); } void loop() { ; } void printUsr(const listUsr_t &user, uint8_t numPhone) { Serial.println(numPhone + 1); Serial.println((const __FlashStringHelper*)user.phoneNum); Serial.println((const __FlashStringHelper*)user.phonePass); Serial.println((const __FlashStringHelper*)user.phonePDU); Serial.println((const __FlashStringHelper*)user.plot); }НО и без структуры можно обойтись, весь проблемный для меня вопрос, это то, что один из строковых массивов имеет длину 250 символов,
весь массив 250 символов или КАЖДЫЙ элемент 250?
Если у вас отдельный элемент 250 символов - то как ни старайся, вам придется копировать его в память. Или выводить по частям. Может в таком случае вы просто не тот контроллер взяли? В Меге 8к памяти, а в СТМ32 - аж целых 20к, стоит посмотреть на них.
Вообще, по-моему вы взялись за проект. слишком сложный для вашего уровня. Так ли уж необходимо запихивать в Нано эту базу данных с телефонами? Может без нее обойтись?
Этот код выводит в монитор Serial-порта все строки правильно... значит в Flash-память они помещены тоже правильно... Кто может помочь - буду благодарен!!!
если этот код работает - используйте его
Ну, вобщем, советовать как лучше решить задачу, смысла которой не знаешь, абсолютно бессмысленно.
Почему вы решили, что нельзя создать стуктуру с указателями на PGM-строки - мне тоже не особо понятно. Переменных в 250 символов я тут у вас не вижу.
весь массив 250 символов или КАЖДЫЙ элемент 250?
Если у вас отдельный элемент 250 символов - то как ни старайся, вам придется копировать его в память. Или выводить по частям. Может в таком случае вы просто не тот контроллер взяли? В Меге 8к памяти, а в СТМ32 - аж целых 20к, стоит посмотреть на них.
Вообще, по-моему вы взялись за проект. слишком сложный для вашего уровня. Так ли уж необходимо запихивать в Нано эту базу данных с телефонами? Может без нее обойтись?
если этот код работает - используйте его
каждый по 250 символов....
использовать код - я не могу понять, как сравнить строку записанную в Flash-память со строкой в динамической памяти, сравнивать нужно строки длиной 13 и 5 символов, соответсвенно строка 13 символов сравнивается со строкой из 13 символов, 13-й символ это \0, завершающий.
Строки из 250 сивловов используются для отправки сообщений при помощи модуля SIM800, в PDU режиме, кодировать в скетче, опять же, много памяти расходуется...
Менять тип контроллера пока не готов, интересно добиться результата и реализовать задачу на нано, т.е. уместив код скетча в 2048 байт...
использовать код - я не могу понять, как сравнить строку записанную в Flash-память со строкой в динамической памяти
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#gab0c75b8cce460448b747c29231da847c <<The strcmp_P() function is similar to strcmp() except that s2 is pointer to a string in program space
Ну, вобщем, советовать как лучше решить задачу, смысла которой не знаешь, абсолютно бессмысленно.
Почему вы решили, что нельзя создать стуктуру с указателями на PGM-строки - мне тоже не особо понятно. Переменных в 250 символов я тут у вас не вижу.
Структуру я создал и строковые массивы с заданной структурой я записал в флеш-память (в коде, прикрепленном мной это видно). Правильность записанных строковых массивов проверяю, пока, пуьем вывода в монитор Serial-порта (также, видно в моем коде).
Задача состоит в том, что при входящем вызове (модуль SIM800), средствами модуля определяем номер телефона, и необходимо сравнить определившийся номер с номерами из массива, номера из массива перебираем при помощи цикла for, если хоть один номера из массива совпадает, то выполняется действие (digitalWrite pin), если не один номер не совпал, то отбой звонка, примерно такая стоит задача.
Строки в 250 символов (максималная длина) это сообщения в PDU режиме для того же модуля, они ни с чем не сравниваются, с их использованием собираются смс-сообщения на русском языке (PDU mode).
Я не могу разобраться, как сравнить строку 13 или 5 символов в флеш-памяти с соответсвующей строкой в динамической памяти контроллера, за помощь или подсказку буду очень признателен!
Ну, может как-то так (на МК не заливал)?
char incomingNumber[] = "70000000003"; digitalWrite(13, LOW); for (uint8_t i = 0; i < 3; i++) { if (0x00 == strcnmp_P(incomingNumber, users[i].phoneNum, 13)) { digitalWrite(13, HIGH); } }Ну, может как-то так (на МК не заливал)?
char incomingNumber[] = "70000000003"; digitalWrite(13, LOW); for (uint8_t i = 0; i < 3; i++) { if (0x00 == strcnmp_P(incomingNumber, users[i].phoneNum, 13)) { digitalWrite(13, HIGH); } }Спасибо огромное!
Я тоже смотрел описание этого макроса - буду пробовать использовать сравнение из PGM, по результатам отпишусь, ещё раз - спасибо!
Строки из 250 сивловов используются для отправки сообщений при помощи модуля SIM800, в PDU режиме, кодировать в скетче, опять же, много памяти расходуется...
Кодируйте динамически
Ну, может как-то так (на МК не заливал)?
char incomingNumber[] = "70000000003"; digitalWrite(13, LOW); for (uint8_t i = 0; i < 3; i++) { if (0x00 == strcnmp_P(incomingNumber, users[i].phoneNum, 13)) { digitalWrite(13, HIGH); } }Доброе утро! Ещё раз спасибо! Код залил на МК - всё работает, память отбирается соответственно переменным, все ОК! Код не много дополнил, в связи с тем, что определение номера идет в String:
String innerPhone = "+70001234567"; // номер входящего вызова, определяемый другой функцией (SIM800) char incPhone[13]; innerPhone.toCharArray(incPhone, 13); if (strncmp_P(incPhone, users[i].phoneNum, 13) == 0x00) Serial.println(F("true")); else Serial.println(F("false"));Логику и действия с пинами МК - это уже готово, практически, главная задача была уместиться в отведенные 2048 байт памяти МК. На данный момент, все константы с номерами, паролями, текмстовыми сообщениями в нескольких форматах, загружаются в флеш-память, расход динамической памяти 10%, ранее было 52%, экономия присутствует...
Ещё раз спасибо всем за помощь и консультации!
Теперь остался один непонятный для меня момент в работе с PGM. Как сравнить строки из ОЗУ и Флеш, разобрался с общей помощью, а как "вытащить" строку из флеш-памяти, чтобы "собрать" необходимый пакет в строку, из нескольких строк, несколько частей составной строки находится в ОЗУ в виде локальных переменных в конкретной функции, а некоторые части составной строки находятся в флеш-памяти.
Подскажите как "вытащить" строку из флеш-памяти в локальную переменную в ОЗУ или сразу добавить в составную строку часть из флеш-памяти???
Памяти не хватает!!!
Памяти не хватает!!!
У меня все хватает, логику поменяйте, в пн могу скинуть часть скетча.
Памяти не хватает!!!
буду признателен!
1) У класса String имеется свойство, дающее указатель типа char* - копировать не надо в буфер.
2) По ссылке на nongnu перечислены все функции, работающие с pgm - например strncpy_p()
буду признателен!
Там относительно просто, используется буфер для исходного сообщения размером максимум 70 байт (максимум для одного смс по русски по стандартам) в однобайтовой кодировке, например win1251. Отсылает сначала заголовки pdu, потом цикл по буферу и каждый символ на ходу переводите UCS2 кодировку и отсылаете.
У меня объем всего скетча вроде половины (не помню точно - в пн скажу) памяти уно со следующим функционалом: приём ( в т ч длинных) и отправка смс в pdu формате, обработка присылаемых команд, работа с олед дисплеем, отображение напряжения питания модема, аптайм и пр.
И да - привыкайте работать со строками char - пригодится
как и обещал, часть скетча (4 файла из 5), вдруг пригодится:
//--s800str.h-- #include <avr\pgmspace.h> #define maxSizeATcommand 40 #define maxSizeResponse 24 #define count_ext_cmd 3 // only ascii chars const char extCmd1[] PROGMEM = "getuptime"; const char extCmd2[] PROGMEM = "getpower"; const char extCmd3[] PROGMEM = "getbalmegafon"; const char * const ext_cmd_list[] PROGMEM = { // external commands extCmd1, extCmd2, extCmd3 }; void getExtCmdByNum(byte numCmd, char* textCmd); const char at0cmdAT[] PROGMEM = "AT\r\n"; const char at1cmdHTTPACTION[] PROGMEM = "AT+HTTPACTION=0\r\n"; const char at1rsp1[] PROGMEM = "+HTTPACTION:"; const char at1rsp2[] PROGMEM = ","; const char at2cmdSAPBR11[] PROGMEM = "AT+SAPBR=1,1\r\n"; const char at2rsp1[] PROGMEM = "operation not allowed\r\n"; const char at3cmdREADSMS[] PROGMEM = "AT+CMGL=4\r\n"; // "AT+CMGL=\"ALL\"\r\n"; const char at4cmdDDET[] PROGMEM = "AT+DDET=1\r\n"; const char at5cmdATE0[] PROGMEM = "ATE0\r\n"; const char at6cmdCLIP1[] PROGMEM = "AT+CLIP=1\r\n"; const char at7cmdATS0[] PROGMEM = "ATS0=0\r\n"; const char at8cmdATV1[] PROGMEM = "ATV1\r\n"; const char at9cmdATCMEE2[] PROGMEM = "AT+CMEE=2\r\n"; const char at10cmdATCMGF1[] PROGMEM = "AT+CMGF=0\r\n"; const char at11cmdATCREG[] PROGMEM = "AT+CREG?\r\n"; const char at11rsp1[] PROGMEM = "+CREG:"; const char at11rsp2[] PROGMEM = ",1\r\n"; const char at12cmdDELSMS[] PROGMEM = "AT+CMGDA=6\r\n"; // "AT+CMGDA=\"DEL ALL\"\r\n"; const char at13cmdSAPBR311[] PROGMEM = "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n"; const char at14cmdSAPBR312[] PROGMEM = "AT+SAPBR=3,1,\"APN\",\"internet\"\r\n"; const char at15cmdSAPBR313[] PROGMEM = "AT+SAPBR=3,1,\"USER\",\"\"\r\n"; const char at16cmdSAPBR314[] PROGMEM = "AT+SAPBR=3,1,\"PWD\",\"\"\r\n"; const char at17cmdSAPBR21[] PROGMEM = "AT+SAPBR=2,1\r\n"; const char at17rsp1[] PROGMEM = "+SAPBR:"; const char at17rsp2[] PROGMEM = ",1,\""; const char at18cmdHTTPINIT[] PROGMEM = "AT+HTTPINIT\r\n"; const char at19cmdHTTPCID[] PROGMEM = "AT+HTTPPARA=\"CID\",1\r\n"; const char at20cmdHTTPURL[] PROGMEM = "AT+HTTPPARA=\"URL\",\"www.ya.ru\"\r\n"; const char at21cmdHTTPREAD[] PROGMEM = "AT+HTTPREAD\r\n"; const char at22cmdHTTPTERM[] PROGMEM = "AT+HTTPTERM\r\n"; const char at23cmdCSCLK1[] PROGMEM = "AT+CSCLK=1\r\n"; // =1 if use DTR pin modem const char at24cmdGETOPS[] PROGMEM = "AT+COPS?\r\n"; // get operator const char at25cmdCSQ[] PROGMEM = "AT+CSQ\r\n"; // get net const char at26cmdCMGS[] PROGMEM = "AT+CMGS="; // begin send sms const char at26rsp1[] PROGMEM = ">"; // begin send sms const char at27cmdCMGS[] PROGMEM = "none"; // text sms const char at27rsp1[] PROGMEM = "+CMGS:"; // text sms const char at28cmdBALMEG[] PROGMEM = "AT+CUSD=1,\"*100#\"\r\n"; // get balance megafon const char at28rsp1[] PROGMEM = "+CUSD:"; const char at28rsp2[] PROGMEM = ", 72\r\n"; const char rspOK[] PROGMEM = "OK\r\n"; const char rspEndLine[] PROGMEM = "\r\n"; const char * const at_list_cmd[] PROGMEM = { // text command at0cmdAT, at1cmdHTTPACTION, at2cmdSAPBR11, at3cmdREADSMS, at4cmdDDET, at5cmdATE0, at6cmdCLIP1, at7cmdATS0, at8cmdATV1, at9cmdATCMEE2, at10cmdATCMGF1, at11cmdATCREG, at12cmdDELSMS, at13cmdSAPBR311, at14cmdSAPBR312, at15cmdSAPBR313, at16cmdSAPBR314, at17cmdSAPBR21, at18cmdHTTPINIT, at19cmdHTTPCID, at20cmdHTTPURL, at21cmdHTTPREAD, at22cmdHTTPTERM, at23cmdCSCLK1, at24cmdGETOPS, at25cmdCSQ, at26cmdCMGS, at27cmdCMGS, at28cmdBALMEG }; const PROGMEM uint8_t at_rresp_cmd[] = { // 0-count right response 1, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3 }; const PROGMEM uint8_t at_oresp_cmd[] = { // 1-count other response - need manual action by response 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const PROGMEM uint8_t at_move_cmd[] = { // step after action cmd 4, 21, 17, 12, 5, 6, 7, 8, 9, 10, 11, 13, 101, 14, 15, 16, 23, 18, 19, 20, 1, 22, 101, 24, 12, 101, 27, 101, 101 }; const char * const at_list_rresp[] PROGMEM = { rspOK, // at0 rspOK, at1rsp1, at1rsp2, rspEndLine, // at1 rspOK, // at3 rspOK, // at4 rspOK, // at5 rspOK, // at6 rspOK, // at7 rspOK, // at8 rspOK, // at9 rspOK, // at10 at11rsp1, at11rsp2, rspOK, // at11 rspOK, // at12 rspOK, // at13 rspOK, // at14 rspOK, // at15 rspOK, // at16 at17rsp1, at17rsp2, rspOK, // at17 rspOK, // at18 rspOK, // at19 rspOK, // at20 rspOK, // at21 rspOK, // at22 rspOK, // at23 rspOK, // at24 rspOK, // at25 at26rsp1, // at26 at27rsp1, rspOK, // at27 rspOK, at28rsp1, at28rsp2 // at28 }; const char * const at_list_oresp[] PROGMEM = { rspOK, at2rsp1 // at2 }; void s800getTextCmdByNum(byte numCmd, char* textCmd); byte s800getCountRrespCmdByNum(byte numCmd); byte s800getCountOrespCmdByNum(byte numCmd); void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd); byte s800getNextStepCmdByNum(byte numCmd); #define GSM_RX 3 // пин RX на модуле подключаем к указаному пину на Ардуино TX #define GSM_TX 2 // пин TX на модуле подключаем к указаному пину на Ардуино RX #define WORK_LEVEL_LED 0 // 1 if HIGH level ON led, else 0 #define WORK_LEVEL_RELAY 0 // 1 if HIGH level ON relay, else 0 #define reset_sim800_pin 4 // pin for reset modem #define dtr_sim800_pin 10 // pin DTR for sleep mode #define power_level_pin A6 // input power level for control #define relay1_pin 6 // pin relay 1 #define relay2_pin 5 // pin relay 2 #define relay3_pin 9 // pin relay 3 #define ledRed_pin 7 // pin RED led #define ledGre_pin 8 // pin GREEN led #if (WORK_LEVEL_LED == 0) #define LEDREDON digitalWrite(ledRed_pin,LOW) #define LEDGREON digitalWrite(ledGre_pin,LOW) #define LEDREDOFF digitalWrite(ledRed_pin,HIGH) #define LEDGREOFF digitalWrite(ledGre_pin,HIGH) #else #define LEDREDON digitalWrite(ledRed_pin,HIGH) #define LEDGREON digitalWrite(ledGre_pin,HIGH) #define LEDREDOFF digitalWrite(ledRed_pin,LOW) #define LEDGREOFF digitalWrite(ledGre_pin,LOW) #endif #if (WORK_LEVEL_RELAY == 0) #define RELAY1ON digitalWrite(relay1_pin,LOW) #define RELAY2ON digitalWrite(relay2_pin,LOW) #define RELAY3ON digitalWrite(relay3_pin,LOW) #define RELAY1OFF digitalWrite(relay1_pin,HIGH) #define RELAY2OFF digitalWrite(relay2_pin,HIGH) #define RELAY3OFF digitalWrite(relay3_pin,HIGH) #else #define RELAY1ON digitalWrite(relay1_pin,HIGH) #define RELAY2ON digitalWrite(relay2_pin,HIGH) #define RELAY3ON digitalWrite(relay3_pin,HIGH) #define RELAY1OFF digitalWrite(relay1_pin,LOW) #define RELAY2OFF digitalWrite(relay2_pin,LOW) #define RELAY3OFF digitalWrite(relay3_pin,LOW) #endif char* LastPos(char *str1, char *str2); int strPos(char *str11, char *str22); //--s800str.cpp-- #include "Arduino.h" #include "s800str.h" void getExtCmdByNum(byte numCmd, char* textCmd) { const char * addrStroki = pgm_read_word_near((int)(ext_cmd_list + numCmd)); strcpy_P(textCmd, addrStroki); } void s800getTextCmdByNum(byte numCmd, char* textCmd) { const char * addrStroki = pgm_read_word_near((int)(at_list_cmd + numCmd)); strcpy_P(textCmd, addrStroki); } byte s800getCountRrespCmdByNum(byte numCmd) { return pgm_read_byte_near(at_rresp_cmd + numCmd); } byte s800getCountOrespCmdByNum(byte numCmd) { return pgm_read_byte_near(at_oresp_cmd + numCmd); } byte s800getNextStepCmdByNum(byte numCmd) { return pgm_read_byte_near(at_move_cmd + numCmd); } void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd) { byte startPos = 0; if (numCmd > 0) for (byte i = 1; i <= numCmd; ++i) { switch (typeResp) { case 0: { startPos += pgm_read_byte_near(at_rresp_cmd + i - 1); break; } case 1: { startPos += pgm_read_byte_near(at_oresp_cmd + i - 1); break; } default : {} } } switch (typeResp) { case 0: { const char * addrStroki = pgm_read_word_near((int)(at_list_rresp + startPos + numResp)); strcpy_P(textCmd, addrStroki); break; } case 1: { const char * addrStroki = pgm_read_word_near((int)(at_list_oresp + startPos + numResp)); strcpy_P(textCmd, addrStroki); break; } default : {} } } char* LastPos(char *str1, char *str2) { // find substring in string int L1 = strlen(str1); int L2 = strlen(str2); for (int i = L1 - L2; i >= 0; i--) { int j = 0; for (; j < L2; j++) if ((str1[i + j] != str2[j])) break; if (j == L2) return str1 + i; } return 0; } int strPos(char *str11, char *str22) { // find position in string(1) substring(2) char*p = LastPos(str11, str22); int n = p - str11; return n; } //--s800sms.h-- #define SHOW_SMS 1 // 1 show sms in console #define max_size_sms_sender 12 // 11 + stopbyte; #define max_size_cmd 16 // maximum size external command #define max_size_out_sms 64 // maximum size out SMS by WIN1251 chars void getDecode7bitChar(byte byte1, byte byte0); byte getByteFromTwoChar(byte byte1, byte byte0); void doSMSbody(byte readByte); void doSMShead(); void cmdClearBuf(); byte findCmdInBuf(byte inByte); byte findCmdFromBuf(char* textCmd); void smsClearOut(); void smsPrepareSender(char* textSender); void smsPrepareText(char* textText); void smsPrepareText(byte inByte); void smsPrepareOut(); byte smsOutPackedByte(); byte smsGetSizePDU(); byte doHaveSendSms(); //--s800sms.cpp-- #include "Arduino.h" #include "s800str.h" #include "s800sms.h" extern void execExtCmd(byte numCmd); extern byte pos_buf; extern char resp_buf[maxSizeResponse]; byte pos_cmd; char cmd_buf[max_size_cmd]; char sms_buf[max_size_out_sms]; byte sms_out_size_packet; byte sms_out_pos_sender; byte sms_out_pos_string; byte sms_out_pos_other; byte sms_out_pos_mode; byte smsLenSender; byte smsLenString; byte smsUDL; void cmdClearBuf() { memset(cmd_buf, 0, max_size_cmd); pos_cmd = 0; } byte findCmdInBuf(byte inByte) { cmd_buf[pos_cmd] = inByte; ++pos_cmd; if (pos_cmd >= max_size_cmd) pos_cmd = 0; char ext_cmd[max_size_cmd]; for (byte i = 0; i < count_ext_cmd; ++i) { getExtCmdByNum(i, ext_cmd); if (findCmdFromBuf(ext_cmd)) { cmdClearBuf(); return (i + 1); } } return 0; } byte findCmdFromBuf(char* textCmd) { if (cmd_buf[pos_cmd] > 0) { byte idxBuf; if (pos_cmd == 0) idxBuf = max_size_cmd - 1; else idxBuf = pos_cmd - 1; byte lenResp = strlen(textCmd); byte idxResp = lenResp - 1; byte cntResp = 0; for (byte i = 0; i < max_size_cmd; ++i) { if (cmd_buf[idxBuf] == 0) break; if (cmd_buf[idxBuf] == textCmd[idxResp]) { --idxResp; if ((++cntResp) == lenResp) return 1; } else { cntResp = 0; idxResp = lenResp - 1; } if ((--idxBuf) == 0) idxBuf = max_size_cmd - 1; } } else if (pos_cmd > 0) { if (strPos(cmd_buf, textCmd) >= 0) { return 1; } } return 0; } byte smsStep = 0; //99 start new sms byte smsOriginalSize; byte smsOriginalPosByte; byte smsTmpByte; byte smsSizePhone; byte smsBodyPosByte; byte smsTPMTICO; byte smsTPUDHI; char smsSender[max_size_sms_sender]; byte smsTPOA; byte smsTmpSize; byte smsTPDCS; byte smsPrevDecodeByte; byte smsIdxCurrentChar; byte smsUDHL; byte smsIEDL; byte smsIED; void getDecode7bitChar(byte byte1, byte byte0) { byte posIdx = smsIdxCurrentChar % 8; byte byteOut; if (posIdx > 0) { byteOut = byte0 << posIdx; byte b2 = byte1 >> (8 - posIdx); byteOut = byteOut | b2; byteOut = byteOut & 0x7F; if (byte1) { #if (SHOW_SMS == 1) Serial.write(byteOut); #endif // find external command byte bc = findCmdInBuf(byteOut); if (bc) execExtCmd(bc - 1); } if (posIdx == 6) { byteOut = byte0 >> 1; #if (SHOW_SMS == 1) Serial.write(byteOut); #endif // find external command byte bc = findCmdInBuf(byteOut); if (bc) execExtCmd(bc - 1); ++smsIdxCurrentChar; } } else { byteOut = byte0; byteOut = byteOut & 0x7F; #if (SHOW_SMS == 1) Serial.write(byteOut); #endif // find external command byte bc = findCmdInBuf(byteOut); if (bc) execExtCmd(bc - 1); } ++smsIdxCurrentChar; } byte getByteFromTwoChar(byte byte1, byte byte0) { byte resultB; if (byte1 >= 0x41) resultB = (byte1 - 0x37) * 16; else resultB = (byte1 - 0x30) * 16; if (byte0 >= 0x41) resultB = resultB + (byte0 - 0x37); else resultB = resultB + (byte0 - 0x30); return resultB; } void doSMShead() { // get length body sms byte posSbyte = 0; byte posBbyte = (pos_buf - 3); while ((resp_buf[posBbyte] >= 0x30) && (resp_buf[posBbyte] <= 0x39)) { if (posSbyte == 0) smsOriginalSize = (resp_buf[posBbyte] - 0x30); else if (posSbyte == 1) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 10; else if (posSbyte == 2) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 100; ++posSbyte; --posBbyte; } smsOriginalPosByte = 0; smsStep = 99; } void doSMSbody(byte readByte) { // get byte from buf ++smsOriginalPosByte; switch (smsStep) { case 99: { // get size sms centr if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte); smsStep = 100; } break; } case 100: { // skip num sms centr if (!bitRead(smsOriginalPosByte, 0)) { if ((--smsSizePhone) == 0) { smsStep = 101; smsBodyPosByte = 0; } } break; } case 101: { // get TP-MTI & Co if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { smsTPMTICO = getByteFromTwoChar(smsTmpByte, readByte); ++smsBodyPosByte; // analize TP-MTI & Co smsTPUDHI = bitRead(smsTPMTICO, 6); if ((bitRead(smsTPMTICO, 0) == 0) && (bitRead(smsTPMTICO, 1) == 0)) smsStep = 102; else smsStep = 0; } break; } case 102: { // get TP-OA - sender if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte); if (bitRead(smsSizePhone, 0)) smsTmpSize = smsSizePhone + 1; else smsTmpSize = smsSizePhone; ++smsBodyPosByte; smsStep = 103; } break; } case 103: { // get TP-OA - sender if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { smsTPOA = getByteFromTwoChar(smsTmpByte, readByte); ++smsBodyPosByte; smsSender[0] = 0; smsStep = 104; } break; } case 104: { // get TP-OA - sender if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; // processing sender byte ts; if (bitRead(smsSizePhone, 0)) ts = smsSizePhone + 1; else ts = smsSizePhone; byte tp = ts - smsTmpSize; if ((bitRead(smsTPOA, 6) == 1) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) && (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 0)) { // char sender // ignore sms smsStep = 0; break; } else if ((bitRead(smsTPOA, 6) == 0) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) && (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 1)) { // number phone if (tp < max_size_sms_sender) smsSender[tp] = readByte; ++tp; if (tp < max_size_sms_sender) smsSender[tp] = smsTmpByte; if ((ts > smsSizePhone) && (smsTmpSize <= 2)) { if (tp < max_size_sms_sender) smsSender[tp] = 0; } else { if ((tp + 1) < max_size_sms_sender) smsSender[tp + 1] = 0; } } else { smsStep = 0; break; } // --- if ((smsTmpSize -= 2) == 0) smsStep = 105; } break; } case 105: { // TP-PID if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; smsStep = 106; } break; } case 106: { // TP-DCS if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; smsTPDCS = getByteFromTwoChar(smsTmpByte, readByte); smsStep = 107; smsTmpSize = 7; } break; } case 107: { // TP-SCTS - skip 7 byte if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; if ((--smsTmpSize) == 0) smsStep = 108; } break; } case 108: { // TP-UDL if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; smsTmpSize = getByteFromTwoChar(smsTmpByte, readByte); if (smsTPUDHI == 0) { #if (SHOW_SMS == 1) Serial.println(smsSender); #endif smsPrevDecodeByte = 0; smsIdxCurrentChar = 0; smsStep = 109; } else { // long sms smsStep = 110; } } break; } case 109: { // body sms if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { byte tb = getByteFromTwoChar(smsTmpByte, readByte); if (smsTPDCS == 0) { // decode 7 bit getDecode7bitChar(smsPrevDecodeByte, tb); smsPrevDecodeByte = tb; } else { // decode UCS2 if ((smsPrevDecodeByte == 0x04) && (tb >= 0x10) && (tb <= 0x4F)) { // rus unicode #if (SHOW_SMS == 1) if (tb >= 0x40) { Serial.write(0xD1); Serial.write(0x40 + tb); } else { Serial.write(0xD0); Serial.write(0x80 + tb); } #endif } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x01)) { #if (SHOW_SMS == 1) Serial.write(0xD0); Serial.write(0x01); #endif } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x51)) { #if (SHOW_SMS == 1) Serial.write(0xD1); Serial.write(0x91); #endif } else if ((smsPrevDecodeByte == 0x00) && (tb >= 0x20) && (tb < 0x7F)) { // ascii #if (SHOW_SMS == 1) Serial.write(tb); #endif // find external command byte bc = findCmdInBuf(tb); if (bc) execExtCmd(bc - 1); } smsPrevDecodeByte = tb; } if ((++smsBodyPosByte) >= smsOriginalSize) { // end sms smsStep = 0; #if (SHOW_SMS == 1) if (smsTPUDHI == 0) { Serial.write('\r'); Serial.write('\n'); } else if (smsIED = smsIEDL) { Serial.write('\r'); Serial.write('\n'); } #endif } } break; } case 110: { // TP-UDH if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; // get num and count sms and show sender smsUDHL = getByteFromTwoChar(smsTmpByte, readByte) - 1; smsStep = 111; } break; } case 111: { // EIDL if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; // get num and count sms and show sender if ((--smsUDHL) == 0) { smsIEDL = getByteFromTwoChar(smsTmpByte, readByte); smsStep = 112; } } break; } case 112: { // EID if (bitRead(smsOriginalPosByte, 0)) { smsTmpByte = readByte; } else { ++smsBodyPosByte; // get num and count sms and show sender smsIED = getByteFromTwoChar(smsTmpByte, readByte); #if (SHOW_SMS == 1) if (smsIED == 1) Serial.println(smsSender); #endif smsPrevDecodeByte = 0; smsIdxCurrentChar = 6; smsStep = 109; } break; } default: {} } } void smsClearOut() { sms_buf[0] = 0; sms_out_size_packet = 0; } void smsPrepareSender(char* textSender) { strcpy(smsSender, textSender); } void smsPrepareText(char* textText) { if ((strlen(sms_buf) + strlen(textText)) < (max_size_out_sms - 1)) strcat(sms_buf, textText); } void smsPrepareText(byte inByte) { byte st = strlen(sms_buf); if (st < (max_size_out_sms - 1)) { sms_buf[st] = inByte; sms_buf[st + 1] = 0; } } void smsPrepareOut() { sms_out_pos_sender = 0; sms_out_pos_string = 0; sms_out_pos_other = 0; sms_out_pos_mode = 0; // calculate size all fields SMS by PDU format sms_out_size_packet = 3; // SCA + PDU Type + MR smsLenSender = strlen(smsSender); byte lenSender = smsLenSender; if (bitRead(lenSender, 0)) ++lenSender; sms_out_size_packet += 2; // lenght + format sender sms_out_size_packet += (lenSender / 2); // sender sms_out_size_packet += 3; // PID + DCS + VP(null) +UDL smsLenString = strlen(sms_buf); smsUDL = (smsLenString * 2); sms_out_size_packet += smsUDL; // UD --sms_out_size_packet; // -SCA } byte smsOutPackedByte() { switch (sms_out_pos_mode) { case 0: { // SCA if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; return '0'; } else { ++sms_out_pos_other; return '0'; } break; } case 1: { // PDU Type if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; return '1'; } else { ++sms_out_pos_other; return '0'; } break; } case 2: { // MR if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; return '0'; } else { ++sms_out_pos_other; return '0'; } break; } case 3: { // DA if (sms_out_pos_other < 2) { // lenght sender // lenth to HEX if (sms_out_pos_other) { ++sms_out_pos_other; byte tb = (smsLenSender % 16); if (tb > 9) return (tb + 0x37); else return (tb + '0'); } else { ++sms_out_pos_other; return ((smsLenSender / 16) + '0'); } } else if (sms_out_pos_other < 4) { // format sender = 91 if (sms_out_pos_other == 2) { ++sms_out_pos_other; return '9'; } else { ++sms_out_pos_other; return '1'; } } else { // sender if (sms_out_pos_sender < smsLenSender) { ++sms_out_pos_other; ++sms_out_pos_sender; if (bitRead(sms_out_pos_sender, 0)) { if ((sms_out_pos_sender >= smsLenSender) && (bitRead(smsLenSender, 0))) return ('F'); else return (smsSender[sms_out_pos_sender]); } else { return (smsSender[sms_out_pos_sender - 2]); } } else { sms_out_pos_other = 0; ++sms_out_pos_mode; if (bitRead(smsLenSender, 0)) return (smsSender[smsLenSender - 1]); else return 0xFF; } } break; } case 4: { // PID if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; return '0'; } else { ++sms_out_pos_other; return '0'; } break; } case 5: { // DCS if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; return '8'; } else { ++sms_out_pos_other; return '0'; } break; } case 6: { // UDL if (sms_out_pos_other) { ++sms_out_pos_mode; sms_out_pos_other = 0; byte uh = smsUDL % 16; if (uh > 9) return (uh + 0x37); else return (uh + '0'); } else { ++sms_out_pos_other; byte uh = smsUDL / 16; if (uh > 9) return (uh + 0x37); else return (uh + '0'); } break; } case 7: { // UD if (sms_out_pos_string < smsLenString) { byte outChar = sms_buf[sms_out_pos_string]; byte bpos = (sms_out_pos_other % 4); switch (bpos) { case 0: { ++sms_out_pos_other; return '0'; break; } case 1: { ++sms_out_pos_other; if (outChar < 0x7F) return '0'; else return '4'; break; } case 2: { ++sms_out_pos_other; if (outChar < 0x7F) { // ascii outChar = (outChar / 16); if (outChar > 9) return (outChar + 0x37); else return (outChar + '0'); } else { // win1251 switch (outChar) { case 168: { return '0'; break; } case 184: { return '5'; break; } default: { outChar -= 0xB0; outChar = (outChar / 16); if (outChar > 9) return (outChar + 0x37); else return (outChar + '0'); } } } break; } case 3: { ++sms_out_pos_other; ++sms_out_pos_string; if (outChar < 0x7F) { // ascii outChar = (outChar % 16); if (outChar > 9) return (outChar + 0x37); else return (outChar + '0'); } else { // win1251 switch (outChar) { case 168: { return '1'; break; } case 184: { return '1'; break; } default: { outChar -= 0xB0; outChar = (outChar % 16); if (outChar > 9) return (outChar + 0x37); else return (outChar + '0'); } } } break; } default: {} } } else { ++sms_out_pos_mode; sms_out_pos_other = 0; return 0; // 0xFF for next step } break; } default: { return 0; }; } } byte smsGetSizePDU() { return sms_out_size_packet; } byte doHaveSendSms() { if ((sms_buf[0] > 0) && (sms_out_size_packet) && (smsSender[0] > 0)) return 1; else return 0; }как и обещал, часть скетча (4 файла из 5), вдруг пригодится:
Спасибо! Такое большое количество команд мне не потребуется для решения моей задачи, все равно - спасибо! Но, опять же, у Вас в коде задется все путем, описанным в ссылках по работе с PGM. У меня же, задается путем объявления структуры, а затем уже записью значений переменных структуры массивов в Flash-память МК.
Со сравнением, с общей помощью разобрался, остался вопрос, как поместить содержимое из Flash-памяти в динамическую память, присвоив значение переменной из Flash-памяти переменной в динамическую память... Код не работает:
#include <avr/pgmspace.h> const uint8_t cntLstPhones = 2; struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; const char plot[9]; }; const listUsr_t PROGMEM users[cntLstPhones] = { { "+78881890123", "0000", "000000000000", "plot #" }, { "+78881901234", "0000", "000000000000", "plot #" } }; void setup() { Serial.begin(9600); char val[13]; strcat_P(val, pgm_read_word(&(users[1].phoneNum))); Serial.println(val); }Модет кто-то подскажет, что не так я делаю...
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
traveler , мне кажеться вам нужно на классы переходить, в PGM харнить все списками, т.е. телефоны отдельный список, ПИН коды отдельным и т.д. Соотвественно когда в экземпляре класса необходимы данные непосредственно из progmem - динамически вытаскивать оттуда данные.
P.S. Классы не люблю, дело вкуса, но в вашей задаче вообще бы не использовал ни классы ни структуры, 4 функции по вытаскиванию данных из pgm и все.
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
Я и strcpy_P и strcat_P - пытался использовать... не работает код и все...
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
Я и strcpy_P и strcat_P - пытался использовать... не работает код и все...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все... Сравнить переменные из Flash с переменными из RAM, уже знаю как, а как "вытащить" переменную из Flash и записать ее в локальную переменную функции в RAM - не знаю, поэтому мне нужна просто подсказка с синтаксисом оператора, который позволит выполнить такой перенос...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все... Сравнить переменные из Flash с переменными из RAM, уже знаю как, а как "вытащить" переменную из Flash и записать ее в локальную переменную функции в RAM - не знаю, поэтому мне нужна просто подсказка с синтаксисом оператора, который позволит выполнить такой перенос...
Т е ссылка которую я дал - там примера чтения в ram вы не увидели?
А хранить в структуре адрес на строку в pgm вы тоже не догадались?
:(
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все...
"подсказок" правильного синтаксиса извлечения строк из флеша тут уже дали не одну и не две...
у вас проблема не со структурой. а вообще с пониманием того, как хранятся строки и массивы во флеше. Возьмите для начала проимер без структур - с массивами и добейтесь того, чтобы он работал. Синтаксис извлечения строк из структуры ТОТ же, что и из массива строк.
А потом - когда у вас чужие примеры заработают - пробуйте перейти к структуре, если она вам так нужна. Непонятно, почему вы за нее так держитесь - экономия памяти при использовании структур и массивов во флеше абсолютно одинаковая.
посмотрел выше - в сообщ #22 sadman41 давал вам пример сравнения строки из флеша и оперативки. Посмотрите внимательно - как у него сделано обращение к полю вашей структуры и как у вас. Сравните внимательно! - у вас там ошибка
Хотя.. все равно же не найдете.Ладно, подскажу - когда вы обращаетесь к своей строке во флеше, вы непонятно зачем выполняете операцию взятия адреса & от массива. Причем вы так делали еще в самом начале ветки и я вас уже поправлял. Поймите - имя массива это и так адрес его первого элемента, а когда вы еще ставите перед ним & - получается "адрес от адреса" - что ерунда.
В прошлом сообщении я был прав - ваши проблемы от непонимания того, как устроены структуры и массивы. Вам бы сначала учебник почитать.
Конечно, же, увидел, НО, в примере, который Вы предложили, как раз таки нет структуры...
Я не держусь за структуру массива, но и понять, действительно не могу, каков должен быть принцип адресации в структуре, в массиве, в массиве строк и его структуре... к сожалению... времени на изучения с нуля, тоже нет...
Честно говоря, я не понимаю, как в структуру "запихнуть" адрес на строку, да и зачем, если сравнить можно и с той структурой, что имеется, то почему нельзя перенести из Flash в RAM...
посмотрел выше - в сообщ #22 sadman41 давал вам пример сравнения строки из флеша и оперативки. Посмотрите внимательно - как у него сделано обращение к полю вашей структуры и как у вас. Сравните внимательно! - у вас там ошибка
Хотя.. все равно же не найдете.Ладно, подскажу - когда вы обращаетесь к своей строке во флеше, вы непонятно зачем выполняете операцию взятия адреса & от массива. Причем вы так делали еще в самом начале ветки и я вас уже поправлял. Поймите - имя массива это и так адрес его первого элемента, а когда вы еще ставите перед ним & - получается "адрес от адреса" - что ерунда.
Я постараюсь сейчас разобраться с указателем...
В прошлом сообщении я был прав - ваши проблемы от непонимания того, как устроены структуры и массивы. Вам бы сначала учебник почитать.
Просто нет на это времени, я ведь не с целью продажи или какого-то бизнеса, просто для себя, для удобства хочу собрать устройство для управления воротами... Как хобби, если хотите... Со временем - разберусь с азов, сейчас времени нет, если появиться время, с азов разберусь...
к сожалению... времени на изучения с нуля, тоже нет...
простите, но после таких заявлений здесь обычно посылают - жестко, матом - и общение заканчивается. Это что за наглость - у вас, видите ли, нет времени это изучать - а у нас. выходит, куча времени чтобы обьяснять вам одно и тоже по 3-4 раза?
Еще раз - работа во флеше со структурой и с массивом отличается минимально и делается одними и теми же командами. Все ссылки, обьясняющие работу с массивом - подходят и для структуры. Вы этого не видите только потому, что вообще слабо знаете программирование...
Такой код, также не работает...
Такой код, также не работает...
Я наверное последний отвечу в этой ветке, т к вы не хотите понимать - неоднократно вам сказали для начала забыть о структуре и сделать тупо выборку из progmem, в конце концов - тупо блин скопируйте из моего скетча несколько строк описания и несколько строк процедуры выборки, вывести в монитор и все.
Вот такой код, возвращает знаки, но не строку...
Такой код, также не работает...
вы похоже, втупую пробуете разные комбинации операторов... опять val описано неправильно.
Так вы программу не напишете. Садитесь за учебники - ваши ворота подождут. Тем более если это хобби, как вы пишете - значит просто сделаете ворота не сейчас. а через полгода-год, когда разберетесь.
Не мог пройти мимо, даже нану новую вытащил из упаковки. Конечно, сообщество меня изругает...
#include <avr/pgmspace.h> struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; }; const listUsr_t PROGMEM users[] = { { "70000000000", "00000", "000000000000"}, { "70000000001", "00001", "000000000000"}, { "70000000002", "00002", "000000000000"}, }; void setup() { char incomingNumber[20]; Serial.begin(115200); Serial.println("Begin!"); for (int i = 0; i < 3; i++) { strncpy_P(incomingNumber, (char*) users[i].phoneNum, sizeof(listUsr_t::phoneNum)); Serial.println(incomingNumber); } } void loop() { // put your main code here, to run repeatedly: }И еще я не совсем уверен, что sizeof можно напускать на такого жука... Ну, если что - поправят.
Почему-то в данном примере помещение строковых констант прямо в массив эквивалентно помещению в массив ссылок на строковые константы (как на arduino.cc), но попытка перетащить данный пример в реальный скетч почему-то дает разные результаты по компиляции. Надо будет этот вопрос изучить. Может компилятор умничает опять.
char val[] = "" - это чего, зарезервировали нуль байт памяти, а потом туда строку копируете? Вы там надеюсь, игрушку-пердушку собираете, а не управление газовым котлом...
вы похоже, втупую пробуете разные комбинации операторов... опять val описано неправильно.
Так вы программу не напишете. Садитесь за учебники - ваши ворота подождут. Тем более если это хобби, как вы пишете - значит просто сделаете ворота не сейчас. а через полгода-год, когда разберетесь.
тут переписал не правильно, указал длину...