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

 
 
> 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
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 27)
AlexBoy
сообщение Apr 26 2007, 16:43
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394



Может до строки PORTD &=~0x80; он и не доходит. Попробуй при входе в прерывание запрещать их
asm("cli");
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 26 2007, 17:29
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(Denisvak @ Apr 26 2007, 16:29) *
Немного удивляет поведение юарта в этом МК.

попробуйте вот так хотя я ине уверен

#define UDRE 5
char i=0;

void USART_Transmit( unsigned char data )
{
if (i =1){
while ( !( UCSRA & (1<<UDRE)) );
UDR = data; }
i =0;
}
Обработчик
#pragma vector = USART_RXC_vect
__interrupt void USART_Receive(void)
{
i = 1;
PORTD |=0x80;
data = UDR;
USART_Transmit(data);
PORTD &=~0x80;
}


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 26 2007, 19:09
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Использовал эту мегу в качестве модема с полным управлением потоком. Как програмным так и аппаратным. Делается лет пять (начиналось с at90s4414). Никаких претензий нет.
Go to the top of the page
 
+Quote Post
freux
сообщение Apr 26 2007, 19:28
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 41
Регистрация: 7-02-05
Пользователь №: 2 473



Цитата(Denisvak @ Apr 26 2007, 17:29) *
Код
#pragma vector = USART_RXC_vect
__interrupt void USART_Receive(void)
{
  PORTD |=0x80;
  USART_Transmit(UDR);
  PORTD &=~0x80;
}


.. он обрабатывает только при первом принятом символе. Дльше никаких дёрганий.
В чем может быть Ошибка.


Состояние седьмой ноги PortD меняется в прерывании дважды - т.е возвращается в первоначальное состояние - это может быть просто не заметно глазу. Я бы рекомендовал делать просто инверсию бита на 7 ноге. Тогда при первом принятом символе загорится, при втором - потухнет и т.д.
Go to the top of the page
 
+Quote Post
Denisvak
сообщение Apr 26 2007, 19:51
Сообщение #6


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

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



По ходу дела все таки он их обрабатывает, просто я осцилом не замечаю. Вписал туда задержку и все нормально стало.
Интересно только почему он первый раз прерывание дольше обрабатывает. первую посылку я успеваю заметить.
Всем спасибо.


З.Ы. Мне просто этой ногой нужно переключать направление 485-го.

Сообщение отредактировал Denisvak - Apr 26 2007, 19:53
Go to the top of the page
 
+Quote Post
Amper25
сообщение Apr 26 2007, 20:21
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 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
Denisvak
сообщение Apr 26 2007, 20:42
Сообщение #8


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

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



Цитата(Amper25 @ Apr 26 2007, 21:21) *
void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<<5)) );
UDR = data;
}
Я знаю в чем баг. У меня был практически такой же глюк.
Проблема вот в чем:
while ( !( UCSRA & (1<<5)) );

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

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


smile.gif Подумайте с чего это биту UDRE быть установленным? если мы до этого ничего не отправляем.
Получается что при первом отправлении запись while ( !( UCSRA & (1<<5)) ); тут не причем.
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение Apr 26 2007, 21:13
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



2 Denisvak - Вообще то при вниматьном прочтении ДШ на этот кристалл замечаем на странице 151 такую вещь как начальное состояние битов регистра UCSRA, так, если приглядется получше то можно увидеть что он изначально установлен в 1.
То есть Amper25 всё правильно написал. Но на счёт ( ( UCSRA & (1<<5)) != 0x00 ) - я думаю это уж слишком...

Это -
//send char proc
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}

тоже неплохо работает, да и взято с того же самого даташита smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 26 2007, 22:21
Сообщение #10


Гуру
******

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



Цитата(Kuzmi4 @ Apr 26 2007, 20:13) *
2 Denisvak - Вообще то при вниматьном прочтении ДШ на этот кристалл замечаем на странице 151 такую вещь как начальное состояние битов регистра UCSRA, так, если приглядется получше то можно увидеть что он изначально установлен в 1.
То есть Amper25 всё правильно написал.
То есть Amper25 написал все с точностью до наоборот. Действительно, UDRE равен единице, UCSR0A & (1<<UDRE0) равен (1<<UDRE0), т.е не нулю, а !(UCSR0A & (1<<UDRE0)) равен нулю. Поэтому никакого зависания в цикле в начале не будет. И ничего отправлять предварительно не нужно.
Цитата(Denisvak @ Apr 26 2007, 18:51) *
З.Ы. Мне просто этой ногой нужно переключать направление 485-го.
Тогда вам нужно для выключения передатчика использовать прерывание по TXC


--------------------
На любой вопрос даю любой ответ
"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, 02:01
Сообщение #11


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
Kuzmi4
сообщение Apr 27 2007, 08:33
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



