Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

a_skr писал(а):если делать вот так:
Да, это всё странно, но, похоже, Вы были правы:

Код: Выделить всё

wiselord@wiselord home $ cat q.c 
#define LD_NUM 3
#define TO_STR(s) #s
char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);

wiselord@wiselord home $ gcc -E q.c 
# 1 "q.c"
# 1 "<command-line>"
# 1 "q.c"

char const str_Dev_Info[]= "MDIOv1.0 LD" "LD_NUM";



wiselord@wiselord home $ cat q.c 
#define LD_NUM 3
#define str(s) #s
#define TO_STR(s) str(s)
char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);

wiselord@wiselord home $ gcc -E q.c 
# 1 "q.c"
# 1 "<command-line>"
# 1 "q.c"

char const str_Dev_Info[]= "MDIOv1.0 LD" "3";
Последний раз редактировалось WiseLord Чт июн 26, 2014 14:02:26, всего редактировалось 5 раз.
Контактная информация:
Реклама
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Аlex писал(а):...вообще бессмысленный макрос. Он будет просто клонировать один в один.
Если бы не проверял, не написал бы сюда. Проверено в C++ Builder и avr-gcc.

ps. Вот, по ссылке с предыдущей страницы:
Существует также еще один случай, когда применяется второй проход. Его можно использовать для подстановки аргумента с его последующей стрингификацией при использовании двухуровневых макросов. Добавим макрос 'xstr' к рассмотренному выше примеру:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
xstr (foo)
Здесь значение 'xstr' заменяется на '"4"', а не на '"foo"'. Причиной этому служит то, что аргумент макроса 'xstr' заменяется при первом проходе (так как он не использует стрингификацию или объединение аргумента). В результате первого прохода формируется аргумент макроса 'str'. Он использует свой аргумент без предварительного просмотра, так как здесь используется стрингификация.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Код: Выделить всё

#define LD_NUM 3
#define TO_STR(s) #s
char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);
Этот код не работает, потому что препроцессор, видимо, работает как-то так (двигаемся по тексту слева направо):

Код: Выделить всё

char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);
char const str_Dev_Info[]= "MDIOv1.0 LD" #LD_NUM;
char const str_Dev_Info[]= "MDIOv1.0 LD" "LD_NUM";
А в случае варианта

Код: Выделить всё

#define LD_NUM 3
#define str(s) #s
#define TO_STR(s) str(s)
- как-то так:

Код: Выделить всё

char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);
char const str_Dev_Info[]= "MDIOv1.0 LD" str(LD_NUM);
char const str_Dev_Info[]= "MDIOv1.0 LD" str(3);
второй проход с начала, так как остались необработанные директивы препроцессора (возвращаемся к str):

Код: Выделить всё

char const str_Dev_Info[]= "MDIOv1.0 LD" #3;
char const str_Dev_Info[]= "MDIOv1.0 LD" "3";
P.S. Смотрю, Вы тоже дополнили своё сообщение ссылкой на второй проход.
Контактная информация:
Опытный кот
Сообщения: 884
Зарегистрирован: Пн июл 08, 2013 22:59:45

Сообщение kelod »

прошу прощения, если я не в тот раздел спрашиваю, но мучаюсь уже три дня, перерыл весь гугл, не могу понять, как в си узнать размер массива в eeprom
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Размер массива Вы должны знать заранее, сами. Там этот размер нигде не указывается. Поконкретнее вопрос можно сформулировать? Какая задача перед Вами стоит?
Fucking static initialization order fiasco
Контактная информация:
Реклама
Опытный кот
Сообщения: 884
Зарегистрирован: Пн июл 08, 2013 22:59:45

Сообщение kelod »

делаю термометр на терморезисторе, следовательно нужно знать зависимость сопротивления от температуры, это храню массивом, а что бы была возможность поменять резистор и не перепрошивать контроллер, храню массив в eeprom, плюс количество точек в графиках зависимостей может быть различно, поэтому задаю его самостоятельно, при создании массива, а вот при чтении нужно узнать размер массива в eeprom, можно конечно создать отдельную переменную, но я думал можно узнать количество элементов, как это есть в обычном си
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Проще всего и лучше по быстродействию задействовать отдельную ячейку EEPROM (самую первую или самую последнюю) со значением размера массива. Иначе количество элементов можно узнать только перебором значений и сравнений их со значением стертой ячейки EEPROM, но при этом можно ошибиться (если значение массива совпадет со значением стертой ячейки).
Последний раз редактировалось Pink-Pank Пт июн 27, 2014 09:59:10, всего редактировалось 2 раза.
Fucking static initialization order fiasco
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

kelod писал(а):это храню массивом... задаю его самостоятельно, при создании массива
Приведите код, который вы пишете для этого. Я вам покажу, где там размер массива.
Ставим плюсы: )
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.

Если зависимость линейная - то R = a1 * T + a0.

Нелинейная зависимость, возможно, достаточно хорошо будет аппроксимироваться параболой R = a2 * T * T + a1 * T + a0.

Просто нужно сделать пару-тройку замеров в разных точках, и решить систему, найдя эти коэффициенты. Их в EEPROM и хранить.
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Это уж сверхмера. Думаю, вопрошающему в его применении такие усложнения ни к чему. )) Хотя, ради тренеровки можно было бы замутить. ;)
Fucking static initialization order fiasco
Контактная информация:
Опытный кот
Сообщения: 884
Зарегистрирован: Пн июл 08, 2013 22:59:45

