Страница 1 из 3
Вопросы по синтаксису СИ
Добавлено: Сб сен 13, 2008 10:23:17
megasvintus
Всех приветствую!
Сижу, разбираю примеры, которые разработчики CVAVR любезно предоставили в комплекте с компилятором. Понятное дело- тексты писаны профессионалами, и кое-что в них совсем не понятно:
1) Файл ds18b20.с, есть строки:
#define MAX_DEVICES 8 //Тут всё ясно
unsigned char rom_code[MAX_DEVICES][9] /* а здесь непонятен синтаксис, вроде бы объявляется массив, но как-то интересно указывается количество членов. Компилятор потом же вместо MAX_DEVICES подставит цифру 8 и получится
unsigned char rom_code[8[9] Как это работает?
2) Код, в котором происходит инициализация термометров и настройка их на 12 битное разрешение, я если честно, мало не понял как сие работает.
for(i=0;i<devices)
if(!ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES))
далее всего лишь вывод результатв на дисплей.
Насколько я понял, идет поочередная инициализация всех найденных девайсов и их настройка. Для этого тут есть цикл for, непонятно вот что:
а) Почему счетчик i++ вынесен в функцию if? неужели помимо проверки условия в скобках if(условие) сразу может исполняться код записанный в этих скобках?
б) для чего стоит ! и DS18B20_12BIT_RES- понятно. Объясните, пожалуйста как работает остальное, для чего, к примеру [0], 10, 20, 30- что это такое? Почему 0 в квадр. скобках, а остальное -нет?
А для чего стоит & перед rom_code?
Добавлено: Сб сен 13, 2008 11:24:59
ARV
1. с define не все так уж и ясно. очень рекомендую не использовать в строке #define комментарий типа // - лучше применяйте /* такой комментарий */
2. объявляется двумерный массив, т.е. матрица из 8 строк и 9 столбцов
3. синтаксис Си допускает использовать операторы ++ и -- всюду, где используются переменные.
4. рекомендую придерживаться стандартно-полного формата записи оператора for - в вашем случае так: for(i=0;i<devices;) - т.е. точка с запятой после второй части оператора
5. посмотрите на параметры функции ds18b20_init() и вы увидите, что у нее 4 параметра - первый это указатель на элемент вашего двумерного массива, а три остальных и указаны через запятые, что это означает - надо смотреть в описании функции (я не пользуюсь CVAVR потому и не могу сказать)
6. & перед rom_code - это оператор получения адреса элемента массива - первый параметр функции ds18b20_init() должен быть указателем, т.е. адресом - вот этот оператор и используется). я бы советовал использовать перед ним (void *) - так корректнее.
P.S. Все рекомендации мои касаются соблюдения стандарта языка Си - то, что компилятор CVAVR допускает вольности - не должно вводить вас в заблуждение, лучше придерживаться требований стандарта, тогда не возникнет проблем с переносимостью на другие компиляторы.
Добавлено: Сб сен 13, 2008 12:29:25
megasvintus
Спасибо! Жаль, что авторы компилятора не придерживаются общих правил, а пользуются "вольностями". Это усложняет процесс понимания данных примеров
Добавлено: Сб сен 13, 2008 12:57:06
ARV
megasvintus писал(а):Спасибо! Жаль, что авторы компилятора не придерживаются общих правил, а пользуются "вольностями". Это усложняет процесс понимания данных примеров
пользуйтесь
WinAVR - его авторы придерживаются стандарта С99 очень сильно
Добавлено: Сб сен 13, 2008 14:08:45
megasvintus
Для начала освою CVAVR, а то и так глаза разбегаются от обилия информации. А то если возьмусь еще и за WinAVR, то будет как в поговорке: за двумя зайцами погонишься...
Хотя чувствую что необходимость изучить WinAVR наступит.
Кстати, там есть такая полезная штука как генератор начального кода?
Добавлено: Сб сен 13, 2008 14:26:02
ARV
megasvintus писал(а):Кстати, там есть такая полезная штука как генератор начального кода?
нет. генератор начального кода с моей точки зрения штука для начинающих
вредная
Добавлено: Сб сен 13, 2008 15:01:59
megasvintus
Может быть я с вами и соглашусь по этому вопросу, когда дорасту хотя бы до 1/10 вашего уровня
Дело вот в чем, я всегда смотрю в даташит почему мастер написал то-то... Есть эталон, где все совершенно верно.
Добавлено: Сб сен 13, 2008 15:15:03
ARV
если бы мастер CVAVR генерировал хороший код - я не так был бы настроен против него. но он генерирует код, который не помогает, а затрудняет понимание происходящего.
сравните:
Код: Выделить всё
// нормальный программист пишет так:
ADCSRA = (1<<ADEN)|(1<<ADIE);
// для WinAVR можно написать так:
ADCSRA = _BV(ADEN)|_BV(ADIE);
// "мастер" генерирует то же самое так:
ADCSRA = 0x88;
в итоге вы быстро делаете то, что работает, но с каждым разом все меньше и меньше понимаете, почему оно работает.
P.S. К сожалению, я не встречал "автогенераторов кода", которые генерировали бы красивый код, хотя никакой проблемы в этом нет
Добавлено: Сб сен 13, 2008 15:39:09
megasvintus
Спасибо! Четко доказали!
Добавлено: Сб сен 13, 2008 16:25:50
tych
megasvintus писал(а): я всегда смотрю в даташит почему мастер написал то-то...
Обязательно надо это читать и понимать значение записываемых в регистры чисел - в курсе я советую
обязательно разбираться и писать СВОИ комментарии к коду мастера с указанием страниц даташита.ARV писал(а): но с каждым разом все меньше и меньше понимаете, почему оно работает.
Вы своим опытом делитесь ?
Спсибо ! он бесценен.
ARV писал(а): Код: Выделить всё
// "мастер" генерирует то же самое так:
ADCSRA = 0x88;
И даже комментариев не даёт ? Ай-ай-ай ...
Добавлено: Сб сен 13, 2008 16:37:58
ARV
tych писал(а):Вы своим опытом делитесь ? Спсибо ! он бесценен.
пожалуйста, пользуйтесь на здоровье

