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

 
 
> UART Mega8, Странное поведенеие
Denisvak
сообщение Apr 26 2007, 16:29
Сообщение #1


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

Группа: Участник
Сообщений: 141
Регистрация: 7-03-06
Из: Санкт-Петербург
Пользователь №: 15 038



Дорый день!

Немного удивляет поведение юарта в этом МК.
Исходник
Код
void main( void )
{
  UCSRA=0x00;//UART init
  UCSRB=0x98;
  UCSRC=0x86;
  UBRRH=0x00;
  UBRRL=0x5F;

  DDRC |=0x03;
  DDRD |=0x80;
  PORTC=0x00;
  
  asm("sei");
  while(1)
  {
  }
}
void USART_Transmit( unsigned char data )
{
  while ( !( UCSRA & (1<<5)) );
  UDR = data;
}


Обработчик

Код
#pragma vector = USART_RXC_vect
__interrupt void USART_Receive(void)
{
  PORTD |=0x80;
  USART_Transmit(UDR);
  PORTD &=~0x80;
}


Прикол в том что если с терминала ему слать данные то он нормально отвечает то что и принял. А вот строки
Код
PORTD |=0x80;
и
Код
PORTD &=~0x80;
он обрабатывает только при первом принятом символе. Дльше никаких дёрганий.
В чем может быть Ошибка.
Спасиба!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Amper25
сообщение Apr 26 2007, 20:21
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 215
Регистрация: 10-04-07
Пользователь №: 26 929



void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<<5)) );
UDR = data;
}



Я знаю в чем баг. У меня был практически такой же глюк.


Проблема вот в чем:
while ( !( UCSRA & (1<<5)) );

Он ждет очистки UDR от предыдущего символа. А так как раньше ничего не отправлялось, то
и ждать он будет до бесконечности.

Тоесть надо отправить хотябы один символ. Затем UDR станет пустым и будет выставлятся UDRE флаг.

Кстати, запись ( !( UCSRA & (1<<5)) ) - не очень корректная. Лучше использовать
( ( UCSRA & (1<<5)) != 0x00 ).
А умный компилятор с оптимизатором потом сам все упростит.

Сообщение отредактировал Amper25 - Apr 26 2007, 20:26
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 27 2007, 02:01
Сообщение #3


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Amper25 @ Apr 26 2007, 17:21) *
Кстати, запись ( !( UCSRA & (1<<5)) ) - не очень корректная. Лучше использовать
( ( UCSRA & (1<<5)) != 0x00 ).
А умный компилятор с оптимизатором потом сам все упростит.

Вы совершенно правы, говоря, что запись while(!(UCSRA&(1<<5))) - не очень корректна. Я бы сказал совсем некорректна. И вот почему. В операторе while (условие) {...;...;...}; аргумент "условие" должен быть логическим выражением, а оператор выполняется до тех пор, пока это условие равно "true".

Что мы имеем в нашем случае? UCSRA&(1<<5) или UCSRA&0х10 есть побитное логическое "И" двух восьмибитных операндов - содержимого регистра UCSRA и числа 0х10. Результат может быть равен или 0х00 или 0х10. Далее идёт побитная инверсия результата, т.е. будет 0хFF или 0xEF. В итоге будет либо оператор while(0хFF), либо оператор while(0хЕF). Неожиданный результат, не так ли?

