реклама на сайте
подробности

 
 
> WinAVR, _delay_ms(), строки и оптимизация.
Laksus
сообщение Nov 5 2010, 19:17
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Програмка для ATmega32, WinAVR-20100110.
Инициализируется USART для передачи.
После этого хочу отправить через USART несколько групп символов. С паузой между группами в несколько секунд.
Задержки решил сделать через _delay_ms(2000).

Оказалось, что если оптимизация "OPT = s", то правильно передается только последняя строка, а вместо остальных строк передается мусор. Насколько я понял указатель ставится на адрес ноль, а не на адрес строки.
Если отключить оптимизацию ("OPT = 0"), то все строки передаются правильно.

Если вместо _delay_ms() использую самодельную задержку delay_sec(uint8_t T){for..{for..{for..{for..{asm("nop")}}}}},
то все строки передаются нормально и при "OPT = s"

Большой проблемы нет, так как с самдельной задержкой вроде бы работает.
Но хотелось бы узнать причину, чтобы не получить проблем в дальнейшем.
_______
Как правильно использовать _delay_ms(), чтобы работало и при оптимизации?

Код
//код . . .

char *StringLCD;
char Hello_1[]= "11111111111111111111111111111111";
char Hello_2[]= "22222222222222222222222222222222";

//------------------------------------------------------
int main(void)
{
init();

UDR= Address_1;// пошлем адрес
StringLCD= Hello_1;
UCSRB|= (1<<UDRIE);//и отправим нужную строку
_delay_ms(2000);

UDR= Address_1;// пошлем адрес
StringLCD= Hello_2;
UCSRB|= (1<<UDRIE);//и отправим нужную строку
_delay_ms(2000);

for(;;);
return 0;
}
//------------------------------------------------------
ISR(USART_UDRE_vect)
{
    static uint8_t    j= 0;
    if(j< 32)
    {
        UDR= StringLCD[j++];
    }
    else
    {
        j=0;
        UCSRB&= ~(1<<UDRIE);
    }
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение Nov 8 2010, 09:08
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(artymen @ Nov 6 2010, 12:32) *
Возможно, плагин кривой, что выбираемый мною девайс не передается линковщику для задания нужной конфигурации. Как бы то ни было, это не мои грабли, я всего лишь указал на баг.
О. уже плагин. А вовсе и не gcc и не avr-libc.
Цитата(MrYuran @ Nov 6 2010, 09:37) *
Речь-то про ms, а не mks
Смысла делать миллисекундные задержки "на NOP-ах" я тоже никакого не вижу.
Лично я при таких задержках отпускаю процессор заниматься другими делами.
Хоть это и несколько сложнее, чем просто тупождать.
Да какая разница. У меня есть инициализация LCD. Одного-единственного. Она выполняется один раз при включении. В конструкторе. ОС на этот момент не запущена, отпускать проц некуда. Так накой мне городить службу времени на таймерах, если тупой цикл занимает гораздо меньше места, а индикатору (не говоря уж о пользователе - он не заметит разницы) не критично затягивание задержек? Мне нужно при старте включить подтяжку, дать паузу ~1 мс на заряд паразитных емкостей и прочитать состояние ноги. Опять на таймерах городить? Но процессору все равно больше нечем заниматься пока не прочитает состояние той ноги, и точность (в плюс) задержки не критична нисколько.


Цитата(alexeyv @ Nov 8 2010, 07:07) *
При посылке ПЕРВОГО байта прерывание USART_UDRE_vect возникает СРАЗУ ЖЕ,
Отчего же? Флаг установится, (точнее он и перед этим стоял), а прерывание возникнет после его разрешения в строке UCSRB|= (1<<UDRIE);//и отправим нужную строку


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Laksus
сообщение Nov 8 2010, 22:16
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Цитата(Сергей Борщ @ Nov 8 2010, 12:08) *
... Так накой мне городить службу времени на таймерах
...
процессору все равно больше нечем заниматься ...

Вы прямо-таки сформулировали мои мысли, прочитав я на какое-то мгновение засомневался, не цитата ли из моего сообщения, я хотел отправить очень похожее (по сути), уже набрал, но потом решил отложить. Абсолютно согласен, проц некуда отпускать, а кроме паразитных емкостей мне еще надо ждать установки RC-цепочек.
___
volatile не помогает, ничего не меняется.
___
Причина не в _delay_ms(2000), если по прерываниям таймера наращивать счетчик (Count++),
а паузу между выводимыми строчками сделать через ожидание пока счетчик натикает нужное число
while(Count < 20); , или if(Count==20)..., то все равно не работает так как казалось бы должно.

Просто оптимизатор считает, что нефиг присваивать одной и той же переменной несколько значений подряд.

Если присваивать в прерывании таймера, тогда все нормально.
Но так как мне очень не хочется путаться с пусковым приветом в прерывании, где будет вся работа программы, то
я лучше использую таки _delay_ms(2000), а для передачи текста использую не указатели, а функцию strcpy(). Ее оптимизатор не выкидывает. Все работает так как мне хотелось.

Насколько я понял для правильного выхода из возникшей ситуации мне надо бы глубоко изучить внутреннюю кухню gcc.
А через strcpy() может и неправильно (быстродействие, размер кода), но так как быстродействия мне не надо, и код (предположительно) влезет с запасом, то меня устраивает и такое половинчатое решение.
Код
char StringLCD[33];
. . .
int main(void)
{
init();

UDR= Address_LCD;// пошлем адрес
strcpy(StringLCD, Hello_1);
UCSRB|= (1<<UDRIE);//и отправим строку1
_delay_ms(2000);

UDR= Address_LCD;// пошлем адрес
strcpy(StringLCD, Hello_2);
UCSRB|= (1<<UDRIE);//и отправим строку2
. . .
for(;;);


Спасибо ответившим.

Сообщение отредактировал Laksus - Nov 8 2010, 22:23
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Nov 8 2010, 23:06
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(Laksus @ Nov 9 2010, 02:16) *
Просто оптимизатор считает, что нефиг присваивать одной и той же переменной несколько значений подряд.

Вам же подсказали квалификатор volatile. Он как раз и позволяет исключить излишний интеллект оптимизатора. По сути все действия с такой переменной вообще не оптимизируются. Почему он не помог непонятно. Может.. не туда добавили? smile.gif
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Laksus   WinAVR, _delay_ms(), строки и оптимизация.   Nov 5 2010, 19:17
- - artymen   Функции из util/delay.h имеют одну пакость, из док...   Nov 5 2010, 19:46
|- - Laksus   Цитата(artymen @ Nov 5 2010, 22:46) ... п...   Nov 5 2010, 22:52
|- - ASZ   Может, это снобизм, но принципиально не использую ...   Nov 5 2010, 23:09
- - Genadi Zawidowski   У функции _delay_ms() есть ограничение на максимал...   Nov 5 2010, 19:48
- - artymen   Посмотрите, укладывается ли полученный бинарник во...   Nov 6 2010, 05:12
|- - Сергей Борщ   Цитата(artymen @ Nov 6 2010, 08:12) GCC (...   Nov 6 2010, 06:44
|- - MrYuran   Цитата(Сергей Борщ @ Nov 6 2010, 09:44) К...   Nov 6 2010, 07:37
- - artymen   ЦитатаФигня полная. Прекрасно следит. А если у вас...   Nov 6 2010, 10:32
- - alexeyv   Маленькое замечание по поводу кода: КодUDR= Addre...   Nov 8 2010, 05:07
||- - Сергей Борщ   Цитата(Laksus @ Nov 9 2010, 00:16) ___ vo...   Nov 10 2010, 08:33
||- - Laksus   Цитата(Сергей Борщ @ Nov 10 2010, 11:33) ...   Nov 10 2010, 11:15
||- - Сергей Борщ   Цитата(Laksus @ Nov 10 2010, 13:15) но в ...   Nov 10 2010, 11:55
|- - alexeyv   Цитата(Сергей Борщ @ Nov 8 2010, 14:08) О...   Nov 9 2010, 04:23
- - Marian   При уровне оптимизации -Os, компилятор выкидывает ...   Nov 8 2010, 14:56


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 14:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.01411 секунд с 7
ELECTRONIX ©2004-2016