Как я могу исправить этот код, чтобы позволить моему AVR взаимодействовать через последовательный порт?

StackOverflow https://stackoverflow.com/questions/846206

  •  21-08-2019
  •  | 
  •  

Вопрос

В последнее время я рвал на себе волосы, пытаясь заставить ATmega162 на моем STK200 общаться с моим компьютером по RS232.Я проверил и убедился, что STK200 содержит чип MAX202CPE.

Я настроил чип на использование внутренней тактовой частоты 8 МГц и разделил ее на 8.

Я пытался скопировать код из таблицы данных (и вносил изменения там, где компилятор жаловался), но безрезультатно.

Мой код приведен ниже, не мог бы кто-нибудь, пожалуйста, помочь мне исправить проблемы, с которыми я сталкиваюсь?

Я подтвердил, что мой последовательный порт работает на других устройствах и не является неисправным.

Спасибо!

#include <avr/io.h>
#include <avr/iom162.h>

#define BAUDRATE 4800

void USART_Init(unsigned int baud)
{
    UBRR0H = (unsigned char)(baud >> 8);
    UBRR0L = (unsigned char)baud;

    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}

void USART_Transmit(unsigned char data)
{
    while(!(UCSR0A & (1 << UDRE0)));

    UDR0 = data;
}

unsigned char USART_Receive()
{
    while(!(UCSR0A & (1 << RXC0)));

    return UDR0;
}

int main()
{

    USART_Init(BAUDRATE);

    unsigned char data;

    // all are 1, all as output
    DDRB = 0xFF;

    while(1)
    {
        data = USART_Receive();

        PORTB = data;

        USART_Transmit(data);


    }
}
Это было полезно?

Решение 4

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

При скорости передачи 4800 бод и тактовой частоте 1 МГц ошибка составляла 0,2%, что было приемлемо для меня.Хитрость заключалась в передаче 12 в функцию USART_Init() вместо 4800.

Надеюсь, это поможет кому-то еще!

Другие советы

Я прокомментировал ответ Грега, но хотел бы добавить еще одну вещь.Для такого рода задач золотой стандартный метод ее отладки заключается в том, чтобы сначала понимать асинхронная последовательная связь, затем достать осциллограф и посмотреть, что происходит на линии.Если происходит обмен символами, и это просто проблема со скоростью передачи данных, это будет особенно полезно, поскольку вы можете вычислить скорость передачи данных, которую вы видите, а затем соответствующим образом скорректировать делитель.

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

Давайте предположим, что 8 бит, без четности, 1 стоповый бит (наиболее распространенная настройка).Затем, если передаваемый символ, скажем, равен 0x3f (= ascii '?'), то строка выглядит следующим образом;

...--+   +---+---+---+---+---+---+       +---+--...
     | S | 1   1   1   1   1   1 | 0   0 | E
     +---+                       +---+---+

Высокий уровень (1) равен +5 В на микросхеме и -12 В после преобразования в уровни RS232.

Низкий уровень (0) равен 0 В на микросхеме и + 12 В после преобразования в уровни RS232.

S - это начальный бит.

Тогда у нас есть 8 битов данных, наименее значимых в начале, так что здесь 00111111 = 0x3f = '?'.

E - это стоповый бит (e для end).

Время движется слева направо, точно так же, как на дисплее осциллографа, если частота передачи равна 4800, то каждый бит занимает (1/4800) секунды = 0,21 миллисекунды (приблизительно).

Приемник работает путем выборки линии и поиска падающего фронта (постоянно находящаяся в состоянии покоя линия - это просто логическое значение "1").Приемник знает скорость передачи данных и количество начальных битов (1), поэтому он измеряет половину битового времени от падающего фронта, чтобы найти середину начального бита, затем выполняет выборку строки 8 битных раз подряд после этого, чтобы собрать биты данных.Затем приемник ожидает еще один бит времени (до половины прохождения стоп-бита) и начинает поиск другого стартового бита (т.е.падающий край).Тем временем считанный символ становится доступным для остальной части системы.Передатчик гарантирует, что следующий падающий фронт не начнется до тех пор, пока не будет завершен стоп-бит.Передатчик можно запрограммировать на более длительное ожидание (с дополнительными стоп-битами), но это устаревшая проблема, дополнительные стоп-биты требовались только при очень медленных настройках оборудования и / или программного обеспечения.

У меня нет под рукой справочного материала, но регистр скорости передачи данных UBRR обычно содержит значение делителя, а не саму желаемую скорость передачи данных в бодах.A быстрый поиск в Google указывает, что правильное значение делителя для 4800 бод может быть равно 239.Так что попробуй:

divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;

Если это не сработает, обратитесь к справочным документам для вашего конкретного чипа за правильной формулой вычисления делителя.

Для отладки связи UART необходимо сделать две полезные вещи:

1) Выполните обратный цикл на соединителе и убедитесь, что вы можете прочитать то, что вы пишете.Если вы отправляете символ и получаете его обратно в точности, вы знаете, что аппаратное обеспечение подключено правильно и что, по крайней мере, базовый набор конфигурации регистра UART верен.

2) Повторно отправьте символ 0x55 ("U") - двоичный разрядный шаблон 01010101 позволит вам быстро увидеть разрядность на осциллографе, что позволит вам убедиться в правильности настройки скорости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top