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:
¿Qué podría estar causando esto?
¿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:
El UART está en el centro a la izquierda.
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);
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.
Solución: Tenía LM317 a bordo configurado a 3,7 V. Conecté TX/RX con él y el problema se resolvió.
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.
Jashaszun
chris stratton
Jashaszun
Jashaszun