00 UART temelleri
UART (Universal Asynchronous Receiver/Transmitter) — saat sinyali olmadan, önceden anlaşılmış baud rate ile çalışan asenkron seri haberleşme.
TX ──────────────────────────────► RX
RX ◄────────────────────────────── TX
GND ─────────────────────────────── GND
Frame yapısı:
│ START │ D0 │ D1 │ D2 │ D3 │ D4 │ D5 │ D6 │ D7 │ [PARITY] │ STOP │
│ (0) │ 8 data bit │ (1) │
Baud rate, data bits, parity, stop bits
UART parametrelerini her iki tarafın aynı şekilde yapılandırması gerekir. En yaygın ayar: 115200 8N1 (115200 baud, 8 data bit, No parity, 1 stop bit).
| Parametre | Yaygın değerler | Açıklama |
|---|---|---|
| Baud rate | 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 | Saniyedeki sembol sayısı (UART'ta 1 sembol = 1 bit) |
| Data bits | 7, 8 | Her frame'deki veri bit sayısı. 8 universaldir. |
| Parity | None (N), Even (E), Odd (O) | Hata tespiti için. Çoğu modern kullanımda N. |
| Stop bits | 1, 2 | Frame sonu boşluk süresi. Genellikle 1. |
| Flow control | None, RTS/CTS (hardware), XON/XOFF (software) | Veri akış denetimi. Bootloader konsollarda genellikle None. |
RS-232 vs TTL vs RS-485 gerilim seviyeleri
| Standart | Logic-1 (mark) | Logic-0 (space) | Mesafe | Kullanım |
|---|---|---|---|---|
| TTL (3.3V) | 3.3V | 0V | <1m | SoC GPIO → USB-TTL dönüştürücü |
| TTL (5V) | 5V | 0V | <1m | Arduino, eski MCU'lar |
| RS-232 | -3V ile -15V | +3V ile +15V | <15m | DB9 konnektör, eski PC com port |
| RS-485 | +1.5V differansiyel (A-B) | -1.5V differansiyel (A-B) | 1200m | Modbus, sanayi otomasyonu |
Raspberry Pi / BeagleBone gibi kartların UART pinleri 3.3V TTL seviyesinde çalışır. Doğrudan RS-232 cihaza bağlamak SoC'yi kalıcı olarak hasar verebilir. MAX3232 veya benzeri seviye dönüştürücü kullan.
01 Linux serial subsystem
Linux tty (TeleTYpe) subsystem, UART donanımını /dev/ttyXXX aygıt dosyaları üzerinden kullanıcıya sunar.
# Mevcut seri portları listele:
ls /dev/tty*
# USB cihaz tanımlama:
dmesg | grep ttyUSB
# [ 14.2] usb 1-1.2: cp210x converter now attached to ttyUSB0
# USB seri cihaz bilgisi:
udevadm info --query=all --name=/dev/ttyUSB0
# Seri porta erişim izni:
ls -la /dev/ttyUSB0
# crw-rw---- 1 root dialout 188, 0 Jan 1 00:03 /dev/ttyUSB0
# Kullanıcıyı dialout grubuna ekle:
sudo usermod -aG dialout $USER
udev rules ile kalıcı cihaz adı
USB-TTL dönüştürücüler her takıldığında farklı numara alabilir (ttyUSB0, ttyUSB1 ...). udev kuralı ile sabit isim verilebilir.
# FTDI FT232 tabanlı cihazı sabit isme bağla:
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
ATTRS{serial}=="A50285BI", SYMLINK+="ttyGSM"
# CP2102 tabanlı cihaz:
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", \
SYMLINK+="ttyESP"
# Cihazın idVendor/idProduct/serial bilgisini öğren:
udevadm info -a -n /dev/ttyUSB0 | grep -E 'idVendor|idProduct|serial'
# Kuralları yeniden yükle:
sudo udevadm control --reload-rules
sudo udevadm trigger
02 stty — baud rate ve ham mod
stty (set tty) — seri port parametrelerini komut satırından yapılandırır. Hem interaktif hem script kullanım için idealdir.
# Mevcut tty ayarlarını görüntüle:
stty -a
stty -F /dev/ttyUSB0 -a
# Baud rate ayarla (115200 8N1):
stty -F /dev/ttyUSB0 115200
# Tam parametre seti:
stty -F /dev/ttyUSB0 115200 cs8 -parenb -cstopb -crtscts
# ↑baud ↑8bit ↑noparity ↑1stopbit ↑no hw flow ctrl
# Ham (raw) mod — line editing, echo, signal karakterleri devre dışı:
stty -F /dev/ttyUSB0 raw
# Script'te okuma için: stty ile ham moda al, cat ile oku:
stty -F /dev/ttyUSB0 9600 raw -echo
cat /dev/ttyUSB0 & # arka planda oku
echo -e "AT\r" > /dev/ttyUSB0 # yaz
# stty ile basit iki yönlü terminal (ctrl-c ile çık):
stty -F /dev/ttyUSB0 115200 raw -echo
cat /dev/ttyUSB0 &
PID=$!
while read -r line; do
printf "%s\r\n" "$line" > /dev/ttyUSB0
done
kill $PID
03 minicom — kurulum ve yapılandırma
minicom — gelişmiş terminal emülatörü. Oturum capture, makro, XMODEM/YMODEM dosya transferi destekler.
sudo apt install minicom
İlk yapılandırma
# Yapılandırma menüsünü aç (root gerekebilir):
sudo minicom -s
# Menü: Serial port setup → (A) Serial Device: /dev/ttyUSB0
# → (E) Bps/Par/Bits: 115200 8N1
# → (F) Hardware Flow Control: No
# Menü: Save setup as dfl (varsayılan olarak kaydet)
# Menü: Exit from Minicom
# Kaydedilmiş yapılandırmayla bağlan:
minicom
# Belirli cihaza doğrudan bağlan:
minicom -D /dev/ttyUSB0 -b 115200
# Echo açık (gönderdiğini gör):
minicom -D /dev/ttyUSB0 -b 115200 -e
# Renkli çıktı:
minicom -c on -D /dev/ttyUSB0
minicom kısayolları
| Kısayol | İşlev |
|---|---|
| Ctrl-A Z | Yardım menüsünü aç |
| Ctrl-A X | minicom'dan çık |
| Ctrl-A C | Ekranı temizle |
| Ctrl-A L | Capture (oturumu dosyaya kaydet) |
| Ctrl-A W | Satır kaydırma aç/kapat |
| Ctrl-A S | Dosya gönder (XMODEM/YMODEM/ZMODEM) |
| Ctrl-A R | Dosya al |
| Ctrl-A O | Yapılandırma menüsü |
| Ctrl-A E | Local echo aç/kapat |
# Script'ten minicom'a komut gönder (expect tarzı):
# minicom'u capture modunda başlat ve çıktıyı dosyaya al:
minicom -D /dev/ttyUSB0 -b 115200 -C /tmp/capture.txt -S script.txt
# script.txt içeriği (minicom script formatı):
# send "AT\r"
# sleep 1
# send "AT+CIMI\r"
# sleep 1
# ! killall minicom
04 picocom — sade alternatif
picocom — minimal terminal emülatörü. Yapılandırma dosyası gerektirmez, argümanlarla anında bağlanır. Embedded geliştirme için idealdir.
sudo apt install picocom
# Temel kullanım:
picocom -b 115200 /dev/ttyUSB0
# 8N1, hardware flow control yok:
picocom -b 115200 --parity n --databits 8 --flow n /dev/ttyUSB0
# CR/LF dönüşümü (her CR için LF ekle — bazı bootloader'lar için):
picocom -b 115200 --omap crcrlf /dev/ttyUSB0
# İki yönlü CR/LF dönüşüm:
picocom -b 115200 --omap crcrlf --imap lfcrlf /dev/ttyUSB0
# Logfile al:
picocom -b 115200 -l --logfile /tmp/uart.log /dev/ttyUSB0
picocom kısayolları
| Kısayol | İşlev |
|---|---|
| Ctrl-A Ctrl-X | picocom'dan çık |
| Ctrl-A Ctrl-Q | Port'u kapatmadan çık |
| Ctrl-A Ctrl-U | Baud rate artır |
| Ctrl-A Ctrl-D | Baud rate azalt |
| Ctrl-A Ctrl-S | Dosya gönder (ASCII, XMODEM, YMODEM seç) |
| Ctrl-A Ctrl-R | Dosya al |
| Ctrl-A Ctrl-C | Hex display aç/kapat |
| Ctrl-A Ctrl-L | Ekranı temizle |
05 screen ve cu
screen ve cu — seri porta bağlanmak için ek yazılım yüklenmeden kullanılabilen araçlar.
# screen ile seri porta bağlan:
screen /dev/ttyUSB0 115200
# Özel baud ve parametreler:
screen /dev/ttyUSB0 115200,cs8,-parenb,-cstopb
# screen'den çıkış:
# Ctrl-A K (kill) → y
# veya: Ctrl-A \ → y
# screen oturumunu yeniden bağlamak (detach/attach):
# Ctrl-A D → detach
screen -r # tekrar bağlan
# Log kaydet:
# Ctrl-A H → screenlog.0 dosyasına log başlar
# cu ile bağlan (uucp paketi içinde gelir):
cu -l /dev/ttyUSB0 -s 115200
# ~. ile bağlantıyı kes (tilde + nokta)
screen'in seri port kullanımı bir yan özelliktir; temel amacı terminal multiplexer'dır. Uzun süre açık kalacak seri konsol oturumları için (detach ve sonra tekrar bağlanma ihtiyacı olan durumlar) screen kullanışlıdır. Sadece seri bağlantı için picocom daha sade bir seçenektir.
06 Python ile serial: pyserial
pyserial — Python'dan seri porta erişimin standart kütüphanesi. Linux, macOS ve Windows üzerinde tutarlı çalışır.
pip3 install pyserial
# veya:
sudo apt install python3-serial
import serial
import time
# Port aç:
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1.0, # read() için timeout (saniye)
write_timeout=1.0,
xonxoff=False, # software flow control
rtscts=False, # hardware flow control
)
print(f"Port: {ser.name} açık: {ser.is_open}")
# Tek satır yaz (CR+LF ile biter):
ser.write(b'AT\r\n')
# Yanıtı satır satır oku:
line = ser.readline() # '\n' bulana kadar veya timeout
print(f"Yanıt: {line.decode('ascii', errors='replace').strip()}")
# N bayt oku:
raw = ser.read(10)
print(f"10 bayt: {raw.hex(' ')}")
# Tampon temizle:
ser.reset_input_buffer() # rx tampon temizle
ser.reset_output_buffer() # tx tampon temizle
ser.close()
import serial
import threading
def reader(ser, stop_event):
while not stop_event.is_set():
try:
line = ser.readline()
if line:
print(f"<< {line.decode('utf-8', errors='replace').rstrip()}")
except serial.SerialException as e:
print(f"Serial hata: {e}")
break
with serial.Serial('/dev/ttyUSB0', 115200, timeout=0.1) as ser:
stop = threading.Event()
t = threading.Thread(target=reader, args=(ser, stop), daemon=True)
t.start()
try:
while True:
cmd = input(">> ")
ser.write((cmd + '\r\n').encode())
except KeyboardInterrupt:
stop.set()
07 Pratik: AT komut seti
AT komutları (Hayes komutları) GSM/LTE modemler, ESP8266/ESP32 WiFi modülleri, Bluetooth modemler ve birçok embedded cihazla haberleşmede kullanılır.
Temel AT komutları
| Komut | Açıklama | Beklenen yanıt |
|---|---|---|
| AT | Modem canlı mı kontrol | OK |
| ATI | Modem kimliği / firmware | Model string + OK |
| AT+CGSN | IMEI numarası | 15 haneli IMEI + OK |
| AT+CIMI | IMSI numarası (SIM) | 15 haneli IMSI + OK |
| AT+CSQ | Sinyal kalitesi | +CSQ: rssi,ber |
| AT+CREG? | Ağ kayıt durumu | +CREG: 0,1 (kayıtlı) |
| AT+COPS? | Operatör adı | +COPS: 0,0,"Turkcell" |
| ATE0 | Echo kapat | OK |
| ATE1 | Echo aç | OK |
| ATZ | Fabrika ayarlarına dön | OK |
import serial
import time
def at_command(ser, cmd, timeout=2.0, expected="OK"):
"""AT komutu gönder ve yanıtı topla."""
ser.reset_input_buffer()
ser.write((cmd + "\r\n").encode("ascii"))
response = []
deadline = time.time() + timeout
while time.time() < deadline:
line = ser.readline().decode("ascii", errors="replace").strip()
if line:
response.append(line)
if line in (expected, "ERROR", "+CME ERROR"):
break
return response
with serial.Serial("/dev/ttyUSB0", 115200, timeout=0.2) as ser:
# Echo kapat:
at_command(ser, "ATE0")
# Modem testi:
resp = at_command(ser, "AT")
print(f"AT: {resp}")
# IMEI:
resp = at_command(ser, "AT+CGSN")
print(f"IMEI: {resp}")
# Sinyal kalitesi:
resp = at_command(ser, "AT+CSQ")
for line in resp:
if line.startswith("+CSQ:"):
parts = line.split(":")[1].strip().split(",")
rssi = int(parts[0])
dbm = -113 + rssi * 2 if rssi < 99 else "bilinmiyor"
print(f"Sinyal: {rssi} ({dbm} dBm)")
ESP8266 AT komutları
picocom -b 115200 --omap crcrlf /dev/ttyUSB0
# ESP8266 AT komutları:
# AT → OK
# AT+GMR → firmware versiyonu
# AT+CWMODE=1 → Station mode (WiFi client)
# AT+CWLAP → Çevredeki WiFi ağlarını listele
# AT+CWJAP="SSID","password" → WiFi'ye bağlan
# AT+CIFSR → IP adresi al
08 RS-485 — half-duplex multi-drop
RS-485 — differansiyel, yarı çift yönlü (half-duplex) multi-drop bus. Tek çift kablo ile 32 cihaza, 1200 metreye kadar 10 Mbps veri aktarımı.
Master RS-485 Bus Slave 1 Slave 2 Slave N
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ TX ├──A(+)──────────────────────┤ ├─┤ ├─┤ │
│ RX ├──B(-)──────────────────────┤ ├─┤ ├─┤ │
│ DE │ 120Ω (terminal) 120Ω └──────┘ └──────┘ └──────┘
└──────┘ (her iki uçta)
RS-485'te sadece bir cihaz aynı anda konuşabilir. UART→RS-485 dönüştürücüler için bir DE (Driver Enable) pini bulunur; bu pin yüksekken TX, düşükken RX modu aktiftir.
Linux'ta RS-485 ayarı: TIOCSRS485
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
int rs485_enable(const char *dev)
{
int fd = open(dev, O_RDWR | O_NOCTTY);
if (fd < 0) { perror("open"); return -1; }
struct serial_rs485 rs485conf = {0};
rs485conf.flags |= SER_RS485_ENABLED; /* RS-485 modunu aktifleştir */
rs485conf.flags |= SER_RS485_RTS_ON_SEND; /* TX sırasında RTS/DE yüksek */
rs485conf.flags &= ~SER_RS485_RTS_AFTER_SEND; /* TX sonrası DE düşük */
rs485conf.delay_rts_before_send = 0; /* TX öncesi gecikme (ms) */
rs485conf.delay_rts_after_send = 0; /* TX sonrası gecikme (ms) */
if (ioctl(fd, TIOCSRS485, &rs485conf) < 0) {
perror("TIOCSRS485");
close(fd);
return -1;
}
return fd; /* fd'yi normal UART gibi kullan */
}
int main(void)
{
int fd = rs485_enable("/dev/ttyS1");
if (fd < 0) return 1;
/* RS-485 üzerinde Modbus RTU çerçevesi gönder (örnek): */
unsigned char frame[] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC5, 0xCD };
write(fd, frame, sizeof(frame));
unsigned char buf[64];
int n = read(fd, buf, sizeof(buf));
if (n > 0) {
for (int i = 0; i < n; i++)
printf("%02X ", buf[i]);
printf("\n");
}
close(fd);
return 0;
}
Termination direnci
RS-485 bus'ının her iki ucuna 120Ω direnç bağlanmalıdır. Terminasyon eksikliği yansıma (reflection) sorunlarına yol açarak veri bozulmasına neden olur. Sadece iki uçta (en başta ve en sonda) direnç olmalıdır; ortaya bağlanan cihazlara terminasyon direnci eklenmez.
| Sorun | Neden | Çözüm |
|---|---|---|
| Çerçeve hataları (framing error) | Baud rate uyumsuzluğu | Her iki taraftaki baud'u eşleştir |
| Veri kayıpları | DE timing yetersiz | delay_rts_before_send artır |
| Echo (kendi gönderdiğini okuma) | Half-duplex; RX aktif | SER_RS485_RX_DURING_TX bayrağını kaldır |
| Uzun kablo hataları | Termination eksik, cap. yük fazla | 120Ω terminal ekle, kablo kalitesini artır |