Avr usart rx frame error

Здравствуйте. Я написал на асемблере следующую программу, но у Proteus пишеться при передачи байта : PC=0x0032 [AVR USART] RX FRAME Error У Proteus использовал VIRTUAL Terminal Настроил его на 4800, 8-Data, 2 stop bits Вот код программы :

Здравствуйте. Я написал на асемблере следующую программу, но у Proteus пишеться при передачи байта :

PC=0x0032 [AVR USART] RX FRAME Error

У Proteus использовал VIRTUAL Terminal

Настроил его на 4800, 8-Data, 2 stop bits

Вот код программы :

.cseg

.Org 0

rjmp Begin

.Org 0x007

rjmp USART_RECEIVE

Begin:

ldi Temp,RamEnd

out SPL,Temp ;

;############ Инициализация USART, как передатчика ####################

;f=4000000MHz

;Глобально запретим прерывания, установим 8-ой бит регистра #

;SREG(регистр статуса) в 0.(Флаг I)

clI

;Установим Бодрейт 4800

;UBRR=(fosc/16*BAUD)-1; UBRR=(4000000/16*4800)-1=0x33

ldi Temp,0x33

out UBRRL,Temp

ldi Temp,0

out UBRRH,Temp

;разрешим передачу и прием

ldi Temp,(1<<RXEN)|(1<<TXEN)

out UCSRB,r16

;Установим формат посылки для USART:асинхронный режим(UMSEL=0) 8data, #

;2 stop bit

ldi Temp,(1<<USBS)|(3<<UCSZ0)

out UCSRC,Temp

sei

;#####################################################################

START:

;вывод r16 на LCD

rjmp start

USART_RECEIVE:

in r16,UDR

; у r16 принятый байт

RETI

Часовой пояс: UTC + 3 часа

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7

Источник

Avr uart rx frame error

Перевод апноута AVR274 [1], который описывает софтовую реализацию однопроводного последовательного порта (UART). Протокол поддерживает полудуплексный обмен данными между 2 устройствами (передача в разных направлениях может происходить поочередно). Для реализации требуется только поддержка внешнего прерывания (external interrupt) на порте ввода/вывода I/O, и прерывание сравнения таймера (timer compare interrupt).

[1. Основные возможности и особенности программного UART]

• UART реализован программно
• Поддерживается полудуплексный обмен данными по одному проводу
• Используются прерывания
• Поддерживаются скорости передачи до 9600 на тактовой частоте ядра 1 МГц
• Описанный программный UART совместим с любым микроконтроллером AVR ® , который поддерживает внешнее прерывание (external interrupt, прерывание по изменению уровня на ножке GPIO) и имеет 8-битный таймер с поддержкой прерывания сравнения (timer compare interrupt).

Обмен данными с помощью физического протокола UART обычно осуществляется с использованием отдельных сигналов данных для приема и передачи (сигналы RX и TX). Однопроводный UART использует для обмена только одну сигнальную линию. Поэтому такой UART является идеальным для случаев, когда нужно реализовать недорогое решения для обмена данными, и не требуется высокая скорость и полнодуплексная передача. Этот апноут описывает софтовую (программную) реализацию однопроводного UART. Протокол поддерживает полудуплексный обмен между двумя устройствами AVR. Для реализации требуется только один вывод порта I/O, на котором поддерживается внешнее прерывание (external interrupt), и требуется прерывание сравнения таймера (timer compare interrupt).

[2. Теория: как это работает]

2.1. Фрейм (битовый кадр) UART

Протокол UART использует стандарт асинхронного последовательного обмена данными. Данные передаются последовательно, бит за битом, каждому биту отводится определенный отрезок времени. Эта реализация использует фрейм из 8 бит данных, 1 стартового бита и 2 стоповых бит, как это показано на рис. 2-1 (таким образом, каждый битовый кадр состоит из 11 элементарных битовых интервалов). Такой формат выбран потому, что на практике именно он чаще всего используется для передачи данных. Другие реализации могут использовать другие форматы фрейма, к примеру состоящие из 5..9 бит данных, 1 бита четности (parity, бит для определения наличия ошибки), и 1 стоповый бит. Конечно же, обе передающие стороны в обмене точка-точка должны быть настроены на один и тот же формат данных. Когда передачи нет, то сигнальная линия UART находится в состоянии лог. 1.

Рис. 2-1. Формат фрейма UART.

Рис. 2.2. Фрейм передачи последовательных данных для символа ASCII ‘a’ (код 0x61).

2.2. Передача данных

Передача инициализируется отправкой стартового бита, который всегда равен 0 (сигнальная линия притягивается к нижнему уровню). Приемник на другой стороне линии детектирует спад уровня на линии, и по этому событию может засинхронизироваться с передатчиком (синхронизация по времени требуется для корректного приема всех бит данных). Самый младший бит данных передается первым (см. рис. 2-2).

Выходы с открытым коллектором часто используются для такого управления линией данных, однако если сразу оба устройства на линии будут передавать в одно и то же время, то передатчик, передающий лог. 0, все равно будет притягивать линию к лог. 0, когда второй передатчик пытается передать бит 1. Чтобы обработать эту ситуацию, UART никогда не запускает передачу, когда он находится в режиме приема. Передатчик также проверяет сигнальную линию перед отправкой нового бита, чтобы убедиться, что её состояние не изменилось, когда передавался последний бит. Флаг ошибки устанавливается, если принят бит низкого уровня, когда последним передавался бит высокого уровня.

2.3. Прием данных

Прием запускается, когда был детектирован стартовый бит на линии. Затем состояние линии анализируется посередине каждого битового интервала фрейма, чтобы принять значение каждого бита информации. Таким образом, к примеру, первый бит данных выбирается после 1.5 периода бита после начала стартового бита. Эта реализация (для упрощения, и уменьшения загрузки ядра AVR) не использует тройную мажоритарную выборку для каждого бита (этот способ уточнения значения бита используется в большинстве аппаратно реализованных UART).

2.4. Битовая скорость передачи (Baud Rate)

Скорость обмена данными UART задается параметром baud rate. Его значение в этом случае эквивалентно количеству битовых интервалов, которые проходят за единицу времени. Так как во фрейме применяются стартовый и стоповые биты, то реальная скорость передачи данных получается несколько меньше (для нашего примера она равна 8/11 от значения baud rate). Приемник и передатчик должны быть настроены на использование одного и того же значения baud rate, иначе они не смогут засинхронизироваться по битам, и обмен данными не получится. Имеется стандартный ряд скоростей baud rate: 4800, 9600, 19200, 28800, 38400 и т. д.

2.5. События ошибки (Error Conditions)

В процессе передачи данных могут произойти ошибки разного вида. Если скорости baud rate слишком отличаются между двумя устройствами, то они будут рассинхронизированы. Поскольку baud rate зависит от таковой частоты ядра AVR, эта проблема может возникнуть, если реальная тактовая частота отличается от той, которая нужна. К примеру, если используется внутренний тактовый генератор (internal RC oscillator), то рекомендуется его откалибровать перед началом использования UART. Пожалуйста обратитесь к соответствующим апноутам, чтобы узнать, как калибровать внутренний RC-генератор.

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

Если шумовой импульс помех принудительно переведет линию сигнала в лог. 0, то AVR определит спад сигнала и начнет прием. Если детектировано начало стартового бита, но он оказался ненулевым, то AVR остановит прием и не сохранит никаких данных, но если импульс шума оказался длиннее нескольких циклов тактовой частоты, то будет принят и сохранен неправильный байт (который на самом деле никто не передавал).

Шум может также исказить фрейм и во время передачи. Так как состояние бита выбирается только один раз, то фрейм может быть принят с ошибкой, если импульс шума пришелся на момент считывания приемником состояния сигнальной линии. Для определения наличия таких ошибок может помочь добавление к фрейму UART бита четности (parity bit), при этом гарантированно могут быть зарегистрированы только одиночные ошибки фрейма.

Поскольку для работы UART используются прерывания, то основной код программы (код приложения, который выполняется в главном цикле main) может выполняться «параллельно», вместе с обменом UART. Имейте в виду, что поскольку AVR не поддерживает приоритетов прерываний, то другие активные источники прерываний могут повлиять на UART (к примеру, не будут точно вычисляться интервалы битов), и это может привести к ошибкам в обмене данными.

Рекомендуется использовать UART в обмене точка-точка, когда одно устройство является главным, другое подчиненным (так называемая конфигурация master/slave). Тогда slave будет передавать данные только тогда, когда их запросил master. Это предотвратит ситуации, когда оба устройства передают в одно и то же время. Если slave находится в состоянии ошибки, то он может сигнализировать об этом для master, если притянет сигнальную линию UART к лог. 0 на заданное время. Тогда будет установлен флаг ошибки master, и обмен будет продолжен только тогда, когда slave прекратит удерживать линию с состоянии лог. 0.

Прим. переводчика: схема обмена master/slave часто используется даже в физически полнодуплексных системах, когда для передачи и приема используются отдельные сигналы TX и RX. Это делается с целью упрощения логики протокола обмена, и позволяет проще синхронизировать высокоуровневое состояние обменивающихся данными устройств. В частности, принцип master/slave используется в последней версии протокола STK500, а также это основной принцип работы шины USB.

[3. Реализация]

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

3.1. Установка скорости Baud Rate

Для генерации интервалов времени, используемых при выборке бит приема и при формировании интервалов передаваемых бит, используется прерывание сравнения содержимого таймера с предустановленным значением (timer compare interrupt). Таймер настраивается в режим очистки при совпадении сравнения, режим Clear Timer on Compare (CTC), и на это событие настраивается прерывание. Это прерывание срабатывает, когда содержимое счетчика таймера уравнивается с содержимым регистра сравнения (output compare register). Время между каждым таким прерыванием зависит от системной тактовой частоты ядра, настройки предделителя тактовой частоты таймера (коэффициента деления прескалера), и от значения, записанного в регистр сравнения (compare register), как это показано в Формуле 3-1. Установка compare value в значение 10 приведет к генерации длительности между прерываниями в 11 тиков. Настройки скорости UART (Baud rate) устанавливаются в хедере UART, файле single_wire_UART.h.

Формула 3-1. Вычисление скорости передачи (Baud Rate).

Формула 3-2. Вычисление значения для регистра совпадения.

Пояснения к формулам: «System Clock» означает тактовую частоту системы в Гц. «One Period Compare Setting» — значение, записанное в регистр сравнения таймера (output compare register). «Timer Prescaler» — коэффициент деления прескалера. «One Period Compare Setting» — значение для регистра сравнения, которое определяет период срабатывания обработчика таймера, что задает длительность бита UART.

Таблица 3-1. Установка периода бита UART для частоты тактового генератора 1, 2, 4 и 8 МГц.

Baud
Rate
(bps)
1 МГц 2 МГц
OPS PS Error OPS PS Error
4800 207 1 -0.16% 51 8 -0.16%
9600 103 1 -0.16% 207 1 -0.16%
19200 не реализовано 103 1 -0.16%
4 МГц 8 МГц
4800 103 8 -0.16% 207 8 -0.16%
9600 51 8 -0.16% 103 8 -0.16%
19200 207 1 -0.16% 51 8 -0.16%
28800 138 1 0.08% 34 8 0.82%
38400 103 1 -0.16% 207 1 -0.16%

Пояснения к таблице: OPS означает One Period Settings (One Period Compare Settings, значение регистра сравнения таймера, от которого зависит длительность между срабатываниями прерываний таймера и вызовами обработчика Timer_Compare_SW_UART_ISR), PS означает Prescaler Setting (коэффициент деления прескалера), Error означает погрешность полученной реальной скорости UART в процентах (по отношению к требуемой стандартной скорости).

В таблице 3-1 показаны установки таймера для некоторых стандартных скоростей передачи, а также получающаяся погрешность установленной скорости. Погрешность установки скорости скорости (Error) вычисляется по формуле 3-3.

Формула 3-3. Вычисление ошибки установки скорости UART.

Пояснения к формуле: Error[%] — погрешность установки скорости, насколько скорость отличается от стандартной. Baud RateClosest Match — скорость UART по стандарту. Baud Rate — полученная по формуле 3-1 реальная скорость.

Имейте в виду, что максимальная скорость UART, которую реально можно получить, зависит от тактовой частоты ядра AVR и от его загруженности другими вычислениями (кодом, который должен выполняться в других прерываниях и в главном цикле main). Если превысить эту скорость, то UART перестанет работать, и основная программа также практически перестанет выполнять свои функции. Так происходит потому, что выполнение обработчика прерывания таймера не успеет завершиться, как таймер снова досчитает до значения регистра сравнения, и произойдет новое прерывание. Максимально допустимое количество циклов, которое может быть выполнено в прерывании compare interrupt, составляет около 100..110, и зависит от настроек компилятора. На практике использование тактовой частоты ядра 1 МГц дает максимально возможную скорость UART около 10000 бит/сек (бод). При этой скорости все время выполнения CPU будет израсходовано только на обработку UART, и на остальные задачи практически циклов не останется. Основной код приложения (действия, которые прокручиваются в основном цикле main) должен иметь некоторое время на обработку принятых данных до того, как поступит новый битовый фрейм, иначе произойдет ошибка переполнения, и некоторые данные на приеме будут потеряны. Поэтому рекомендуется установить скорость обмена UART несколько ниже предельно допустимой для заданной частоты ядра, в зависимости от требований к коду основного приложения.

Формула 3-4. Максимально допустимая скорость обмена программного UART.

Пояснения к формуле: Baud Rate — полученная по формуле 3-1 реальная скорость. System Clock — тактовая частота, на которой работает AVR. Maximum Cycles in Compare Interrupt — максимальная длительность выполнения обработчика прерывания сравнения таймера в циклах ядра.

3.2. Аппаратура, на которой реализован UART (Hardware)