2 Сергей Борщ - я имел ввиду что, согласен с тем что "... запись ( !( UCSRA & (1<<5)) ) - не очень корректная..." - всмысле что тут смотреть надо, и привёл свой пример решения этой задачи.
smile.gif
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Apr 27 2007, 09:39
Сообщение #13


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Оператор ! это не побитная инверсия, а логическая.
При этом UCSRA&0х10 = true или false. Инверсия этого будет соответственно false или true.
Так что запись while(!(UCSRA&(1<<5))) правильна.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2007, 09:55
Сообщение #14


Гуру
******

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


Участник
*

Группа: Новичок
Сообщений: 41
Регистрация: 7-02-05
Пользователь №: 2 473



Цитата(Denisvak @ Apr 26 2007, 20:51) *
Вписал туда задержку и все нормально стало.

Вставлять в обработчик прерывания задержку равно, как и ожидание, обсуждаемое выше - плохой стиль. Лучше, тот же Transmit вызывать в бесконечном цикле по флагу в main_e, а в прерывании этот самый флаг взводить.
Go to the top of the page
 
+Quote Post
Denisvak
сообщение Apr 27 2007, 13:28
Сообщение #16


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

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



Цитата(freux @ Apr 27 2007, 12:14) *
Вставлять в обработчик прерывания задержку равно, как и ожидание, обсуждаемое выше - плохой стиль. Лучше, тот же Transmit вызывать в бесконечном цикле по флагу в main_e, а в прерывании этот самый флаг взводить.


Задержку я вставлял только для того чтобы увидеть сам импульс на осциле! smile.gif
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 27 2007, 15:41
Сообщение #17


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
IgorKossak
сообщение Apr 27 2007, 16:08
Сообщение #18


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(=GM= @ Apr 27 2007, 15:41) *
Насчёт оператора "!" я ошибся, прошу пардону. Но от этого UCSRA&0х10 не станет логической переменной, это двоичное 8-битное число. Да, так можно делать для проверки на 0, но это неправильно, в смысле нелогично. К чему приложим оператор логической инверсии? Я думаю, к логической переменной или выражению....

Здесь действует правило приведения. Если применяется логический оператор (!), то выражение под ним приводится к логическому типу, т. е. если 0 - false, если не 0 - true.
Поскольку это свойство является стандартным, то оно врядли претерпит изменение и код будет корректным пока существует язык.
Ссылки на Кернигана и Ричи приводились на этом форуме.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2007, 17:36
Сообщение #19


Гуру
******

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



Цитата(=GM= @ Apr 27 2007, 14:41) *
Что-то я знаю в С, что-то нет, конечно, в полном объёме С я не знаю, может быть и никто не знает, кроме вас(:-).
Напрасно ерничае - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего smile.gif
Цитата(=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))) работает ПОКА, согласен, то что она правильная или будет правильная ВСЕГДА - сомневаюсь.
Напрасно. Поверьте wink.gif
Цитата(=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)
Go to the top of the page
 
+Quote Post
Denisvak
сообщение Apr 27 2007, 19:05
Сообщение #20


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

Группа: Участник
Сообщений: 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
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 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
сообщение Apr 27 2007, 19:37
Сообщение #22


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

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



Цитата(Сергей Борщ @ Apr 27 2007, 20:24) *
В некоторых случаях (когда чтение изменяет содержимое читаемого регистра) это недопустимо. Чтобы проверялось два бита, надо писать while ( !( UCSRA & ( (1<<5)|(1<<6) ) )).


Спасибо что поправили.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 27 2007, 23:14
Сообщение #23


Ambidexter
*****

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



Цитата(Denisvak @ Apr 27 2007, 16:05) *
Думаю можно так
Код
while ( !(( UCSRA & (1<<5))&&( UCSRA & (1<<6)) ));
- тут ждем пока 5-й и 6-й бит установятся!!! Можете проверить.

Я верю, боюсь только представить в какой ужасный код превратится сия конструкция после компилятора. Да и разобраться в логике ой как не просто. А если 5 бит? Застрелиться можно.
Цитата(Denisvak @ Apr 27 2007, 16:05) *
А вот while(UCSRA&0x6A==0x6A); насколько я понимаю, не будет работать. Может конечно и ошибаюсь!!!

Нет, это я лопухнулся, вместо "неравно" поставил "равно", вот так надо: while(UCSRA&0x6A!=0x6A); И проверяй хоть 1, хоть 2, хоть 5 бит...конструкция останется той же.

Даже для нашего случая будет читабельнее: while(UCSRA&0x10!=0x10);


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


Гуру
******

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



