Страница 195 из 386

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

Добавлено: Чт июн 26, 2014 13:56:04
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";

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

Добавлено: Чт июн 26, 2014 13:58:09
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'. Он использует свой аргумент без предварительного просмотра, так как здесь используется стрингификация.

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

Добавлено: Чт июн 26, 2014 14:10:36
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. Смотрю, Вы тоже дополнили своё сообщение ссылкой на второй проход.

размер массива в atmel studio

Добавлено: Пт июн 27, 2014 09:15:26
kelod
прошу прощения, если я не в тот раздел спрашиваю, но мучаюсь уже три дня, перерыл весь гугл, не могу понять, как в си узнать размер массива в eeprom

Re: размер массива в atmel studio

Добавлено: Пт июн 27, 2014 09:17:09
Pink-Pank
Размер массива Вы должны знать заранее, сами. Там этот размер нигде не указывается. Поконкретнее вопрос можно сформулировать? Какая задача перед Вами стоит?

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

Добавлено: Пт июн 27, 2014 09:53:07
kelod
делаю термометр на терморезисторе, следовательно нужно знать зависимость сопротивления от температуры, это храню массивом, а что бы была возможность поменять резистор и не перепрошивать контроллер, храню массив в eeprom, плюс количество точек в графиках зависимостей может быть различно, поэтому задаю его самостоятельно, при создании массива, а вот при чтении нужно узнать размер массива в eeprom, можно конечно создать отдельную переменную, но я думал можно узнать количество элементов, как это есть в обычном си

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

Добавлено: Пт июн 27, 2014 09:55:18
Pink-Pank
Проще всего и лучше по быстродействию задействовать отдельную ячейку EEPROM (самую первую или самую последнюю) со значением размера массива. Иначе количество элементов можно узнать только перебором значений и сравнений их со значением стертой ячейки EEPROM, но при этом можно ошибиться (если значение массива совпадет со значением стертой ячейки).

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

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

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

Добавлено: Пт июн 27, 2014 10:06:44
WiseLord
Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.

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

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

Просто нужно сделать пару-тройку замеров в разных точках, и решить систему, найдя эти коэффициенты. Их в EEPROM и хранить.

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

Добавлено: Пт июн 27, 2014 10:51:54
urry
от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.

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

Добавлено: Пт июн 27, 2014 10:59:12
Pink-Pank
Это уж сверхмера. Думаю, вопрошающему в его применении такие усложнения ни к чему. )) Хотя, ради тренеровки можно было бы замутить. ;)

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

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

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

uint32_t EEPROM mass[]={177, 192,240};
значений намного больше, около 15
WiseLord писал(а):Кстати, возможно, есть смысл хранить не весь массив, а только пару-тройку коэффициентов.
зависимость не линейная и не квадратичная, скорее похожа на логарифм, интерполирование или слишком сложное или не удовлетворяет точности, поэтому после долгих размышлений принял решение о линейной интерполяции относительно двух ближайших точек
urry писал(а):вероятность повреждения данных в епром очень высокая
перезапись будет происходить очень редко, только при смене датчика

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

Добавлено: Пт июн 27, 2014 12:01:49
ibiza11

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

uint32_t EEPROM mass[]={177, 192,240};
#define MASS_SIZE (sizeof(mass)/sizeof(uint32_t))
uint32_t massSize = MASS_SIZE;

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

Добавлено: Пт июн 27, 2014 13:13:04
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 писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая
Почему?

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

Добавлено: Сб июн 28, 2014 00:04:35
menzoda
urry писал(а):от себя добавлю, что вероятность повреждения данных в епром очень высокая - нужно данные дублировать и закрывать контрольной суммой.
Могу сказать, что если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало). У нас много лет используется по несколько EEPROM в составе частотного инвертора (условия не лучшие), за все время был только один зарегистрированный косяк.

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

Добавлено: Ср июл 02, 2014 09:06:53
aam
Скажите, а можно ли использовать return; в прерываниях?
Ато тут у меня какая-то фигня получается в нештатных ситуациях. Использую библиотеку протокола wake, так если слишком часто слать запросы от компа, то МК виснит и бесконца вызывает прерывание по поступлению данных в приемник УАРТ. Причем не отвисает когда уже я слать данные перестал. Сторожевой таймер тоже не оживляет МК - без конца вызывается прерывание, хотя я смотрел - флаг того, что UDR полон - уже сброшен.
menzoda писал(а):если данные записываются/читаются не очень интенсивно, то с надежностью все хорошо (а на них никто и не будет писать интенсивно, циклов перезаписи же мало)
А я тут девайс с пультом от телека сделал, особых мер, кроме проверки на допустимость значения, не принимал. Вот теперь думаю, а это правильно?

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

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

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

Добавлено: Ср июл 02, 2014 09:46:14
WiseLord
ARV писал(а):плевать он хотел на return
Наверное, корректнее сказать, что обработчик прерывания отработает return как и обычная void-фунция, коей он, по большому счёту, и является.

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

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

Не могу понять, это глюк Протеуса или косяк проги?

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

Добавлено: Чт июл 03, 2014 11:33:47
pokk
Здравствуйте, решил я сделать отладку по uart. Т.е расставить контрольные точки в программе и смотреть в терминале как они выполняются ). Естественно что в готовом варианте эта отладка не нужна и чтобы каждый раз не удалять сделал через

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

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

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

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