В этой реализации шина данных UART разработана в расчете на использование внешнего верхнего нагрузочного резистора (pull-up). Таким образом, должны использоваться ножки ввода вывода (I/O, GPIO) с открытым коллектором (открытым стоком). Дополнительно нужно использовать вешнее прерывания для детектирования начала приходящего битового фрейма.

Типичное значение нагрузочного резистора pull-up микроконтроллера AVR составляет 15..40k?. Когда отправляется бит с высоким логическим уровнем, или когда происходит прием, то порт AVR для данных UART находится в третьем состоянии (настроен как вход с отключенным внутренним нагрузочным резистором). Бит с низким логическим уровнем отправляется путем конфигурирования порта как выхода с выведенным в порт лог. 0.

Если требуется обмен данными по физическому каналу стандарта RS-232, то необходимо приведение уровня сигнала UART к значениям -12..-15V (соответствует лог. 1) и +12..+15V (соответствует лог. 0). Для этого нужна специальная схема, которая делает инверсию, и приводит уровни сигнала к нужным значениям. Например, можно использовать специальный чип интерфейса MAX232 компании Maxim. Он работает от одного напряжения питания 5V, и имеет встроенный преобразователь напряжения DC/DC, чтобы генерировать стандартные уровни RS-232.

Прим. переводчика: можно также использовать преобразователь с гальванической изоляцией на основе оптронов [2].

3.3. Регистр состояния (Status register)

Регистр состояния однопроводного UART содержит следующие 4 флага: SW_UART_TX_BUFFER_FULL, SW_UART_RX_BUFFER_FULL, SW_UART_RX_BUFFER_OVERFLOW, SW_UART_FRAME_ERROR.

SW_UART_TX_BUFFER_FULL устанавливается, если данные TX готовы к передаче. Этот флаг должен быть обнулен, когда вызывается функция SW_UART_transmit.

SW_UART_RX_BUFFER_FULL устанавливается, если в приемном буфере есть необработанные принятые данные. Этот флаг должен установиться в лог. 1, когда вызывается функция SW_UART_Receive.

SW_UART_RX_BUFFER_OVERFLOW устанавливается, когда приходящие данные потеряны из-за переполнения буфера приема (новый прием начался, но ранее принятые данные не были обработаны).

SW_UART_FRAME_ERROR устанавливается, если неожиданно обнаружена лог. 1 в стартовом бите (на самом деле стартовый бит должен быть всегда нулевым), или если обнаружен лог. 0 в стоповом бите (стоповый бит должен быть всегда в лог. 1). Также устанавливается, когда при передаче считанный бит отличается от того, что был передан.

Чтобы уменьшить размер кода, регистр состояния может быть помещен в регистр GPIO, если это доступно (это нельзя сделать для ATmega32).

3.4. Счетчик UART

Переменная счетчика используется в коде драйвера UART, чтобы управлять состоянием, и какой бит принимается/передается через UART. UART переходит в состояние ожидания, когда значение счетчика равно 0. Значение счетчика является четным при передаче и нечетным при приеме, как показано на рис. 3-1.

Рис. 3-1. Значения счетчика UART.

3.5. Функции UART

Драйвер состоит из трех глобальных функций (описание функций см. далее):

SW_UART_status является глобальной переменной, которая удерживает флаги состояния UART (см. раздел 3.3). Макросы SET_FLAG, CLEAR_FLAG и READ_FLAG, определенные в хедере single_wire_UART.h, можно использовать для получения доступа к флагам.

В реализации UART используются также следующие обработчики прерывания:

Перед тем, как данные могут быть приняты или переданы через UART, он должен быть разрешен вызовом функции SW_UART_Enable. Он переводит ножку UART в состояние ожидания (при этом на выходе получается высокий уровень благодаря внешнему pull-up резистору). Регистр состояния и счетчик очищаются, так что исходящие передачи, если они работали, будут остановлены. Запрет внешнего прерывания и прерывания таймера остановят работу UART.

Рис. 3-2. Алгоритм работы функции SW_UART_Enable().

Функция SW_UART_Transmit() получает 1 байт в качестве параметра и добавляет этот байт в буфер передачи. Когда вызывается эта функция, то флаг SW_UART_TX_BUFFER_FULL должен быть очищен (его должен очищать внешний код передачи байт), иначе зарегистрируется потеря данных. Если передача данных не происходит, когда вызывается эта функция, то запустится новая передача путем отправки стартового нулевого бита и разрешения работы прерывания таймера.

Рис. 3-3. Алгоритм работы функции SW_UART_Transmit().

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

Рис. 3-4. Алгоритм работы функции SW_UART_Receive().

Обработчик внешнего прерывания External_SW_UART_ISR() будет вызван при детектировании спада уровня сигнала данных UART, когда нет выполняющихся операций передачи или приема. Обработчик проверяет, что ножка вывода данных UART находится в лог. 0. Если это не так, то прием не запускается. После начала приема фрейма запрещаются дальнейшие внешние прерывания, так что последующие спады уровня не вызовут повторного срабатывания внешнего прерывания с новым вызовом обработчика External_SW_UART_ISR. Таким образом, External_SW_UART_ISR используется только для детектирования стартового бита фрейма.

Рис. 3-5. Алгоритм работы обработчика прерывания External_SW_UART_ISR().

Обработчик прерывания по совпадению таймера Timer_Compare_SW_UART_ISR() (моменты срабатывания таймера показаны стрелочками на рис. 3-1) управляет обработкой передачи и приема битового фрейма. Он вызывается автоматически, когда значение регистра сравнения (output compare) уравнивается со значением аппаратного счетчика таймера, и когда разрешено прерывание таймера. На передаче счетчик UART начинает считать с четного значения (2, 4, . ), а на приеме с нечетного значения (1, 3, . Не путайте счетчик UART со аппаратным счетчиком таймера). Обработчики приема (рис. 3-8) и передачи (рис. 3-7) реализованы напрямую в обработчике прерывания таймера. Пожалуйста обратитесь к рис. 3-1 для подробностей по поводу разных значений счетчика.

Рис. 3-6. Алгоритм работы обработчика прерывания Timer_Compare_SW_UART_ISR().

Рис. 3-7. Обработчик передачи UART_Transmit_Handler().

Рис. 3-8. Обработчик приема UART Receive Handler().

3.6. Программа примера

Модуль main.c содержит код программы примера для тестирования софтового однопроводного UART. Он принимает данные в массив байт, и передает эти данные обратно, когда массив заполнится, или когда будет принят символ возврата каретки ‘n’.

3.7. Размер кода

При компиляции с использованием IAR® EWAVR 4.21A, с включенной оптимизацией по скорости по максимуму, размер кода драйвера UART занимает около 500 байт.

[4. Указания по быстрому старту]

Источник

Adblock
detector

  • proteus

  • avr

  • max485

  • uaert

  • rx frame error


davemaks

  • Ответить

  • Создать новую тему

Рекомендуемые сообщения

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже.

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

Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

  • Последние посетители

      0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Сообщения

    • Black-мур

      Автор

      Black-мур · Опубликовано 6 минут назад

      Вряд ли, это нормальная реакция нормального человека, способного защищаться. Но меня, к примеру(только с меня пример брать не нужно ) только за намёк-упоминание об этом иногда в бане запирают. Хорошо ещё, что находятся адекватные, трезвомыслящие люди и выпускают. 

    • IvanTikh

      Автор

      IvanTikh · Опубликовано 10 минут назад

      вот нарисовал еще, это 2 секции первички на каркасе(как мы на него смотрим, и как расположились выводы обмотки), как соединить правильней, лучше, и т.д., для триода se? 2ой вывод с каким?

    • vrytsev

    • Alex Ferrum

      Автор

      Alex Ferrum · Опубликовано 17 минут назад

      @IMXO и что, что я этот вопрос задавал. Если уж собрались симулировать схемы нужно реальные параметры задавать, а не такие что при которых на 60-120 ваттном двигателе рассеиваться аж 2 киловатта.

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

    • Black-мур

    • Aknod

    • ВасяШпунт

      Автор

      ВасяШпунт · Опубликовано 20 минут назад

      Здравствуйте уважаемые!

      Оплатил я 2 шт. ТВЗ 80 Ростову «66 д.0.8 1300 д.0.281300 д.0.28 33 +33 д.0.8.   66+33 =8 ом   66+33+33=16 ом.»  (они ближе). Пока едут решил шасси доделать, наждак и грунтовка — вот результат. Хочу вишнёвый металлик.

  • Похожий контент

    • Deerael

      0

      Автор

      Deerael
      Started 11 часов назад

    • Super Akk

    • Super Akk

    • Super Akk

    • lollik68

      1

      Автор

      lollik68
      Started 11 ноября, 2022

Blekzet

4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

1

18.11.2019, 15:03. Показов 4005. Ответов 18

Метки нет (Все метки)


Собственно у меня вообще отказываются работать прерывания с USART

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// UART на ATmega16
#define F_CPU 8000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
volatile int count = 0;
volatile unsigned char data;
 
 
void USARTInit(unsigned int ubrr) {
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)(ubrr);
    
    UCSRB = 0b11011000;
    UCSRC = 0b10000110;
}
 
ISR(USART_RXC_vect){
    while(!( UCSRA & (1 << RXC)));
    data = UDR;
    UDR = data;
}
 
int main(void) {
    USARTInit(MYUBRR);
    sei();
}

Вот такой простенький код, не хочет работать (собираю на AtmelStudio 7, симулирую в протеусе 7.7)

Добавлено через 36 минут
И еще добавлю, что все настроено нормально(вроде), если делать без прерываний, все работает.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



liv

Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 15:13

2

Blekzet, два вопроса:
1)

Assembler
1
while(!( UCSRA & (1 << RXC)));

лишнее. Вы же работаете по прерыванию, а не по опросу.
2) если разрешены прерывания по передаче, то где вектор отработки передачи?
По-умолчанию там стоит jmp на себя.
В принципе, для Вашей програмы вполне достаточно

Assembler
1
UCSRB = 0b10011000;



0



Blekzet

4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:20

 [ТС]

3

да там такая же история, тишина

C
1
2
3
4
5
6
7
ISR(USART_RXC_vect){
    data = UDR;
}
 
ISR(USART_TXC_vect){
    UDR = data;
}

Добавлено через 1 минуту
liv, хотя скорее тут чет не то делаю…



0



liv

Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:22

4

Ничего не надо делать.

C
1
ISR(USART_TXC_vect){};



0



Blekzet

4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:24

 [ТС]

5

liv, тишина….

C
1
2
3
4
5
6
ISR(USART_RXC_vect){
    data = UDR;
    UDR = data;
}
 
ISR(USART_TXC_vect){}



0



Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:25

6

Blekzet, а запретить прерывания по передаче не пробовал?



0



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:25

 [ТС]

7

liv, так тоже тишина



0



Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:27

8

Blekzet, еще момент, рассказывай, какие фьюзы



0



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:27

 [ТС]

9

liv, 1111



0



Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:29

10

Хотя, если по опросу работает… Хм, интересненько…

Добавлено через 1 минуту

Цитата
Сообщение от Blekzet
Посмотреть сообщение

1111

Расшифруй. Я Протеусом не пользуюсь. Работаю всегда только с железом



0



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:38

 [ТС]

11

liv, Ext. Crystal/Resonator High Freq.; Start-up time: 16K CK + 64 ms; [CKSEL=1111 SUT=11]

Добавлено через 6 минут
liv, или так (внешнее тактирование от кварца 16 МГц) я просто не знаю, как понятнее будет, сам то с этим 2-3 дня работаю



0



Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:39

12

А в программе 8 МГц



0



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:42

 [ТС]

13

liv, разве? Я вроде все по методичке делал…



0



liv

Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 16:45

14

И даже не 8 МГц, а 800КГц !!!

C
1
#define F_CPU 8000000UL

А не, обознался… 8 МГц

Добавлено через 2 минуты
Если так, то скорость USART-а будет не 9600, а 19200



0



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 16:55

 [ТС]

15

liv, та же тишина…

Добавлено через 6 минут
liv, а нет, заметил замечания, протеус пишет что не та частота, поменял на 9600 и теперь норм (в консоли пусто, но замечаний нет)
(AVR USART RX Frame Error)



0



Модератор

Эксперт CЭксперт С++

5107 / 4538 / 854

Регистрация: 07.10.2015

Сообщений: 9,462

18.11.2019, 17:00

16

Лучший ответ Сообщение было отмечено Blekzet как решение

Решение

Blekzet, так все-таки, частота-то какая? 8 или 16МГц?

Добавлено через 2 минуты
Blekzet, стоп! А где бесконечный цикл в main()?



1



4 / 4 / 0

Регистрация: 21.12.2015

Сообщений: 195

18.11.2019, 17:00

 [ТС]

17

liv, 8, да

Добавлено через 48 секунд
liv, пхахахах, вот она где была проблема… боже… даже бы не подумал



0



BadNews_13

0 / 0 / 0

Регистрация: 11.01.2020

Сообщений: 2

11.01.2020, 20:53

18

Здравствуйте! Помогите понять как работают прерывания в USART.

Пишу код в Atmel Studio 7 для Atmega328p.

В функции putch() я отправляю байты в массив и разрешаю прерывание по опустошению регистра UDR.
Затем в этом векторе прерывания отправляю байт из массива в регистр UDR. Если байтов нет, то прерывание запрещаю.

Для теста отправляю в putch() переменную, которая увеличивается на 1 в бесконечном цикле.

Результат: Отправляется корректно только первые два байта, затем начинает проскакивать по десятку байтов и шлет например 15-й, а затем 28-й и т.д., но в какой-то момент (начиная с 133 байта) начинают приходить последовательные байты. Проверял в протеусе.