к несчастью для себя, я делюсь действительно своим опытом, а не чужим, как вы,
tych. правда на счет непонимания опыта у меня нет, делиться нечем...
Добавлено: Сб сен 13, 2008 16:40:02
ARV
tych писал(а):И даже комментариев не даёт ? Ай-ай-ай ...
не знаю на счет комментариев - не пользуюсь CVAVR, если не считать пары опытов, чтоб войти в курс дела...
Добавлено: Сб сен 13, 2008 16:43:27
tych
ARV писал(а): на счет непонимания опыта у меня нет, делиться нечем...
У вас большой опыт врать цитируя то что вам выгодно ! Но зря вы им делитесь.
А реально код мастера в примере
C:\CVAVR\examples\ADC8535
выглядит вот так:
Код: Выделить всё
// ADC initialization
// ADC Clock frequency: 57.600 kHz
// ADC Voltage Reference: AREF pin
// ADC High Speed Mode: Off
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
// Select ADC input 0
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x8E;
SFIOR&=0xEF;
// Global enable interrupts
#asm("sei")
// Start the first AD conversion
ADCSRA|=0x40;
ПОЧУВСТВУЙТЕ РАЗНИЦУ !!!ARV писал(а):не знаю на счет комментариев - не пользуюсь CVAVR, если не считать пары опытов, чтоб войти в курс дела...
Пастернака не читал, но осуждаю ...
Добавлено: Сб сен 13, 2008 16:52:51
ARV
tych писал(а):У вас большой опыт врать цитируя то что вам выгодно ! Но зря вы им делитесь.
в этом мы одинаковы - вы тоже цитируете только то, что вам выгодно. и назовите мне хоть кого-то, кто делает цитаты себе во вред

кроме того, я не цитирую, а говорю по тем впечатлениям, что получил от нескольких опытов.
что же касается показанного вами примера - и что толку с тех комментариев?! я понимаю, что лично вам, благодаря мастеру-автогенератору кода, не надо думать ("было бы ошибкой думать" ©В.И.Ленин), как настроить АЦП на другую частоту сэмплов, но если придется - как поступать станете? много ли пользы получите от "
// ADC Clock frequency: 57.600 kHz " и "
ADCSRA=0x8E;"? для чего в хидерах расписаны имена всех битов всех регистров?! чтобы их использовать, а не загадочные числа шестнадцатеричные писать - вот мое мнение.
Добавлено: Вс сен 14, 2008 19:19:45
Aheir
В любом случае, если человеку оно надо, он возьмет шестнадцатиричное число, переведет его в двоичное, посмотрит название и функционал соответствующих битов в даташите и навсегда запомнит, ну а если человеку это не нужно - так и говорить не о чем. Такое мое мнение.
Заканчиваем оффтоп, дружненько так, хорошо?
Добавлено: Пн сен 15, 2008 14:56:49
kalobyte
в справке по компилятору описаны входные параметры для этой функции термометра
Добавлено: Пн сен 15, 2008 15:09:16
savage
С WinAVR не все так гладко. С ATTiny13 у меня он почему то ругается на
PORTB|=1<<OUTBIT;
и
PORTB&=~(1<<OUTBIT);
Приходится указывать явно PORTB|=b00001000;
В тоже время CVAVR работает нормально.
С другими контроллерами работает нормально. Интересно почему?
Дня три убил пока разобрался.Так что не все так просто.
Добавлено: Пн сен 15, 2008 15:26:19
chuchxe
savage писал(а):С WinAVR не все так гладко. С ATTiny13 у меня он почему то ругается на
PORTB|=1<<OUTBIT;
и
PORTB&=~(1<<OUTBIT);
Наверно OUTBIT в хидере
.h не определен - может и в даташите такого бита нету. Можно самому define сделать.
Добавлено: Вт сен 16, 2008 23:21:54
Yellow Tiger
ARV писал(а):рекомендую придерживаться стандартно-полного формата записи оператора for - в вашем случае так: for(i=0;i<devices;) - т.е. точка с запятой после второй части оператора
Вообще-то, в указанном файле так и написано - с двумя точко-запятыми:

А кроме того - по идее, компилятор должен выдать ошибку "For statement missing ;" на такой фортель, как отсутствие точки с запятой.
megasvintus писал(а):Жаль, что авторы компилятора не придерживаются общих правил, а пользуются "вольностями".
Нет здесь вольности

- точка с запятой в исходнике на месте, а "i++" вынесен в тело цикла для того, чтобы в вызове
sprintf счетчик цикла имел диапазон значений от 1, а не от 0 - так всем (кроме пишущих на Си) привычнее.
Добавлено: Ср сен 17, 2008 08:18:12
ARV
Yellow Tiger писал(а):Вообще-то, в указанном файле так и написано - с двумя точко-запятыми
я отвечал по тексту сообщения, файла этого я и в глаза не видел