Страница 1 из 2

Согласование UART AVR и мобильника... хелп!

Добавлено: Вс май 03, 2009 01:00:35
d2r
Сутки бьюсь, ни как не могу врубиться в нижеследующую ситацию:

Пишу прошивку для контроллера (мега161). По идее, контроллер должен выдавать в UART команду для модема мобильного телефона (в моем случае - Sony J5).

1. Даю простую команду "ATD*101#". Мобильник молчит... ладно,
2. Подключаю к контроллеру ГиперТерминал через адаптер на MAX323, питание от USB - терминал принимает команду как и положено.
3. Подключаю мобильник к этому же адаптеру, даю ту же команду через ГиперТерминал - мобильник реагирует!

Настройки ГиперТерма не менял, даже не отключал связь.

Пробовал баловаться с завершающими символами - это те, которые везде в мануалах как <CR> обозначаются. Пробовал и "\r" и "\n" и "\r\n" и "\n\r" и даже "\r\0" - ничего не помогает!

Фрагмент кода вывода в UART:

Код: Выделить всё


void put_char( char SendC ) {
   cli();
   wdt_reset();
   while ( UCSR0A ^ (1<<UDRE) ) {
      _delay_ms(1);
   }
   UDR0 = SendC;
   sei();
}

void put_string( char *str ) {
   char sl = strlen( str );
   for ( char i=0; i< sl; i++)
      put_char( str[i] );
   put_char( 10 );
   put_char( 13 );
//   put_char( 0 );
}

......

put_string("ATD*101#");



Телефон подключен к RX и TX контроллера через резисторы 200 Ом.

F - 1.8432Mhz. Скорость 9600.

Может ткнет кто-нибудь носом, что мне поможет в этой ситуации?

Добавлено: Вс май 03, 2009 02:42:43
asteroid7
Вот тут промахнулись по клавише:

Код: Выделить всё

while ( UCSR0A ^ (1<<UDRE) )

Попробуйте так:

Код: Выделить всё

void put_char( char SendC ) { 
   cli();
   wdt_reset();
   while (! (UCSR0A & (1 << UDRE)) );
   UCSR0A |= (1 << TXC); //сброс этого флага лишним не будет
   UDR0 = SendC;
   sei();
}

Команды удобнее и нагляднее передавать в формате:
put_string("AT\r");
put_string("ATD*101#\r");

Добавлено: Вс май 03, 2009 12:52:34
NiTr0
Если не ошибаюсь, в начале нужно подавать ATZ. И ессно слушать ответ комманд ;)

Добавлено: Вс май 03, 2009 13:33:56
d2r
2asteroid7
Спасибо за пример, но, в принципе работает и так и так. Сброс флага TXC добавлю.

2NiTr0
ATZ - сброс в настройки по умолчанию (ессно, терминала). Не обязательно, но желательно.
Слушать ответ не обязательно, более того, смысл? Если телефон не принал данные, он и не ответит.
Далее в обработке будет естественно реакция на прием из UART

-= Проблема решена. Откликнувшимся - огромное спасибо! =-

Сам баран, перепутал RX и TX на телефоне. В результате Мега - Комп и Комп - Телефон = нормально, Мега - Телефон = облом.

Добавлено: Вс май 03, 2009 20:14:29
__Alexander
[quote="asteroid7"]Вот тут промахнулись по клавише:

Код: Выделить всё

while ( UCSR0A ^ (1<<UDRE) )


А если подумать? :))

Добавлено: Вс май 03, 2009 23:31:52
asteroid7
__Alexander О смысле жизни что ли?... :)

Добавлено: Пн май 04, 2009 11:11:39
__Alexander
asteroid7 писал(а):__Alexander О смысле жизни что ли?... :)


Неа, о том что эти команды одинаково правильно работают, и никто по клавишам не промахивался.

^ это XOR

while ( UCSR0A ^ (1<<UDRE) )
while (! (UCSR0A & (1 << UDRE)) );

Добавлено: Пн май 04, 2009 20:19:49
asteroid7
__Alexander
Вы ошибаетесь.

В Си, строка while ( UCSR0A ^ (1<<UDRE) ) не имеет смысла, т.к. в операторе while выражение всегда будет истинно... или true... , а проще просто зациклится.

Добавлено: Пн май 04, 2009 20:57:10
__Alexander
asteroid7 писал(а):__Alexander
Вы ошибаетесь.

