UART - как передать байт?

Тема в разделе "WASM.ELECTRONICS", создана пользователем cresta, 9 мар 2011.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Код (Text):
    1. unsigned char currKey, prevKey;
    2.  
    3. //-----------код А
    4.  
    5. while (1){
    6.     currKey = PINA;
    7.     if ( currKey != 0xFF){
    8.         UART1_Write(currKey);
    9.     }
    10. }
    11.  
    12. //-----------код Б
    13.  
    14. while (1){
    15.     currKey = PINA;
    16.     if ( currKey != 0xFF ){
    17.         if (currKey != prevKey){
    18.             UART1_Write(currKey);
    19.         }
    20.     }
    21.     prevKey = currKey;
    22. }
    Контроллер Atmega16. На порту А сидят кнопки. PullUp включен. Если нажата кнопка, передать состояние порта (код) по UART на терминал.
    Два варианта кода.
    Вариант А. Нажимаю кнопку (замыкаю один из входов порта на землю) - в терминал начинают сыпаться коды состояния порта. Например, нажата кнопка на 0 бите - код 0хFE, на 7 бите - 0х7F. Все хорошо, кроме одного: пока нажата кнопка, контроллер бомбардирует терминал одним и тем же кодом. Мне не надо столько раз посылать этот код. Достаточно один раз передать в терминал код.
    Поэтому родился вариант Б.
    А в варианте Б происходит не то, что я ожидаю: в терминал как и предполагалось, приходит один код на одно нажатие кнопки.
    Вся проблема в том, что этот код всегда равен 0х00, какую бы кнопку я не нажал.
    Или я что-то не понял, или одно из двух...
    В чем тут засада?
     
  2. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    может быть так правильнее?:

    Код (Text):
    1. prevKey = 0;
    2. while (1){
    3.     currKey = PINA;
    4.     if ( currKey != 0xFF ){
    5.         if (currKey != prevKey){
    6.             UART1_Write(currKey);
    7.             prevKey = currKey;
    8.         }
    9.     }
    10. }
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    это не меняет сути. В чем проблема я примерно нащупал: это регистр UDR. Зачем-то приходится его обнулять принудительно перед передачей байта. Тогда передача будет идти правильно. Надо ковыряться в UАRT либе.
     
  4. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    cresta
    У меня основная масса чудес случается из-за оптимизации компилятором. А вот если в регистре состояния UART установлены биты ошибок, то отладчик регистр UDR отображается как 0 (может ли отладчик показать в нём что-то другое - не проверял). Попробуй прочитать перед передачей его и/или регистр состояния.
    Еще для кнопок хорошо бы сделать защиту от дребезга (механический износ кнопок и наводки никто не отменял). Можно читать кнопки с интервалом в 10-15мс и по нескольким совпадающим значениям принимать решение нажата/не нажата(считается, что для механических контактов дребезг заканчивается в течении 50мс):
    Код (Text):
    1. b[3&++cnt]=PINA;
    2. currKey|=(b[0]&b[1]&b[2]&b[3]);
    3. currKey&=(b[0]|b[1]|b[2]|b[3]);
     
  5. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    Советую посмотреть доку на отмегу там есть примеры по передачи. Необходимо просматривать бит занятости передатчика перед отправкой. По поводу одной отправке то либо как сказали паузы либо можно завязать на внешнее прерывание и тогда по перепаду отправлять, правда проблему дребезга это не решит.
     
  6. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Проблему решил, уйдя от библиотечной функции.
    Сделал свою:

    Код (Text):
    1. void  RS_Send_Char(char c){
    2.      while ( !(UCSRA & 0b00100000) );  //waiting for ready
    3.      UDR = c;
    4. }
    5.  
    6. void RS_Send_Text (char *text){
    7.      while ( *text ){
    8.            RS_Send_Char (*text);
    9.            text ++;
    10.      }
    11. }