Не знаю, как вся конструкция работает, могу только предполагать. Например, для данного компилятора 0х00 - это "false", а инверсная к нему величина 0хFF - "true". Возможно, оператор while воспринимает 0хFF, как "true", а всё остальное, как "false", а может и наоборот(:-(, надо смотреть код после компилятора.

Ну вот, чтобы избежать таких подвохов, надо писать правильно, а именно

while((UCSRA & (1<<5))==0х00); //стоять здесь и ждать, пока бит UDRE не станет равным 1.

Так что, примеры, приведенные в даташитах, не всегда верны(:-(.

Кстати, недавно была дискуссия по похожему поводу - в операторе if(условие) аргумент "условие" также не был логическим выражением.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2007, 09:55
Сообщение #4


Гуру
******

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



Цитата(=GM= @ Apr 27 2007, 01:01) *
Кстати, недавно была дискуссия по похожему поводу - в операторе if(условие) аргумент "условие" также не был логическим выражением.
Все подобные дискуссии - от отсутствия знаний. Вам уже IgorKossak написал, чем операция ! отличается от операции ~. А про отквоченное - так в книжках по С и в стандарте языка четко сказано: в языке С 0 считается false а все, что не 0 считается true. И никиаких ограничений на "логическость" аргумента оператора if (и while и т.д.) не накладывается. Это одна из основ языка С. Зная ее, приходишь к пониманию, что while ( !( UCSR0A & (1<<UDRE0)) ) - конструкция абсолютно нормальная и правильная.
Цитата(=GM= @ Apr 27 2007, 01:01) *
Возможно, оператор while воспринимает 0хFF, как "true", а всё остальное, как "false", а может и наоборот(:-(,
Нет, в языке С такое невозможно. А если вы такое допускаете - вы не знаете элементарных основ языка С.


--------------------
На любой вопрос даю любой ответ
"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
=GM=
сообщение Apr 27 2007, 15:41
Сообщение #5


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(IgorKossak @ Apr 27 2007, 05:39) *
Оператор ! это не побитная инверсия, а логическая.
При этом UCSRA&0х10 = true или false. Инверсия этого будет соответственно false или true.
Так что запись while(!(UCSRA&(1<<5))) правильна.

Насчёт оператора "!" я ошибся, прошу пардону. Но от этого UCSRA&0х10 не станет логической переменной, это двоичное 8-битное число. Да, так можно делать для проверки на 0, но это неправильно, в смысле нелогично. К чему приложим оператор логической инверсии? Я думаю, к логической переменной или выражению. Логичнее было бы сравнивать выработанное число с 0х00 или 0х10, тогда бы появилась логическая переменная. Кстати, как быть, если надо сравнивать несколько бит? По-моему, логичнее так: while(UCSRA&0х6А==0х6А). 0х6А взято от фонаря, как пример. Здесь чётко видно, что для оператора while в скобках проверяется логическая переменная, никаких двусмысленностей.

Цитата(Сергей Борщ @ Apr 27 2007, 05:55) *
Все подобные дискуссии - от отсутствия знаний. А про отквоченное - так в книжках по С и в стандарте языка четко сказано: в языке С 0 считается false а все, что не 0 считается true. И никаких ограничений на "логическость" аргумента оператора if (и while и т.д.) не накладывается. Это одна из основ языка С. Зная ее, приходишь к пониманию, что while ( !( UCSR0A & (1<<UDRE0)) ) - конструкция абсолютно нормальная и правильная.


Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-). Кстати, где бы этого Карнигана&Ричи найти и почитать? Хотелось бы заодно поиметь и текущий стандарт на С, никто не выручит?

Предположим, что всё так, как вы говорите, зачем тогда ввели true и false вообще? Так бы и считали, что 0 - это НЕТ, а что ОТЛИЧНО ОТ 0 - это ДА. Ан нет, ввели, и 10 лет не прошло, как ввели. То, что конструкция while(!(UCSR0A&(1<<UDRE0))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь.

Как знаток С (это без стеба), объясните мне, пожалуйста, такой пример на С, хорошо бы с недвусмысленными пояснениями
Код
int a=0,i=1;
bool b=true;
cout<<boolalpha;

1) if(b++) a=1;

2) if(i++) a=2;

3) if(b--) a=3;

4) if(i--) a=4;

5) if(i=0.5) a=5;

6) if(i==0.5) a=6;

cout<<a,b;

Что будет выведено в каждом случае?

И вот эту строчку поясните: while(*dest++=*src++);


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Denisvak
сообщение Apr 27 2007, 19:05
Сообщение #6


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

Группа: Участник
Сообщений: 141
Регистрация: 7-03-06
Из: Санкт-Петербург
Пользователь №: 15 038



Цитата(=GM= @ Apr 27 2007, 16:41) *
Кстати, как быть, если надо сравнивать несколько бит? По-моему, логичнее так: while(UCSRA&0х6А==0х6А). 0х6А взято от фонаря, как пример.


Думаю можно так
Код
while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) ));
- тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить.