В Си, строка while ( UCSR0A ^ (1<<UDRE) ) не имеет смысла, т.к. в операторе while выражение всегда будет истинно... или true... , а проще просто зациклится.


Это вы ошибаетесь, в Си while будет выполняться, пока результат равен "1". Учим матчасть.
Теперь смотрим: 0 xor 0 = 1; зацикливаемся
если UDRE станет в единицу, то
0 xor 1 = 0, то есть из while выпадаем.

Добавлено: Вт май 05, 2009 00:14:50
smac
__Alexander писал(а):Это вы ошибаетесь, в Си while будет выполняться, пока результат равен "1". Учим матчасть.
Теперь смотрим: 0 xor 0 = 1; зацикливаемся
если UDRE станет в единицу, то
0 xor 1 = 0, то есть из while выпадаем.

ВО-ПЕРВЫХ учить матчасть Вам тоже нужно
0 xor 0=0;
0 xor 1=1;
1 xor 1=0;
от перемены мест операндов результат операции не меняется.
По-поводу результата проверки Вы тоже не правы, т. к. на результат операции ( UCSR0A ^ (1<<UDRE) ) влияет значение не только бита UDRE, но и других битов. Например если один из битов (кроме UDRE) всегда будет 1 то результат операции всегда будет отличен от 0, т. е. для while это будет истина, и произойдет зацикливание "навсегда".
Вариант while ( UCSR0A ^ (1<<UDRE) ) можно применять только если быть уверенным что все бит кроме UDRE в регистре UCSR0A всегда равны 0.

Добавлено: Вт май 05, 2009 08:00:05
asteroid7
__Alexander писал(а):... в Си while будет выполняться, пока результат равен "1"...

мда.. с булем в С у вас серьезные проблемы.
А если результат будет больше 1, процессор растеряется? :)
Ответив на вопрос, когда оператор while не будет выполняться, подставьте в UCSR0A два значения 0 и 255, и отксорте их UDRE битом.

Добавлено: Вт май 05, 2009 08:07:20
asteroid7
smac писал(а):...
Вариант while ( UCSR0A ^ (1<<UDRE) ) можно применять только если быть уверенным что все бит кроме UDRE в регистре UCSR0A всегда равны 0.

Да вы сговорились. :))
Но вам то smac, неужели трудно проверить этот while, прежде, чем писать подобные глупости.

Добавлено: Вт май 05, 2009 11:12:37
__Alexander
ВО-ПЕРВЫХ учить матчасть Вам тоже нужно
0 xor 0=0;
0 xor 1=1;
1 xor 1=0;
Вариант while ( UCSR0A ^ (1<<UDRE) ) можно применять только если быть уверенным что все бит кроме UDRE в регистре UCSR0A всегда равны 0.[/quote]


Упс, опечатался, но сути дело не меняет. :))

Добавлено: Вт май 05, 2009 11:58:54
__Alexander
smac писал(а):
__Alexander писал(а):Вариант while ( UCSR0A ^ (1<<UDRE) ) можно применять только если быть уверенным что все бит кроме UDRE в регистре UCSR0A всегда равны 0.


Так точно. Только для стандартного уарта, по крайней мере у меня, этот регистр не используется, т.е. равен нулю. Хотя не знаю насчет RXC и TXC, они могут и помешать для такого рода операций.

Добавлено: Вт май 05, 2009 14:25:28
smac
asteroid7 писал(а):Да вы сговорились. :))
Но вам то smac, неужели трудно проверить этот while, прежде, чем писать подобные глупости.

Вы не рубите сплеча. Я проверил, специально для сомневающихся привожу код и листинг, относящегося только к проверке, естественно на реальном железе нужно еще и инициализацию USART добавить.

Код: Выделить всё

#include <avr>

int main(void){
   while (1){
      while (UCSRA^(1<<UDRE));
      UDR=0xAA;
   }
}

листинг

Код: Выделить всё

0000005e <main>:
#include <avr>

