Приветствую тебя, мой уважаемый читатель! Продолжаем пилить ПЛИСины (FPGA). Сегодня у нас UART. Информации много о принципах работы UART и в ARM-ах мы его уже “юзали“.
Передача данных в UART осуществляется по одному биту в равные промежутки времени. Этот временной промежуток определяется заданной скоростью UART и для конкретного соединения указывается в бодах (что в данном случае соответствует битам в секунду). Существует общепринятый ряд стандартных скоростей: 300; 600; 1200; 2400; 4800; 9600; 19200; 38400; 57600; 115200; 230400; 460800; 921600 бод. Скорость (S, бод) и длительность бита (T, секунд) связаны соотношением T = 1/S. Скорость в бодах иногда называют сленговым словом битрейт.
Помимо собственно информационного потока UART автоматически вставляет в поток синхронизирующие метки, так называемые стартовый и стоповый биты. При при приёме эти лишние биты удаляются из потока информационного назначения. Обычно стартовый и стоповый биты обрамляют один байт информации (8 бит), однако встречаются реализации UART, которые позволяют передавать по 5,6,7, 8 или 9 бит. Обрамленные стартом и стоповым битами, последовательность битов являются минимальной посылкой. Некоторые реализации UART позволяют вставлять два стоповых бита при передаче для уменьшения вероятности рассинхронизации приёмника и передатчика при плотном трафике. Приёмник игнорирует второй стоповый бит, воспринимая его как короткую паузу на линии.
Принято соглашение, что пассивным (в отсутствие потока данных) состоянием входа и выхода UART является логическая 1. Стартовый бит всегда логический 0, поэтому приёмник UART ждёт перепада из 1 в 0 и отсчитывает от него временной промежуток в половину длительности бита (середина передачи стартового бита). Если в этот момент на входе всё ещё 0, то запускается процесс приёма минимальной посылки. Для этого приёмник отсчитывает 9 битовых длительностей подряд (для 8-бит данных) и в каждый момент фиксирует состояние входа. Первые 8 значений являются принятыми данными, последнее значение проверочное (стоп-бит). Значение стоп-бита всегда 1, если реально принятое значение иное, UART фиксирует ошибку.
Для формирования временных интервалов передающий и приёмный UART имеют источник точного времени (тактирования). Точность этого источника должна быть такой, чтобы сумма погрешностей (приёмника и передатчика) установки временного интервала от начала стартового импульса до середины стопового импульса не превышала половины (а лучше хотя бы четверти) битового интервала. Для 8-бит посылки 0,5/9,5 = 5 % (в реальности не более 3 %). Поскольку эта сумма ошибок приёмника и передатчика плюс возможные искажения сигнала в линии, то рекомендуемый допуск на точность тактирования UART не более 1,5 %.
Поскольку синхронизирующие биты занимают часть битового потока, то результирующая пропускная способность UART не равна скорости соединения. Например, для 8-битных посылок формата 8-N-1 синхронизирующие биты занимают 20 % потока, что для физической скорости 115 200 бод даёт битовую скорость данных 92160 бит/с или 11 520 байт/с.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use IEEE.math_real.all; entity UARTv1 is port (clk : in std_logic := '0'; Tx : out std_logic := '1'); end UARTv1; architecture UARTv1_architecture of UARTv1 is function DividerUART(HSE : in integer; BitsPerSecond : in integer) return integer is begin return HSE/BitsPerSecond; end DIViderUART; constant ConstantCounter : integer := 1; constant ConstantFrequency_HSE : integer := 50000000; constant ConstantBitsPerSecondUART : integer := 9600; constant ConstantDividerUART : integer := DividerUART(ConstantFrequency_HSE, ConstantBitsPerSecondUART); signal CounterDivederUART : integer := 0 ; begin process (clk) begin if(clk = '1' and clk'event) then CounterDivederUART <= CounterDivederUART + ConstantCounter; --СТАРТОВЫЙ БИТ if ((CounterDivederUART >= (ConstantDividerUART * 1)) and (CounterDivederUART < (ConstantDividerUART * 2))) then Tx <= '0'; --0 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 2)) and (CounterDivederUART < (ConstantDividerUART * 3))) then Tx <= '1'; --1 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 3)) and (CounterDivederUART < (ConstantDividerUART * 4))) then Tx <= '0'; --2 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 4)) and (CounterDivederUART < (ConstantDividerUART * 5))) then Tx <= '0'; --3 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 5)) and (CounterDivederUART < (ConstantDividerUART * 6))) then Tx <= '0'; --4 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 6)) and (CounterDivederUART < (ConstantDividerUART * 7))) then Tx <= '0'; --5 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 7)) and (CounterDivederUART < (ConstantDividerUART * 8))) then Tx <= '0'; --6 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 8)) and (CounterDivederUART < (ConstantDividerUART * 9))) then Tx <= '1'; --7 БИТ ДАННЫХ elsif ((CounterDivederUART >= (ConstantDividerUART * 9)) and (CounterDivederUART < (ConstantDividerUART * 10))) then Tx <= '0'; --СТОПОВЫЙ БИТ elsif (CounterDivederUART < (ConstantDividerUART * 1)) then Tx <= '1'; else CounterDivederUART <= 0; Tx <= '1'; end if; end if; end process; end UARTv1_architecture;
UARTv1 – исходник проекта.
Спасибо за Ваше внимание.