Сообщение kelod »

ibiza11 писал(а):
kelod писал(а):это храню массивом... задаю его самостоятельно, при создании массива
Приведите код, который вы пишете для этого. Я вам покажу, где там размер массива.

Код: Выделить всё

uint32_t EEPROM mass[]={177, 192,240};
значений намного больше, около 15
WiseLord писал(а):Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.
зависимость не линейная и не квадратичная, скорее похожа на логарифм, интерполирование или слишком сложное или не удовлетворяет точности, поэтому после долгих размышлений принял решение о линейной интерполяции относительно двух ближайших точек
urry писал(а):вероятность повреждения данных в епром очень высокая
перезапись будет происходить очень редко, только при смене датчика
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Код: Выделить всё

uint32_t EEPROM mass[]={177, 192,240};
#define MASS_SIZE (sizeof(mass)/sizeof(uint32_t))
uint32_t massSize = MASS_SIZE;
Ставим плюсы: )
aam
Собутыльник Кота
Аватара пользователя
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Сообщение aam »

Всем спасибо, все получилось. Сделал так:

Код: Выделить всё

#define STR(s) #s
#define TO_STR(s) STR(s)

char __flash start0[]="MDIOv1.0 LD" TO_STR(LD_NUM)
***
kelod писал(а):но я думал можно узнать количество элементов, как это есть в обычном си
В обычном си вы тоже не создадите просто так массив произвольной длины. Размер массива в си определяется на этапе компиляции.

В вашем случае размер лучше хранить не в 1-й ячейке ЕЕПРОМ (легко забыть поменять размер), а ввести завершающий символ, который не встречается в реальных данных (например, 0 или 0xFF). И просто просматривать всю таблицу, пока не наткнетесь на этот символ. Если опасаетесь за быстродействие, просматривайте таблицу 1 раз при включении питания и запоминайте в ОЗУ ее размер в переменной.
urry писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая
Почему?
Вымогатель припоя
Аватара пользователя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

Сообщение menzoda »

urry писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.
Могу сказать, что если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало). У нас много лет используется по несколько EEPROM в составе частотного инвертора (условия не лучшие), за все время был только один зарегистрированный косяк.
aam
Собутыльник Кота
Аватара пользователя
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Сообщение aam »

Скажите, а можно ли использовать return; в прерываниях?
Ато тут у меня какая-то фигня получается в нештатных ситуациях. Использую библиотеку протокола wake, так если слишком часто слать запросы от компа, то МК виснит и бесконца вызывает прерывание по поступлению данных в приемник УАРТ. Причем не отвисает когда уже я слать данные перестал. Сторожевой таймер тоже не оживляет МК - без конца вызывается прерывание, хотя я смотрел - флаг того, что UDR полон - уже сброшен.
menzoda писал(а):если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало)
А я тут девайс с пультом от телека сделал, особых мер, кроме проверки на допустимость значения, не принимал. Вот теперь думаю, а это правильно?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18680
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

aam писал(а):Скажите, а можно ли использовать return; в прерываниях?
Ато тут у меня какая-то фигня получается в нештатных ситуациях. Использую библиотеку протокола wake, так если слишком часто слать запросы от компа, то МК виснит и бесконца вызывает прерывание по поступлению данных в приемник УАРТ. Причем не отвисает когда уже я слать данные перестал.
а каким боком return может быть связан с вашей бедой?! avr-gcc не нуждается в return в обработчике прерываний, но и при наличии ничего не ухудшается - плевать он хотел на return. на счет других компиляторов не скажу, не знаю.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

ARV писал(а):плевать он хотел на return
Наверное, корректнее сказать, что обработчик прерывания отработает return как и обычная void-фунция, коей он, по большому счёту, и является.
Контактная информация:
aam
Собутыльник Кота
Аватара пользователя
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Сообщение aam »

С return понятно уже...
Непонятно другое. Вот щас завел сторожевой таймер. При этом глюке 1 раз срабатывает ватчдог, проц ресетится и начинает выполнять прогу. Но сразу после команды sei начинает беспорядочный вызов прерывания по приему данных, хотя данные УЖЕ не передаются (это видно на осциллографе и терминале Протеуса), бесконечно выскакивает сообщение
Reading from UDR1 while no data received.
При этом регистры имеют значения:
UBBR1H=0
UBBR1L=0x07
UCSR1A=0x20
UCSR1B=0xD8
UCSR1C=0x06
UDR1=0
Прерывание таймера 0, тактирующее прогу, при этом вызывается как и положено.

Не могу понять, это глюк Протеуса или косяк проги?
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Сообщение pokk »

Здравствуйте, решил я сделать отладку по uart. Т.е расставить контрольные точки в программе и смотреть в терминале как они выполняются ). Естественно что в готовом варианте эта отладка не нужна и чтобы каждый раз не удалять сделал через

Код: Выделить всё

#if __DEBUG__
....
#endif  
Но в итоге получается не сильно удобный код. Можно ли его как-то ужать до 1 функции ?

Код: Выделить всё

#if __DEBUG__      
if(debug_ON_OFF==ON){ // вкл/выкл по usart
    USART_SendStr("INIT:......\0"); 
}
#endif   
Пробовал внести #if __DEBUG__ #endif внутрь функции, но после выключения отладчика функция всё равно остаётся хоть она и пустая но это неприемлемо.
Ответить

Вернуться в «Разные вопросы по МК»