Дебажил в Atmel Studio — тот же результат. После 2-го байта прекращает заходить в прерывание (флаг опустошения регистра UDR не поднимается) UCSRA = 0 , а UCSRB = -8 (как так?). Но до 133 цикла я не дощелкал.

Ниже приведен код:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
void uart_ini(uint8_t _dipBaudRate, uint8_t _dipAdress)     // настройка UART
{
    main_rs485_address = _dipAdress;
    UART_BAUDRATE = _dipBaudRate*100;
    BAUD_PRESCALE = (((F_CPU / (UART_BAUDRATE * 16UL))) - 1);
 
    cli();
 
    UBRR0L =    BAUD_PRESCALE;          //Младшие 8 бит UBRRL_value
    UBRR0H =    (BAUD_PRESCALE >> 8);  //Старшие 8 бит UBRRL_value
 
    UCSR0A =    (0<<RXC0)|          // Bit - 7  RXC — флаг завершения приема, устанавливается в 1 при наличие непрочитанных данных в буфере приемник — UDR;
                (0<<TXC0)|          // Bit - 6  TXC — флаг завершения передачи, устанавливается в 1 при передачи всех разрядов из передатчика — UDR;
                (0<<UDRE0)|         // Bit - 5  UDRE — флаг опустошения регистра передатчика, устанавливается в 1 при пустом буфере передатчика — UDR после передачи;
                (0<<FE0)|           // Bit - 4  FE — флаг ошибки кадрирования, устанавливается в 1 при обнаружение неправильного кадра, когда стоп бит равен 0-лю
                (0<<DOR0)|          // Bit - 3  DOR —  флаг переполнения регистра приемника, устанавливается в 1, когда байт данных принят, а предыдущий еще не прочитан из UDR;
                (0<<UPE0)|          // Bit - 2  PE —  флаг ошибки контроля четности, устанавливается в 1 при обнаружение ошибки контроля четности (если включена проверка);
                (0<<U2X0)|          // Bit - 1  U2X — бит установки удвоенной скорости обмена, если установлена 1, то скорость передачи удваивается (частота делится на 8, а не на 16), данный бит используется только при асинхронном режиме работы;
                (0<<MPCM0);         // Bit - 0  MPCM — бит мультипроцессорного обмена, если установлена 1, то контроллер аппаратно не принимает информацию, а только кадры с адресами, далее устанавливается бит завершения приема (или прерывание) и программа обрабатывает адрес, её ли это адрес. Отличие информации от адреса определяется  с помощью 9-ого бита в режиме 9-и битового обмена.
    
    UCSR0B =    (1<<RXCIE0)|        // Bit - 7  RXCIE — бит разрешения прерывания по завершению приема, если установлена 1, то при установке флага RXC регистра UCSRA произойдет прерывание «прием завершен«;
                (1<<TXCIE0)|        // Bit - 6  TXCIE — бит разрешения прерывания по завершению передачи, если установлена 1, то при установке флага TXC регистра UCSRA произойдет прерывание «передача завершена«;
                (0<<UDRIE0)|        // Bit - 5  UDRIE — бит разрешения прерывания по опустошению регистра передатчика, если установлена 1, то при установке флага UDRE регистра UCSRA произойдет прерывание «регистр данных пуст«;
                (1<<RXEN0)|         // Bit - 4  RXEN — бит разрешения приема, при установки 1 разрешается работа приемника USART и переопределяется функционирование вывода RXD;
                (1<<TXEN0)|         // Bit - 3  TXEN —  бит разрешения передачи, при установки 1 разрешается работа передатчика USART и переопределяется функционирование вывода TXD;
                (0<<UCSZ02)|        // Bit - 2  UCSZ2 — бит формат посылок, данный бит совместно с битами UCSZ1 и UCSZ0 регистра UCSRC определяют количество бит данных в кадрах
                (0<<RXB80)|         // Bit - 1  RXB8 — 9-ый разряд принимаемых данных при использование 9-и битого режима, считывать из данного бита нужно до считывание регистра UDR;
                (0<<TXB80);         // Bit - 0  TXB8 — 9-ый разряд передаваемых данных при использование 9-и битного режима, записывать в данный бит нужно до записи в регистр UDR.
    
    UCSR0C =    (0<<UMSEL01)|       // Bit - 7  UMSEL1 — бит выбора режима Master SPI. Если 1 и UMSEL0 = 1 то режим Master SPI (MSPIM)
                (0<<UMSEL00)|       // Bit - 6  UMSEL0 — бит выбора режима асинхронный или синхронный, если установлен 1 — режим синхронный (т.е. с использованием линии синхронизации XCK), если 0 — режим асинхронный;
                (0<<UPM01)|         // Bit - 5  UPM1 — бит выбора режима проверки на четность/нечетность;
                (0<<UPM00)|         // Bit - 4  UPM0 — бит выбора режима проверки на четность/нечетность;
                (0<<USBS0)|         // Bit - 3  USBS — бит отвечающий за количество стоп-битов, если установлена 1 — два стоп-бита, если 0 — один стоп-бит;
                (1<<UCSZ01)|        // Bit - 2  UCSZ1 — совместно с битом UCSZ2 регистра UCSRB определяют количество бит данных в кадрах (см. таблицу выше);
                (1<<UCSZ00)|        // Bit - 1  UCSZ0 — совместно с битом UCSZ2 регистра UCSRB определяют количество бит данных в кадрах (см. таблицу выше);
                (0<<UCPOL0);        // Bit - 0  UCPOL — бит полярность тактового сигнала, при синхронном режиме определяет по какому фронту принимать/передавать данные – по спадающему или по нарастающему.
    sei();
}
 
void putch(uint8_t c)
{
    while (tx_counter == TX_BUFFER_SIZE);   
    cli();
    tx_buffer[++tx_counter] = c;
    UCSR0B |= (1<<UDRIE0);      // разрешаем прерывание по опустошению регистра UDR0
    sei();
}
 
ISR(USART_UDRE_vect)        // отправлять данные, если есть (вызывается, когда регистр пуст)
{
    if(tx_counter)
    {
        UDR0 = tx_buffer[tx_counter--];
    }
    else
    {       
        UCSR0B &= ~(1<<UDRIE0);         // запрещаем прерывание по опустошению регистра UDR0
    }
}

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
int main(void)
{
    uart_ini(48,13);    // скорость 4800, адрес 13
    sei();
    
    int i = 0;
 
while(1)
{
    putch(i++);     // для теста
    }
}

как скрины добавлять еще не разобрался, так что результат пока так покажу:

000001 20:14:55.746 00 01 1C 38 55 71 85 86 87 88 89 8A 8B 8C 8D 8E …8Uq…†‡€‰Љ‹ЊЌЋ
000002 20:14:55.746 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E Џђ‘’“”•–—˜™љ›њќћ
000003 20:14:55.774 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE џ ЎўЈ¤Ґ¦§Ё©Є«¬­®
000004 20:14:55.836 AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE Ї°±Ііґµ¶·ё№є»јЅѕ
000005 20:14:55.841 BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE їАБВГДЕЖЗИЙКЛМНО
000006 20:14:55.899 CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE ПРСТУФХЦЧШЩЪЫЬЭЮ
000007 20:14:55.960 DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE Яабвгдежзийклмно
000008 20:14:55.965 EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE прстуфхцчшщъыьэю
000009 20:14:56.024 FF 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E я……………
000010 20:14:56.085 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E …………….
000011 20:14:56.087 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E . !»#$%&'()*+,-.
000012 20:14:56.149 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E /0123456789:;<=>
000013 20:14:56.209 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E ?@ABCDEFGHIJKLMN
000014 20:14:56.213 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E OPQRSTUVWXYZ[]^
000015 20:14:56.272 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E _`abcdefghijklmn
000016 20:14:56.335 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E opqrstuvwxyz{|}~
000017 20:14:56.339 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋ
000018 20:14:56.395 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E Џђ‘’“”•–—˜™љ›њќћ
000019 20:14:56.458 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE џ ЎўЈ¤Ґ¦§Ё©Є«¬­®
000020 20:14:56.462 AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE Ї°±Ііґµ¶·ё№є»јЅѕ
000021 20:14:56.524 BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE їАБВГДЕЖЗИЙКЛМНО
000022 20:14:56.585 CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE ПРСТУФХЦЧШЩЪЫЬЭЮ
000023 20:14:56.590 DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE Яабвгдежзийклмно
000024 20:14:56.649 EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE прстуфхцчшщъыьэю
000025 20:14:56.708 FF 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E я……………
000026 20:14:56.709 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E …………….
000027 20:14:56.773 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E . !»#$%&'()*+,-.
000028 20:14:56.832 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E /0123456789:;<=>
000029 20:14:56.833 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E ?@ABCDEFGHIJKLMN
000030 20:14:56.898 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E OPQRSTUVWXYZ[]^
000031 20:14:56.957 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E _`abcdefghijklmn
000032 20:14:56.959 6F 70 71 72 73 opqrs

PS: Ожидание в цикле while (как в большинстве примеров) пока не освободиться регистр UDR работает без пропусков, но надо же делать как правильно, а не как будто это единственная задача контроллера.

PPS: предлагаю высказывания типа «Зачем мучиться? лучше купить готовое решение» прировнять к нецензурной лексике и наказывать баном.



0



0 / 0 / 0

Регистрация: 11.01.2020

Сообщений: 2

12.01.2020, 19:09

19

У меня максимальный размер буфера (TX_BUFFER_SIZE) равен 128. Соответственно когда он заполняется из-за того, что не попадаем в прерывание по опустошению UDR, тогда начинает работать цикл while в функции putch(), давая задержку по времени. Благодаря этой задержке начинают успевать улетать данные из UDR, и опять выполняется прерывание по опустошения, и как следствие получилась последовательная передача байт через ожидание в цикле (способ от которого нужно уйти).

Только что нашел ошибку: Когда UDR занят, то байты складываю в массив. А когда мы наконец попадаем в прерывание, то в UDR кладется

последний

байт из массива, а не следующий после

последнего отправленного

. Вот и теряется по 25 байтов (пока UDR опустеет и поднимется флаг моя программа успевает сделать примерно 25 циклов).

Но самые первые два байта нормально улетают. Возможно первый проваливается в UDR, а второй в сдвиговый регистр перед ним, поэтому сохраняется последовательность. Но это предположение.

PPS: предлагаю высказывания типа «Зачем мучиться? лучше купить готовое решение» прировнять к нецензурной лексике и наказывать баном.



0



Проблемы с UART. Frame error.

top Дата: Воскресенье, 25.11.2012, 03:14 | Сообщение # 1

Группа: Друзья

Статус: Offline

Уважаемые, выручайте. Это просто какой-то бич sad
Передаю из МК в ПК данные (текст и числа). МК тактируется от внутренних 8 Мгц, скорость 9600 Бод. Прошиваю через USB ASP, выставляю фьюзы как положено. Модуль на FT232RL. На компьютере получаю каракули, а не то что надо. В Terminal by Bray каракули и frame error, а в баскомовском терминале просто каракули. Терминалы тоже настроены на 9600 Бод, дата 8 бит, без четности, один стоповый бит, без хэндшейка.
Где искать косяк не знаю.

 
exersizze Дата: Воскресенье, 25.11.2012, 12:45 | Сообщение # 2

Группа: Администраторы

Статус: Offline

в самой программе прописано $crystal = 8000000 $baud=9600 ? Если да, попробуй выставить это и в настройке компилятора во вкладке Communication

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

 
top Дата: Воскресенье, 25.11.2012, 13:30 | Сообщение # 3

Группа: Друзья

Статус: Offline

В компиляторе выставляю как на твоем скрине, в самой программе прописываю.
Вот архив с программой.

 
top Дата: Воскресенье, 25.11.2012, 13:49 | Сообщение # 4

Группа: Друзья

Статус: Offline

Спасибо за предположение, что дело в железе. happy Оправдалось.
Вот так вот я понадеялся на новые контроллеры. Сейчас проверил. Из пяти mega8 в двух оказался дохлый uart. wacko
Больше из Китая не хочу заказывать.
Так из-за чего у них он не работает? Это брак?

Сообщение отредактировал topВоскресенье, 25.11.2012, 13:53

 
exersizze Дата: Воскресенье, 25.11.2012, 16:59 | Сообщение # 5

Группа: Администраторы

Статус: Offline

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

 

Avr usart rx frame error

UART (USART) обычно нужен для организации взаимодействия с внешним миром — чтобы передать микроконтроллеру какие-то команды и забрать у него данные. Или как минимум для отладки — чтобы понять, что происходит с Вашей программой.

Примечание: аббревиатура USART переводится как Universal Synchronous and Asynchronous serial Receiver and Transmitter (USART), т. е. последовательный порт может работать как синхронный (по внешнему тактовому сигналу), так и асинхронный (аппаратно формировать посылки бит по интервалам времени).

Запуск USART обычно состоит из следующих простых действий:

1. Создать буферы приема и передачи (типа FIFO, обычно кольцевые).
2. Написать код инициализации USART.
3. Написать обработчик прерывания приема символа из USART.
4. Написать обработчик передачи USART.
5. Перенаправление вывода printf в USART.

Рассмотрим каждую из этих операций. Все, что написано далее, может относиться во многом не только к микроконтроллеру ATmega2560, но и к любому AVR, который имеет на борту аппаратуру USART (или UART).

[1. Буферы приема и передачи USART]

Буферы приема и передачи нужны для того, чтобы упорядочить потоки входных и выходных данных в программе. На приеме обработчик прерывания нужен потому, что символ (байт) может прийти из внешнего мира асинхронно, т. е. в любой момент времени. Аппаратный буфер USART у AVR очень мал — всего лишь 2 байта.

Примечание: в микроконтроллере ATmega2560 буфер приема читается через регистр UDRn, где буква n меняется на номер используемого порта 0, 1, 2 или 3 (у ATmega2560 целых 4 последовательных порта USART: USART0, USART1, USART2 и USART3).

