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

В последнее время я вырывал свои волосы, пытаясь заставить 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 ]

6 голосов
/ 11 мая 2009

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

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

Давайте предположим, что 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 для конца).

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

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

5 голосов
/ 11 мая 2009

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

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

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

5 голосов
/ 11 мая 2009

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

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

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

2 голосов
/ 11 мая 2009

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

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

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

...