Плавающее напряжение UART на пользовательской печатной плате?

Я тестирую свою первую печатную плату, основанную на ATMega328, и столкнулся с нежелательным поведением UART:

Когда у меня есть UART, подключенный к моему компьютеру через USB-кабель FTDI, он работает отлично, но если я отсоединю кабель от печатной платы, я могу отправить ввод на линию Rx печатной платы, просто коснувшись Rx и заземления одним пальцем на в то же время.

На самом деле у меня раньше была проблема с пальцами, вызывающими плохой ввод, и ответом на это было то, что у меня были плавающие напряжения.

Конечно, линии Rx/Tx, когда они ни к чему не подключены, тоже будут плавающими, что, я думаю, вызывает здесь ту же проблему.

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

Тогда два вопроса:

  1. Что может быть причиной этого?

  2. Что мне делать, чтобы это исправить? Подтягивание на линии Rx?

Дополнительная информация: так я тестировал.

#include <avr/io.h>

#define USART_BAUDRATE 9600
#define F_CPU 16000000UL
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#define pin (PC3)

void initUART(void)
{
    // Set baud rate
    UBRR0H = (uint8_t)(UBRR_VALUE >> 8);
    UBRR0L = (uint8_t)UBRR_VALUE;
    // Set frame format to 8 data bits, no parity, 1 stop bit
    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
    //enable transmission and reception
    UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
}
void sendUARTByte(uint8_t data)
{
    // Wait for byte to be transmitted
    while (!(UCSR0A & (1<<UDRE0))) { }
    // Transmit data
    UDR0 = data;
}
uint8_t receiveUARTByte()
{
    // Wait for byte to be received
    while (!(UCSR0A & (1<<RXC0))) { }
    // Receive data
    return UDR0;
}
int main(void)
{
    uint8_t input = '!';

    DDRC = _BV(pin);
    PORTC = 0;

    initUART();
    while(1)
    {
        PORTC |= _BV(pin);
        sendUARTByte(input);
        input = receiveUARTByte();

        PORTC &= ~_BV(pin);
        sendUARTByte(input);
        input = receiveUARTByte();
    }
}

По сути, все, что он делает, это переключается PC3(= pin) всякий раз, когда есть какой-либо вход на UART, и просто отражает вход обратно на выход.

Он отлично работает при подключении к моему компьютеру, но затем, если я отсоединяю линию Rx и перемещаю линию заземления на другую площадку (чтобы я мог легко одновременно касаться контактов Rx и заземления), я все еще получаю переключение контактов. на высокой частоте, но я не получаю никакого вывода на компьютер (хотя линии Tx и заземления все еще подключены).

Вот соответствующая часть схемы:Схема печатной платы

UART находится в центре слева.

Ответы (2)

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

Например, на ATmega вы можете установить внутреннюю подтяжку основного последовательного вывода следующим образом.

/* Idea copied from arduino bootloader - Enable internal pull-up 
resistor on pin D0 (RX), in order to supress line noise */
  DDRD &= ~_BV(PIND0);
  PORTD |= _BV(PIND0);
Если вы знаете, как это сделать, не могли бы вы предоставить код, который устанавливает внутреннее подтягивание? Я просматриваю таблицу данных, и я не совсем уверен, как это сделать. (Будет ли нормально, если я каким-то образом вручную настрою контакт Rx в качестве входа в коде, помимо того, что просто скажу модулю UART позаботиться об этом?)
Если вы найдете основной код UART Arduino, я полагаю, что это сработает; если я правильно помню, на AVR, чтобы установить подтягивание на входе, вы записываете регистр выходных данных для этого бита в 1, в дополнение к установке его в качестве входа в регистре направления данных.
О, подождите, я только что пропустил одну часть данных — Rx — это контакт PD0! Да, я должен просто установить PORTD = 1 и DDRD = 0 (конечно, для бита 0).
Круто, работает!! На самом деле я понял эти две строки кода всего за секунду до того, как вы отредактировали свой пост, но я рад, что смог перепроверить его. Спасибо!

Я столкнулся с той же проблемой, когда разрабатывал свою печатную плату ATmega64.

Он работал нормально, когда TX / RX подключался к компьютеру через USB-кабель FTDI, и если я отключал FTDI от компьютера или от платы ATmega64, то выходные контакты контроллера переключались без какого-либо ввода.

  1. Решение: у меня на плате был установлен LM317 на 3,7 В. Я подключил к нему TX/RX, и проблема была решена.

  2. Решение: я разработал вторую печатную плату с более прочным заземлением и плоскостью 3,7 В, и тогда TX/RX не показал никаких проблем. Таким образом, вы можете улучшить плоскость GND и V CC в проектировании печатных плат.