Следовательно, чтобы не потерять пришедшие данные, нужно как можно быстрее считать из буфера и обработать принятый байт, иначе следующий поступивший байт может затереть только что пришедший байт, и этот предыдущий байт может быть потерян (так называемый RX overrun).

Для быстрого считывания поступившего байта обычно используется обработчик прерывания приема USART. Буфер считывается из регистра UDRn и помещается в буфер, откуда он потом может быть выбран основной программой. Возникает вопрос: так зачем все-таки нужен буфер, почему нельзя сразу в обработчике прерывания предпринять какие-то действия, и обойтись без дополнительного буфера? Ответ прост: да, можно так сделать, но только для самых простых случаев, когда обработка байта не займет много времени, и когда не нужно производить дополнительных действий. Например, не получится обойтись без программного буфера, если поток входных данных соответствует какому-то протоколу, нельзя обрабатывать каждый байт по отдельности, нужно отслеживать таймауты в потоке входных байт и т. п. Такие сложные действия иногда нельзя возложить на обработчик прерывания, потому что они займут слишком много времени, и это повлияет на работоспособность всей программы в целом. Таким образом, обработчик приема может просто поместить принятый в буфер байт и быстро завершить свою работу. Опустошать буфер приема может основная программа, которая может быть довольно сложной и медлительной.

Буфер для передачи делают потому, что в одном действии программы обычно надо передать через USART не один байт, а сразу несколько. Например, нужно вывести приветствие printf(«Hello World!»), или какое-то диагностическое сообщение, состоящее из нескольких байт. Но USART может передавать только по одному байту, через аппаратный буфер регистра UDRn. Если аппаратный буфер не опустошился, т. е. если USART не успел еще передать только что записанный в UDRn байт, то нельзя в цикле без задержки писать все символы передаваемой строки в UDRn, иначе произойдет потеря данных при передаче (TX overrun). Чтобы не было непроизводительных потерь процессорного времени на циклы ожидания, делается программный буфер достаточного размера, куда программа может без задержки поместить все данные, которые надо передать. Опустошаться буфер передачи будет по одному байту — в основной программе и/или в обработчике прерывания опустошения буфера, по мере того, как аппаратура USART будет готова передать очередной байт.

Вот пример организации буферов передачи и приема USART (подробнее про кольцевые буферы см. [1]):

В этом примере размеры буферов приема и передачи выбраны одинаковыми, но это совершенно не обязательно. К размеру буферов передачи и приема есть два простых требования, которые зависят от того, как работает Ваша программа. Во-первых, размер буфера должен быть достаточно велик, чтобы он никогда не переполнялся. Это означает, что на приеме Вы всегда успеваете забрать и обработать поступающие данные до того, как буфер переполнится (т. е. данные поступают всегда медленнее, чем Вы их читаете и обрабатываете). Аналогично на передаче Вы не должны писать в буфер передачи слишком часто, буфер передачи должен успевать опустошаться кодом поддержки аппаратуры передачи USART. Во-вторых, есть требование, которое вытекает из примененного принципа обработки кольцевого буфера [1]: размер буфера должен быть равен степени 2, т. е. 2, 4, 8, 16, 32, 64 и т. д. Это требование не обязательное, если Вы согласны усложнить обработку индексов буфера, но имейте в виду, что усложнение кода обработки индексов замедлит обработку приема и передачи, и иногда такое замедление может оказаться недопустимым.

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

[2. Код инициализации USART]

В этом примере будем настраивать USART0, который используется в плате Arduino Mega 2560 [2] в качестве стандартного канала обмена с компьютером через USB. Параметры для настройки 115200 bps, 8 бит данных, без четности, 1 стоп-бит.

После сброса (перезагрузки) все регистры AVR, в том числе и регистры, которые устанавливаются в исходное состояние. Чтобы USART заработал как нужно, необходимо настроить биты его регистров (подробное описание регистров см. во врезке «Справочная информация по USART ATmega2560»):

UCSR0A.U2Xn бит двойной скорости передачи.
UCSR0A.MPCMn бит включения функции мультипроцессорного обмена.

Обе эти функции не нужны, поэтому в UCSR0A нужно записать 0.

Примечание: можно было бы этого и не делать, потому что после сброса регистр UCSR0A сам автоматически обнуляется. Однако сброс регистра UCSR0A в программе не помешает, он будет явно показывать, какая настройка порта USART используется.

UCSR0B.RXCIE0 разрешение прерывания приема. Мы будем использовать обработчик прерывания по наличию в буфере приема данных, поэтому этот бит нужно установить в 1.
UCSR0B.RXEN0 разрешение работы приемника, сюда нужно записать 1.
UCSR0B.TXEN0 разрешение работы передатчика, сюда нужно записать 1.
UCSR0B.UCSZ02 это один из 3 бит, который настраивает количество бит данных во фрейме. У нас размер данных фрейма 8 бит, по таблице 22-7 значение этого бита должно быть равно 0.

Остальные биты не нужны, поэтому они будут сброшены.

UCSR0C.UMSEL01 и UMSEL00 эти биты определяют режим работы USART. Нас интересует асинхронный режим, по таблице 22-4 значение этих бит должно быть нулевое.
UCSR0C.UPM01 и UPM00 эти биты определяют контроль четности. Нам он не нужен, поэтому по таблице 22-5 значение этих бит будет нулевое.
UCSR0C.USBS0 бит количества стоп-битов фрейма. У нас 1 стоп-бит, поэтому согласно таблице 22-6 значение этого бита нулевое.
UCSR0C.UCSZ00 и UCSZ01 эти биты совместно с битом UCSR0B.UCSZ02 определяют количество бит данных во фрейме. По таблице 22-7 значение бит UCSZ01 и UCSZ00 должно быть 11.
UCSR0C.UCPOL0 этот бит работает только в синхронном режиме, поэтому должен быть сброшен в 0.

Следовательно, в регистре UCSR0C нужно установить только биты UCSZ01 и UCSZ00:

UBRR0H , UBRR0L . Для этих регистров нужно по формуле рассчитать настройки для скорости (это 12-битный регистр UBRR0, доступ к которому дает пара регистров UBRR0H:UBRR0L). Поскольку у нас асинхронный режим, нет включенной двойной скорости, то наша формула будет следующей (см. таблицу 22-1):

16000000
UBRR0 = —————- — 1
16 * 115200

Получается, что значение для UBRR0 должно быть 7.68. Это дробное число, и его конечно же записать в регистры, поэтому число нужно округлить до ближайшего целого, получится 8.

Примечание: можно было бы воспользоваться таблицей 22-12, где есть готовое вычисленное значение UBRR для скорости 115.2K. Как следует из таблицы, для режима двойной скорости настройка получится точнее, в этом случае нужно записать в UBRR0 значение 16, и бит U2X0 в регистре UCSR0A нужно установить в 1:

Несмотря на то, что на двойной скорости настройка получается точнее, все равно не факт, что это будет работать лучше, потому что оцифровка бит RXD будет осуществляться не по 16 выборкам, а по 8 (см. подробное описание работы приемника во врезке «Справочная информация по USART ATmega2560»).

Примечание: после того, как будет разрешен приемник и передатчик установкой бит RXEN0 и TXEN0 соответственно, функционирование портов ввода/вывода PE0 и PE1 будет автоматически переназначено. Теперь они будут работать как вход приемника и выход передатчика USART.

[3. Обработчик прерывания приема USART]

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

Примечание: константу USART0_RX_vect можно подсмотреть в файле avrincludeavriomxx0_1.h тулчейна (это может быть WinAVR или тулчейн AVR-GCC, который устанавливается в составе Atmel Studio).

[4. Обработка передачи USART]

Обработка передачи будет простейшая: в главный цикл main будет вставлена процедура handlerTXUSART, проверяющая наличие данных в буфере передачи. Если данные в буфере передачи есть, и передатчик свободен, то из буфера передачи будет выбран байт и записан в регистр UDR0.

Минимальная настройка завершена. Все, что будет попадать в буфер передачи bufTX, будет выведено через USART0. Все, что поступит из внешнего мира, попадет в буфер приема bufRX. Само собой основной код должен использовать эту возможность, чтобы осуществлять обмен данными через USART, т. е. при необходимости нужно читать буфер приема и писать данные в буфер передачи. Все остальное будет происходить автоматически.

Что можно улучшить: если написать обработчик прерывания опустошения буфера передатчика, то можно ускорить передачу. В этом обработчике можно делать то же самое, что осуществляется в подпрограмме handlerTXUSART, за исключением того, что не нужно проверять флаг UDRE0, достаточно проверить только наличие данных в кольцевом буфере bufTX.

[5. Настройка printf на вывод через USART]

Перенаправление printf в USART нужно в основном чисто для удобства: чтобы проще выводить нужные отладочные (или какие-то другие) текстовые сообщения в какое-то устройство, где их можно отобразить и прочитать. Если для перенаправления используется USART (можно кстати использовать и другие устройства вывода текста, например экран LCD), то выводимые текстовые сообщения можно увидеть на компьютере в окне программы-терминала (например, putty, TerraTerm, HyperTerminal, Serial Monitor у Arduino IDE), подключенной к COM-порту, куда поступают данные от микроконтроллера (обычно это виртуальный COM-порт через соединение USB, как например это сделано у плат Arduino). Короче говоря, задача состоит в том, чтобы текст, который выводится оператором printf, сразу попадал в консоль программы терминала.

Описание решения этой задачи подробно описано в [4], здесь я просто кратко покажу что нужно сделать. Вывод в USART через printf с использованием библиотек avr-libc настраивается за 3 простых шага (последний шаг необязательный):

1. Подключить заголовочный файл stdio.h.

2. Определить функцию, которая будет выводить символ в UART (в этом примере функция uart_putchar).

3. (Необязательно) опциями линкера выбрать вариант обработки преобразований формата printf.

Здесь настраивается поток mystdout, который привязывается к функции вывода символа и стандартному потоку вывода stdout.

Если пропустить шаг 3, то оператор printf будет работать с ограничениями при обработке формата для чисел с плавающей запятой (подробнее про это и про опции настройки линкера см. [4]).

Как уже упоминалось, у ATmega2560 имеется 4 последовательных порта USART: USART0, USART1, USART2 и USART3, которые фиксировано привязаны к определенным ножкам корпуса микроконтроллера. Т. е. определенный вывод микроконтроллера может работать либо просто как порт ввода/вывода, либо как аппаратный вход или выход интерфейса USART. Все зависит от программной настройки — данных, которые Вы запишете в управляющие регистры микроконтроллера. В таблице и на картинке показана привязка аппаратуры USART к выводам микроконтроллера.

Имя Прерывания Регистры Порты RXD, TXD, XCK
USART0 UDRE0, TXC0, RXC0 UDR0, UCSR0A, UCSR0B, UCSR0C, UBRR0L, UBRR0H PE0, PE1, PE2
USART1 UDRE1, TXC1, RXC1 UDR1, UCSR1A, UCSR1B, UCSR1C, UBRR1L, UBRR1H PD2, PD3, PD5
USART2 UDRE2, TXC2, RXC2 UDR2, UCSR2A, UCSR2B, UCSR2C, UBRR2L, UBRR2H PH0, PH1, PH2
USART3 UDRE3, TXC3, RXC3 UDR3, UCSR3A, UCSR3B, UCSR3C, UBRR3L, UBRR3H PJ0, PJ1, PJ2

Порты USART обладают следующими основными возможностями:

• Поддерживают полный дуплекс (имеют независимые аппаратные буферы приема и передачи).
• Могут работать асинхронно и синхронно.
• В синхронном режиме могут либо вырабатывать такты, либо использовать внешнее тактирование (Master or Slave Clocked Synchronous Operation).
• Генератор скорости передачи, настраиваемый с высокой точностью (High Resolution Baud Rate Generator).
• Поддерживает размеры фрейма передачи из 5, 6, 7, 8 или 9 бит данных и 1 или 2 стоповых бита.
• Аппаратная поддержка генерации и проверки на нечетность или четность (Odd or Even Parity).
• Детектирование потери данных на приеме (Data OverRun Detection).
• Детектирование ошибок фрейма (Framing Error Detection).
• Фильтрация помех (Noise Filtering) с помощью цифрового ФНЧ, включающая детектирования ошибочного стартового бита.
• 3 отдельных прерывания по событиям TX Complete, TX Data Register Empty и RX Complete.
• Режим обмена с несколькими процессорами (Multi-processor Communication Mode).
• Асинхронный режим с двойной скоростью (Double Speed Asynchronous Communication Mode).

Для уменьшения общего энергопотребления кристалла ненужные USARTn могут быть полностью выключены с помощью битов управления регистров PRR0 и PRR1.

Порт USART0 используется в платах Arduino Mega 2560 [2] под аппаратный мост USB-UART, чтобы обеспечить работу загрузчика кода и поддержку отладочного вывода через Serial Monitor.

Рис. 22-1. Блок-диаграмма внутреннего устройства USART.

