PIC16: Проблемы с приемом UART

У меня есть PIC16 , для которого (асинхронная) передача UART работает нормально, но прием UART дает неверные результаты.

Например, aинтерпретируется как O, bинтерпретируется как ', и cполучает как N.

Вот моя функция приема:

char UART_read(void) {
    while(!PIR1bits.RCIF) {}

    return RCREG;
}

Моя гипотеза состоит в том, что полярность UART неверна для приемника, так что, в частности, перепутались стартовые/стоповые биты. Я установил SCKPбит (см. стр. 302) для инвертирования данных на выводе TX/CK, но я не могу найти эквивалент для контакта RX/DT.

Что может быть причиной того, что прием UART не работает? Как я могу инвертировать данные на выводе RX/DT?

Что является источником данных? Вы уверены, что источник и приемник имеют одинаковую скорость передачи данных, стоповые биты, четность, уровни напряжения и т. д.?
Кроме того, что произойдет, если вы выполните петлевой тест?
Я заметил подобное, когда скорость передачи не соответствует частоте внутреннего генератора. OSCCONbits.IRCFрегистр настроен правильно?

Ответы (2)

РЕДАКТИРОВАТЬ : этот ответ был изменен, чтобы отразить комментарий задавшего вопрос, и указывает, что он совершенно прав в своем диагнозе проблемы, что не очень полезная информация. Единственная полезная информация в разделе - это то, что бита инвертирования приема нет... Но, возможно, это поможет будущим людям диагностировать свои проблемы с UART.


Итак, давайте посмотрим

a сопоставляется с O, что означает, что 01100001 сопоставляется с 01001111

b сопоставляется с ', что означает, что 01100010 сопоставляется с 00100111

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

so 'a' == 1 10000110 0 initially (we send least significant bit first)
1 (implicit start bit) and starting 1 are both consumed as idle bits
then the first 0 is treated as a start bit
so received == 00001100 inverted (the extra zeros are the stop bit and idle bits after transmission has ended)
11110011 and reverse it (it was sent LSB first)
11001111 is what the inverted input would look like
01001111 is what's actually received which is super close!
if what you actually sent was "abc" all in a row, then the start bit of the b would make what was received 01001111 which matches exactly

'b' == 1 01000110 0 ==> 10001100 inverted and reversed gives
11001110 is what should have "logically" happened
00100111 actual
So that doesn't quite match, but if we assume that the "abc" is what happened again, we get
01001110 which is close enough (not sure where the shift came from)

Похоже, вы поставили диагноз, к сожалению, в приемнике на PIC нет аналогичного бита конфигурации «инвертировать сигнал». Хотя поставить инвертор на приемный тракт несложно, что я бы, кстати, и рекомендовал!

Как заметил Олин, стандартные сигналы RS-232 составляют от +3 В до +15 В для логической «1» и от -3 В до -15 В для логического «0». PIC разработан для работы на уровне «TTL», что означает «транзисторно-транзисторная логика». Идея состоит в том, что PIC предназначен для общения с другими объектами, которые физически находятся близко (т. е. на той же плате), и, таким образом, дополнительное расстояние передачи и шумоподавление, обеспечиваемые полными уровнями rs-232, не требуются для «стандартной» работы. Нецелесообразно иметь возможность полностью внутренне генерировать положительные / отрицательные напряжения, необходимые для работы RS-232, полностью внутри PIC, поэтому «нормальная» связь RS-232 никогда не была вариантом.

Поскольку уровни TTL не являются стандартом, а являются производными от стандарта (один и тот же протокол для синхронизации, стартовый и стоповый биты, контроль четности, но разные напряжения), вы не покупаете потребительский «адаптер RS-232» для своего компьютера, если только он придерживается стандарта. Они делают адаптеры rs-232 уровня TTL, и они очень популярны на сайтах любителей! Ознакомьтесь с кабелем Adafruit или прорывом Sparkfun FTDI . Я считаю, что в целом, если он подходит к разъему DB9, это, вероятно, адаптер уровня rs-232.

