Ich teste mein allererstes PCB-Design, das auf einem ATMega328 basiert, und bin beim UART auf ein unerwünschtes Verhalten gestoßen:
Wenn ich den UART über ein FTDI-USB-Kabel an meinen Computer angeschlossen habe, funktioniert er einwandfrei, aber wenn ich das Kabel von der Platine trenne, kann ich Eingaben auf die Rx-Leitung der Platine senden, indem ich einfach sowohl Rx als auch Masse mit einer Fingerspitze berühre gleiche Zeit.
Ich hatte tatsächlich schon früher ein Problem mit Fingern, die schlechte Eingaben verursachten, und die Antwort darauf war, dass ich schwebende Spannungen hatte.
Natürlich würden die Rx/Tx-Leitungen, wenn sie mit nichts verbunden sind, auch schwimmen, was meiner Meinung nach das gleiche Problem hier verursacht.
Ich brauche das wirklich, um zuverlässig zu sein - insbesondere möchte ich, dass der UART keine Eingaben enthält, wenn keine Eingaben gesendet werden.
Dann zwei Fragen:
Was könnte dies verursachen?
Was soll ich tun, um es zu beheben? Pull-up auf der Rx-Leitung?
Weitere Informationen: So habe ich getestet.
#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();
}
}
Im Wesentlichen wird nur umgeschaltet PC3
(= pin
), wenn eine Eingabe auf dem UART vorhanden ist, und die Eingabe einfach wieder auf die Ausgabe gespiegelt.
Es funktioniert einwandfrei, wenn es an meinen Computer angeschlossen ist, aber wenn ich dann die Rx-Leitung abtrenne und die Erdungsleitung auf ein anderes Pad verschiebe (damit ich die Rx- und Erdungsstifte gleichzeitig berühren kann), wird der Stift immer noch umgeschaltet bei einer hohen Frequenz, aber ich bekomme keine Ausgabe zurück zum Computer (obwohl die Tx- und Masseleitungen noch verbunden sind).
Hier ist auch der relevante Teil des Schaltplans:
Der UART befindet sich in der Mitte links.
Es ist ziemlich üblich, zumindest den internen Pullup zu aktivieren und vielleicht einen stärkeren externen bereitzustellen. Schwebende Eingänge verursachen nicht nur falsche Signale; Ein Eingang in der Nähe der Übergangsspannung des Logikpegels kann dazu führen, dass ein Chip übermäßig viel Strom verbraucht, da sowohl der obere als auch der untere FET teilweise eingeschaltet werden können, was einen Leitpfad von der Versorgung zur Masse verursacht.
Auf einem ATmega können Sie beispielsweise den internen Pullup des primären seriellen Empfangspins wie folgt einstellen.
/* 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);
Ich hatte das gleiche Problem, als ich meine ATmega64-Leiterplatte individuell gestaltete.
Es funktionierte gut, wenn TX/RX über ein FTDI-USB-Kabel mit dem Computer verbunden war, und wenn ich FTDI vom Computer oder von der ATmega64-Platine trenne, schalteten die Controller-Ausgangspins ohne Eingabe um.
Lösung: Ich hatte LM317 an Bord auf 3,7 V eingestellt. Ich habe TX/RX damit verbunden und das Problem war gelöst.
Lösung: Ich habe eine zweite Platine mit stärkerer Masse und 3,7-V-Ebene entworfen, und TX/RX zeigte damals kein Problem. So können Sie die GND- und VCC - Ebene beim PCB-Design verbessern.
Jashaszun
Chris Stratton
Jashaszun
Jashaszun