На диаграмме пунктирными линиями выделены 3 отдельных блока USART (перечисленные далее сверху вниз): Clock Generator (тактовый генератор), Transmitter (передатчик) и Receiver (приемник). Регистры управления общие для всех этих блоков. Логика Clock Generation состоит из логики синхронизации для внешних тактов (SYNC LOGIC, используется в подчиненном режиме для синхронизации передачи бит), и генератора скорости передачи (BAUD RATE GENERATOR). Вывод XCKn (такты передачи) используется только для синхронного режима работы (synchronous transfer mode). Передатчик состоит из одиночного буфера записи (UDR), последовательного регистра сдвига (TRANSMIT SHIFT REGISTER), генератора четности (PARITY GENERATOR) и логики управления (TX CONTROL) для поддержки разных форматов фрейма. Наличие аппаратного буфера фрейма позволяет вести непрерывные передачи без задержек между отдельными фреймами. Приемник наиболее сложный узел USART, потому что он имеет узлы восстановления тактов (CLOCK RECOVERY) и данных (DATA RECOVERY), которые используются для асинхронного приема данных. В дополнение к узлам восстановления приемник содержит блок проверки на четность (PARITY CHECKER), логику управления (RX CONTROL), регистр сдвига и двухуровневый буфер приема (UDR). Приемник поддерживает одинаковый формат фрейма, который использует передатчик, и может детектировать ошибку фрейма (Frame Error), событие потери данных на приеме (Data OverRun) и ошибку четности (Parity Error). Модуль PIN CONTROL управляет поведением порта микроконтроллера — или этот вывод работает как обычный порт ввода/вывода GPIO, или он подключен к аппаратуре USART и выполняет специальную функцию.

[Генерация тактов]

Логика генерации тактов синтезирует базовую частоту синхронизации для передатчика и приемника. The USARTn поддерживает 4 режима тактирования: нормальный асинхронный (Normal asynchronous), асинхронный двойной скорости (Double Speed asynchronous), синхронный главный (Master synchronous) и синхронный подчиненный (Slave synchronous). Бит UMSELn в USART Control and Status Register C (UCSRnC) выбирает между асинхронным и синхронным режимами. Двойная скорость (применимо только к асинхронному режиму) управляется битом U2Xn, находящемся в регистре UCSRnA. Когда используется синхронный режим (UMSELn = 1), регистр направления данных (Data Direction Register, DDR) для вывода XCKn определяет, каким будет тактирование для синхронного режима: внутренним (Master mode) или внешним (Slave mode). Вывод XCKn активен только в при использовании синхронного режима, в асинхронном режиме он работает как простой порт GPIO.

Рис. 22-2. Блок-диаграмма логики генерации тактов USART.

txclk такты передатчика (внутренний сигнал).
rxclk базовые такты передатчика (внутренний сигнал).
xcki ввод от вывода XCK (внутренний сигнал). Используется для работы в синхронном подчиненном режиме (synchronous slave operation).
xcko выходной сигнал тактов для подачи на вывод XCK (внутренний сигнал). Используется для работы в синхронном подчиненном режиме (synchronous master operation).
fOSC частота вывода XTAL (System Clock, системная частота).
DDR_XCK разряд регистра DDRX, управляющий направлением работы ножки порта (вход или выход).

Baud Rate Generator, внутренняя генерация тактов. Генерация тактов внутри чипа используется для асинхронного и синхронного режимов работы. USART Baud Rate Register (UBRRn) и считающий вниз счетчик (Prescaling Down-Counter) подключены к программируемому прескалеру, или другими словами к генератору скорости передачи (Baud Rate Generator). Обратно-считающий счетчик (down-counter), работающей на системной частоте (fOSC), каждый раз загружается значением из UBRRn, когда счетчик достигает нуля, или когда записан регистр UBRRLn. В этот момент генерируется тактовый импульс для USART, появляющийся на выходе Baud Rate Generator (= fOSC/(UBRRn+1)). Передатчик делит выходную тактовую частоты Baud Rate Generator на 2, 8 или 16 в зависимости от режима. Выход Baud Rate Generator напрямую используется для тактирования приемника и узлов восстановления данных. Однако узлы восстановления используют машину состояний из 2, 8 или 16 состояний в зависимости от режима, установленного битами UMSELn, U2Xn и DDR_XCKn.

Таблица 22-1 содержит выражения для вычисления скорости baud rate (в битах на секунду) и для вычисления значения UBRRn для каждого режима работы, когда используется генерируемый внутри источник тактов.

Табл. 22-1. Формулы для расчета скорости и настроек в зависимости от режима.

Режим Скорость (1) UBRR
Асинхронный нормальный (U2XN = 0) fOSC
BAUD = ————————
16 * (UBRRn+1)
fOSC
UBRRn = —————- — 1
16 * BAUD
Асинхронный двойной скорости (U2XN = 1) fOSC
BAUD = ————————
8 * (UBRRn+1)
fOSC
UBRRn = ————— — 1
8 * BAUD
Синхронный главный fOSC
BAUD = ————————
2 * (UBRRn+1)
fOSC
UBRRn = ————— — 1
2 * BAUD

Примечание (1). Скорость передачи определена как скорость следования бит в секунду (baud rate, bit per second, bps).

BAUD Baud rate (в битах/сек, bps).
fOSC системная тактовая частота (System Oscillator clock frequency).
UBRRn содержимое регистров UBRRHn и UBRRLn (0-4095).

Некоторые примеры значений UBRRn для разных тактовых частот микроконтроллера можно найти в таблице 22-9.

Double Speed Operation (U2Xn). Скорость передачи может быть удвоена (это пошло еще от микроконтроллеров серии MCS51) путем установки бита U2Xn в регистре UCSRnA. Установка этого бита дает эффект только для асинхронной работы USART, сбросьте этот бит в 0 для синхронного функционирования.

Установка бита U2Xn уменьшит коэффициент деления синтезатора скорости с 16 до 8, что соответствует удвоению скорости передачи и приема для асинхронного режима. Имейте в виду, что приемник в этом случае будет делать в 2 раза меньше выборок при восстановлении данных и тактов (количество выборок также уменьшиться с 16 до 8), так что для удвоения скорости с сохранением точной установки скорости понадобится более точно выдерживать системную частоту. Это важно для приемника, а для передатчика нет никаких проблем.

Внешнее тактирование. Используются в подчиненном синхронном режиме работы. Внешние такты поступают от вывода XCKn (см. рис. 22-2), и их значения выбираются регистром синхронизации, чтобы уменьшить шансы нестабильности. Выход регистра синхронизации затем должен поступить сначала на детектор перепада, перед тем как сигнал тактов можно было использовать в передатчике и приемнике. Этот процесс занимает два цикла системной тактовой частоты CPU, так что эта задержка ограничивает максимально возможную тактовую частоту XCKn:

fOSC
fXCK Примечание: эти функции передачи написаны только для примера. Они могут быть оптимизированы, если содержимое UCSRnB статическое. Например, после инициализации в регистре UCSRnB используется только бит TXB8.

9-й бит может использоваться для того, чтобы показать адрес фрейма в режиме обмена с несколькими процессорами (multi processor communication mode) или для другого протокола, например для синхронизации.

Флаги передатчика и прерывания. У передатчика USART есть 2 флага, которые показывают его состояние: USART Data Register Empty (UDREn) и Transmit Complete (TXCn). Оба флага можно использовать для генерации прерываний.

Флаг Data Register Empty (UDREn) показывает, готов или нет буфер передачи к записи туда новых данных. Этот бит устанавливается, когда буфер передачи опустошается, и очищается, когда буфер передачи содержит данные для отправки, которые еще пока не перемещены в регистр сдвига. Для совместимости с микроконтроллерами, которые возможно появятся в будущем, всегда записывайте этот бит в 0, когда записываете регистр UCSRnA.

Когда в бит Data Register Empty Interrupt Enable (UDRIEn) регистра UCSRnB записана 1, будет возможен запуск прерывания USART Data Register Empty, если установлен бит UDREn (подразумевается, что глобально прерывания разрешены).

UDREn очищается путем записи UDRn. Когда используется передача данных с управлением по прерываниям, подпрограмма прерывания Data Register Empty должна либо записать новые данные в UDRn, чтобы очистить UDREn, либо запретить прерывание Data Register Empty, иначе новое прерывание запустится после завершения обработчика прерывания.

Бит флага Transmit Complete (TXCn) устанавливается в 1, когда весь фрейм в регистре сдвига передачи будет выдвинут наружу, и в буфере передачи нет новых данных. Бит флага TXCn Flag автоматически очищается, когда запускается прерывание transmit complete, или этот флаг может быть очищен записью в него лог. 1. Флаг TXCn полезен при полудуплексном обмене (наподобие стандарта RS-485), где передающее приложение должно войти в режим приема и немедленно освободить шину обмена после завершения передачи.

Если бит Transmit Compete Interrupt Enable (TXCIEn) в регистре UCSRnB установлен, запустится прерывание USART Transmit Complete, когда установится флаг TXCn (подразумевается, что глобально прерывания разрешены). Когда используется прерывание transmit complete, обработчику прерывания не нужно очищать флаг TXCn, это автоматически произойдет, когда сработает прерывание.

Parity Generator. Генератор четности (Parity Generator) вычисляет бит четности для последовательного фрейма данных. Когда разрешен бит четности (UPMn1 = 1), логика управления передатчиком вставляет бит четности между последним битом данных и первым stop-битом отправляемого фрейма.

Запрет передатчика. Запрет передатчика (сброс TXEN в 0) не вступит в силу, пока происходит активная передача, т. е. пока регистр сдвига и регистр буфера передачи еще содержат данные для передачи. После того, как передатчик запрещен, но больше не будет переназначать вывод порта TxDn.

[Прием данных – USART Receiver]

Приемник USART разрешатся путем записи бита Receive Enable (RXENn) регистра UCSRnB в 1. Когда приемник разрешен, нормальная работа порта RxDn переназначается аппаратурой USART, и этот порт становится входом приемника для последовательных данных. Параметры baud rate, режима работы и формат фрейма должны быть установлены до того, как можно будет осуществлять любой прием. Если используется синхронный режим, то вывод XCKn будет использоваться как такты приема.

Прием фреймов длиной от 5 до 8 бит данных. Приемник начнет прием данных, когда детектирует допустимый start-бит. Каждый бит, который следует за стартовым, будет оцифровывается на скорости baud rate, или с тактами XCKn, и вдвигаться регистр сдвига, пока не будет принят первый stop-бит фрейма. Второй stop-бит будет приемником игнорироваться. Когда будет принят первый stop-бит, т. е. когда полный фрейм присутствует в регистре сдвига, то содержимое регистра сдвига будет перемещено в буфер приема. Буфер приема может быть прочитан через UDRn.

Следующий пример кода показывает простую функцию приема USART на базе опроса флага Receive Complete (RXCn). Когда используются фреймы размером меньше 8 бит, самый старший бит байта данных, прочитанного из UDRn, будет маскирован нулем. USART должен быть инициализирован перед использованием этой функции.

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

Прием фреймов длиной 9 бит данных. Если используются 9-битные символы (UCSZn=7), то 9-й бит должен быть прочитан из бита RXB8n регистра UCSRnB до чтения младших 8 бит из UDRn. То же самое правило действует и для флагов состояния FEn, DORn и UPEn. Сначала прочитайте состояние из UCSRnA, затем данные из UDRn. Чтение UDRn по его адресу I/O поменяет состояние приемного буфера FIFO и следовательно поменяется состояние битов TXB8n, FEn, DORn и UPEn, которые все сохраняются в FIFO.

Следующий пример кода покажет простую функцию приема USART, которая обрабатывает как 9-й бит, так и биты статуса.

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

Флаг и прерывание Receive Compete. У приемника USART есть 1 флаг, который показывает состояние приемника. Флаг Receive Complete (RXCn) показывает, что в буфере приема есть не прочитанные данные. Этот флаг равен 1, когда не прочитанные данные есть в буфере приема, и 0, когда буфер приема пуст (т. е. в нем не содержится никаких не прочитанных данных). Если приемник запрещен (RXENn = 0), буфер приема сбрасывается, и следовательно флаг RXCn обнуляется.

Когда установлен бит Receive Complete Interrupt Enable (RXCIEn) в регистре UCSRnB, выполнится прерывание USART Receive Complete, когда флаг RXCn установится (подразумевается, что глобально прерывания разрешены). Когда работает прием данных по прерываниям, то подпрограмма обработчика прерывания Receive Complete должна прочитать принятые данные UDRn, чтобы очистить флаг RXCn, иначе после завершения работы обработчика прерывания снова запуститься тот же обработчик прерывания.

Флаги ошибок приемника. У приемника USART есть 3 флага ошибки: Frame Error (FEn), Data OverRun (DORn) и Parity Error (UPEn). Все биты ошибок доступны через чтение UCSRnA. Общим для флагов ошибок является то, тчо они размещены в буфере приема вместе с данными фрейма, для которого флаги ошибок показывают состояние (т. е. буферизация данных фрейма привязана к буферизации флагов ошибки). По этой причине сначала нужно прочитать UCSRnA, и только потом буфер данных приема (UDRn), поскольку чтение UDRn по его месту размещения I/O освободит буфер под новые данные. Еще флаги ошибок объединяет то, что их нельзя сбросить программно записью. Однако для обеспечения совместимости с изменениями в USART, которые возможно появятся в будущем, все флаги должны быть сброшены в 0, когда осуществляется запись UCSRnA. Флаги ошибки не могут генерировать прерывание.

Флаг Frame Error (FEn) показывает состояние первого stop-бита принятого фрейма, находящегося в буфере приема. Флаг FEn равен 0, если stop-бит был прочитан правильно (как 1), и флаг FEn будет в 1, когда stop-бит ошибочен (равен 0). Этот флаг может использоваться для детектирования событий выхода из синхронизации, событий остановки потока (break conditions) и поддержки обработки протокола. На флаг FEn не влияет настройка бита USBSn в регистре UCSRnC, поскольку приемник игнорирует все stop-биты, кроме первого. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда сбрасывайте этот бит в 0, когда записываете UCSRnA.

Флаг Data OverRun (DORn) показывает потерю данных, из-за того, что у буфере приемника были не прочитанные данные. Data OverRun произойдет, когда буфер приема заполнен (в нем находится 2 символа), ожидается прием следующего символа, и детектирован новый start-бит. Если флаг DORn установлен, то была потеря одного или большего количества фреймов между последним чтением и следующим чтением фрейма из UDRn. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда записывайте этот бит в 0, когда записываете UCSRnA. Флаг DORn очищается, когда принятый фрейм успешно перемещен из регистра сдвига в буфер приема.