Это O(буква), а не 0(число). Итак 01100001, 01100010, 01100011сопоставьте с , 01001111соответственно . Кроме того, помните, что биты LSB отправляются первыми. Таким образом, если линия приема инвертирована, крайний правый бит является начальным. Так становится , становится и становится , все соответствует тому, что я получаю. 0010011101001110 101100001~1011000001100010~1101100001100010~10100111
@Randomblue: я исправил свой ответ, чтобы действительно правильно провести анализ, и добавил несколько дополнительных замечаний о несоответствии rs-232 и TTL для взаимодействия PIC с компьютером.
Ни один из двух продуктов, которые вы связали, не преобразует сигналы логического уровня в RS-232. Оба они представляют собой преобразователи USB в последовательный порт, что здесь неприменимо.
@OlinLathrop: я никогда не был уверен, как называется настоящий протокол. «Последовательный» подразумевает любой непараллельный протокол связи, а «Асинхронный последовательный протокол», по-видимому, допускает всевозможные методы кадрирования символов, порядок байтов и т. Д. Вы правы в том, что ссылки, которые я дал, явно не rs -232 переходники. Является ли USB-UART правильным термином? Кабель Adafruit на самом деле называет себя «кабелем USB FTDI TTL-232», поэтому я предположил, что «адаптер rs-232 уровня TTL» является подходящим названием.
@OlinLathrop: Что касается их применимости к этому разговору, я признаю, что делал здесь предположение об использовании Randomblue. Он сказал, что пытался связать свой компьютер с Windows 7 со своим проектом (в комментарии под вашим ответом), и я дал ссылки на продукты, которые облегчат ему это. Он мог бы использовать схемы max232 для сопряжения имеющегося у него чипа с имеющимся у него последовательным адаптером, но я предполагаю, что, как и большинство любителей, он быстро устанет от этого и захочет более простой метод.

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

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

Добавлен:

Теперь вы показали, что вы просто подключили линии PIC UART к линиям приема и передачи RS-232 и каким-то образом ожидали, что все будет работать. Цифровые логические уровни, используемые PIC, и уровни RS-232 несовместимы, а также инвертируются высокий/низкий уровни. RS-232 должен быть ниже -5 В для незанятой линии (пробел) и выше +5 В для активной (отметка). Очевидно, что PIC не может гарантировать эти уровни при передаче и может быть поврежден этими уровнями при приеме. Обычные цифровые логические уровни высоки для пробела и низки для метки, что также делает PIC, за исключением нескольких ограниченных, таких как ваша, где одна или обе линии могут быть инвертированы.

Некоторые микросхемы приемника RS-232 не соответствуют спецификациям RS-232 и работают с сигналами 0-5 В, управляющими их приемной линией. По-видимому, это относится и к вашему ПК, поэтому вы смогли получать символы на ПК после того, как просто инвертировали линию передачи PIC. Чтобы заставить ПК -> передачу PIC работать, вы должны инвертировать сигнал и сопоставить результат с диапазоном Vss до Vdd PIC. Несоблюдение этого требования может привести к повреждению PIC, что уже могло произойти.

Все это то, почему был создан тип микросхемы MAX232. Он питается от PIC Vdd и Vss, содержит собственные зарядовые насосы для создания напряжений RS-232, имеет соответствующие схемы драйвера и приемника с каждой стороны, а также выполняет инверсию. Многие компании делают несколько вариантов этого. Это очень распространенные и доступные чипы.

Вы также можете получить небольшие модули, которые имеют микросхему преобразователя, зарядный насос и крышки блока питания, а также стандартный разъем DB-9 в одном устройстве. Я делаю один из них, который даже продается на microchipdirect. См . http://www.microchipdirect.com/ProductSearch.aspx?Keywords=TEMRS002 .

Чтобы ответить на ваш вопрос, я использую то, что, как я предполагаю, является чрезвычайно распространенной установкой: Win7 с TeraTerm с одной стороны и PIC16 с другой. Разве UART не должен «просто работать»?
@Random: Абсолютно нет, как показал бы даже беглый взгляд на соответствующие спецификации. Подключение PIC напрямую к RS-232 может повредить PIC и не обеспечить правильные уровни на стороне RS-232, даже если вы просто инвертировали логические сигналы. Вот почему существуют такие чипы, как обычный MAX232, а также его многочисленные варианты и подделки. Вам действительно нужно время от времени читать некоторые спецификации .
Вы не представляете, сколько раз я читал эту EUSARTглаву (стартовая страница 291 таблицы данных PIC16 ). Нет упоминания или предупреждения о прямом подключении к RS232 или MAX232. Где я ошибся в процессе? Я предполагал, что глава таблицы данных PIC16 по EUSART будет охватывать общий вариант использования: RS232.
В техническом описании указаны максимальные уровни входного сигнала на любом выводе. RS232 находится далеко за пределами этих уровней. На самом деле описание того, как их преобразовать, не входит в сферу применения PIC16. В общем, если вы пытаетесь соединить две вещи, вы не можете ожидать, что получите всю информацию, прочитав спецификации только одной из них.
@Random: это не работа Microchip, и это загромождает таблицу данных, чтобы объяснить RS-232 или какие преобразования необходимы для подключения PIC к чему-то другому. Они документируют то, что делает PIC. Ваша задача — знать, к чему вы подключаете PIC, и добавлять любые интерфейсные схемы, которые могут потребоваться, исходя из спецификаций другой стороны.