|
WinAVR, _delay_ms(), строки и оптимизация. |
|
|
|
Nov 5 2010, 19:17
|
Частый гость
 
Группа: Участник
Сообщений: 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); } }
|
|
|
|
|
 |
Ответов
|
Nov 8 2010, 09:08
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Nov 8 2010, 22:16
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Nov 10 2010, 08:33
|

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

|
Цитата(Laksus @ Nov 9 2010, 00:16)  ___ volatile не помогает, ничего не меняется. ___ Покажите, как вы его применили. Сдается, что вы вместо volatile-указателя на char объявили указатель на volatile char. Потому и не помогло. alexeyv - насчет безликого init() согласен. Но раз дальше идет разрешение прерывания UDRIE, то логично предположить что оно было запрещено до этого. Иначе бы мы просто постоянно крутились в его обработчике.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 10 2010, 11:15
|
Частый гость
 
Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069

|
Цитата(Сергей Борщ @ Nov 10 2010, 11:33)  ... Сдается, что вы вместо volatile-указателя на char объявили указатель на volatile char. Потому и не помогло. ... Так точно! Я ж эту volatile пытался влепить в кучу мест (примерно как мартышка очки), и только после звездочки не догадался (она ж у меня вплотную к переменной пририсована, вот как-то в голову и не пришло, .что туды можно что-то добавить.) Код char *volatile StringLCD;// работает так как хотел Большое спасибо за помощь. Хоть в данном случае большой проблемы и не было, но в дальнейшем незнание разницы между volatile-указателем и укзателем на volatle еще не раз бы о себе напомнило. (Хотя я пока еще толком не понял этой разницы, но гугль говорит, что на эти грабли настапают многие. Есть много обсуждений этого вопроса, почитаю, надеюсь пойму.)
|
|
|
|
Сообщений в этой теме
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  Qwertty Цитата(Laksus @ Nov 9 2010, 02:16) Просто... Nov 8 2010, 23:06    Сергей Борщ Цитата(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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|