Флаг ошибки четности Parity Error (UPEn) показывает, что следующий фрейм, находящийся в буфере приема, имеет ошибку четности на приеме. Если контроль четности не разрешен, то бит UPEn будет всегда читаться как 0. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда сбрасывайте этот бит в 0, когда пишете в UCSRnA.

Узел проверки бита четности (Parity Checker) активен, когда установлен в 1 бит USART Parity mode (UPMn1). Тип выполняемой проверки на четность (нечетность odd или четность even) выбирается битом UPMn0. Когда проверка четности разрешена, Parity Checker вычисляет четность от бит данных приходящих фреймов, и сравнивает результат с битом четности из последовательного фрейма. Результат проверки сохраняется в буфере приема вместе с принятыми данными и stop-битами. Флаг Parity Error (UPEn) может быть прочитан программно, чтобы проверить, была ли во фрейме ошибка четности.

Бит UPEn установится, если в следующем символе, который можно прочитать из буфера приема, была ошибка четности на приеме, и проверка четности в этот момент была разрешена (UPMn1 = 1). Этот бит действителен, пока не произойдет чтение буфера приема (регистра UDRn).

Запрет приемника. В отличие от передатчика, запрет приемника срабатывает немедленно. Таким образом, принимаемый в настоящий момент фрейм данных (и конечно последующие после запрета) будут потеряны. Когда приемник запрещен (т. е. RXENn сброшен в 0), то он больше не переназначает нормальную работу порта RxDn как ножки GPIO. При запрете приемника буфер FIFO приемника будет сброшен, все оставшиеся в нем непрочитанные данные будут потеряны.

Сброс буфера приема. Буфер FIFO приемника будет сброшен, когда приемник запрещен, т. е. запомненные в буфере данные уничтожаются, непрочитанные данные будут потеряны. Если нужно сбросить буфер во время нормальной работы, например по причине события ошибки, просто делайте чтение UDRn, пока флаг RXCn не очистится. В следующем примере кода показана очистка буфера приема.

[Асинхронный прием данных]

В состав USART включены блоки восстановления тактов (Asynchronous Clock Recovery) и данных (Asynchronous Data Recovery), чтобы поддержать асинхронный прием данных. Логика восстановления используется для синхронизации генерируемых внутри тактов скорости (baud rate) для входящих асинхронных последовательных фреймов на выводе RxDn. Логика восстановления данных оцифровывает и пропускает через ФНЧ каждый бит приходящих данных, чтобы улучшить стойкость приемника к помехам. Диапазон работоспособности асинхронного приема зависит от точности внутренних тактов скорости, скорости входящих фреймов, размера фрейма в количестве бит.

Asynchronous Clock Recovery. Логика восстановления тактов синхронизирует внутренние такты по входящим последовательным фреймам. На рис. 22-5 показан процесс оцифровки стартового бита входящего фрейма. Частота оцифровки в 16 раз больше частоты бит (baud rate) для нормального режима (Normal mode), и в 8 раз больше частоты бит для режима двойной скорости (Double Speed mode). Горизонтальные стрелки показывают интервалы подстройки синхронизации в процессе оцифровки. Обратите внимание на увеличенные интервалы для режима двойной скорости (Double Speed mode, U2Xn = 1). Выборки, помеченные нулями, означают выборки, когда сигнал RxDn в состоянии ожидания idle (т. е. нет активной передачи).

Рис. 22-5. Выборка (оцифровка) start-бита.

Когда логика восстановления тактов детектировала переход от лог. 1 (idle) к лог. 0 (start) на линии RxDn, инициируется последовательность детектирования start-бита. Выборка 1 на рисунке показывает первую нулевую выборку. Затем логика восстановления тактов использует выборки 8, 9 и 10 для нормального режима, и выборки 4, 5 и 6 для режима двойной скорости (эти цифры выделены прямоугольной рамкой на рисунке), чтобы определить, что действительно принят допустимый start-бит. Если 2 или большее количество этих выборок имеют лог. 1 (принцип большинства), то start-бит отбрасывается как шумовая помеха, и приемник снова начинает детектирование следующего перехода от 1 к 0. Однако если детектирован допустимый start-бит («большинство» указывает на 0), то в логика восстановления тактов синхронизируется, и может начаться процесс восстановления данных. Процесс синхронизации повторяется для каждого start-бита.

Asynchronous Data Recovery. Когда произошла синхронизация тактов приемника по start-биту, может начать работу восстановление данных. Блок восстановления данных использует машину из 16 состояний для каждого бита в нормальном режиме и машину 8 состояний для режима двойной скорости. На рис. 22-6 показана оцифровка битов данных и бита четности (BITn). Каждая выборка помечена цифрой, которая равна состоянию блока восстановления.

Рис. 22-6. Выборка данных и бита четности.

Принятие решения о лог. уровне принятого бита выполняется по тому же самому «принципу большинства» на 3 выборках посередине принимаемого бита. Номера этих выборок помечены на рисунке рамочками. Если 2 или большее количество из этих 3 выборок прочитаны как 1, то принятый бит регистрируется как лог. 1. И аналогично если 2 или большее количество из этих 3 выборок прочитаны как 0, то принятый бит регистрируется как лог. 0. Этот принцип работает как простейший цифровой ФНЧ для входящего сигнала на выводе RxDn. Процесс восстановления данных повторяется для каждого бита, пока не завершится прием всего фрейма, включая первый stop-бит. Имейте в виду, что приемник использует только первый stop-бит фрейма.

На рис. 22-7 показана оцифровка stop-бита как можно раньше относительно начала start-бита следующего фрейма.

Рис. 22-7. Выборка стоп-бита и следующего стартового бита.

Для оцифровки (получения значения) stop-бита применяется тот же самый мажоритарный принцип голосования, как и для других бит фрейма. Если определено, что stop-бит равен лог. 0, то регистрируется ошибка фрейма, и будет установлен флаг Frame Error (FEn).

Новый переход 1 -> 0 покажет начало start-бита нового фрейма, и он может появиться сразу после последнего бита, в котором использовалось детектирование уровня по мажоритарному принципу. Для режима Normal Speed, первая выборка с низким уровнем может быть в точке, промаркированной как (A) на рис. 22-7. Для Double Speed mode первый низкий уровень должен быть задержан до (B). (C) помечает stop-бит полной длины. Раннее детектирование start-бита влияет на рабочий диапазон приемника (Asynchronous Operational Range).

Asynchronous Operational Range. Рабочий диапазон приемника зависит от несоответствия скорости принимаемых бит и генерируемой внутри скорости. И передатчик, и приемник должны быть настроены на одну и ту же скорость, но из-за погрешности частоты системного тактового генератора реальные частоты могут отличаться. Если передатчик посылает фреймы со слишком большой частотой бит или слишком малой частотой бит, или если генерируемая частота бит приемника имеет отличающуюся базовую частоту (см. таблицу 22-2), то приемник не сможет синхронизировать фреймы по start-биту.

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

(D + 1) * S
Rslow = ———————-
S — 1 + D*S + SF
(D + 2) * S
Rfast = ———————-
(D + 1) * S + SM

D сумма числа бит символа и бита четности (D = 5 .. 10 бит).
S количество выборок на бит, S = 16 для Normal Speed mode и S = 8 для Double Speed mode.
SF номер первой выборки, используемой для детектирования уровня по мажоритарному принципу. SF = 8 для Normal Speed mode и SF = 4 для Double Speed mode.
SM номер средней выборки, используемой для детектирования уровня по мажоритарному принципу. SM = 9 для Normal Speed mode и SM = 5 для Double Speed mode.
Rslow соотношение между самой низкой входной скоростью и собственной скоростью приемника, при котором приемник все еще может принимать данные.
Rfast соотношение между самой высокой входной скоростью и собственной скоростью приемника, при котором приемник все еще может принимать данные.

Таблицы 22-2 и 22-3 дают список максимально допустимой ошибки baud rate приемника. Обратите внимание, что для Normal Speed mode допуск больше.

Табл. 22-2. Рекомендуемые максимальные скорости передачи и погрешность приемника для нормального режима скорости (U2Xn = 0).

D (Data + Parity Bit) Rslow (%) Rfast (%) MAX общая ошибка, % Рекомендуемая MAX ошибка приемника, %
5 93.20 106.67 +6.67 / -6.8 ±3.0
6 94.12 105.79 +5.79 / -5.88 ±2.5
7 94.81 105.11 +5.11 / -5.19 ±2.0
8 95.36 104.58 +4.58 / -4.54 ±2.0
9 95.81 104.14 +4.14 / -4.19 ±1.5
10 96.17 103.78 +3.78 / -3.83 ±1.5

Табл. 22-3. Рекомендуемые максимальные скорости передачи и погрешность приемника для двойной скорости (U2Xn = 1).

D (Data + Parity Bit) Rslow (%) Rfast (%) MAX общая ошибка, % Рекомендуемая MAX ошибка приемника, %
5 94.12 105.66 +5.66 / -5.88 ±2.5
6 94.92 104.92 +4.92 / -5.08 ±2.0
7 95.52 104.35 +4.35 / -4.48 ±1.5
8 96.00 103.90 +3.90 / -4.00 ±1.5
9 96.39 103.53 +3.53 / -3.61 ±1.5
10 96.70 103.23 +3.23 / -3.30 ±1.0

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

Есть 2 возможных источника ошибок baud rate приемника. Системная тактовая частота приемника (XTAL) всегда будет незначительно зависеть от напряжения питания и температуры окружающей среды. Когда для генерации системной частоты используется кварц, то в этом случае проблем чаще всего не будет. Однако если применить некачественный резонатор с допуском более 2%, то это может послужить причиной ошибок. Второй источник ошибки более управляемый. Генератор baud rate не всегда делает точное деление системной частоты, чтобы получить желаемое значение baud rate. В этом случае желательно использовать то значение для UBRR, которое дает ошибку как можно меньше.

[Multi-processor Communication Mode]

Установка бита Multi-processor Communication mode (MPCMn) в регистре UCSRnA разрешает функцию фильтрации входящих фреймов, полученных приемником USART. Фреймы, которые не содержат информацию адреса, будут игнорироваться и не попадут в буфер приема. Это эффективно уменьшит количество входящих фреймов, которые должны быть программно обработаны CPU в системе, где несколько процессоров (MCU) обмениваются данными по одной и той же последовательной шине данных. На передатчик не влияет установка бита MPCMn, но передатчик должен использоваться по-другому, когда он работает как часть системы, использующей Multi-processor Communication mode.

Если приемник настроен для приема фреймов, содержащих от 5 до 8 бит данных, то первый stop-бит показывает, есть ли во фрейме информация адреса. Если приемник настроен на фреймы с 9 битами данных, то 9-й бит (RXB8n) используется для идентификации фреймов адреса и данных. Когда бит типа фрейма (это первый stop-бит или 9-й бит) равен 1, то фрейм содержит адрес. Когда бит типа фрейма равен 0, то это будет фрейм данных.

Multi-processor Communication mode разрешает нескольким подчиненным MCU принимать данные от главного MCU. Это осуществляется путем декодирования фрейма адреса, чтобы определить, какой именно MCU адресован на шине. Если адресован конкретный подчиненный MCU, то он примет следующие фреймы данных как обычно, в то время другие подчиненные MCUs будут игнорировать принятые фреймы, пока не будет принят другой адресный фрейм.

Использование MPCMn. Для MCU, который работает как главный на общей шине, можно использовать 9-битный формат фрейма (UCSZn = 7). Девятый бит (TXB8n) должен быть установлен, когда передается фрейм адреса (TXB8n = 1), или очищен, когда передается фрейм данных (TXB = 0). Подчиненные MCU в этом случае должны быть настроены для использования 9-битного формата фрейма.

Для обмена данными в Multi-processor Communication mode должна использоваться следующая процедура:

1. Все подчиненные MCU настроены в Multi-processor Communication mode (установлен бит MPCMn в регистре UCSRnA).

2. Главный MCU посылает фрейм адреса, и все подчиненные устройства принимают и читают этот фрейм. В подчиненных MCU флаг RXCn в регистре UCSRnA будет установлен как обычно.

3. Каждый подчиненный MCU читает регистр UDRn, чтобы определить, что для приема выбран именно он (проверяет совпадение адреса). Если так, то он очищает бит MPCMn в регистре UCSRnA, в противном случае просто ждет следующего адресного фрейма, сохраняя установленным бит MPCMn.

4. Адресованный MCU будет принимать все фреймы данных, пока не поступит новый фрейм адреса. Другие подчиненные MCUs, у которых установлен бит MPCMn, будут (аппаратно) игнорировать фреймы данных.

5. Когда адресованный MCU примет последний фрейм данных, то он устанавливает бит MPCMn и ждет новый фрейм адреса от главного MCU. Затем процедура повторяется начиная с шага 2.

Можно использовать любой формат фрейма от 5 до 8 бит, но это непрактично, потому что приемник нужно перепрограммировать между использованием n и n+1 форматом бит фрейма. Это делает полнодуплексный обмен сложным, потому что передатчик и приемник используют настройку для одного и того же размера символа. Если используется формат символа от 5 до 8 бит, то передатчик должен быть установлен на использование двух stop-битов (USBSn = 1), поскольку первый stop-бит используется для указания типа фрейма (адрес или данные).

Не используйте инструкции ассемблера Read-Modify-Write (SBI и CBI) для установки или очистки бита MPCMn. Бит MPCMn использует то же самое место в пространстве I/O, как и флаг TXCn, и это может случайно очистить его при использовании инструкций SBI или CBI.

USART ATmega2560 может также работать в режиме SPI, но здесь этот вариант настройки USART не рассматривается.