Цитата(=GM= @ Apr 27 2007, 22:14) *
Нет, это я лопухнулся, вместо "неравно" поставил "равно", вот так надо: while(UCSRA&0x6A!=0x6A); И проверяй хоть 1, хоть 2, хоть 5 бит...конструкция останется той же.
Да не будет она работать: у != и == приоритет выше чем у &. Поэтому сначала будет выполнено 0x6A != 0x6A и даст в результате 0, а потом будет проверяться UCSRA & 0, что всегда дает 0 и компилятор выкинет весь код после if который никогда не должен выполниться и оставит только чтение USCRA, и то только потому, что UCSRA объявлено как volatile. А если бы оно было не volatile - выкинул бы и его чтение. Расставьте правильно скобки и получите то, что вы хотите: while( (UCSRA&0x6A) != 0x6A);
При этом осталось разобраться, чего мы хотим: ждать пока не будут выставлены все биты while( (UCSRA&0x6A) != 0x6A); или пока не будет выставлен хотя бы один:while( (UCSRA&0x6A) == 0); <=> while( ! (UCSRA&0x6A) ); или пока выставлен хотя бы один: while( (UCSRA&0x6A) != 0); <=> while(UCSRA&0x6A);


--------------------
На любой вопрос даю любой ответ
"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 28 2007, 00:02
Сообщение #25


Ambidexter
*****

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



Цитата(Сергей Борщ @ Apr 27 2007, 14:36) *
Напрасно ерничаете - если я не уверен в чем-то, то прежде чем писать ответ копаюсь в документации и сначала проясняю для себя вопрос. Часто бывает, что был не прав и после ознакомления понимаю, что писать нечего smile.gif
Не обижайтесь, я смайлик там поставил, хотел пошутить, а вы на полном серьёзе...

За ссылки спасибо, кое-что уже скачал, и днём еще Карнигана, спасибо нашему модератору, изучаю, времени только не хватает, как всегда, столько всего интересного кругом...
Цитата(Сергей Борщ @ Apr 27 2007, 14:36) *
Реальный тип bool вместе с ключевыми словами true и false введены в С++.Но даже в С++ в логических выражениях bool преобразуется к int, вычисляется результат и результат преобразуется обратно к bool.
Ужос, зачем нам такой си(:-)?
Цитата(Сергей Борщ @ Apr 27 2007, 14:36) *
3) if(b--) a=3; a станет равно 3, b будет преобразован к int (1), выполнен декремент и результат (0) будет преобразован к bool (false).
Не так. Уже нарыл в книгах, здесь операция "b--" запрещена, компилятор не пропустит.

Ладно, буду изучать дальше.


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


Гуру
******

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



Цитата(=GM= @ Apr 27 2007, 22:14) *
Я верю, боюсь только представить в какой ужасный код превратится сия конструкция после компилятора.
Что-то близкое к
Код
Loop:
   sbis  UCSRA, 5
   rjmp Loop
   sbis  UCSRA, 6
   rjmp Loop



Цитата(=GM= @ Apr 27 2007, 23:02) *
Ужос, зачем нам такой си(:-)?
-Какой же вы Рыцарь?
-Да вот какой уж есть!
Шрек1 laugh.gif

Цитата(=GM= @ Apr 27 2007, 23:02) *
Не так. Уже нарыл в книгах, здесь операция "b--" запрещена, компилятор не пропустит.
Интересно, видимо я это пропустил. Процитируйте, если не сложно.


--------------------
На любой вопрос даю любой ответ
"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 28 2007, 00:37
Сообщение #27


Ambidexter
*****

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



Цитата(Сергей Борщ @ Apr 27 2007, 21:10) *
Интересно, видимо я это пропустил. Процитируйте, если не сложно.

Use of an Operand of Type bool with the Postfix ++ Operator
Applying postfix ++ to a variable of type bool is still allowed for backward compatibility with old code that uses plain int or some typedef, as in bool done = false;
while(!done)
{
if(condition)
//...do something
else done++; //deprecated
}
Incrementing a bool always yields true, regardless of the original value. However, this practice is deprecated; therefore, it might not be supported in the future. Remember that applying -- (decrement operator) to a bool variable is illegal.

Из книги "ANSI/ISO C++ Professional Programmer's Handbook". Еле эту ссылку нашёл, а вот где оригинальная ссылка, не могу найти(:-(


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


Гуру
******

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



Цитата(=GM= @ Apr 27 2007, 23:37) *
Из книги "ANSI/ISO C++ Professional Programmer's Handbook". Еле эту ссылку нашёл, а вот где оригинальная ссылка, не могу найти(:-(
Спасибо, записал на корочку. Хотя и не приходилось еще декрементироваить и инкриментировать bool cranky.gif
cheers.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

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

 


RSS Текстовая версия Сейчас: 27th July 2025 - 00:28
Рейтинг@Mail.ru


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