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

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
d2r
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн апр 20, 2009 12:48:30

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

Сообщение 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.

Может ткнет кто-нибудь носом, что мне поможет в этой ситуации?
Реклама
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение 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");
Реклама
Аватара пользователя
NiTr0
Друг Кота
Сообщения: 3051
Зарегистрирован: Пт авг 10, 2007 12:49:55
Откуда: kr.ua
Контактная информация:

Сообщение NiTr0 »

Если не ошибаюсь, в начале нужно подавать ATZ. И ессно слушать ответ комманд ;)
d2r
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн апр 20, 2009 12:48:30

Сообщение d2r »

2asteroid7
Спасибо за пример, но, в принципе работает и так и так. Сброс флага TXC добавлю.

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

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

Сам баран, перепутал RX и TX на телефоне. В результате Мега - Комп и Комп - Телефон = нормально, Мега - Телефон = облом.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
__Alexander
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

[quote="asteroid7"]Вот тут промахнулись по клавише:

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

while ( UCSR0A ^ (1<<UDRE) )


А если подумать? :))
Реклама
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

__Alexander О смысле жизни что ли?... :)
Реклама
Аватара пользователя
__Alexander
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

asteroid7 писал(а):__Alexander О смысле жизни что ли?... :)


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

^ это XOR

while ( UCSR0A ^ (1<<UDRE) )
while (! (UCSR0A & (1 << UDRE)) );
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

__Alexander
Вы ошибаетесь.

В Си, строка while ( UCSR0A ^ (1<<UDRE) ) не имеет смысла, т.к. в операторе while выражение всегда будет истинно... или true... , а проще просто зациклится.
Аватара пользователя
__Alexander
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

asteroid7 писал(а):__Alexander
Вы ошибаетесь.

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


Это вы ошибаетесь, в Си while будет выполняться, пока результат равен "1". Учим матчасть.
Теперь смотрим: 0 xor 0 = 1; зацикливаемся
если UDRE станет в единицу, то
0 xor 1 = 0, то есть из while выпадаем.
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение 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.
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

__Alexander писал(а):... в Си while будет выполняться, пока результат равен "1"...

мда.. с булем в С у вас серьезные проблемы.
А если результат будет больше 1, процессор растеряется? :)
Ответив на вопрос, когда оператор while не будет выполняться, подставьте в UCSR0A два значения 0 и 255, и отксорте их UDRE битом.
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

smac писал(а):...
Вариант while ( UCSR0A ^ (1<<UDRE) ) можно применять только если быть уверенным что все бит кроме UDRE в регистре UCSR0A всегда равны 0.

Да вы сговорились. :))
Но вам то smac, неужели трудно проверить этот while, прежде, чем писать подобные глупости.
Аватара пользователя
__Alexander
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

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


Упс, опечатался, но сути дело не меняет. :))
Аватара пользователя
__Alexander
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Вт сен 11, 2007 10:27:08
Откуда: Киев

Сообщение __Alexander »

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


Так точно. Только для стандартного уарта, по крайней мере у меня, этот регистр не используется, т.е. равен нулю. Хотя не знаю насчет RXC и TXC, они могут и помешать для такого рода операций.
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение 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 - реализующий "мультипроцесорный режим связи"
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение 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. после сноса компилятора, я бы ещё диск форматнул, где он стоял :)
Вложения
while_xor.txt
(111 байт) 168 скачиваний
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

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

ахахахаха)))что за ненависть) в жизни и не такое бывает)) протеус например....
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение smac »

asteroid7 писал(а):smac
Нет, правильно я рубанул.

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

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

Но дело не в этом, если рассматривать Ваш вариант (я промолчу по поводу его оптимальности), то результат будет именно таким как я и говорил, т. е. если UCSRA == 0x20, то программа выйдет из петли.
Еще раз повторюсь, что такой способ использовать вредо, в этом я с Вами согласен, однако работа программы (правда, в случае с уартом меги, нестабильная) возможна.
Аватара пользователя
NiTr0
Друг Кота
Сообщения: 3051
Зарегистрирован: Пт авг 10, 2007 12:49:55
Откуда: kr.ua
Контактная информация:

Сообщение NiTr0 »

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

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

loop:
  SBIS UCRSA, UDRE
  RJMP loop
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Сообщение smac »

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

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

loop:
  SBIS UCRSA, UDRE
  RJMP loop

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

Вернуться в «Микроконтроллеры и ПЛИС»