UDRn – USART I/O Data Register n

№ разрядов 7 6 5 4 3 2 1
Регистры
RXB[7:0] (UDRn при чтении)
TXB[7:0] (UDRn при записи)
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение

Регистры USART Transmit Data Buffer (TXB) и Receive Data Buffer (RXB) разделяют одну и ту же ячейку пространства адресов I/O, которая носит мнемоническое название USART Data Register, или UDRn. TXB будет точкой назначения для записываемых в UDRn данных. Чтение UDRn вернет данные из RXB.

Для 5, 6 или 7-разрядных символов верхние неиспользуемые биты будут игнорироваться при передаче и автоматически обнуляться при приеме.

Буфер передачи можно записать только тогда, когда установлен флаг UDREn в регистре UCSRnA. Данные, записанные в UDRn, когда флаг UDREn не установлен, будут игнорироваться передатчиком USART. Если данные записаны в буфер передачи, и передатчик разрешен, то передатчик загрузит данные в регистр сдвига передачи, когда регистр сдвига пуст. Тогда данные будут последовательно передаваться через вывод TxDn.

Буфер приема состоит из 2-уровневого FIFO. FIFO поменяет свое состояние независимо от того, был ли к нему доступ, или нет. Из-за этого поведения буфера приема не используйте для него инструкции ассемблера Read-Modify-Write (SBI и CBI). Будьте осторожны, когда используете инструкции проверки бит (SBIC и SBIS), поскольку они также изменят состояние FIFO.

UCSRnA – USART Control and Status Register A

№ разрядов 7 6 5 4 3 2 1
Имена бит RXCn TXCn UDREn FEn DORn UPEn U2Xn MPCMn
Чтение/запись r rw r r r r rw rw
Нач. значение 1

• 7 – RXCn: USART Receive Complete

Этот флаг установится, когда в буфере приема есть непрочитанные данные, и очищается, когда буфер приема пуст (т. е. в нем не содержатся какие-либо непрочитанные данные). Если приемник запрещен, то буфер приема сбрасывается, следовательно бит RXCn становится нулем. Флаг RXCn может использоваться для генерации прерывания Receive Complete (см. описание бита RXCIEn).

• 6 – TXCn: USART Transmit Complete

Этот бит установится, когда весь фрейм в регистре сдвига передачи выдвинут на выход, так что в настоящий момент нет новых данных в буфере передачи (UDRn). Флаг TXCn автоматически очищается, когда запускается прерывание Transmit Complete, или этот бит может быть очищен программно записью туда 1. Флаг TXCn может генерировать прерывание Transmit Complete (см. описание бита TXCIEn).

• 5 – UDREn: USART Data Register Empty

Флаг UDREn показывает, что буфер передачи (UDRn) пуст и готов к записи туда новых данных. Если бит UDREn в состоянии 1, то буфер пуст, и туда можно записать новый символ для передачи. Флаг UDREn может генерировать прерывание Data Register Empty (см. описание бита UDRIEn).

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

• 4 – FEn: Frame Error

Этот бит установится, если следующий символ в буфере приема получил ошибку фрейма, т. е. когда первый stop-бит оказался нулевым. Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. FEn равен 0, когда stop-бит принятого фрейма равен 1 (нормальная ситуация, ошибки нет). Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 3 – DORn: Data OverRun

Этот бит установится, если детектировано событие Data OverRun. Оно произойдет, когда буфер приема заполнен (в нем находится 2 принятых символа), ожидается прием нового символа, и был детектирован новый start-бит. Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 2 – UPEn: USART Parity Error

Этот бит установится, если следующий символ в буфере приема имеет ошибку четности на приеме, и в момент его приема была разрешена проверка четности (UPMn1 = 1). Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 1 – U2Xn: Double the USART Transmission Speed

Этот бит работает только для асинхронного режима. Запишите этот бит в 0, когда используете синхронный режим.

Запись в этот бит лог. 1 уменьшит в 2 раза коэффициент деления генератора скорости (с 16 до 8), так что в асинхронном режиме скорость увеличится в 2 раза.

• 0 – MPCMn: Multi-processor Communication Mode

Этот бит разрешит работу Multi-processor Communication mode. Когда этот бит в 1, все входящие фреймы, принятые приемником USART, не содержащие информации адреса, будут игнорированы. Этот бит не влияет на передатчик. Подробнее см. описание «Multi-processor Communication Mode».

UCSRnB – USART Control and Status Register B

№ разрядов 7 6 5 4 3 2 1
Имена бит RXCIEn TXCIEn UDRIEn FERXENn n TXENn UCSZn2 RXB8n TXB8n
Чтение/запись rw rw rw rw rw rw r rw
Нач. значение

• 7 – RXCIEn: RX Complete Interrupt Enable n

Запись в этот бит 1 разрешает работу прерывания по флагу RXCn. Прерывание USART Receive Complete будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит RXCn регистра UCSRnA.

• 6 – TXCIEn: TX Complete Interrupt Enable n

Запись этого бита в 1 разрешает работу прерывания по флагу TXCn. Прерывание USART Transmit Complete будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит TXCn в регистре UCSRnA.

• 5 – UDRIEn: USART Data Register Empty Interrupt Enable n

Запись в этот бит 1 разрешает работу прерывания по флагу UDREn. Прерывание Data Register Empty будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит UDREn в регистре UCSRnA.

• 4 – RXENn: Receiver Enable n

Запись этого бита в 1 разрешает работу приемника USART. Приемник переназначит нормальную работу ножки порта как GPIO, и она станет входом приемника RxDn. Запрет приемника очистит буфер приема и сделает недействительными флаги FEn, DORn и UPEn.

• 3 – TXENn: Transmitter Enable n

Запись этого бита в 1 разрешает работу передатчика USART. Передатчик переназначит нормальную работу ножки порта как GPIO, и она станет выходом передатчика TxDn. Запрет передатчика (запись в TXENn нуля) не вступит в силу, пока не завершится текущие передачи, т. е. пока не опустошаться регистр сдвига передачи и буфер передачи. Когда передатчик запрещен, то он не занимает порт TxDn под выход передатчика (порт может работать как обычный GPIO).

• 2 – UCSZn2: Character Size n

Бит UCSZn2 комбинируется с битами UCSZn1:0 регистра UCSRnC, и вместе с ними задает количество бит данных (Character SiZe) в фрейме передатчика и приемника.

• 1 – RXB8n: Receive Data Bit 8 n

RXB8n содержит 9-й бит данных принятого символа, когда осуществляется работа с последовательными фреймами из 9 бит данных. Бит RXB8n должен быть прочитан перед чтением младших бит из UDRn.

• 0 – TXB8n: Transmit Data Bit 8 n

TXB8n содержит 9-й бит данных передаваемого символа, когда осуществляется работа с последовательными фреймами из 9 бит данных. Бит TXB8n должен быть записан перед записью младших бит в UDRn.

UCSRnC – USART Control and Status Register C

№ разрядов 7 6 5 4 3 2 1
Имена бит UMSELn1 UMSELn0 UPMn1 UPMn0 USBSn UCSZn1 UCSZn0 UCPOLn
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 1 1

• 7:6 – UMSELn1:0 USART Mode Select

Эти биты выбирают режим работы USARTn, как это показано в таблице 22-4.

Табл. 22-4. Настройки бит UMSELn.

UMSELn1 UMSELn1 Режим
Асинхронный USART
1 Синхронный USART
1 зарезервировано
1 1 Master SPI (MSPIM) (1)

Примечание (1): см. в даташите раздел «USART in SPI Mode».

• 5:4 – UPMn1:0: Parity Mode

Эти биты разрешают проверку на четность и задают её тип. Если проверка на четность разрешена, то передатчик автоматически будет генерировать и передавать четность данных в каждом фрейме. Приемник будет генерировать значение четности для приходящих данных и сравнивать их с установкой UPMn. Если обнаружится несоответствие, то флаг UPEn в регистре UCSRnA будет установлен.

UPMn1 UPMn0 Режим проверки четности
Отключено
1 зарезервировано
1 Разрешено, проверка по четности (Even Parity)
1 1 Разрешено, проверка по нечетности (Odd Parity)

• 3 – USBSn: Stop Bit Select

Этот бит выбирает количество stop-битов, которые вставляет передатчик. Приемник эту настройку игнорирует.

USBSn Количество стоп-битов
1
1 2

• 2:1 – UCSZn1:0: Character Size

Биты UCSZn1:0 в комбинации с битом UCSZn2 регистра UCSRnB устанавливают количество бит данных (Character SiZe) в фрейме передатчика и приемника.

UCSZn2 UCSZn1 UCSZn0 Размер символа, бит
5
1 6
1 7
1 1 8
1 зарезервировано
1 1
1 1
1 1 1 9

• Bit 0 – UCPOLn: Clock Polarity

Этот бит используется только в синхронном режиме. Запишите в этот бит 0, когда используется асинхронный режим работы. Бит UCPOLn устанавливает взаимосвязь между изменениями данных на выходе, выборкой данных на входе и тактами синхронизации (XCKn).

UCPOLn Когда изменяются передаваемые данные (на выводе TxDn) Когда считываются данные на входе (на выводе RxDn)
По нарастанию уровня на XCKn По спаду уровня на XCKn
1 По спаду уровня на XCKn По нарастанию уровня на XCKn

UBRRnL и UBRRnH – регистры USART Baud Rate

№ разрядов 15 14 13 12 11 10 9 8
UBRRHn UBRR[11:8]
UBRRLn UBRR[7:0]
№ разрядов 7 6 5 4 3 2 1
Чтение/запись r r r r rw rw rw rw
rw rw rw rw rw rw rw rw
Нач. значение

Эти биты зарезервированы для возможного использования в будущем. Для совместимости в эти биты следует записывать 0, когда Вы записываете UBRRH.

• 11:0 – UBRR11:0: USART Baud Rate Register

Это 12-разрядный регистр, который содержит настройку скорости для USART (baud rate). UBRRH содержит 4 старших бита, UBRRL 8 младших USART baud rate. Текущая активная передача передатчика или активный прием приемника будут испорчены, если на лету была изменена скорость. Запись UBRRL приведет к немедленному обновлению прескалера в генераторе baud rate.

Для стандартных частот кварцев и резонаторов наиболее часто используемые скорости для асинхронного режима работы могут быть сгенерированы настройкой UBRR по таблицам от 22-9 до 22-12. Рекомендуется использовать настройки с погрешностью скорости 0.5% от целевой или менее. Более высокие погрешности допустимы, но в этом случае приемник будет меньше защищен от шумов, и вероятность возникновения ошибки будет больше, особенно на фреймах большого размера (см. раздел «Asynchronous Operational Range»). Значение ошибки установки скорости вычисляется по следующей формуле:

Табл. 22-9. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
fosc = 1.0000 МГц
fosc = 1.8432 МГц fosc = 2.0000 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 25 0.2% 51 0.2% 47 95 51 0.2% 103 0.2%
4800 12 0.2% 25 0.2% 23 47 25 0.2% 51 0.2%
9600 6 -7.0% 12 0.2% 11 23 12 0.2% 25 0.2%
14.4K 3 8.5% 8 -3.5% 7 15 8 -3.5% 16 2.1%
19.2K 2 8.5% 6 -7.0% 5 11 6 -7.0% 12 0.2%
28.8K 1 8.5% 3 8.5% 3 7 3 8.5% 8 -3.5%
38.4K 1 -18.6% 2 8.5% 2 5 2 8.5% 6 -7.0%
57.6K 8.5% 1 8.5% 1 3 1 8.5% 3 8.5%
78.8K 1 -18.6% 1 -25.0% 2 1 -18.6% 2 8.5%
115.2K 8.5% 1 8.5% 1 8.5%
230.4
250K
MAX (1) 62.5K 125K 115.2K 230.4K 125K 250K

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-10. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
f osc = 3.6864 МГц f osc = 4.0000 МГц f osc = 7.3728 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 95 191 103 0.2% 207 0.2% 191 383
4800 47 95 51 0.2% 103 0.2% 95 191
9600 23 47 25 0.2% 51 0.2% 47 95
14.4K 15 31 16 2.1% 34 -0.8% 31 63
19.2K 11 23 12 0.2% 25 0.2% 23 47
28.8K 7 15 8 -3.5% 16 2.1% 15 31
38.4K 5 11 6 -7.0% 12 0.2% 11 23
57.6K 3 7 3 8.5% 8 -3.5% 7 15
78.8K 2 5 2 8.5% 6 -7.0% 5 11
115.2K 1 3 1 8.5% 3 8.5% 3 7
230.4 1 8.5% 1 8.5% 1 3
250K -7.8% 1 -7.8% 1 1 -7.8% 3 -7.8%
0.5M -7.8% -7.8% 1 -7.8%
1M -7.8%
MAX (1) 230.4K 480.8K 250K 0.5M 460.8K 921.6K

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-11. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
f osc = 8.0000 МГц f osc = 11.0592 МГц f osc = 14.7456 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 207 0.2% 416 -0.1% 287 575 383 767
4800 103 0.2% 207 0.2% 143 287 191 383
9600 51 0.2% 103 0.2% 71 143 95 191
14.4K 34 -0.8% 68 0.6% 47 95 63 127
19.2K 25 0.2% 51 0.2% 35 71 47 95
28.8K 16 2.1% 34 -0.8% 23 47 31 63
38.4K 12 0.2% 25 0.2% 17 35 23 47
57.6K 8 -3.5% 16 2.1% 11 23 15 31
78.8K 6 -7.0% 12 0.2% 8 17 11 23
115.2K 3 8.5% 8 -3.5% 5 11 7 15
230.4 1 8.5% 3 8.5% 2 5 3 7
250K 1 3 2 -7.8% 5 -7.8% 3 -7.8% 6 5.3%
0.5M 1 2 -7.8% 1 -7.8% 3 -7.8%
1M -7.8% 1 -7.8%
MAX (1) 0.5M 1M 691.2K 1.3824M 921.6K 1.8432M

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-12. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
f osc = 16.0000 МГц f osc = 18.4320 МГц f osc = 20.0000 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 416 -0.1% 832 479 959 520 1041
4800 207 0.2% 416 -0.1% 239 479 259 0.2% 520
9600 (2) 103 0.2% 207 0.2% 119 239 129 0.2% 259 0.2%
14.4K 68 0.6% 138 -0.1% 79 159 86 -0.2% 173 -0.2%
19.2K 51 0.2% 103 0.2% 59 119 64 0.2% 129 0.2%
28.8K 34 -0.8% 68 0.6% 39 79 42 0.9% 86 -0.2%
38.4K 25 0.2% 51 0.2% 29 59 32 -1.4% 64 0.2%
57.6K 16 2.1% 34 -0.8% 19 39 21 -1.4% 42 0.9%
78.8K 12 0.2% 25 0.2% 14 29 15 1.7% 32 -1.4%
115.2K (3) 8 -3.5% 16 2.1% 9 19 10 -1.4% 21 -1.4%
230.4 3 8.5% 8 -3.5% 4 9 4 8.5% 10 -1.4%
250K 3 7 4 -7.8% 8 2.4% 4 9
0.5M 1 3 4 -7.8% 4
1M 1
MAX (1) 1M 2M 1.152M 2.304M 1.25M 2.5M

