How UART Works
The UART that is going to transmit data receives the data from a data bus. The data bus is used to send data to the UART by another device like a CPU, memory, or microcontroller. Data is transferred from the data bus to the transmitting UART in parallel form. After the transmitting UART gets the parallel data from the data bus, it adds a start bit, a parity bit, and a stop bit, creating the data packet. Next, the data packet is output serially, bit by bit at the Tx pin. The receiving UART reads the data packet bit by bit at its Rx pin. The receiving UART then converts the data back into parallel form and removes the start bit, parity bit, and stop bits. Finally, the receiving UART transfers the data packet in parallel to the data bus on the receiving end:
UART transmitted data is organized into packets. Each packet contains 1 start bit, 5 to 9 data bits (depending on the UART), an optional parity bit, and 1 or 2 stop bits:
Start Bit
The UART data transmission line is normally held at a high voltage level when it’s not transmitting data. To start the transfer of data, the transmitting UART pulls the transmission line from high to low for one clock cycle. When the receiving UART detects the high to low voltage transition, it begins reading the bits in the data frame at the frequency of the baud rate.
Data Frame
The data frame contains the actual data being transferred. It can be 5 bits up to 8 bits long if a parity bit is used. If no parity bit is used, the data frame can be 9 bits long. In most cases, the data is sent with the least significant bit first.
Parity
Parity describes the evenness or oddness of a number. The parity bit is a way for the receiving UART to tell if any data has changed during transmission. Bits can be changed by electromagnetic radiation, mismatched baud rates, or long distance data transfers. After the receiving UART reads the data frame, it counts the number of bits with a value of 1 and checks if the total is an even or odd number. If the parity bit is a 0 (even parity), the 1 bits in the data frame should total to an even number. If the parity bit is a 1 (odd parity), the 1 bits in the data frame should total to an odd number. When the parity bit matches the data, the UART knows that the transmission was free of errors. But if the parity bit is a 0, and the total is odd; or the parity bit is a 1, and the total is even, the UART knows that bits in the data frame have changed.
Stop Bits
To signal the end of the data packet, the sending UART drives the data transmission line from a low voltage to a high voltage for at least two bit durations.
UART_Printf
Defination | void UART_Printf(const char *argList, …) |
Input Arguments | variable length arguments similar to printf |
Return Value | none |
Description | This function is similar to printf function in C. It takes the arguments with specified format and transmits accordingly .
The supported format specifiers are as below.
|
Usage |
void main() UART_Printf(«%d %l %f %x %b %s»,decNum,longDec,floatNum,hexNum,hexNum,myString); |
Как работает UART
Передатчик и приемник используют стартовый бит, стоповый бит и параметры синхронизации для взаимодействия друг с другом. Исходные данные находятся в параллельной форме. Например есть 4-х битные данные, и чтобы преобразовать их в последовательную форму нужен преобразователь из параллельного в последовательный. Обычно для проектирования преобразователей используются D-триггеры.
D-триггер, также известный как триггер данных, сдвигает один бит со стороны входа на сторону выхода только тогда, когда таймер изменяет переход из высокого состояния в низкое или из низкого состояния в высокое. Точно так же, если надо передать 4 бита данных, понадобится 4 триггера.
- D — входные данные.
- CLK — тактовые импульсы.
- Q — выходные данные.
Теперь спроектируем преобразователь из параллельного в последовательный и из последовательного в параллельный.
UART
Универсальный асинхронный приемник / передатчик, обычно называемый UART, представляет собой асинхронный приемник / передатчик, который является частью компьютерного оборудования. Он будет передавать данные вПоследовательная связьпротивПараллельное общениеЧтобы преобразовать между. Как микросхема, преобразующая параллельные входные сигналы в последовательные выходные сигналы, UART обычно интегрируется в соединение с другими интерфейсами связи.
Последовательный порт во встроенной системе обычно относится к порту UART, но мы часто не знаем разницы между ним и COM-портом, а также отношения между RS232, TTL и т. Д. Фактически, UART, COM относятся к форме физического интерфейса (аппаратного), а TTL, RS-232 относится к стандарту уровня (электрический сигнал).
UART имеет 4 контакта (VCC, GND, RX, TX), используя уровень TTL, низкий уровень — 0 (0 В), высокий уровень — 1 (3,3 В или выше).
Особенности UART: Как правило, контроллеры uart создаются вместе с процессорами во встроенных системах.Как и микросхема Freescale IMX6, существует несколько контроллеров uart.
Введение в интерфейс SPI
В последние несколько дней я наткнулся на флэш-память, использующую интерфейс SPI, и знаю, что флэш-память также может быть последовательной. Кажется, что это действительно была лягушка на дне колодца. Я нашел некоторую информацию об интерфейсе SPI. Позже я нашел информацию на английском языке, перевел ее и добавил Мое личное понимание было собрано в статью, надеюсь, она будет полезна новичкам.
Полное название интерфейса SPI — «Serial Peripheral Interface», что означает последовательный периферийный интерфейс. Впервые он был определен компанией Motorola для процессоров серии MC68HCXX. Интерфейс SPI в основном используется между EEPROM, FLASH, часами реального времени, аналого-цифровым преобразователем, процессором цифрового сигнала и декодером цифрового сигнала.
Интерфейс SPI — это синхронная последовательная передача данных между ЦП и периферийными низкоскоростными устройствами. Под импульсом сдвига ведущего устройства данные передаются в битах, старший бит находится спереди, а положение — сзади. Это полнодуплексная связь, и скорость передачи данных общая. Он быстрее шины I2C, а скорость может достигать нескольких Мбит / с.
Интерфейс SPI работает в режиме ведущий-ведомый. В этом режиме обычно есть ведущее устройство и одно или несколько ведомых устройств. Интерфейс включает следующие четыре сигнала:
(1) Вывод данных MOSI-ведущего устройства, ввод данных ведомого устройства
(2) Ввод данных MISO-ведущего устройства, вывод данных ведомого устройства
(3) Сигнал SCLK-clock, генерируемый ведущим устройством.
(4) / SS — сигнал включения ведомого устройства, управляемый ведущим устройством
В двухточечной связи интерфейс SPI не требует операций адресации и является полнодуплексным, что является простым и эффективным.
В системе с несколькими подчиненными устройствами каждое подчиненное устройство нуждается в независимом разрешающем сигнале, который немного сложнее аппаратно, чем система I2C.
Интерфейс SPI на самом деле представляет собой два простых регистра сдвига во внутреннем оборудовании.Передаваемые данные составляют 8 бит.Под сигналом включения ведомого и импульсом сдвига, генерируемым ведущим устройством, он передается бит за битом, причем старший бит находится спереди, а младший бит — сзади. . Как показано на рисунке ниже, данные изменяются по заднему фронту SCLK, и в то же время в регистре сдвига сохраняется один бит данных.
Схема внутреннего оборудования интерфейса SPI:
Наконец, один недостаток интерфейса SPI: нет назначенного управления потоком и нет механизма ответа, подтверждающего, получены ли данные.
Основной код — main.c
Cначала настраивается частота ядра на 128 МГц — реализация вынесена в Clock.c, поэтому необходимо подключить Clock.h. Затем настраивается блок UART и включаются прерывания от него. Реализация также вынесена в Uart.c (необходимо подключить Uart.h.)
Фрагмент кода 1
Далее микроконтроллер крутится в бесконечном цикле, пока не возникнет прерывание от UART. На демоплате есть возможность задать джамперами подключение к внешнему разъему RS-232 интерфейса UART1 или UART2 (см. рисунок 2).
В коде выбор используемого UART_X происходит в файле Uart.h. Для универсальности оба обработчика прерываний (UART1_IRQHandler() и UART2_IRQHandler()) вызывают одну и ту же функцию обработки UART_Handler_RX_TX(). При таком решении не нужно править код main.c при смене интерфейса в файле Uart.h.
Фрагмент кода 2
Обработчик прерывания один на прием и передачу слова, поэтому в UART_Handler_RX_TX() необходимо проверять, что явилось источником текущего прерывания. В рассматриваемом примере вся работа происходит в прерывании по приему. Каждое принятое слово посылается обратно — это так называемый режим «Эхо».
Далее это же принятое слово обрабатывается и проверяется, является ли оно командой. Под командой воспринимается символ ‘R’, за которым должен придти индекс новой скорости обмена. Этот индекс скорости также эхом отправляется назад, и затем новая скорость применяется в UART — функция UartSetBaud().
Поскольку UART настроен на обмен 8-ми битными словами, то для передачи конкретной скорости (например, значения 115200) потребуется приемка нескольких байт, а это усложнит код. Поэтому в примере доступные скорости ограничены массивом UART_Rates[] = {9600, 56000, 115200}. Количество значений в данном случае не принципиально — их можно сделать и больше
При работе с этим примером важно запомнить, что скоростей всего 3, следовательно, в микроконтроллер можно будет посылать команды ‘R’ с индексами — 0, 1 и 2.
Функция инициализации
Как и любой другой периферийный модуль, USART перед использованием нужно настроить. Для этого в микроконтроллере ATmega8535 есть 5 регистров – UBRRH, UBRRL, UCSRA, UCSRB, UCSRC.
//инициализация usart`avoidvoid //скорость обмена 9600 бод //разр. прерыв при приеме, разр приема, разр передачи. //обращаемся к регистру UCSRS, размер слова – 8 битUCSRB Принятый символ USART модуль сохраняет в регистре данных UDR. Оттуда мы его потом переписываем в буфер. Выполняется это в прерывании, а для этого оно должно быть разрешено. Устанавливаем бит – RXCIE – разрешение прерывания по завершению приема в единицу.
Биты TXCIE и UDRIE – разрешают прерывания по завершению передачи и прерывания при очистке регистра данных соответственно. Эти прерывания мы сейчас использовать не будем.
Модуль USART состоит из трех основных частей – блока тактирования, блока передатчика и блока приемника. Для разрешения работы приемника и передатчика нужно установить в единицу биты RXEN и TXEN соответственно.
Размер слова данных передаваемых/принимаемых модулем USART может варьироваться от 5 до 9 разрядов и определяется битами UCSZ2..UCSZ0. В регистре UCSRB находится только бит UCSZ2. Остальные биты находятся в регистре UCSRC. Мы будем использовать 8-ми разрядные слова, а значит эти три бита должны быть установлены так — 011.
Биты RXB8 и TXB8 – это 8-ой разряд принимаемых/передаваемых данных соответсвенно. Они используются, если размер слова данных – 9 бит.
//разр. прерывания при приеме, разр. приема, разр. передачиUCSRC У микроконтроллера ATmega8535 регистр UCSRC размещен по тому же адресу что и регистр UBRRH (это тоже регистр модуля USART, вместе с регистром UBRRL он определяет скорость обмена), поэтому при обращении к ним нужно выполнять ряд дополнительных действий для выбора конкретного регистра. За это отвечает бит URSEL. Если он установлен в 1 обращение производится к UCSRC. Устанавливаем его.
UMSEL – определяет режим работы модуля USART – синхронный, асинхронный. У нас режим работы асинхронный, разряд должен быть сброшен.
UPM1, UPM0 – определяют режимы работы схем контроля и формирования четности. Используются для повышения надежности передачи данных. В нашем случае контроль четности выключен – биты должны быть сброшены.
USBS – количество стоп битов. Для нашего случай бит сброшен.
UCSZ1, UCSZ0 – формат посылок. О них мы уже говорили выше. Для 8-ми разрядного слова эти биты должны быть установлены в единицы.
UCPOL – полярность тактового сигнала. Пропускаем мимо, потому что разряд используется только при работе в синхронном режиме.
//обращаемся к регистру UCSRS, размер слова – 8 битUBRR – UBRRH:UBRRL Скорость обмена данными определяется содержимым регистра UBRR. Это 12 разрядный регистр и он физически размещается в двух регистрах ввода/вывода — UBRRH:UBRRL. Скорость обмена выбирается из ряда стандартных значений, в нашем примере она равна 9600 бод. Значение UBRR для обычного асинхронного режима (есть еще асинхронный режим с удвоенной скоростью обмена) вычисляется по формуле:
UBRR = (Fck/(16*BAUD)) – 1
где Fck – тактовая частота микроконтроллера, BAUD скорость обмена в бодах
Для нашего случая UBRR = 8000000/(16*9600) – 1 = 51. Это округленное значение, поэтому реальная скорость обмена будет отличаться от 9600. Рекомендуется использовать такие значение регистра UBRR, при которых получаемая скорость передачи отличается от требуемой на величину < 0.5%. Большая ошибка будет снижать помехозащищенность линии передачи.
//скорость обмена 9600 бодUCSRA Этот регистр в основном содержит флаги устанавливаемые самим модулем USART. Единственный флаг который нам понадобится в программе – UDRE – флаг опустошения регистра данных. Он устанавливается в 1 при пустом буфере передатчика. Установленный флаг означает, что в регистр данных можно загружать новое значение.
Постановка задачи
Нужно отправить из Qt-приложения пакет данных на устройство с микроконтроллером STM8. К компьютеру присоединён USB-RS485 преобразователь, а на устройстве соответственно преобразователь RS485-UART. Нужно учесть, что на линии связи возможен высокий уровень помех. В этой ситуации было принято решение написать быструю и легкую библиотеку для гарантии целостности принятых данных. *Гарантию доставки данных брала на себе бизнес-логика. Библиотеку решил назвать Sheller.
Требования к разрабатываемой библиотеки были следующие:
-
Фиксированная длинна пакета: количество байт, которые пользователь хочет передать не влияют на общую длину пакета, она остается фиксированной;
-
Минимальное количество внутренних буферов;
-
Наличие надежной, быстровычисляемой контрольной суммы;
-
Побайтного занесения данных;
-
Возможность работы в условиях поврежденных и потерянных байт в пакете;
Скетч
После подготовки и сборки компонентов, мы готовы программировать наши платы. Для этого проекта обе платы будут иметь одинаковые скетчи.
Сначала, мы устанавливаем режим контакта 8 (кнопка) в , режим контакта 13 (светодиод) в и устанавливаем начальное состояние контакта 13 в состояние (светодиод выключен).
Как всегда, Arduino позволяет нам легко использовать встроенное оборудование UART с помощью объекта serial. Последовательный serial объект имеет необходимые функции для простого использования UART-интерфейса Arduino.
Serial.begin()
Для связи через UART-интерфейс необходимо сначала его настроить. Самый простой способ настроить UART Arduino — это использовать функцию . Параметр («Скорость») — это скорость передачи данных, с которой мы хотим запустить UART. С помощью этой функции остальные параметры UART будут установлены на значения по умолчанию:
- Data length = 8 (длина данных)
- Parity bit = 1 (бит четности)
- Number of Stop Bits = None (количество стоп-битов = нет)
Если настройки по умолчанию для вас не работают, используйте функцию вместо . Дополнительный параметров используется для изменения настроек длины блока данных, бита четности, количества стоповых битов. Определенные значения для конфигурирования параметра можно найти здесь.
Нижеприведенный код добавляет внутри для инициализации Arduino Uno UART со скоростью 9600 бит/с и другими параметрами, установленными по умолчанию.
Следующая часть кода — это чтение и сохранение значения, полученного из последовательного интерфейса. Для этого мы будем использовать функцию вместе с оператором , чтобы проверить, не получены ли данные. Затем мы вызовем для получения одного байта полученных данных и сохраним значение в переменную . Значение управляет включением/выключением встроенного светодиода.
Serial.available()
Для проверки наличия данных, ожидающих чтения в буфере UART (или в последовательном интерфейсе), воспользуемся функцией . возвращает количество байт, ожидающих чтения в буфере.
Serial.read()
Для чтения данных, ожидающих в последовательном буфере, будем использовать функцию . Эта функция возвращает один байт данных, считанных из буфера.
Serial.write()
Для отправки данных через контакты Arduino TX0 мы будем использовать функцию . Параметр — это байт (или серия байтов), который будет отправлен.
В нашем скетче мы будем посылать значение в зависимости от состояния контакта 8. Мы отправим значение char ‘1’, если пин 8 HIGH, или значение char ‘0’, если пин 8 LOW.
Параметры UART
UART имеет настройки, которые должны быть одинаковыми на обоих устройствах, чтобы иметь правильную связь. Этими настройками UART являются скорость передачи данных, длина данных, бит четности, количество стоповых битов и управление потоком.
Скорость передачи
Скорость в бодах — это количество битов в секунду (бит/с), которое может передавать/принимать устройство UART. Для правильной передачи данных необходимо настроить оба прибора UART с одинаковой скоростью передачи данных в бодах. Распространенными значениями скорости передачи данных являются 9600, 1200, 2400, 4800, 19200, 38400, 57600 и 115200 бит в секунду.
Бит четности
Бит четности — это бит, добавляемый к передаваемым данным и сообщающий приемнику, является ли число единиц в передаваемых данных нечетным или четным. Возможная настройка для бита четности — «нечетный» (ODD) или «четный» (EVEN).
- ODD — бит четности равен ‘1’, если в данных присутствует нечетное число 1. В противном случае бит четности устанавливается равным нулю.
- EVEN — бит четности равен ‘1’, если в данных присутствует четное число единиц. В противном случае бит четности устанавливается равным нулю.
Количество стоп-битов
Приборы UART могут использовать ни одного, один или два стоповых бита для маркировки конца переданного набора битов (так называемых пакетов).
Управление потоком
Flow Control (управление потоком) — это метод, позволяющий избежать риска потери данных при передаче данных через UART. В устройстве UART в качестве управления потоком для запуска/остановки передачи данных используются специальные символы.
Разница между SPI, I2C и UART тремя протоколами последовательной шины:
Первый, разница, конечно же, в названии:
SPI (последовательный периферийный интерфейс: последовательный периферийный интерфейс);
I2C(INTER IC BUS)
UART (универсальный асинхронный приемный передатчик: универсальный асинхронный приемный передатчик)
Во-вторых, разница заключается в линии электрического сигнала:
Шина SPI состоит из трех сигнальных линийСостав: последовательные часы (SCLK), последовательный вывод данных (SDO), последовательный ввод данных (SDI). Шина SPI может соединять несколько устройств SPI друг с другом. Устройство SPI, которое обеспечивает последовательные часы SPI, является ведущим или ведущим SPI, а другие устройства являются ведомыми или ведомыми (ведомыми) SPI. Полнодуплексная связь может быть реализована между ведущими и ведомыми устройствами.При наличии нескольких ведомых устройств может быть добавлена строка выбора ведомого устройства.
Если вы используете универсальный порт ввода-вывода для имитации шины SPI, у вас должен быть выходной порт (SDO), входной порт (SDI), а другой порт зависит от типа реализованного устройства.Если вы хотите реализовать устройство ведущее-ведомое, вам понадобится порт ввода и вывода. , Если реализовано только ведущее устройство, порта вывода достаточно; если реализовано только ведомое устройство, требуется только порт ввода.
Шина I2C — это стандарт двустороннего, двухпроводного (SCL, SDA), последовательного интерфейса и интерфейса с несколькими ведущими устройствами.Он имеет механизм арбитража шины и очень подходит для передачи данных между устройствами на короткие расстояния и нечасто. В его системе протокола адрес устройства-получателя всегда переносится при передаче данных, поэтому может быть реализована сеть устройств.
Если порт ввода-вывода общего назначения используется для имитации шины I2C и достижения двунаправленной передачи, требуется порт ввода-вывода (SDA), а также порт вывода (SCL). (Примечание: данные I2C относительно плохо изучены, описание здесь может быть очень неполным)
Шина UART — это асинхронный последовательный портСледовательно, он, как правило, намного сложнее, чем структура первых двух синхронных последовательных портов. Он обычно состоит из генератора скорости передачи (генерируемая скорость передачи в 16 раз больше скорости передачи), приемника UART и передатчика UART.На оборудовании есть два провода: один для отправки, а другой для приема.
Очевидно, что если универсальный порт ввода-вывода используется для моделирования шины UART, требуются один входной порт и один выходной порт.
В-четвертых, посмотрите на мнение быдла!
Wudanyu: Количество линий I2C меньше. Я думаю, что он более мощный, чем UART и SPI, но технически более проблематичный, потому что I2C требует поддержки двунаправленного ввода-вывода иИспользуйте подтягивающий резистор, Я думаю, что способность к помехам слабая, обычно используется для связи между чипами на одной плате и меньше используется для междугородной связи. Реализация SPI проще. UART требует фиксированной скорости передачи данных, что означает, что интервал между двумя битами данных должен быть одинаковым. SPI не имеет значения, потому что это синхронизированный протокол.
Quickmouse: скорость I2C немного ниже, чем у SPI, и протокол немного сложнее, чем SPI, но соединение меньше, чем у стандартного SPI.
Примеры конфигурации плат[править]
BTT SKR 1.3править
Для соединения плат используется 3 провода с DuPont разъемами
SKR 1.3 Pin | Цвет | Raspberry Pin |
---|---|---|
GND | GPIO6_GND | |
P0.3_RXD | GPIO8_TXD | |
P0.2_TXD | GPIO10_RXD |
Собираем прошивку
cd ~/klipper/ make menuconfig
Собираем прошивку
make
Копируем файл klipper.bin на sd-карту, переименовываем в firmware.bin, вставляем в принтер и включаем его.
MKS RobinNano 1.2править
Подключение к плате MKS RobinNano 1.2 осуществляется через порт UART, который расположен на разъеме, предназначенном для Wi-Fi Карты. Естественно, Wi-Fi плата при этом снимается.
Со стороны Raspberry Pi подключаем пины 8, 10 и 9.
MSK RobinNano 1.2 Pin | Цвет | Raspberry Pin |
---|---|---|
GND | GPIO9_GND | |
TX-PA9 | GPIO10_RXD | |
RX-PA10 | GPIO8_TXD |
Далее пересобираем Klipper:
cd ~/klipper make menuconfig
Выбираем в Communication interface USART1:
Baud rate оставляем 250000.
Выходим и делаем и собираем прошивку
make ./scripts/update_mks_robin.py out/klipper.bin out/Robin_nano.bin
Скорее всего файл Robin_nano.bin придётся переименовать в ROBIN_NANO35.bin для прошивки в принтер. Заливаем файл на sd карту и перешиваем принтер.
Chitu V6править
Для подключения по UART платы Chitu V6 нам нужны пины на Wi-Fi разъёме:
Chitu V6 Pin | Цвет | Raspberry Pin |
---|---|---|
WiFi_Pin1_GND | GPIO9_GND | |
WiFi_Pin2_RX | GPIO8_TXD | |
WiFi_Pin7_TX | GPIO10_RXD |
Всё это соединяем
Собираем прошивку
cd ~/klipper/ make menuconfig
Выставляем Baud rate 230400:
Собираем Klipper
make ./scripts/update_chitu.py ./out/klipper.bin ./out/update.cbd
Заливаем update.cbd на sd карту и прошиваете принтер. Не забываем после прошивки принтер перезапустить.
Так как используемый Baud rateотличается от значения по умолчанию — то вносим изменения в конфигурационный файл printer.cfg
serial: /dev/serial0 restart_method: command baud: 230400
Creality 4.2.2править
Для подключения используются три провода, то необходимые для нас GPIO на Raspberry это: 6-GND,8-TXD,10-RXD. Подключаем их к плате принтера на IDC10 — EXP1:
Creality Pin | Цвет | Raspberry4 Pin |
---|---|---|
GND | GPIO6_GND | |
PB11_RXD | GPIO8_TXD | |
PB10_TXD | GPIO10_RXD |
IDC_10 — EXP1 Pinout | ||
---|---|---|
PC6 | PB2 (LM2596) | |
PB10 (USART) | PB11 (USART) | |
PB14 (ADXL) | PB13 (ADXL) | |
PB12 (ADXL) | PB15 (ADXL) | |
GND (USART) | VCC_5V |
cd ~/klipper make menuconfig
включаем low-level configuration options
в разделе communication interface выбираем Serial (on USART3 PB11/PB10)
Сразу обращаю внимание, что нужно запомнить Baud rate, потом эта цифра перейдет в конфиг Klipper
Собираем прошивку
make
и затем устанавливаем её.
Вносим коррективы в printer.cfg, тут в параметре baud указываем то же значение, что и на этапе прошивки.
#Creality 4.2.2 Mainboard serial: /dev/ttyAMA0 baud: 115200 restart_method: command
Синхронизация и выборка
Стандартные цифровые данные бесполезны без какого-либо механизма синхронизации. На рисунке ниже показано почему:
Выборка двоичных данных при приеме через UART
Типовой сигнал данных представляет собой просто напряжение, уровень которого изменяется между состояниями логического нуля и единицы. Приемник может правильно преобразовать эти логические состояния в цифровые данные, только если он знает, когда сделать выборку сигнала. Это может быть легко выполнено с помощью отдельного тактового сигнала – например, передатчик обновляет сигнал данных при каждом нарастающем фронте тактового сигнала, а приемник затем делает выборку данных по каждому заднему фронту.
Однако, как следует из названия «универсальный асинхронный приемник/передатчик», интерфейс UART не использует тактовый сигнал для синхронизации устройств Tx и Rx. Так как же приемник узнает, когда сделать выборку сигнала данных передатчика?
Передатчик формирует битовый поток на основе своего тактового сигнала, а целью приемника является использование своего тактового сигнала для выборки входящих данных в середине каждого битового периода. Выполнение выборки в середине битового периода не является обязательным, но этот момент оптимален, так как выборка ближе к началу или к концу битового периода делает систему менее устойчивой к различиям тактовых частот приемника и передатчика.
Последовательность приемника начинается с заднего фронта стартового бита. Это очень важный момент процесса синхронизации. Внутренний тактовый генератор приемника полностью независим от внутреннего тактового генератора передатчика – другими словами, эта граница спада сигнала может соответствовать любой точке в тактовом сигнале приемника.
Момент прихода стартового бита в приемник UART
Чтобы гарантировать, что активный фронт тактового сигнала приемника будет приходиться примерно на середину битового периода, частота тактового сигнала битовой скорости, переданная в модуль приемника, значительно выше (в 8 или 16, или даже в 32 раза) реальной битовой скорости.
Допустим, что один битовый период соответствует 16 циклам тактового сигнала приемника. В этом случае синхронизация и выборка могут быть выполнены следующим образом:
- процесс приема запускается по границе спада стартового бита;
- приемник ждет в течение 8 циклов тактового сигнала, чтобы установить момент выборки, который находится близко к середине периода бита;
- приемник ждет в течение 16 циклов тактового сигнала, которые приводят его к середине периода первого бита данных;
- первый бит данных оцифровывается и сохраняется в регистре приемника, а затем модуль снова ожидает 16 циклов тактового сигнала перед выборкой второго бита данных;
- этот процесс повторяется до тех пор, пока все биты данных не будут выбраны и сохранены, а затем нарастающий фронт стопового бита возвращает интерфейс UART в режим ожидания.
Выборка данных при приеме через UART
Настройка тактирования — Clock.c
Настройка тактирования реализована в файле Clock.c, функция Clock_Init_HSE_PLL(). Данная функция настраивает частоту ядра на работу от генератора HSE c использованием умножителя PLL, который передается во входном параметре. В примере используется максимальный коэффициент умножения PLL_MUL = 16 (main.c).
Код легче понять, если ориентироваться на рисунок 3.
Увеличить фото
Рисунок 3 — структурная блок-схема формирования тактовой частоты
В основном, код состоит из включения мультиплексоров С1, С2, С3 и PLL. Но есть два важных момента:
-
Выборка команд из EEPROM не может происходить быстрее, чем 25МГц, поэтому необходимо выставлять задержку доступа к EEPROM при работе ядра на больших частотах. Ядро останавливается на время этой задержки, пока считывается очередная порция инструкций. За раз из EEPROM извлекается 16 байт, где может быть закодировано от 4 до 8 инструкций процессора. Установка задержки происходит функцией EEPROM_SetLatency(), при этом предварительно на блок EEPROM подается тактирование.
-
При работе на высоких частотах необходимо регулировать параметры внутреннего регулятора напряжения ядра(LDO). В спецификации это параметры SelectRI и LOW в регистре REG_0E, которые выбираются по частоте ядра и всегда должны быть равны. Раздельное управление этими параметрами возможно, но, согласно спецификации, не рекомендуется. Если используется много периферийных блоков, то случается, что без выставления данных параметров МК сбоит, поэтому рекомендуется выставлять эти параметры всегда — функция SetSelectRI().
В приведенном списке SelectRI присутствует значение RI_Gens_Off. Оно выставляется, когда тактирование снаружи микросхемы задается не резонатором, а внешним генератором. В таком варианте необходимость во внутреннем генераторе отпадает и частота напрямую (режим ByPass) идет на вход схемы тактирования, мультиплексор С1 вход HSE.
Резонатор генерирует синусоидальный сигнал, который далее генератором преобразуется в прямоугольные импульсы.
main.c
The default main.c file automatically has the SYSTEM_Initialize() function defined. This will call all the initialization routines that were created by the MCC and is defined in the mcc.c file. These include:OSCILLATOR_Initialize();PIN_MANAGER_Initialize();EUSART_Initialize();
main.c also requires a few lines to be uncommented for the interrupt to work properly. To enable the interrupt to work, Global Interrupts and Peripheral Interrupts need to be enabled. MCC already has the control commands in the default main.c file, they are just commented out with two forward slashes (//). The forward slashes need to be removed to enable these lines of code.
The main loop requires two additional lines: UART_Demo_Initialize() and UART_Demo_Command_INT(). These are both defined in a file UART_Demo.c that needs to be created. That will be done next.
Интерфейс UART
UART (Serial) — асинхронный интерфейс передачи данных, последовательно передающий биты из байта данных. Асинхронная передача позволяет осуществлять передачу данных без использования тактирующего сигнала от передатчика к приёмнику. Вместо этого приёмник и передатчик заранее договариваются о временных параметрах и специальных «стартовых битах», которые добавляются к каждому слову данных для синхронизации приёмника и передатчика. Существует множество устройств, с которыми Raspberry Pi может обмениваться данными по UART протоколу.
В Raspberry Pi 3 есть два аппаратных UART интерфейса:
- PL011 (/dev/ttyAMA0) – для своей работы использует тактирование видеоядра RPi, в связи с чем ограничивает его частоту.
- Mini UART (/dev/ttyS0) – полноценный UART интерфейс выполненный на отдельном блоке кристалла микроконтроллера.
Для удобства работы с этими выходами в Raspbian существуют алиасы:
- /dev/serial0 – всегда указывает на то TTY устройство, что подключено к GPIO портам.
- /dev/serial1 – всегда указывает на то TTY устройство, что подключено к Bluetooth модулю.
Отключить консоль:
sudo systemctl stop serial-getty@ttyS0.service sudo systemctl disable serial-getty@ttyS0.service
Интерфейс SPI
SPI — последовательный четырёх-проводной интерфейс передачи данных, предназначенный для обеспечения простого и недорогого высокоскоростного сопряжения микроконтроллеров и периферии.
Raspberry Pi имеет одну шину — SPI0. Но более новые версии одноплатника — например, Raspberry Pi 4 Model B — обладают двумя шинами: SPI0 и SPI1
Включения шины SPI0
По умолчанию шина SPI0 отключена. Для включения выполните следующие действия.
-
Откройте терминал с рабоче стола Raspberry Pi или подключитесь по SSH-соединению.
-
Зайдите в настройки Raspberry Pi.
sudo raspi-config
- Выберите пункт
- Далее пункт .
- Нажмите для подтверждения включения шины.
-
Для проверки включения шины SPI0 запустите листинг директории /dev:
ls /dev/
В ответ вы должны увидеть полотно файлов, среди которых два: и .
Это значит что у вас включён SPI0 с возможностью подключения двух ведомых устройств.
Теперь вы можете использовать интерфейс SPI для коммуникации с датчиками и модулями.
Включения шины SPI1
Если вы используете Raspberry Pi 4 Model B, то вам доступно две шины SPI: и .
Для включения шины SPI1, необходимо вручную отредактировать файл настроек загрузки системы.
-
Откройте от пользователя файл настройки загрузки системы.
sudo nano /boot/config.txt
-
В конец файла добавьте команду включения .
dtoverlay=spi1-3cs
- Сохраните файл сочетанием клавиш +.
-
Для вступления изменений в силу перезагрузите Raspberry Pi.
sudo reboot
-
Для проверки включения шины SPI1 запустите листинг директории /dev:
ls /dev/
В ответ вы должны увидеть полотно файлов, среди которых три отвечают за SPI1: , и .
Если у вас включена шина SPI0, то будут ещё два файла: и .
Это значит что у вас включён SPI0 с возможностью подключения двух ведомых устройств и SPI1 с возможностью подключения трёх ведомых устройств.
Порядок работы со стороны хоста
- Получаем информацию с устройства: размер флеша, ChipID, размер буфера приёма, адрес старта, версия загрузчика и чипа.
- Даём команду стирания либо всей прошивки, либо части указав размер стираемой области.
- По завершению стирания начинаем непрерывно отправлять команды записи блоками друг за другом, проверяя что текущая записанная позиция в устройстве увеличивается.
- Если позиция перестала увеличиваться (приняли два ответа на команду «запись» с одинаковым адресом), то скорректировать адрес на Хосте, сбросить буферы отправки и начать передавать с нового скорректированного адреса.
- По завершению записи подать команду «Старт» передав CRC32 всей прошивки, в ответ Устройство сообщит фактическое CRC32.
- Если фактическое CRC32 равно расчётному, то загрузка успешно закончена и прошивка запущена.