|
Atmega48, DS18S20 и пресловутая оптимизация AVRStudio |
|
|
|
Jan 23 2009, 12:19
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Доброго всем времени суток. Появилась задачка мерить температуру на нескольких датчиках. В качестве управляющего МК дана ATmega48, в качестве датчика решил использовать DS18S20, поскольку работа через 1-wire показалась очень удобной штукой. Проштудировал переведённую статью про интерфейс 1-wire и вперёд. Вооружившись осциллографом стал пытаться что-нибудь отиравить и принять. Отправка РЕСЕТ и приём ПРЕСЕНС прошли замечательно, отправка команды SEARCH ROM тоже, а вот попытка получить ответ на последнюю команду как-то не прошла... Точнее так, судя по осциллографу датчик мне отвечает, а вот если пытаться посмотреть на экране монитора через Watch, то он говорит, что одни нули... Вот тут я добрался до самого неприятного момента и пока малопонятного для меня. Дело в том, что я себе не очень хорошо представляю, что есть пресловутая оптимизация в АВРСтудии. Да, я знаю, что она выкидывает ненужный по её мнению код, куда она ессно отправляет функции, которые ничего не получают и не возвращают, переменные, которые по ЕЁ мнению не несут смысловой нагрузки и что её вроде как можно отучить от этого через написание магического слова volatile перед объявлением переменных. Всё, более точно я про неё ничего не знаю, а в настройках проекта помимо этого, можно выбрать аж 4 режима этой оптимизации... Так вот, дабы она не компостировала мне мозги, я её всегда вырубал и не испытывал никаких угрызений совести, а тут вот проблема - на шине 1-wire необходимо строго выдерживать временные интервалы, естественно я сразу желаю использовать функции "_delay_us/ms" (просто другого я не знаю способа), но тут как обычно всё обламывается, т.к. они без оптимизации не работают... Что делать дальше - хз... Можно конечно использовать таймер, но почему-то не очень хочется=), хотя если это единственный выход как обойти проблема - куда деваеться... Просто проект будет дальше разрастаться, а как-то мучатся в нём с этой оптимизацией не хочется=/ Вот этот простой код, с которым у меня ничего пока не вышло сегодня. Заранее спасибо за ответы CODE #include <avr/io.h> #include <avr/sfr_defs.h> #include <avr/interrupt.h>
#define F_CPU 20000000UL #include <util/delay.h>
#define READ_ROM 0x33
void init_ports(void) { DDRB = (1<<DD0); PORTB = (1<<PB0);
PORTD = (1<<PD6) | (0<<PD5) | (0<<PD4) | (0<<PD3) | (0<<PD2); DDRD = (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2); asm("nop"); return; }
volatile void write1() { DDRB = (1<<DDB0); PORTB &= ~(1<<PB0); _delay_us(2); PORTB = (1<<PB0); _delay_us(28); DDRB = (0<<DDB0); _delay_us(10); }
volatile void write0() { DDRB = (1<<DDB0); PORTB &= ~(1<<PB0); _delay_us(30); DDRB = (0<<DDB0); _delay_us(10); }
void main () { volatile char help_byte = 0xFF; volatile char help_byte_2 = 0; init_ports();
//---отсылка импульса RESET----- PORTB &= ~(1<<PB0); _delay_us(500);
//---приём импульса PRESENSE----- DDRB = (0<<DDB0); _delay_us(61); help_byte = PIN0;
help_byte_2 = help_byte; _delay_us(500);
//---отправка команды чтения адреса устройства----- volatile char command = READ_ROM;
for (int i=0;i<8;i++) { if((command & 1) == 1) write1(); else write0(); command = command >> 1; } _delay_ms(1);
//---попытка получить от устройства его серийник--- volatile char serial_number[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; volatile char help_byte_3 = 0x00;
for (int i=0;i<8;i++) { for (int k=0;k<8;k++) { serial_number[i] = serial_number[i]<<1; DDRB = (1<<DDB0); PORTB &= ~(1<<PB0); _delay_us(5); DDRB = (0<<DDB0); _delay_us(8); help_byte_3 = PINB0; serial_number[i] = serial_number[i] + (help_byte_3<<k); _delay_us(45); _delay_us(10); } } }
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Jan 23 2009, 13:06
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Да, читал соответственно в доке WinAVR/// Всё что там сказано, если не ошибаюсь, то это то, что должна быть включена оптимизация и то, что она не может реализоватть задержку свыше 768мкс разделённые на частоту проца в МГц.
|
|
|
|
|
Jan 23 2009, 13:17
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(NikitoS-86 @ Jan 23 2009, 16:06)  Да, читал соответственно в доке WinAVR/// Всё что там сказано, если не ошибаюсь, то это то, что должна быть включена оптимизация и то, что она не может реализоватть задержку свыше 768мкс разделённые на частоту проца в МГц. void _delay_us ( double __us ) ... The maximal possible delay is 768 us / F_CPU in MHz. #define F_CPU 20000000UL 768 us / 20 = 38,4 us _delay_us(500); - ????? _delay_us(45); - ????? Попробуйте: _delay_ms(0.5); _delay_ms(0.045); Анатолий.
Сообщение отредактировал aesok - Jan 23 2009, 13:18
|
|
|
|
|
Jan 23 2009, 13:20
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Попробую, хотя на мой взгляд это не поможет... Ибо в том же мануале есть запись: If the user requests a delay greater than the maximal possible one, _delay_us() will automatically call _delay_ms() instead. The user will not be informed about this case.
|
|
|
|
|
Jan 23 2009, 14:47
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(NikitoS-86 @ Jan 23 2009, 16:20)  Попробую, хотя на мой взгляд это не поможет... Ибо в том же мануале есть запись: If the user requests a delay greater than the maximal possible one, _delay_us() will automatically call _delay_ms() instead. The user will not be informed about this case. _delay_us так начала работать в только в последних версиях avr-libc. В следующий раз указывайте верию WinAVR. volatile void write0(){ DDRB = (1<<DDB0); PORTB &= ~(1<<PB0); // хорохо пин установили в 0 _delay_us(30); // подождали 30 us DDRB = (0<<DDB0); // отпустили пин _delay_us(10); } Тоесть 0 присутствует на пине 30 us, но согласно рисенку 11 даташита, DS18S20 может прочитать состояния пина в любой момнт начиная с 15 и по 60 us после того как он установлен в 0. Так что задержка должна быть немного больше 60 us. Тоже самое в write1. Анатолий.
Сообщение отредактировал aesok - Jan 23 2009, 15:04
|
|
|
|
|
Jan 23 2009, 14:52
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
На счёт оптимизации - можно тогда узнать, что это такое? Почему несколько вариантов? Что именно оптимизируется и как?
|
|
|
|
|
Jan 23 2009, 15:08
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(NikitoS-86 @ Jan 23 2009, 17:52)  На счёт оптимизации - можно тогда узнать, что это такое? Почему несколько вариантов? Что именно оптимизируется и как? В 99.9 случаев наилудшим выбором является -Os. Считайте что -O0 это только для разработчиков компилятора. Очень долго отвечать на заданые вами вопрасы, но ответ все равно будет -Os. Анатолий
Сообщение отредактировал aesok - Jan 23 2009, 15:12
|
|
|
|
|
Jan 23 2009, 15:11
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Цитата(NikitoS-86 @ Jan 23 2009, 22:52)  На счёт оптимизации - можно тогда узнать, что это такое? Ну например вот это код никогда не выполнится: Код if(10 > 15) { // something here } Есть ли смысл переводить его в машинный код и формировать с ним hex? Нет такого смысла! Оптимизатор спокойно выкинит этот фрагмент, ну а программист получит предупреждение (зависит от опций компилятора). Вообще оптимизация может быть выключена. Тогда все, что Вы написали будет переведено в машинный код именно в том виде, в которым программа написана. Оптимизация по объему дасти минимальный объем машинного кода, но не обязательно он будет быстро выполняться. Оптимизация по скорости наоборот даст минимальный по времени машинный код, но не обязательно его размер будет малым. Вообще все что я показал, это довольно примитивно. Уважаемый aesok лучше расскажет! Он, как я понял, gcc лучше многих знает!
--------------------
Выбор.
|
|
|
|
|
Jan 23 2009, 15:22
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(haker_fox @ Jan 23 2009, 18:11)  Уважаемый aesok лучше расскажет! Он, как я понял, gcc лучше многих знает! Пожалуйста избавьте меня от этого, в GCC над программой выполняться порядка 200 проходов, основная масса из них оптимизирующие. Я не знаю их все. И зачем Вам процесс, Вас же интересует результат. А результат это -Os (оптимизация по размеру) плюс, иногда отключение проходов которые вредны для AVR платформы. В очень редких случаях оптимизация по скорости -O3. Анатолий.
Сообщение отредактировал aesok - Jan 23 2009, 15:23
|
|
|
|
|
Jan 23 2009, 15:47
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Итак, спасибо всем откликнувшимся=) 1) Вроде бы получилось считать его серийник и он совпал с показаниями осциллографа, уже радует=). Правда на всякий несколько завысил некоторые интервалы, которые были слишком малы. Как говорится, когда ничего не работает - надо садиться и писать всё заного и пошагово=). Но теперь буду дальше мучать датчик, измерение температуры ведь ещё не пробовал, так что может опять на что напорюсь) 2) Возвращаясь к оптимизации - ну хорошо, опустим все объяснения, но есть ли какие-нибудь источники, где можно это всё почитать? Общение с атмегами мне ещё долгое предстоит, а не на один раз (сделал и забыл), так что надо вникать, без вариантов.
Спасибо.
Сообщение отредактировал NikitoS-86 - Jan 23 2009, 15:49
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|