А вот while(UCSRA&0x6A==0x6A); на сколько я понимаю не будет работать. Может конечно и ошибаюсь!!!

Сообщение отредактировал Denisvak - Apr 27 2007, 19:06
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2007, 19:24
Сообщение #7


Гуру
******

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



Цитата(Denisvak @ Apr 27 2007, 18:05) *
Думаю можно так
Код
while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) ));
- тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить.
Да, работать будет, но вместо ожидаемой проверки двух битов за раз будет два раза считан USCRA и после каждого чтения проверено по одному биту. В некоторых случаях (когда чтение изменяет содержимое читаемого регистра) это недопустимо. Чтобы проверялось два бита, надо писать while ( !( UCSRA & ( (1<<5)|(1<<6) ) )).

Цитата(Denisvak @ Apr 27 2007, 18:05) *
А вот while(UCSRA&0x6A==0x6A); на сколько я понимаю не будет работать. Может конечно и ошибаюсь!!!
Совершенно верно. Ибо это эквивалентно while(UCSRA& (0x6A==0x6A) ) => while(UCSRA & 1), что совсем не похоже на желаемое. (для =GM=: на всякий случай перепроверил себя по книге wink.gif )


--------------------
На любой вопрос даю любой ответ
"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

Сообщений в этой теме
- Denisvak   UART Mega8   Apr 26 2007, 16:29
- - AlexBoy   Может до строки PORTD &=~0x80; он и не доходит...   Apr 26 2007, 16:43
- - sKWO   Цитата(Denisvak @ Apr 26 2007, 16:29) Нем...   Apr 26 2007, 17:29
- - SasaVitebsk   Использовал эту мегу в качестве модема с полным уп...   Apr 26 2007, 19:09
- - freux   Цитата(Denisvak @ Apr 26 2007, 17:29) Код...   Apr 26 2007, 19:28
- - Denisvak   По ходу дела все таки он их обрабатывает, просто я...   Apr 26 2007, 19:51
|- - freux   Цитата(Denisvak @ Apr 26 2007, 20:51) Впи...   Apr 27 2007, 11:14
|- - Denisvak   Цитата(freux @ Apr 27 2007, 12:14) Вставл...   Apr 27 2007, 13:28
|- - Denisvak   Цитата(Amper25 @ Apr 26 2007, 21:21) void...   Apr 26 2007, 20:42
|- - IgorKossak   Цитата(=GM= @ Apr 27 2007, 15:41) Насчёт ...   Apr 27 2007, 16:08
|- - Сергей Борщ   Цитата(=GM= @ Apr 27 2007, 14:41) Что-то ...   Apr 27 2007, 17:36
||- - =GM=   Цитата(Сергей Борщ @ Apr 27 2007, 14:36) ...   Apr 28 2007, 00:02
||- - Denisvak   Цитата(Сергей Борщ @ Apr 27 2007, 20:24) ...   Apr 27 2007, 19:37
|- - =GM=   Цитата(Denisvak @ Apr 27 2007, 16:05) Дум...   Apr 27 2007, 23:14
|- - Сергей Борщ   Цитата(=GM= @ Apr 27 2007, 22:14) Нет, эт...   Apr 27 2007, 23:57
|- - Сергей Борщ   Цитата(=GM= @ Apr 27 2007, 22:14) Я верю,...   Apr 28 2007, 00:10
|- - =GM=   Цитата(Сергей Борщ @ Apr 27 2007, 21:10) ...   Apr 28 2007, 00:37
|- - Сергей Борщ   Цитата(=GM= @ Apr 27 2007, 23:37) Из книг...   Apr 28 2007, 01:05
- - Kuzmi4   2 Denisvak - Вообще то при вниматьном прочтении ДШ...   Apr 26 2007, 21:13
|- - Сергей Борщ   Цитата(Kuzmi4 @ Apr 26 2007, 20:13) 2 Den...   Apr 26 2007, 22:21
- - Kuzmi4   2 Сергей Борщ - я имел ввиду что, согласен с тем ч...   Apr 27 2007, 08:33
- - IgorKossak   Оператор ! это не побитная инверсия, а логичес...   Apr 27 2007, 09:39


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

 


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


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