Примечания:
(1): UBRR = 0, Error = 0%.
(2) скорость по умолчанию, которая используется в консоли Serial Monitor и скетчах Arduino.
(3) на этой скорости работает UART-загрузчик платы Arduino Mega 2560 [2].

Источник

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

Hi,

  I am using a 18F87J50 with the internal clock (default to 4 MHz). I am using the USART library in C18. The USART set-up is as follows:


 //configure USART
 Open1USART(  USART_TX_INT_OFF  &
                     USART_RX_INT_ON  &
                     USART_ASYNCH_MODE &
                     USART_EIGHT_BIT  &
                     USART_CONT_RX  &
                     USART_BRGH_HIGH,
                     25 );                                   //9600,n,8,1 - for a 4 MHz Osc.

  I am analysing the serial Tx line using the microchip serial analyser, with the software set to 9600 baud.

  While the data looks right, it reports framing errors and displays the data something like:

  61[Err] 54 [Err] 67 [Err] ….. where [Err] represents framing errors.

  I have tried tuning the internal osc with the osctune register, as follows:


   OSCTUNE = tuneReg;
   Nop();

  I right a value into tuneReg via the DMCI slider at run time and even when I go through the full range of tuning values, I still get framing errors (full range 1 — 63).

  Any thoughts?

  Regards,
Tom

jgmartinez

Super Member

  • Total Posts : 537
  • Reward points : 0
  • Joined: 2007/06/28 06:13:39
  • Location: Madrid, Spain.
  • Status: offline

RE: USART Framing Error


2008/05/20 07:57:36

(permalink)

Internal oscillator is not stable and acuracy for high data rate transmission. There are some threads about this matter, chek them.

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/20 09:18:51

(permalink)

Same problem persists with external clock.

  Regards,
Tom

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/20 15:57:31

(permalink)

Hi Tom, at times a «fine tune» (+/- 1) of BRG value can help in these cases…

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/20 23:10:17

(permalink)

Hi Dario,

  I have observed the changes from BRG = 10 through to 30 with +1 increments. Even though at the extremeties the framing error ceases, the data is garbage. I have also tried it at multiples i.e. 50, 100 etc..

  On the scope the baud rate looks to be correct approx. 9600 KHz period between successive bits when BRG = 25.

  I have used the USART many many times, but never on a J series PIC nor on a device with multiple USARTS.

  I am very scepticle of the clock settings on this device, however, the baud rate looks right? [:@]

  Isn’t a framing error caused by a misplaced stop bit? If so, why would this become independant of the rest of the packet i.e. in inter bit timing looks correct, surely the stop bit should follow correctly? (although I haven’t scoped it! Smile).

  Argggghhhhhhhh …….

  Regards,
Tom

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/21 01:36:25

(permalink)

Well, definitely strange Smile

Yeah, the framing error is that one.
What about Erratas? And… baudUSART() ?

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/21 02:07:15

(permalink)

Dario,

  I had checked the errata and there is nothing on this.

    Should BaudUSART() be used as well as the Open1USART( config ) function?

  Regards,
Tom

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/21 03:34:41

(permalink)

Yes, it completes the settings.

tunelabguy

Super Member

  • Total Posts : 1713
  • Reward points : 0
  • Joined: 2005/04/03 08:30:19
  • Location: Hopkins, MN USA
  • Status: offline

RE: USART Framing Error


2008/05/21 04:15:25

(permalink)

Just a wild guess, but have you checked your polarity? The TX output pin is usually inverted through a MAX232 or other similar RS-232 interface chip, which inverts the polarity. On the TX pin the start bit should be low and the stop bit should be high. On the RS-232 end, the start bit is high and the stop bit is low. Are you using such a chip?

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/21 05:08:51

(permalink)

Hi,

  Both very interesting points.

  1) I will try the BaudUSART() — although I have never used this in any previous applications.

  2) I am not using any level translating IC. I am working at 3.3V on the PIC and the device which I am talking to also uses 3.3V — I wonder could this be the problem?

  I have placed the PIC Serial Analyzer in parallel to may PIC and this communicates with the device perfectly.

  Regards,
Tom

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/21 09:18:48

(permalink)

Hi,

  I have been looking through the .c files associated with USART and USART.h — in these files definitions are tested and depending on the outcome various registers set.

  For example:

  #if defined (EAUSART_V6)|| defined (EAUSART_V7) || defined (EAUSART_V8) || defined (EAUSART_V9) || defined (EAUSART_V10)  || defined (EAUSART_V10)

  Where are these definitions made? I have looked in the .h files associated with my processor i.e. p18f87j50.h and they are not contained in there?

  Where are they? Should the programmer conciously define them? I have never done so in the past — maybe I have just been fortunate!

  Regards,
Tom

Tom Myers

Super Member

  • Total Posts : 444
  • Reward points : 0
  • Joined: 2003/11/07 12:37:50
  • Status: offline

RE: USART Framing Error


2008/05/21 10:30:32

(permalink)

FIXED ………………….

  Thanks for all your help guys. It was a partial effort in the end. It seems like it was the clock idle state!

  With the addition of:


  baud1USART( BAUD_IDLE_CLK_LOW &
    BAUD_8_BIT_RATE  &
    BAUD_WAKEUP_OFF  &
    BAUD_AUTO_OFF  );

  Which I have never used before SmileSmile (my luck has run out!). With BAUD_IDLE_CLK_HIGH I got framing errors and with it set as above, things are running perfectly!

  Thank you and regards.

  Tom

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/21 10:37:26

(permalink)

Hi Tom, I can see those EAUSART_ things in a «pconfig.h» file into MCC18 include folder…

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/21 10:39:04

(permalink)

ORIGINAL: Tom Myers

With the addition of:


 baud1USART( BAUD_IDLE_CLK_LOW &
   BAUD_8_BIT_RATE  &
   BAUD_WAKEUP_OFF  &
   BAUD_AUTO_OFF  );

Well, very good then Smile

tunelabguy

Super Member

  • Total Posts : 1713
  • Reward points : 0
  • Joined: 2005/04/03 08:30:19
  • Location: Hopkins, MN USA
  • Status: offline

RE: USART Framing Error


2008/05/21 12:40:11

(permalink)

ORIGINAL: Tom Myers
..It seems like it was the clock idle state!

With the addition of:


 baud1USART( BAUD_IDLE_CLK_LOW &
   BAUD_8_BIT_RATE  &
   BAUD_WAKEUP_OFF  &
   BAUD_AUTO_OFF  );

Ah, so it was polarity after all! I didn’t realize that these PIC18F devices had the ability to flip polarity, but now that you brought this to light, I see that the BAUDCON register has two bits called RXDTP and TXCKP, which set the polarity of the transmit and receive pins. That must be what your BAUD_IDLE_CLK_LOW setting does. If you were using a 16F series part, then you would have been stuck with IDLE_CLK_HIGH as the only choice.

vloki

Jo, alla!

  • Total Posts : 6815
  • Reward points : 0
  • Joined: 2007/10/15 00:51:49
  • Location: Germany
  • Status: offline

RE: USART Framing Error


2008/05/21 13:18:10

(permalink)

ORIGINAL: Tom Myers

FIXED ………………….

Thanks for all your help guys. It was a partial effort in the end. It seems like it was the clock idle state!

With the addition of:


baud1USART( BAUD_IDLE_CLK_LOW &
BAUD_8_BIT_RATE  &
BAUD_WAKEUP_OFF  &
BAUD_AUTO_OFF  );

Which I have never used before SmileSmile (my luck has run out!). With BAUD_IDLE_CLK_HIGH I got framing errors and with it set as above, things are running perfectly!

Thank you and regards.

Tom

IMO you are a lucky guy — each time i was using this baudUSART() i got crazy gringringrin

Now i hope that I know why this hapened and would suggest to use it this way:
(edit: in asyncronous mode)

baud1USART(

BAUD_IDLE_RX_PIN_STATE_HIGH &
                BAUD_IDLE_TX_PIN_STATE_HIGH

                BAUD_8_BIT_RATE  &
                BAUD_WAKEUP_OFF  &
                BAUD_AUTO_OFF  );

Don’t know it causes problems with PIC18F87J50 but it seems more save to me defining
both bits.
(see

bad documentation of baudUSART() function ?)

post edited by vloki — 2008/05/21 13:20:58

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/05/21 13:43:52

(permalink)

In fact I thought about you Vloki grin

Malin Dixon

Starting Member

  • Total Posts : 51
  • Reward points : 0
  • Joined: 2007/07/17 14:38:34
  • Location: 0
  • Status: offline

RE: USART Framing Error


2008/06/14 01:24:01

(permalink)

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

RE: USART Framing Error


2008/06/16 02:50:02

(permalink)

Yes, BusyUSART() uses TRMT:


char BusyUSART(void)
{
  if(!TXSTAbits.TRMT)  // Is the transmit shift register empty
    return 1;          // No, return FALSE
  return 0;            // Return TRUE
}

(and putsUSART() relies on that on top)

moiska

New Member

  • Total Posts : 2
  • Reward points : 0
  • Joined: 2013/12/02 23:03:25
  • Location: 0
  • Status: offline

RE: USART Framing Error


2013/12/02 23:36:49

(permalink)

数据手册介绍:使用高波特率(BRGH = 1)或16 位BRG 有利于减小波特率误差,或者在快速振荡频率条件下实现低波特率。 

  我使用PIC18F4525,我遇到接收字符错误和帧错误(向PIC18F4525发送03h,RCREG收到:0Ah   FERR=1),此时我使用内部振荡器模块,工作频率32MHz(4x8MHz)。 
考虑是否速度过高,因此我改用16MHz(4x4MHz),然而现象依旧。

 我也试过利用OSCTUN 降低或频率,RCREG收到数据有变,但FERR=1始终存在。

 最后,我取消使用PLL,直接使用FOSC=8MHz,问题得到解决。 

因此,我认为,可能内部振荡器模块输出频率存在误差,这个误差是可以允许的,但经过PLL 4倍频以后,误差被放大就超出了允许的限度。 
还好,8MHz对我的工作完全胜任。 


;-----------------------------------------
;OSCCON:振荡器控制寄存器 //0100 q000 //0100 q000 //uuuu uuqu 
; //IDLEN //IRCF2 //IRCF1 //IRCF0 //OSTS //IOFS //SCS1 //SCS0 
          MOVLW B'11111010' 
          MOVWF OSCCON 
;-----------------------------------------ok
;OSCTUNE:振荡器调节寄存器 //00-0 0000 //00-0 0000 //uu-u uuuu 
; //INTSRC //PLLEN(1) //— //TUN4 //TUN3 //TUN2 //TUN1 //TUN0 
         MOVLW B'10000000' 
         MOVWF OSCTUNE 
;---------------------------------------------------------------- 
         movlw 0xc0 ;  set tris bits for Tx and RX 
         iorwf TRISC,F 
;------------------------------------------------ 
;BAUDCON //01-0 0-00 //01-0 0-00 //--uu uuuu 
; //ABDOVF //RCIDL //— //SCKP //BRG16 //— //WUE //ABDEN 
         bsf BAUDCON,BRG16 ;bit 3 BRG16:16 位波特率发生器位 ; 1=使用16 位波特率发生器 ; 0=使用8 位波特率发生器 
         ...... 
        TBLRD*+ ; read into TABLAT and increment 
        MOVF TABLAT,W ; get data 
        MOVWF SPBRGH 
        TBLRD*+ ; read into TABLAT and increment 
        MOVF TABLAT,W ; get data 
        MOVWF SPBRG;L 
         ...... 
SetupSerial01: 
;------------------------------------------------ 
;TXSTA //0000 0010 //0000 0010 //uuuu uuuu 
          movlw B'01000110';=B'00100100' 
          movwf TXSTA 
;------------------------------------------------ 
;RCSTA //0000 000x //0000 000x //uuuu uuuu 
          movlw B'11000000' ;=B'10010000' 
          movwf RCSTA 
         ......
 

pink

post edited by moiska — 2013/12/02 23:59:09

Понравилась статья? Поделить с друзьями:
  • Avr relay weld apc ошибка
  • Avr gcc error no such file or directory
  • Avr g error missing device or architecture after mmcu
  • Avr g error createprocess no such file or directory arduino
  • Avpui exe системное предупреждение unknown hard error