Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Atmega48, DS18S20 и пресловутая оптимизация AVRStudio
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
NikitoS-86
Доброго всем времени суток.
Появилась задачка мерить температуру на нескольких датчиках. В качестве управляющего МК дана 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);
}
}
}
aesok
Вы читали описание функции _delay_us(..)?

Анатолий.
NikitoS-86
Да, читал соответственно в доке WinAVR/// Всё что там сказано, если не ошибаюсь, то это то, что должна быть включена оптимизация и то, что она не может реализоватть задержку свыше 768мкс разделённые на частоту проца в МГц.
aesok
Цитата(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);

Анатолий.
NikitoS-86
Попробую, хотя на мой взгляд это не поможет... Ибо в том же мануале есть запись:
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.
GDI
В исходниках программ и библиотек поройтесь, там есть несколько реализаций 1wire шины, выбирайте на вкус. Да и оптимизации не стоит так панически бояться.
aesok
Цитата(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.


Анатолий.
NikitoS-86
На счёт оптимизации - можно тогда узнать, что это такое? Почему несколько вариантов? Что именно оптимизируется и как?
Qwertty
Битовый интервал в 40мкс это очень мало. Должно быть не меньше 60 и не больше 120.
Если так напрягает оптимизация - вынесите функции задержки в отдельный файл, для него оптимизацию включите. Остальным можно не включать. smile.gif
haker_fox
Уж на Си-то исходников для работы с DS18B20 хватает! Здесь, на www.avrfreaks.net Ну как я понял, Вы используете AVR Studio для работы. Просимулируйте в ней всю работы программы, заодно и увидите как работают паузы.
Успехов!
aesok
Цитата(NikitoS-86 @ Jan 23 2009, 17:52) *
На счёт оптимизации - можно тогда узнать, что это такое? Почему несколько вариантов? Что именно оптимизируется и как?


В 99.9 случаев наилудшим выбором является -Os. Считайте что -O0 это только для разработчиков компилятора.

Очень долго отвечать на заданые вами вопрасы, но ответ все равно будет -Os.

Анатолий
haker_fox
Цитата(NikitoS-86 @ Jan 23 2009, 22:52) *
На счёт оптимизации - можно тогда узнать, что это такое?

Ну например вот это код никогда не выполнится:
Код
if(10 > 15)
  {
     // something here
   }

Есть ли смысл переводить его в машинный код и формировать с ним hex? Нет такого смысла! Оптимизатор спокойно выкинит этот фрагмент, ну а программист получит предупреждение (зависит от опций компилятора).

Вообще оптимизация может быть выключена. Тогда все, что Вы написали будет переведено в машинный код именно в том виде, в которым программа написана.
Оптимизация по объему дасти минимальный объем машинного кода, но не обязательно он будет быстро выполняться.
Оптимизация по скорости наоборот даст минимальный по времени машинный код, но не обязательно его размер будет малым.
Вообще все что я показал, это довольно примитивно. Уважаемый aesok лучше расскажет! Он, как я понял, gcc лучше многих знает!
aesok
Цитата(haker_fox @ Jan 23 2009, 18:11) *
Уважаемый aesok лучше расскажет! Он, как я понял, gcc лучше многих знает!


Пожалуйста избавьте меня от этого, в GCC над программой выполняться порядка
200 проходов, основная масса из них оптимизирующие. Я не знаю их все. И зачем
Вам процесс, Вас же интересует результат. А результат это -Os (оптимизация по размеру)
плюс, иногда отключение проходов которые вредны для AVR платформы. В очень
редких случаях оптимизация по скорости -O3.

Анатолий.
haker_fox
Цитата(aesok @ Jan 23 2009, 23:22) *
Пожалуйста избавьте меня от этого

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

Спасибо.
haker_fox
Цитата(NikitoS-86 @ Jan 23 2009, 23:47) *
2) Возвращаясь к оптимизации - ну хорошо, опустим все объяснения, но есть ли какие-нибудь источники, где можно это всё почитать?