int main(void){
  5e:   9a ea          ldi   r25, 0xAA   ; 170
   while (1){
      while (UCSRA^(1<<UDRE));
  60:   8b b1          in   r24, 0x0b   ; 11
  62:   80 32          cpi   r24, 0x20   ; 32
  64:   e9 f7          brne   .-6         ; 0x60 <main>
      UDR=0xAA;
  66:   9c b9          out   0x0c, r25   ; 12
  68:   fb cf          rjmp   .-10        ; 0x60 <main>

0000006a <_exit>:
  6a:   f8 94          cli

0000006c <__stop_program>:
  6c:   ff cf          rjmp   .-2 

строчки

Код: Выделить всё

      while (UCSRA^(1<<UDRE));
  60:   8b b1          in   r24, 0x0b   ; 11
  62:   80 32          cpi   r24, 0x20   ; 32
  64:   e9 f7          brne   .-6         ; 0x60 <main>
      UDR=0xAA;
  66:   9c b9          out   0x0c, r25   ; 12

говорят о том, что происходит считывание регистра UCSRA, далее оператор искл. или заменен на сравнение, но сути это не меняет,
если считанное число не равно 0х20 (это будет в том случае если не установлен бит UDRE или установлены еще какие-то биты кроме него), то цикл повторяется, если же считанное число равно 20 (установлен толко бит UDRE) то происходит запись в регистр UDR, так что я не соврал нисколько.

Однако, подобным образом я никогда не проверял, не проверяю и не буду проверять состояние бита UDRE, и другим не советую. Наверное это было ошибкой выделять жирным шрифтом часть моего высказывания, но цель была скорее предостеречь от подобных шагов чем призвать использовать этот вариант.

__Alexander писал(а):
Так точно. Только для стандартного уарта, по крайней мере у меня, этот регистр не используется, т.е. равен нулю. Хотя не знаю насчет RXC и TXC, они могут и помешать для такого рода операций.

Да и RXC и TXC, и флаги ошибок могут повлиять, но самое главное, что есть в регистре еще и два бита настройки - U2X - включающий удвоенную скорость передачи и MPCM - реализующий "мультипроцесорный режим связи"

Добавлено: Ср май 06, 2009 06:08:50
asteroid7
smac
Нет, правильно я рубанул.

После такого кода листинга, разработчиков данного компилятора мало на кол посадить. Куда команда EOR делась? Если это только не оптимизация такая хитрая, то да, тогда их нужно отпустить... привязать за руки к двум берёзам... и отпустить.

Вот примерный, но правильный компилируемый код этой несчастной строки:

Код: Выделить всё

while (UCSRA ^ (1 << UDRE));
loop:
   IN   R17, UCSRA
   LDI   R16, 0x20
   EOR   R17, R16
   TST   R17
   BRNE   loop

В нормальном компиляторе приведение логической операции к булю сводится к проверке результата этой операции с нулём. Если ноль, то это false. Всё что больше нуля – true. Т.е. запись "while (UCSRA ^ (1 << UDRE));" должна быть тождественна записи (блин, скрипт форума код рубит, см. во вложении)

p.s. после сноса компилятора, я бы ещё диск форматнул, где он стоял :)

Добавлено: Ср май 06, 2009 08:12:00
ibiza11
asteroid7 писал(а):p.s. после сноса компилятора, я бы ещё диск форматнул, где он стоял :)

ахахахаха)))что за ненависть) в жизни и не такое бывает)) протеус например....

Добавлено: Ср май 06, 2009 10:27:41
smac
asteroid7 писал(а):smac
Нет, правильно я рубанул.

p.s. после сноса компилятора, я бы ещё диск форматнул, где он стоял :)

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

Но дело не в этом, если рассматривать Ваш вариант (я промолчу по поводу его оптимальности), то результат будет именно таким как я и говорил, т. е. если UCSRA == 0x20, то программа выйдет из петли.
Еще раз повторюсь, что такой способ использовать вредо, в этом я с Вами согласен, однако работа программы (правда, в случае с уартом меги, нестабильная) возможна.

Добавлено: Ср май 06, 2009 14:01:41
NiTr0
Да, компилятор жжот :)
Кстати, код вида while (!(UCSRA & (1 << UDRE))); должен быть заметно короче в нормальном компиляторе. Что-то вроде такого:

Код: Выделить всё

loop:
  SBIS UCRSA, UDRE
  RJMP loop

Добавлено: Ср май 06, 2009 15:11:08
smac
NiTr0 писал(а):Да, компилятор жжот :)
Кстати, код вида while (!(UCSRA & (1 << UDRE))); должен быть заметно короче в нормальном компиляторе. Что-то вроде такого:

Код: Выделить всё

loop:
  SBIS UCRSA, UDRE
  RJMP loop

Вы тоже жжоте :), речь шла о компиляции строки while (UCSRA ^ (1 << UDRE));
Ваш пример компилируется именно так как вы сказали.