¿Tensión flotante UART en PCB personalizada?

Estoy probando mi primer diseño de PCB, que se basa en un ATMega328, y me encontré con un comportamiento no deseado con el UART:

Cuando tengo el UART conectado a mi computadora a través de un cable USB FTDI, funciona perfectamente, sin embargo, si desconecto el cable de la PCB, puedo enviar la entrada en la línea Rx de la PCB simplemente tocando Rx y tierra con la punta de un dedo en el Mismo tiempo.

De hecho, he tenido un problema con los dedos que causaban malas entradas antes, y la respuesta a eso fue que tenía voltajes flotantes.

Por supuesto, las líneas Rx/Tx, cuando no están conectadas a nada, también estarían flotando, lo que creo que está causando el mismo problema aquí.

Realmente necesito que esto sea confiable; en particular, me gustaría que no haya ninguna entrada en el UART cuando en realidad no hay nada que envíe una entrada.

Dos preguntas entonces:

  1. ¿Qué podría estar causando esto?

  2. ¿Qué debo hacer para arreglarlo? ¿Parada en la línea Rx?

Más información: así es como estaba probando.

#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();
    }
}

Esencialmente, todo lo que está haciendo es alternar PC3(= pin) siempre que haya alguna entrada en el UART, y simplemente reflejar la entrada en la salida.

Funciona bien cuando lo conecto a mi computadora, pero luego, si desconecto la línea Rx y muevo la línea de tierra a otra almohadilla (para que pueda tocar fácilmente los pines Rx y de tierra al mismo tiempo), todavía obtengo el cambio de pin a alta frecuencia, pero no obtengo ninguna salida a la computadora (aunque las líneas Tx y de tierra todavía están conectadas).

Aquí está la parte relevante del esquema también:Esquema de PCB

El UART está en el centro a la izquierda.

Respuestas (2)

Es bastante común activar al menos el pullup interno, y tal vez proporcionar uno externo más fuerte. Las entradas flotantes no solo provocan señales falsas; una entrada cerca del voltaje de cruce del nivel lógico puede hacer que un chip consuma una corriente excesiva, ya que tanto el FET superior como el inferior pueden encenderse parcialmente, lo que provoca una ruta de conductancia desde el suministro a tierra.

Por ejemplo, en un ATmega puede configurar el pull-up interno del pin de recepción en serie principal de esta manera.

/* 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);
Si sabe cómo hacerlo, ¿podría proporcionar un código que establezca el pull-up interno? Estoy mirando la hoja de datos y no estoy muy seguro de cómo hacerlo. (¿Estará bien si de alguna manera configuro el pin Rx como una entrada en el código manualmente, además de decirle al módulo UART que se encargue de eso?)
Si encuentra el código UART del núcleo Arduino, creo que lo hace; si no recuerdo mal, en un AVR para configurar el pullup en una entrada, escribe el registro de datos de salida para ese bit en 1, además de configurarlo como una entrada en el registro de dirección de datos.
Oh, espera, me perdí un dato: ¡Rx es el pin PD0! Sí, debería poder configurar PORTD = 1 y DDRD = 0 (para el bit 0, por supuesto).
Impresionante, funciona!! De hecho, descubrí esas dos líneas de código solo un segundo antes de que editaras tu publicación, pero me alegro de haber podido verificarlas dos veces. ¡Gracias!

Enfrenté el mismo problema cuando diseñé a medida mi PCB ATmega64.

Funcionó bien cuando TX/RX se conectó a la computadora a través del cable USB FTDI y si desconecto FTDI de la computadora o de la placa ATmega64, los pines de salida del controlador se alternaban sin ninguna entrada.

  1. Solución: Tenía LM317 a bordo configurado a 3,7 V. Conecté TX/RX con él y el problema se resolvió.

  2. Solución: Diseñé una segunda PCB con una conexión a tierra más fuerte y un plano de 3,7 V y TX/RX no mostró ningún problema en ese momento. Por lo tanto, puede mejorar el plano GND y V CC en el diseño de PCB.