Да, впринципе, зачем это знать? То, что сказал уважаемый aesok, вполне достаточно. Ну если уж так хочется, то google.com рулит.
aesok
Цитата(NikitoS-86 @ Jan 23 2009, 18:47) *
2) Возвращаясь к оптимизации - ну хорошо, опустим все объяснения, но есть ли какие-нибудь источники, где можно это всё почитать? Общение с атмегами мне ещё долгое предстоит, а не на один раз (сделал и забыл), так что надо вникать, без вариантов.


Почитать что каждая оптимизация делает Вы можете в GCC User Manual. В разделе посвященном ключам оптимизации. А вот о том какие какие из них полезны/вредны для AVR очень мало информации. Немножко есть в avr-libc-user-manual. И повторяюсь, пока Вам хватит -Os.

Анатолий.
NikitoS-86
Значит так, в пятницу вечером мне, как я уже писал, удалось прочитать серийник припаянного и единственного на шине датчика. Но вот дальше что-то дело не пошло...
Естественно первое, что я попытался сделать, это прочитать температуру. Для этого в соответствии с даташитом я выбрал следующую последовательность действий:
1) Посылаю импульс сброса и принимаю ответ термометра.
2) Т.к. датчик на шине единственный, то посылаю сразу команду Skip ROM [CCh].
3) Посылаю команду Convert T [44h].
4) Формирую задержку 750мс (для уверенности даже попытался формировать 1 с).
5) Опять импульс сброса и ответ термометра.
6) Опять команда Skip ROM [CCh].
7) Команда Read Scratchpad [BEh]....
И вот после этого при попытке принять данные по температуре он мне шлёт сплошные единицы.... Сейчас я пишу не со своего компа, где прога плата, поэтому может быть, что я впопыхах в пятницу где-то ошибся, поэтому поставим вопрос так:
1) Правильную ли я делаю последовательность?
2) Можно ли считать данные и забить на CRC? Просто на сколько я понял, сами данные это вообще всего два байта... При этом в даташите в примерах написано, что присылается 9 байт, включая данные для проверки CRC... Какие данные являются непосредственно температурой?

Заранее спасибо за советы...
Сергей Борщ
Цитата(NikitoS-86 @ Jan 25 2009, 11:49) *
2) Можно ли считать данные и забить на CRC?
Можно, если вас не интересует результат.
Цитата(NikitoS-86 @ Jan 25 2009, 11:49) *
При этом в даташите в примерах написано, что присылается 9 байт, включая данные для проверки CRC... Какие данные являются непосредственно температурой?
Там же в даташите и написано. Просьба прочитать за вас даташит выглядит несколько, хм...странной. И вы надеетесь, что кто-то захочет помогать человеку, которому лень почесть даташит?
777777
Цитата(NikitoS-86 @ Jan 23 2009, 15:19) *
Так вот, дабы она не компостировала мне мозги, я её всегда вырубал и не испытывал никаких угрызений совести

Я слышал много страшилок об ошибках оптимизации, но не помню ни одного случая, чтобы они подтвердились - всегда ошибка оказывалась в программе. Поэтому выключать оптимизацию - это... глупо - самое мягкое, что можно сказать. От этого код становится больше раза в 4...5 и, соответственно медленнее. Я подозреваю, что такой режим оставлен для тех, кто помешан на ошибках оптимизатора - чтобы они могли отключив оптимизацию убедиться в том, что ошибка не исчезла.
NikitoS-86
Да, в оптимизации судя по всему действительно нет ничего криминального... Отключал по неопытности и по причине страшилок того, что оптимизатор чуть ли не всё лишнее по его мнению порезает, но вот вроде сейчас работает и нормально...

По теме: Тему можно закрывать=) Разобрался со всем полностью. Данные и принимает и CRC считает... Хотя конечно было тяжеловато понять алгоритм CRC... Однако сейчас всё работает и всё прекрасно считает и отсылает/принимает).

Всем спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.