|
UART Mega8, Странное поведенеие |
|
|
|
Apr 26 2007, 16:29
|
Частый гость
 
Группа: Участник
Сообщений: 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; он обрабатывает только при первом принятом символе. Дльше никаких дёрганий. В чем может быть Ошибка. Спасиба!!!
|
|
|
|
|
 |
Ответов
|
Apr 27 2007, 02:01
|

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(условие) аргумент "условие" также не был логическим выражением.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Apr 27 2007, 09:55
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Apr 27 2007, 15:41
|

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++);
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Apr 27 2007, 17:36
|

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

|
Цитата(=GM= @ Apr 27 2007, 14:41)  Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-). Напрасно ерничае - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего  Цитата(=GM= @ Apr 27 2007, 14:41)  Кстати, где бы этого Карнигана&Ричи найти и почитать? Хотелось бы заодно поиметь и текущий стандарт на С, никто не выручит? Да сколько угодно: Керниган и Ритчи, прямая ссылка Стандарт СЦитата(=GM= @ Apr 27 2007, 14:41)  Предположим, что всё так, как вы говорите, зачем тогда ввели true и false вообще? Будете смеяться, но: Цитата Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int. ----------------- 7.16 Booleantype and values<stdbool.h> 2 The macro bool expands to _Bool. 3 The remaining three macros are suitable for use in #if preprocessing directives. They are true which expands to the integer constant 1, false which expands to the integer constant 0 4 Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros bool, true, and false. Как видите, это всего лишь макросы. Реальный тип bool вместе с ключевыми словами true и false введены в С++.Но даже в С++ в логических выражениях bool преобразуется к int, вычисляется результат и результат преобразуется обратно к bool. Цитата(=GM= @ Apr 27 2007, 14:41)  Так бы и считали, что 0 - это НЕТ, а что ОТЛИЧНО ОТ 0 - это ДА. Да, так и считают. Цитата 6.3.1.2 Boolean type 1 When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1. Цитата(=GM= @ Apr 27 2007, 14:41)  То, что конструкция while(!(UCSR0A&(1<<UDRE0))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь. Напрасно. Поверьте Цитата(=GM= @ Apr 27 2007, 14:41)  Как знаток С (это без стеба), объясните мне, пожалуйста, такой пример на С, хорошо бы с недвусмысленными пояснениями Это не С, это С++. С++ я знаю сильно хуже, но попробую: Код int a=0,i=1; bool b=true; cout<<boolalpha; выходной поток переключается на вывод значений типа bool в виде "true" и "false" 1) if(b++) a=1; А будет равно 1 ибо результатом будет значение b до инкремента(true), b будет преобразован к int (1), выполнен инкремент и результат инкремента (2) будет преобразован к bool (true). 2) if(i++) a=2; a станет равно 2, ибо i было равно 1 и результатом i++ будет 1, i после этого будет равно 2 3) if(b--) a=3; a станет равно 3, b будет преобразован к int (1), выполнен декремент и результат (0) будет преобразован к bool (false). 4) if(i--) a=4; a станет равно четырем, i станет равным 1 5) if(i=0.5) a=5; a останется равным 4, ибо: 0.5 преобразуется к int (преобразование из float делается методом отбрасывания дробной части), т.е. к 0, далее выполняется присвоение i=0, результатом этого присвоениия является 0 (побочным эффектом - то, что i принимает значение 0), аргумент if() приводится к типу bool ( 0=>false ), выражение после if() (a=5) не выполняется (пропускается). 6) if(i==0.5) a=6; i будет преобразован в float, результат сравнениия 0, выражение a=6 пропускается. cout<<a,b; в выходной поток выводятся символы "4false" Кстати, для ответа на 1, 6 пришлось полистать Страуструпа. Цитата(=GM= @ Apr 27 2007, 14:41)  И вот эту строчку поясните: while(*dest++=*src++); Пожалуй наиболее понятно это объясняют Керниган и Ритчи в главе 5: Цитата Дополнительные моменты, связанные с указателями и массивами, проиллюстрируем на несколько видоизмененных вариантах двух полезных программ, взятых нами из стандартной библиотеки. Первая из них, функция strcpy (s, t), копирует строку t в строку s. Хотелось бы написать прямо s = t, но такой оператор копирует указатель, а не символы. Чтобы копировать символы, нам нужно организовать цикл. Первый вариант strcpy, с использованием массива, имеет следующий вид: /* strcpy: копирует t в s; вариант с индексируемым массивом*/ void strcpy(char *s, char *t) { int i; i = 0; while ((s[i] = t[i]) != '\0') i++; }
Для сравнения приведем версию strcpy с указателями:
/* strcpy: копирует t в s: версия 1 (с указателями) */ void strcpy(char *s, char *t) { while ((*s = *t) != '\0') { s++; t++; } }
Поскольку передаются лишь копии значений аргументов, strcpy может свободно пользоваться параметрами s и t как своими локальными переменными. Они должным образом инициализированы указателями, которые продвигаются каждый раз на следующий символ в каждом из массивов до тех пор, пока в копируемой строке t не встретится '\0'.
На практике strcpy так не пишут. Опытный программист предпочтет более короткую запись: /* strcpy: копирует t в s; версия 2 (с указателями) */ void strcpy(char *s, char *t) { while ((*s++ = *t++) != '\0') ; }
Приращение s и t здесь осуществляется в управляющей части цикла. Значением *t++ является символ, на который указывает переменная t перед тем, как ее значение будет увеличено; постфиксный оператор ++ не изменяет указатель t, пока не будет взят символ, на который он указывает. То же в отношении s: сначала символ запомнится в позиции, на которую указывает старое значение s, и лишь после этого значение переменной s увеличится. Пересылаемый символ является одновременно и значением, которое сравнивается с '\0'. В итоге копируются все символы, включая и заключительный символ '\0'.
Заметив, что сравнение с '\0' здесь лишнее (поскольку в Си ненулевое значение выражения в условии трактуется и как его истинность), мы можем сделать еще одно и последнее сокращение текста программы: /* strcpy: копирует t в s; версия 3 (с указателями) */ void strcpy(char *s, char *t) { while (*s++ = *t++) ; }
Хотя на первый взгляд то, что мы получили, выглядит загадочно, все же такая запись значительно удобнее, и следует освоить ее, поскольку в Си-программах вы будете с ней часто встречаться.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
Сообщений в этой теме
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:36) ... Apr 28 2007, 00:02    Denisvak Цитата(=GM= @ Apr 27 2007, 16:41) Кстати,... Apr 27 2007, 19:05     Сергей Борщ Цитата(Denisvak @ Apr 27 2007, 18:05) Дум... Apr 27 2007, 19:24      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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|